AIDL effect: Add ashmem buffer implementation in libaudiohal

Also add TIME_CHECK and binder dump call implementation

Bug: 261129656
Test: enable AIDL
Test: atest
android.media.audio.cts.LoudnessEnhancerTest#test3_0MeasureGainChange
and check if data consumed by effect threads.

Change-Id: Ib2462bf47c7e9602d9eceed1bfb28d38b559fe65
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.cpp b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
index 5af8e24..a701852 100644
--- a/media/libaudiohal/impl/EffectBufferHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
@@ -14,26 +14,39 @@
  * limitations under the License.
  */
 
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <sys/mman.h>
 #define LOG_TAG "EffectBufferHalAidl"
 //#define LOG_NDEBUG 0
 
+#include <cutils/ashmem.h>
 #include <utils/Log.h>
 
 #include "EffectBufferHalAidl.h"
 
+using ndk::ScopedFileDescriptor;
+
 namespace android {
 namespace effect {
 
 // static
 status_t EffectBufferHalAidl::allocate(size_t size, sp<EffectBufferHalInterface>* buffer) {
-    ALOGE("%s not implemented yet %zu %p", __func__, size, buffer);
     return mirror(nullptr, size, buffer);
 }
 
 status_t EffectBufferHalAidl::mirror(void* external, size_t size,
                                      sp<EffectBufferHalInterface>* buffer) {
-    // buffer->setExternalData(external);
-    ALOGW("%s not implemented yet %p %zu %p", __func__, external, size, buffer);
+    sp<EffectBufferHalAidl> tempBuffer = new EffectBufferHalAidl(size);
+    status_t status = tempBuffer.get()->init();
+    if (status != OK) {
+        ALOGE("%s init failed %d", __func__, status);
+        return status;
+    }
+
+    tempBuffer->setExternalData(external);
+    *buffer = tempBuffer;
     return OK;
 }
 
@@ -48,7 +61,22 @@
 }
 
 status_t EffectBufferHalAidl::init() {
-    ALOGW("%s not implemented yet", __func__);
+    int fd = ashmem_create_region("audioEffectAidl", mBufferSize);
+    if (fd < 0) {
+        ALOGE("%s create ashmem failed %d", __func__, fd);
+        return fd;
+    }
+
+    ScopedFileDescriptor tempFd(fd);
+    mAudioBuffer.raw = mmap(nullptr /* address */, mBufferSize /* length */, PROT_READ | PROT_WRITE,
+                            MAP_SHARED, fd, 0 /* offset */);
+    if (mAudioBuffer.raw == MAP_FAILED) {
+        ALOGE("mmap failed for fd %d", fd);
+        mAudioBuffer.raw = nullptr;
+        return INVALID_OPERATION;
+    }
+
+    mMemory = {std::move(tempFd), static_cast<int64_t>(mBufferSize)};
     return OK;
 }
 
@@ -76,11 +104,26 @@
 }
 
 void EffectBufferHalAidl::update() {
-    ALOGW("%s not implemented yet", __func__);
+    update(mBufferSize);
 }
 
 void EffectBufferHalAidl::commit() {
-    ALOGW("%s not implemented yet", __func__);
+    commit(mBufferSize);
+}
+
+void EffectBufferHalAidl::copy(void* dst, const void* src, size_t n) const {
+    if (!dst || !src) {
+        return;
+    }
+    std::memcpy(dst, src, std::min(n, mBufferSize));
+}
+
+void EffectBufferHalAidl::update(size_t n) {
+    copy(mAudioBuffer.raw, mExternalData, n);
+}
+
+void EffectBufferHalAidl::commit(size_t n) {
+    copy(mExternalData, mAudioBuffer.raw, n);
 }
 
 } // namespace effect
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.h b/media/libaudiohal/impl/EffectBufferHalAidl.h
index f488708..035314b 100644
--- a/media/libaudiohal/impl/EffectBufferHalAidl.h
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <aidl/android/hardware/common/Ashmem.h>
+
 #include <media/audiohal/EffectBufferHalInterface.h>
 #include <system/audio_effect.h>
 
@@ -44,16 +46,18 @@
   private:
     friend class EffectBufferHalInterface;
 
+    // buffer size in bytes
     const size_t mBufferSize;
     bool mFrameCountChanged;
     void* mExternalData;
+    aidl::android::hardware::common::Ashmem mMemory;
     audio_buffer_t mAudioBuffer;
 
     // Can not be constructed directly by clients.
     explicit EffectBufferHalAidl(size_t size);
 
     ~EffectBufferHalAidl();
