audiohal: Support stateful downmixer effects

Fraunhofer's downmixer has additional buffering, this is incompatible
with how DownmixerBufferProvider used to process incomplete buffers.

Now the effects HIDL wrapper delivers frameCount updates in
audiobuffers to the server side. This fixes playback of multichannel
sound streams.

Bug: 36181621
Test: play 5.1 track from Play Music
Change-Id: I3b2cd097d61873c6ba329f1a574235ac88b21cac
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/EffectBufferHalHidl.cpp
index d6a41a2..ef4097a 100644
--- a/media/libaudiohal/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/EffectBufferHalHidl.cpp
@@ -56,7 +56,8 @@
 }
 
 EffectBufferHalHidl::EffectBufferHalHidl(size_t size)
-        : mBufferSize(size), mExternalData(nullptr), mAudioBuffer{0, {nullptr}} {
+        : mBufferSize(size), mFrameCountChanged(false),
+          mExternalData(nullptr), mAudioBuffer{0, {nullptr}} {
     mHidlBuffer.id = makeUniqueId();
     mHidlBuffer.frameCount = 0;
 }
@@ -107,6 +108,13 @@
 void EffectBufferHalHidl::setFrameCount(size_t frameCount) {
     mHidlBuffer.frameCount = frameCount;
     mAudioBuffer.frameCount = frameCount;
+    mFrameCountChanged = true;
+}
+
+bool EffectBufferHalHidl::checkFrameCountChange() {
+    bool result = mFrameCountChanged;
+    mFrameCountChanged = false;
+    return result;
 }
 
 void EffectBufferHalHidl::setExternalData(void* external) {
diff --git a/media/libaudiohal/EffectBufferHalHidl.h b/media/libaudiohal/EffectBufferHalHidl.h
index 6e9fd0b..66a81c2 100644
--- a/media/libaudiohal/EffectBufferHalHidl.h
+++ b/media/libaudiohal/EffectBufferHalHidl.h
@@ -37,6 +37,7 @@
 
     virtual void setExternalData(void* external);
     virtual void setFrameCount(size_t frameCount);
+    virtual bool checkFrameCountChange();
 
     virtual void update();
     virtual void commit();
@@ -51,6 +52,7 @@
     static uint64_t makeUniqueId();
 
     const size_t mBufferSize;
+    bool mFrameCountChanged;
     void* mExternalData;
     AudioBuffer mHidlBuffer;
     sp<IMemory> mMemory;
diff --git a/media/libaudiohal/EffectBufferHalLocal.cpp b/media/libaudiohal/EffectBufferHalLocal.cpp
index 9fe2c7b..7951c8e 100644
--- a/media/libaudiohal/EffectBufferHalLocal.cpp
+++ b/media/libaudiohal/EffectBufferHalLocal.cpp
@@ -39,13 +39,13 @@
 
 EffectBufferHalLocal::EffectBufferHalLocal(size_t size)
         : mOwnBuffer(new uint8_t[size]),
-          mBufferSize(size),
+          mBufferSize(size), mFrameCountChanged(false),
           mAudioBuffer{0, {mOwnBuffer.get()}} {
 }
 
 EffectBufferHalLocal::EffectBufferHalLocal(void* external, size_t size)
         : mOwnBuffer(nullptr),
-          mBufferSize(size),
+          mBufferSize(size), mFrameCountChanged(false),
           mAudioBuffer{0, {external}} {
 }
 
@@ -62,6 +62,7 @@
 
 void EffectBufferHalLocal::setFrameCount(size_t frameCount) {
     mAudioBuffer.frameCount = frameCount;
+    mFrameCountChanged = true;
 }
 
 void EffectBufferHalLocal::setExternalData(void* external) {
@@ -69,6 +70,12 @@
     mAudioBuffer.raw = external;
 }
 
+bool EffectBufferHalLocal::checkFrameCountChange() {
+    bool result = mFrameCountChanged;
+    mFrameCountChanged = false;
+    return result;
+}
+
 void EffectBufferHalLocal::update() {
 }
 
diff --git a/media/libaudiohal/EffectBufferHalLocal.h b/media/libaudiohal/EffectBufferHalLocal.h
index 202d878..d2b624b 100644
--- a/media/libaudiohal/EffectBufferHalLocal.h
+++ b/media/libaudiohal/EffectBufferHalLocal.h
@@ -32,6 +32,7 @@
 
     virtual void setExternalData(void* external);
     virtual void setFrameCount(size_t frameCount);
+    virtual bool checkFrameCountChange();
 
     virtual void update();
     virtual void commit();
@@ -43,6 +44,7 @@
 
     std::unique_ptr<uint8_t[]> mOwnBuffer;
     const size_t mBufferSize;
+    bool mFrameCountChanged;
     audio_buffer_t mAudioBuffer;
 
     // Can not be constructed directly by clients.
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 0babfda..7d61443 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -168,13 +168,20 @@
     return OK;
 }
 
+bool EffectHalHidl::needToResetBuffers() {
+    if (mBuffersChanged) return true;
+    bool inBufferFrameCountUpdated = mInBuffer->checkFrameCountChange();
+    bool outBufferFrameCountUpdated = mOutBuffer->checkFrameCountChange();
+    return inBufferFrameCountUpdated || outBufferFrameCountUpdated;
+}
+
 status_t EffectHalHidl::processImpl(uint32_t mqFlag) {
     if (mEffect == 0 || mInBuffer == 0 || mOutBuffer == 0) return NO_INIT;
     status_t status;
     if (!mStatusMQ && (status = prepareForProcessing()) != OK) {
         return status;
     }
-    if (mBuffersChanged && (status = setProcessBuffers()) != OK) {
+    if (needToResetBuffers() && (status = setProcessBuffers()) != OK) {
         return status;
     }
     // The data is already in the buffers, just need to flush it and wake up the server side.
diff --git a/media/libaudiohal/EffectHalHidl.h b/media/libaudiohal/EffectHalHidl.h
index c8db36f..0d011aa 100644
--- a/media/libaudiohal/EffectHalHidl.h
+++ b/media/libaudiohal/EffectHalHidl.h
@@ -92,6 +92,7 @@
 
     status_t getConfigImpl(uint32_t cmdCode, uint32_t *replySize, void *pReplyData);
     status_t prepareForProcessing();
+    bool needToResetBuffers();
     status_t processImpl(uint32_t mqFlag);
     status_t setConfigImpl(
             uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
diff --git a/media/libaudiohal/include/EffectBufferHalInterface.h b/media/libaudiohal/include/EffectBufferHalInterface.h
index 6fa7940..e862f6e 100644
--- a/media/libaudiohal/include/EffectBufferHalInterface.h
+++ b/media/libaudiohal/include/EffectBufferHalInterface.h
@@ -39,6 +39,8 @@
 
     virtual void setExternalData(void* external) = 0;
     virtual void setFrameCount(size_t frameCount) = 0;
+    virtual bool checkFrameCountChange() = 0;  // returns whether frame count has been updated
+                                               // since the last call to this method
 
     virtual void update() = 0;  // copies data from the external buffer, noop for allocated buffers
     virtual void commit() = 0;  // copies data to the external buffer, noop for allocated buffers