media c2.aidl: PersistentSurface related aidl defs & impls

Bug: 322870482
Test: m libstagefright_graphicbuffersource_aidl
Merged-In: I61aa0bcb82344430ca7e828624f3cfbf7d888af8
Change-Id: I61aa0bcb82344430ca7e828624f3cfbf7d888af8
diff --git a/media/module/aidlpersistentsurface/AidlGraphicBufferSource.cpp b/media/module/aidlpersistentsurface/AidlGraphicBufferSource.cpp
new file mode 100644
index 0000000..c208666
--- /dev/null
+++ b/media/module/aidlpersistentsurface/AidlGraphicBufferSource.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+
+#define LOG_TAG "AidlGraphicBufferSource"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <media/stagefright/bqhelper/ComponentWrapper.h>
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+#include <media/stagefright/aidlpersistentsurface/AidlGraphicBufferSource.h>
+#include <media/stagefright/aidlpersistentsurface/C2NodeDef.h>
+
+namespace android::media {
+
+namespace {
+
+class AidlComponentWrapper : public ComponentWrapper {
+public:
+    explicit AidlComponentWrapper(const sp<IAidlNodeWrapper> &node)
+        : mAidlNode(node) {}
+    virtual ~AidlComponentWrapper() = default;
+
+    status_t submitBuffer(
+            int32_t bufferId, const sp<GraphicBuffer> &buffer,
+            int64_t timestamp, int fenceFd) override {
+        return mAidlNode->submitBuffer(
+                bufferId, BUFFERFLAG_ENDOFFRAME, buffer, timestamp, fenceFd);
+    }
+
+    status_t submitEos(int32_t bufferId) override {
+        return mAidlNode->submitBuffer(
+            bufferId, BUFFERFLAG_ENDOFFRAME | BUFFERFLAG_EOS);
+    }
+
+    void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+        mAidlNode->dispatchDataSpaceChanged(dataSpace, aspects, pixelFormat);
+    }
+
+private:
+    sp<IAidlNodeWrapper> mAidlNode;
+
+    DISALLOW_EVIL_CONSTRUCTORS(AidlComponentWrapper);
+};
+
+}  // namespace
+
+::ndk::ScopedAStatus AidlGraphicBufferSource::onStart() {
+    status_t err = start();
+    return (OK == err) ? ::ndk::ScopedAStatus::ok() :
+            ::ndk::ScopedAStatus::fromServiceSpecificError(err);
+}
+
+::ndk::ScopedAStatus AidlGraphicBufferSource::onStop() {
+    status_t err = stop();
+    return (OK == err) ? ::ndk::ScopedAStatus::ok() :
+            ::ndk::ScopedAStatus::fromServiceSpecificError(err);
+}
+
+::ndk::ScopedAStatus AidlGraphicBufferSource::onRelease(){
+    status_t err = release();
+    return (OK == err) ? ::ndk::ScopedAStatus::ok() :
+            ::ndk::ScopedAStatus::fromServiceSpecificError(err);
+}
+
+status_t AidlGraphicBufferSource::configure(
+        const sp<IAidlNodeWrapper>& aidlNode,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
+        uint64_t consumerUsage) {
+    if (aidlNode == NULL) {
+        return BAD_VALUE;
+    }
+
+    return GraphicBufferSource::configure(
+            new AidlComponentWrapper(aidlNode), dataSpace, bufferCount,
+            frameWidth, frameHeight, consumerUsage);
+}
+
+}  // namespace android::media
diff --git a/media/module/aidlpersistentsurface/Android.bp b/media/module/aidlpersistentsurface/Android.bp
new file mode 100644
index 0000000..5c1a010
--- /dev/null
+++ b/media/module/aidlpersistentsurface/Android.bp
@@ -0,0 +1,69 @@
+aidl_interface {
+    name: "graphicbuffersource-aidl",
+    unstable: true,
+    local_include_dir: "aidl",
+    min_sdk_version: "29",
+    srcs: [
+        "aidl/android/media/AidlColorAspects.aidl",
+        "aidl/android/media/IAidlGraphicBufferSource.aidl",
+        "aidl/android/media/IAidlBufferSource.aidl",
+        "aidl/android/media/IAidlNode.aidl",
+    ],
+    headers: [
+        "HardwareBuffer_aidl",
+    ],
+    imports: [
+        "android.hardware.graphics.common-V5",
+    ],
+    include_dirs: [
+        "frameworks/native/aidl/gui",
+    ],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: false,
+        },
+        ndk: {
+            enabled: true,
+            additional_shared_libraries: [
+                "libnativewindow",
+            ],
+        },
+        rust: {
+            // No users, and no rust implementation of android.os.Surface yet
+            enabled: false,
+        },
+    },
+}
+
+cc_library_shared {
+    name: "libstagefright_graphicbuffersource_aidl",
+    min_sdk_version: "29",
+    srcs: [
+        "AidlGraphicBufferSource.cpp",
+        "wrapper/WAidlGraphicBufferSource.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    header_libs: [
+        "media_plugin_headers",
+    ],
+
+    export_header_lib_headers: [
+        "media_plugin_headers",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.common-V5-ndk",
+        "graphicbuffersource-aidl-ndk",
+        "libbinder_ndk",
+        "libcutils",
+        "libgui",
+        "liblog",
+        "libnativewindow",
+        "libstagefright_bufferqueue_helper",
+        "libutils",
+    ],
+}
diff --git a/media/module/aidlpersistentsurface/aidl/android/media/AidlColorAspects.aidl b/media/module/aidlpersistentsurface/aidl/android/media/AidlColorAspects.aidl
new file mode 100644
index 0000000..4edd6ce
--- /dev/null
+++ b/media/module/aidlpersistentsurface/aidl/android/media/AidlColorAspects.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * Ref: frameworks/native/include/media/hardware/VideoAPI.h
+ *
+ * Framework defined color aspects. These are based mainly on ISO 23001-8 spec. As this standard
+ * continues to evolve, new values may be defined in the future. Use OTHER for these future values
+ * as well as for values not listed here, as those are not supported by the framework.
+ */
+parcelable AidlColorAspects {
+    @Backing(type="int")
+    enum Range {
+        UNSPECIFIED,  // Unspecified
+        FULL,         // Full range
+        LIMITED,      // Limited range (if defined), or not full range
+
+        OTHER = 0xff, // Not one of the above values
+    }
+
+    // Color primaries
+    @Backing(type="int")
+    enum Primaries {
+        UNSPECIFIED,  // Unspecified
+        BT709_5,      // Rec.ITU-R BT.709-5 or equivalent
+        BT470_6M,     // Rec.ITU-R BT.470-6 System M or equivalent
+        BT601_6_625,  // Rec.ITU-R BT.601-6 625 or equivalent
+        BT601_6_525,  // Rec.ITU-R BT.601-6 525 or equivalent
+        GENERIC_FILM, // Generic Film
+        BT2020,       // Rec.ITU-R BT.2020 or equivalent
+
+        OTHER = 0xff, // Not one of the above values
+    }
+
+    // Transfer characteristics
+    @Backing(type="int")
+    enum Transfer {
+        UNSPECIFIED,  // Unspecified
+        LINEAR,       // Linear transfer characteristics
+        SRGB,         // sRGB or equivalent
+        SMPTE170M,    // SMPTE 170M or equivalent (e.g. BT.601/709/2020)
+        GAMMA22,      // Assumed display gamma 2.2
+        GAMMA28,      // Assumed display gamma 2.8
+        ST2084,       // SMPTE ST 2084 for 10/12/14/16 bit systems
+        HLG,          // ARIB STD-B67 hybrid-log-gamma
+
+        // values unlikely to be required by Android follow here
+        SMPTE240M = 0x40, // SMPTE 240M
+        XVYCC,        // IEC 61966-2-4
+        BT1361,       // Rec.ITU-R BT.1361 extended gamut
+        ST428,        // SMPTE ST 428-1
+
+        OTHER = 0xff, // Not one of the above values
+    }
+
+    // YUV <-> RGB conversion
+    @Backing(type="int")
+    enum MatrixCoeffs {
+        UNSPECIFIED,    // Unspecified
+        BT709_5,        // Rec.ITU-R BT.709-5 or equivalent
+        BT470_6M,       // KR=0.30, KB=0.11 or equivalent
+        BT601_6,        // Rec.ITU-R BT.601-6 625 or equivalent
+        SMPTE240M,      // SMPTE 240M or equivalent
+        BT2020,         // Rec.ITU-R BT.2020 non-constant luminance
+        BT2020CONSTANT, // Rec.ITU-R BT.2020 constant luminance
+
+        OTHER = 0xff,   // Not one of the above values
+    }
+
+    Range range;
+    Primaries primaries;
+    Transfer transfer;
+    MatrixCoeffs matrixCoeffs;
+}
diff --git a/media/module/aidlpersistentsurface/aidl/android/media/IAidlBufferSource.aidl b/media/module/aidlpersistentsurface/aidl/android/media/IAidlBufferSource.aidl
new file mode 100644
index 0000000..0679e41
--- /dev/null
+++ b/media/module/aidlpersistentsurface/aidl/android/media/IAidlBufferSource.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Binder interface for controlling and handling IAidlGraphicBufferSource
+ * from the process which owns IAidlNode.
+ *
+ * In order to support Persistent InputSurface and/or MediaRecorder
+ */
+interface IAidlBufferSource {
+    /**
+     * This is called when IAidlGraphicBufferSource can start handing buffers.
+     * If we already have buffers of data sitting in the BufferQueue,
+     * this will send them to the codec.
+     */
+    void onStart();
+
+    /**
+     * This is called when IAidlGraphicBufferSource indicaters that
+     * the codec is meant to return all buffers back to the client for them
+     * to be freed. Do NOT submit any more buffers to the component.
+     */
+    void onStop();
+
+    /**
+     * This is called when IAidlGraphicBufferSource indicates that
+     * we are shutting down.
+     */
+    void onRelease();
+
+    /**
+     * A "codec buffer", i.e. a buffer that can be used to pass data into
+     * the encoder, has been allocated.
+     */
+    void onInputBufferAdded(int bufferID);
+
+    /**
+     * Called from OnEmptyBufferDone. If we have a BQ buffer available,
+     * fill it with a new frame of data; otherwise, just mark it as available.
+     *
+     * fence contains the fence's fd that the callee should wait on before
+     * using the buffer (or pass on to the user of the buffer, if the user supports
+     * fences). Callee takes ownership of the fence fd even if it fails.
+     */
+    void onInputBufferEmptied(int bufferID, in @nullable ParcelFileDescriptor fence);
+}
+
diff --git a/media/module/aidlpersistentsurface/aidl/android/media/IAidlGraphicBufferSource.aidl b/media/module/aidlpersistentsurface/aidl/android/media/IAidlGraphicBufferSource.aidl
new file mode 100644
index 0000000..6642e89
--- /dev/null
+++ b/media/module/aidlpersistentsurface/aidl/android/media/IAidlGraphicBufferSource.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.hardware.graphics.common.Dataspace;
+import android.media.AidlColorAspects;
+import android.media.IAidlNode;
+
+/**
+ * Binder interface for configuring/controlling a Codec2 AIDL encoder instance
+ * on behalf of a Surface which will produce input buffers.
+ *
+ * In order to support Persistent InputSurface and/or MediaRecorder.
+ */
+interface IAidlGraphicBufferSource {
+    void configure(IAidlNode node, Dataspace dataSpace);
+    void setSuspend(boolean suspend, long suspendTimeUs);
+    void setRepeatPreviousFrameDelayUs(long repeatAfterUs);
+    void setMaxFps(float maxFps);
+    void setTimeLapseConfig(double fps, double captureFps);
+    void setStartTimeUs(long startTimeUs);
+    void setStopTimeUs(long stopTimeUs);
+    long getStopTimeOffsetUs();
+    void setColorAspects(in AidlColorAspects aspects);
+    void setTimeOffsetUs(long timeOffsetsUs);
+    void signalEndOfInputStream();
+}
diff --git a/media/module/aidlpersistentsurface/aidl/android/media/IAidlNode.aidl b/media/module/aidlpersistentsurface/aidl/android/media/IAidlNode.aidl
new file mode 100644
index 0000000..6cac19e
--- /dev/null
+++ b/media/module/aidlpersistentsurface/aidl/android/media/IAidlNode.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.hardware.HardwareBuffer;
+import android.media.IAidlBufferSource;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Binder interface abstraction for codec2 encoder instance.
+ *
+ * In order to support Persistent InputSurface and/or MediaRecorder.
+ */
+interface IAidlNode {
+
+    /**
+     * InputBuffer parameter for retrieval for the Node
+     */
+    parcelable InputBufferParams {
+        int bufferCountActual;
+        int frameWidth;
+        int frameHeight;
+    }
+
+    void freeNode();
+    void sendCommand(int cmd, int param);
+    long getConsumerUsage();
+    InputBufferParams getInputBufferParams();
+    void setConsumerUsage(long usage);
+    void setAdjustTimestampGapUs(int gapUs);
+    void setInputSurface(IAidlBufferSource bufferSource);
+    void submitBuffer(
+            int buffer,
+            in HardwareBuffer hBuffer,
+            int flags,
+            long timestampUs,
+            in @nullable ParcelFileDescriptor fence);
+    void onDataSpaceChanged(int dataSpace, int aspects, int pixelFormat);
+}
diff --git a/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/AidlGraphicBufferSource.h b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/AidlGraphicBufferSource.h
new file mode 100644
index 0000000..4b38294
--- /dev/null
+++ b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/AidlGraphicBufferSource.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#include <media/stagefright/aidlpersistentsurface/IAidlNodeWrapper.h>
+
+#include <utils/Errors.h>
+
+#include <aidl/android/media/BnAidlBufferSource.h>
+
+namespace android::media {
+
+/*
+ * This class is used to emulate feed OMX codecs from a Surface via BufferQueue or
+ * HW producer using AIDL binder interfaces.
+ *
+ * See media/stagefright/bqhelper/GraphicBufferSource.h for documentation.
+ */
+class AidlGraphicBufferSource : public GraphicBufferSource {
+public:
+    AidlGraphicBufferSource() = default;
+    virtual ~AidlGraphicBufferSource() = default;
+
+    // For IAidlBufferSource interface
+    // ------------------------------
+
+    // When we can start handling buffers.  If we already have buffers of data
+    // sitting in the BufferQueue, this will send them to the codec.
+    ::ndk::ScopedAStatus onStart();
+
+    // When the codec is meant to return all buffers back to the client for
+    // them to be freed. Do NOT submit any more buffers to the component.
+    ::ndk::ScopedAStatus onStop();
+
+    // When we are shutting down.
+    ::ndk::ScopedAStatus onRelease();
+
+    // Rest of the interface in GraphicBufferSource.
+
+    // IAidlGraphicBufferSource interface
+    // ------------------------------
+
+    // Configure the buffer source to be used with a codec2 aidl node given
+    // parameters.
+    status_t configure(
+        const sp<IAidlNodeWrapper> &aidlNode,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
+        uint64_t consumerUsage);
+
+    // Rest of the interface in GraphicBufferSource.
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(AidlGraphicBufferSource);
+};
+
+}  // namespace android::media
diff --git a/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/C2NodeDef.h b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/C2NodeDef.h
new file mode 100644
index 0000000..64de7ae
--- /dev/null
+++ b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/C2NodeDef.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android::media {
+
+// Node definitions for aidl input surface.
+//
+// Copied from non-aidl version implementation.
+// Unnecessary definitions for input surface implementation
+// are all omitted.
+
+enum C2NodeBufferFlag : uint32_t {
+    BUFFERFLAG_EOS = 1,
+    BUFFERFLAG_ENDOFFRAME = (1 << 4)
+};
+
+enum C2NodeCommand : int32_t {
+    CommandStateSet = 1
+};
+
+enum C2NodeStatus : int32_t {
+    NodeStatusLoaded = 1
+};
+
+}  // namespace android::media
diff --git a/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/IAidlNodeWrapper.h b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/IAidlNodeWrapper.h
new file mode 100644
index 0000000..f23b5e4
--- /dev/null
+++ b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/IAidlNodeWrapper.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+#include <ui/GraphicBuffer.h>
+
+#include <stdint.h>
+
+namespace android::media {
+
+struct IAidlNodeWrapper : public RefBase {
+    virtual status_t submitBuffer(
+            int32_t bufferId, uint32_t flags,
+            const sp<GraphicBuffer> &buffer = nullptr,
+            int64_t timestamp = 0, int fenceFd = -1) = 0;
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) = 0;
+};
+
+}  // namespace android::media
diff --git a/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/wrapper/Conversion.h b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/wrapper/Conversion.h
new file mode 100644
index 0000000..dcb83f6
--- /dev/null
+++ b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/wrapper/Conversion.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_auto_utils.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Errors.h>
+
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidl/android/media/AidlColorAspects.h>
+
+namespace android::media::aidl_conversion {
+
+inline status_t fromAidlStatus(const ::ndk::ScopedAStatus &status) {
+    if (!status.isOk()) {
+        if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            return static_cast<status_t>(status.getServiceSpecificError());
+        } else {
+            return static_cast<status_t>(FAILED_TRANSACTION);
+        }
+    }
+   return NO_ERROR;
+}
+
+inline ::ndk::ScopedAStatus toAidlStatus(status_t status) {
+    if (status == NO_ERROR) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return ::ndk::ScopedAStatus::fromServiceSpecificError(status);
+}
+
+inline int32_t compactFromAidlColorAspects(::aidl::android::media::AidlColorAspects const& s) {
+    return static_cast<int32_t>(
+            (static_cast<uint32_t>(s.range) << 24) |
+            (static_cast<uint32_t>(s.primaries) << 16) |
+            (static_cast<uint32_t>(s.transfer)) |
+            (static_cast<uint32_t>(s.matrixCoeffs) << 8));
+}
+
+inline int32_t rawFromAidlDataspace(
+        ::aidl::android::hardware::graphics::common::Dataspace const& s) {
+    return static_cast<int32_t>(s);
+}
+
+}  // namespace android::media::aidl_conversion
diff --git a/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.h b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.h
new file mode 100644
index 0000000..f4d7fe8
--- /dev/null
+++ b/media/module/aidlpersistentsurface/include/media/stagefright/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/RefBase.h>
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
+#include <aidl/android/media/IAidlBufferSource.h>
+#include <aidl/android/media/IAidlNode.h>
+#include <aidl/android/media/BnAidlGraphicBufferSource.h>
+
+namespace android::media {
+
+class AidlGraphicBufferSource;
+
+using ::android::sp;
+
+/**
+ * Aidl wrapper implementation for IAidlGraphicBufferSource
+ */
+class WAidlGraphicBufferSource : public ::aidl::android::media::BnAidlGraphicBufferSource {
+public:
+
+    struct WAidlNodeWrapper;
+    class WAidlBufferSource;
+
+    sp<AidlGraphicBufferSource> mBase;
+    std::shared_ptr<::aidl::android::media::IAidlBufferSource> mBufferSource;
+
+    WAidlGraphicBufferSource(sp<AidlGraphicBufferSource> const& base);
+    ::ndk::ScopedAStatus configure(
+            const std::shared_ptr<::aidl::android::media::IAidlNode>& node,
+            aidl::android::hardware::graphics::common::Dataspace dataspace) override;
+    ::ndk::ScopedAStatus setSuspend(bool suspend, int64_t timeUs) override;
+    ::ndk::ScopedAStatus setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
+    ::ndk::ScopedAStatus setMaxFps(float maxFps) override;
+    ::ndk::ScopedAStatus setTimeLapseConfig(double fps, double captureFps) override;
+    ::ndk::ScopedAStatus setStartTimeUs(int64_t startTimeUs) override;
+    ::ndk::ScopedAStatus setStopTimeUs(int64_t stopTimeUs) override;
+    ::ndk::ScopedAStatus getStopTimeOffsetUs(int64_t *_aidl_return) override;
+    ::ndk::ScopedAStatus setColorAspects(
+            const ::aidl::android::media::AidlColorAspects& aspects) override;
+    ::ndk::ScopedAStatus setTimeOffsetUs(int64_t timeOffsetUs) override;
+    ::ndk::ScopedAStatus signalEndOfInputStream() override;
+};
+
+}  // namespace android::media
diff --git a/media/module/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.cpp b/media/module/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.cpp
new file mode 100644
index 0000000..5526b10
--- /dev/null
+++ b/media/module/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#define LOG_NDEBUG 0
+#define LOG_TAG "WAidlGraphicBufferSource"
+#include <android/hardware_buffer_aidl.h>
+#include <private/android/AHardwareBufferHelpers.h>
+#include <utils/Log.h>
+
+#include <aidl/android/media/BnAidlBufferSource.h>
+#include <aidl/android/media/IAidlNode.h>
+
+#include <media/stagefright/aidlpersistentsurface/AidlGraphicBufferSource.h>
+#include <media/stagefright/aidlpersistentsurface/C2NodeDef.h>
+#include <media/stagefright/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.h>
+#include <media/stagefright/aidlpersistentsurface/wrapper/Conversion.h>
+
+namespace android::media {
+using ::android::binder::unique_fd;
+using ::aidl::android::hardware::graphics::common::PixelFormat;
+using ::aidl::android::hardware::graphics::common::Dataspace;
+using ::aidl::android::media::AidlColorAspects;
+using ::aidl::android::media::IAidlNode;
+using ::aidl::android::media::BnAidlBufferSource;
+
+// Conversion
+using ::android::media::aidl_conversion::fromAidlStatus;
+using ::android::media::aidl_conversion::toAidlStatus;
+using ::android::media::aidl_conversion::compactFromAidlColorAspects;
+using ::android::media::aidl_conversion::rawFromAidlDataspace;
+
+struct WAidlGraphicBufferSource::WAidlNodeWrapper : public IAidlNodeWrapper {
+    std::shared_ptr<IAidlNode> mNode;
+
+    WAidlNodeWrapper(const std::shared_ptr<IAidlNode> &node): mNode(node) {
+    }
+
+    virtual status_t submitBuffer(
+            int32_t bufferId, uint32_t flags,
+            const sp<GraphicBuffer> &buffer,
+            int64_t timestamp, int fenceFd) override {
+        AHardwareBuffer *ahwBuffer = nullptr;
+        ::aidl::android::hardware::HardwareBuffer hBuffer;
+        if (buffer.get()) {
+            ahwBuffer = AHardwareBuffer_from_GraphicBuffer(buffer.get());
+            AHardwareBuffer_acquire(ahwBuffer);
+            hBuffer.reset(ahwBuffer);
+        }
+
+        ::ndk::ScopedFileDescriptor fence(fenceFd);
+
+        return fromAidlStatus(mNode->submitBuffer(
+              bufferId,
+              hBuffer,
+              flags,
+              timestamp,
+              fence));
+    }
+
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+        ::ndk::ScopedAStatus err = mNode->onDataSpaceChanged(
+                dataSpace, aspects, pixelFormat);
+        status_t status = fromAidlStatus(err);
+        if (status != NO_ERROR) {
+            ALOGE("WAidlNodeWrapper failed to change dataspace (%d): "
+                    "dataSpace = %ld, aspects = %ld, pixelFormat = %ld",
+                    static_cast<int>(status),
+                    static_cast<long>(dataSpace),
+                    static_cast<long>(aspects),
+                    static_cast<long>(pixelFormat));
+        }
+    }
+};
+
+class WAidlGraphicBufferSource::WAidlBufferSource : public BnAidlBufferSource {
+    sp<AidlGraphicBufferSource> mSource;
+
+public:
+    WAidlBufferSource(const sp<AidlGraphicBufferSource> &source): mSource(source) {
+    }
+
+    ::ndk::ScopedAStatus onStart() override {
+        mSource->onStart();
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    ::ndk::ScopedAStatus onStop() override {
+        mSource->onStop();
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    ::ndk::ScopedAStatus onRelease() override {
+        mSource->onRelease();
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    ::ndk::ScopedAStatus onInputBufferAdded(int32_t bufferId) override {
+        mSource->onInputBufferAdded(bufferId);
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    ::ndk::ScopedAStatus onInputBufferEmptied(
+            int32_t bufferId, const ::ndk::ScopedFileDescriptor& fence) override {
+        mSource->onInputBufferEmptied(bufferId, ::dup(fence.get()));
+        return ::ndk::ScopedAStatus::ok();
+    }
+};
+
+// WAidlGraphicBufferSource
+WAidlGraphicBufferSource::WAidlGraphicBufferSource(
+        sp<AidlGraphicBufferSource> const& base) :
+    mBase(base),
+    mBufferSource(::ndk::SharedRefBase::make<WAidlBufferSource>(base)) {
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::configure(
+        const std::shared_ptr<IAidlNode>& node, Dataspace dataspace) {
+    if (node == NULL) {
+        return toAidlStatus(BAD_VALUE);
+    }
+
+    // Do setInputSurface() first, the node will try to enable metadata
+    // mode on input, and does necessary error checking. If this fails,
+    // we can't use this input surface on the node.
+    ::ndk::ScopedAStatus err = node->setInputSurface(mBufferSource);
+    status_t fnStatus = fromAidlStatus(err);
+    if (fnStatus != NO_ERROR) {
+        ALOGE("Unable to set input surface: %d", fnStatus);
+        return err;
+    }
+
+    // use consumer usage bits queried from encoder, but always add
+    // HW_VIDEO_ENCODER for backward compatibility.
+    int64_t  consumerUsage;
+    fnStatus = OK;
+    err = node->getConsumerUsage(&consumerUsage);
+    fnStatus = fromAidlStatus(err);
+    if (fnStatus != NO_ERROR) {
+        if (fnStatus == FAILED_TRANSACTION) {
+            return err;
+        }
+        consumerUsage = 0;
+    }
+
+    IAidlNode::InputBufferParams rDef ;
+    err = node->getInputBufferParams(&rDef);
+    fnStatus = fromAidlStatus(err);
+    if (fnStatus != NO_ERROR) {
+        ALOGE("Failed to get port definition: %d", fnStatus);
+        return toAidlStatus(fnStatus);
+    }
+
+    return toAidlStatus(mBase->configure(
+            new WAidlNodeWrapper(node),
+            rawFromAidlDataspace(dataspace),
+            rDef.bufferCountActual,
+            rDef.frameWidth,
+            rDef.frameHeight,
+            static_cast<uint64_t>(consumerUsage)));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::setSuspend(
+        bool suspend, int64_t timeUs) {
+    return toAidlStatus(mBase->setSuspend(suspend, timeUs));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+        int64_t repeatAfterUs) {
+    return toAidlStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::setMaxFps(float maxFps) {
+    return toAidlStatus(mBase->setMaxFps(maxFps));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::setTimeLapseConfig(
+        double fps, double captureFps) {
+    return toAidlStatus(mBase->setTimeLapseConfig(fps, captureFps));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
+    return toAidlStatus(mBase->setStartTimeUs(startTimeUs));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+    return toAidlStatus(mBase->setStopTimeUs(stopTimeUs));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::getStopTimeOffsetUs(int64_t* _aidl_return) {
+    status_t status = mBase->getStopTimeOffsetUs(_aidl_return);
+    return toAidlStatus(status);
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::setColorAspects(
+        const AidlColorAspects& aspects) {
+    return toAidlStatus(mBase->setColorAspects(compactFromAidlColorAspects(aspects)));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
+    return toAidlStatus(mBase->setTimeOffsetUs(timeOffsetUs));
+}
+
+::ndk::ScopedAStatus WAidlGraphicBufferSource::signalEndOfInputStream() {
+    return toAidlStatus(mBase->signalEndOfInputStream());
+}
+
+
+}  // namespace android::media