-
+    void copy(void* dst, const void* src, size_t n) const;
     status_t init();
 };
 
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 37ca75d..f9a4e49 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -30,6 +30,10 @@
     status_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
                            void* pReplyData);
     virtual ~EffectConversionHelperAidl() {}
+    const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn&
+    getEffectReturnParam() const {
+        return mOpenReturn;
+    }
 
   protected:
     const int32_t mSessionId;
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 8fa301a..a684dee 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <cstddef>
 #define LOG_TAG "EffectHalAidl"
 //#define LOG_NDEBUG 0
 
@@ -136,24 +137,51 @@
 }
 
 status_t EffectHalAidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
-    if (buffer == nullptr) {
-        return BAD_VALUE;
-    }
-    ALOGW("%s not implemented yet", __func__);
+    mInBuffer = buffer;
     return OK;
 }
 
 status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
-    if (buffer == nullptr) {
-        return BAD_VALUE;
-    }
-    ALOGW("%s not implemented yet", __func__);
+    mOutBuffer = buffer;
     return OK;
 }
 
+
+// write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
 status_t EffectHalAidl::process() {
-    ALOGW("%s not implemented yet", __func__);
-    // write to input FMQ here, and wait for statusMQ STATUS_OK
+    size_t available = mInputQ->availableToWrite();
+    size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
+    if (floatsToWrite == 0) {
+        ALOGW("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
+              mInBuffer->getSize() / sizeof(float), available);
+        return INVALID_OPERATION;
+    }
+    if (!mInputQ->write((float*)mInBuffer->ptr(), floatsToWrite)) {
+        ALOGW("%s failed to write %zu into inputQ", __func__, floatsToWrite);
+        return INVALID_OPERATION;
+    }
+
+    IEffect::Status retStatus{};
+    if (!mStatusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
+        (size_t)retStatus.fmqConsumed != floatsToWrite || retStatus.fmqProduced == 0) {
+        ALOGW("%s read status failed: %s", __func__, retStatus.toString().c_str());
+        return INVALID_OPERATION;
+    }
+
+    available = mOutputQ->availableToRead();
+    size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
+    if (floatsToRead == 0) {
+        ALOGW("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
+              mOutBuffer->getSize() / sizeof(float), available);
+        return INVALID_OPERATION;
+    }
+    if (!mOutputQ->read((float*)mOutBuffer->ptr(), floatsToRead)) {
+        ALOGW("%s failed to read %zu from outputQ", __func__, floatsToRead);
+        return INVALID_OPERATION;
+    }
+
+    ALOGD("%s %s consumed %zu produced %zu", __func__, mDesc.common.name.c_str(), floatsToWrite,
+          floatsToRead);
     return OK;
 }
 
@@ -165,14 +193,32 @@
 
 status_t EffectHalAidl::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
                                 uint32_t* replySize, void* pReplyData) {
-    return mConversion
-                   ? mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData)
-                   : INVALID_OPERATION;
+    TIME_CHECK();
+    if (!mConversion) {
+        ALOGE("%s can not handle command %d when conversion not exist", __func__, cmdCode);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+    // update FMQs when effect open successfully
+    if (ret == OK && cmdCode == EFFECT_CMD_INIT) {
+        const auto& retParam = mConversion->getEffectReturnParam();
+        mStatusQ = std::make_unique<StatusMQ>(retParam.statusMQ);
+        mInputQ = std::make_unique<DataMQ>(retParam.inputDataMQ);
+        mOutputQ = std::make_unique<DataMQ>(retParam.outputDataMQ);
+        if (!mStatusQ->isValid() || !mInputQ->isValid() || !mOutputQ->isValid()) {
+            ALOGE("%s return with invalid FMQ", __func__);
+            return NO_INIT;
+        }
+    }
+
+    return ret;
 }
 
 status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
-    ALOGW("%s %p", __func__, pDescriptor);
+    TIME_CHECK();
     if (pDescriptor == nullptr) {
+        ALOGE("%s null descriptor pointer", __func__);
         return BAD_VALUE;
     }
     Descriptor aidlDesc;
@@ -184,12 +230,13 @@
 }
 
 status_t EffectHalAidl::close() {
+    TIME_CHECK();
     return statusTFromBinderStatus(mEffect->close());
 }
 
 status_t EffectHalAidl::dump(int fd) {
-    ALOGW("%s not implemented yet, fd %d", __func__, fd);
-    return OK;
+    TIME_CHECK();
+    return mEffect->dump(fd, nullptr, 0);
 }
 
 } // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 83b644b..194150d 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -16,11 +16,13 @@
 
 #pragma once
 
+#include <memory>
+
 #include <aidl/android/hardware/audio/effect/IEffect.h>
 #include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <fmq/AidlMessageQueue.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <system/audio_effect.h>
-#include <memory>
 
 #include "EffectConversionHelperAidl.h"
 
@@ -29,6 +31,12 @@
 
 class EffectHalAidl : public EffectHalInterface {
   public:
+    using StatusMQ = ::android::AidlMessageQueue<
+            ::aidl::android::hardware::audio::effect::IEffect::Status,
+            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+    using DataMQ = ::android::AidlMessageQueue<
+            float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+
     // Set the input buffer.
     status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) override;
 
@@ -63,6 +71,9 @@
         return mEffect;
     }
 
+    // for TIME_CHECK
+    const std::string getClassName() const { return "EffectHalAidl"; }
+
   private:
     friend class sp<EffectHalAidl>;
 
@@ -73,6 +84,8 @@
     const int32_t mIoId;
     const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
     std::unique_ptr<EffectConversionHelperAidl> mConversion;
+    std::unique_ptr<StatusMQ> mStatusQ;
+    std::unique_ptr<DataMQ> mInputQ, mOutputQ;
 
     sp<EffectBufferHalInterface> mInBuffer, mOutBuffer;
     effect_config_t mConfig;
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index ed952a3..7ecdbd2 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -107,13 +107,13 @@
 }
 
 status_t EffectHalHidl::process() {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
 
     return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS));
 }
 
 status_t EffectHalHidl::processReverse() {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
 
     return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE));
 }
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index 0aae87b..b418b6c 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -20,7 +20,6 @@
 #define LOG_TAG "EffectsFactoryHalAidl"
 //#define LOG_NDEBUG 0
 
-#include <aidl/android/hardware/audio/effect/IFactory.h>
 #include <error/expected_utils.h>
 #include <android/binder_manager.h>
 #include <media/AidlConversionCppNdk.h>
@@ -139,20 +138,18 @@
 }
 
 status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
-    ALOGE("%s not implemented yet, fd %d", __func__, fd);
-    return INVALID_OPERATION;
+    // TODO: add proxy dump here because AIDL service EffectFactory doesn't have proxy handle
+    return mFactory->dump(fd, nullptr, 0);
 }
 
 status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
     ALOGI("%s size %zu buffer %p", __func__, size, buffer);
-    // Buffer doesn't allocated here for AIDL, instead each effect open will return I/O data FMQ.
     return EffectBufferHalAidl::allocate(size, buffer);
 }
 
 status_t EffectsFactoryHalAidl::mirrorBuffer(void* external, size_t size,
                                              sp<EffectBufferHalInterface>* buffer) {
     ALOGI("%s extern %p size %zu buffer %p", __func__, external, size, buffer);
-    // TODO: implement with FMQ
     return EffectBufferHalAidl::mirror(external, size, buffer);
 }
 
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index 1e85da9..9c3643b 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -20,6 +20,7 @@
 #include <memory>
 #include <mutex>
 
+#include <aidl/android/hardware/audio/effect/IFactory.h>
 #include <android-base/thread_annotations.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <system/thread_defs.h>
@@ -59,6 +60,9 @@
 
     detail::AudioHalVersionInfo getHalVersion() const override;
 
+    // for TIME_CHECK
+    const std::string getClassName() const { return "EffectHalAidl"; }
+
   private:
     std::mutex mLock;
     const std::shared_ptr<IFactory> mFactory;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 39c3f4a..838c40d 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -261,7 +261,7 @@
 
 status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
     ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
     mWorkerTid.store(gettid(), std::memory_order_release);
     // Switch the stream into an active state if needed.
@@ -407,7 +407,7 @@
         const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
         ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
         bool safeFromNonWorkerThread) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (!safeFromNonWorkerThread) {
         const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire);
         LOG_ALWAYS_FATAL_IF(workerTid != gettid(),
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 07c6df5..192790c 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -441,7 +441,7 @@
 #endif
 
 status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     *written = 0;
 
@@ -587,7 +587,7 @@
 }
 
 status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     Result retval;
     Return<void> ret = mStream->getRenderPosition(
@@ -668,7 +668,7 @@
 }
 
 status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     if (mWriterClient == gettid() && mCommandMQ) {
         return callWriterThread(
@@ -1012,7 +1012,7 @@
 }
 
 status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     *read = 0;
 
@@ -1146,7 +1146,7 @@
 }
 
 status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     if (mReaderClient == gettid() && mCommandMQ) {
         ReadParameters params;