Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c404f8a authored by John Reck's avatar John Reck
Browse files

Support AHB in AIDL

Bug: 162794619
Test: CtsHardwareTestCases
Change-Id: Ifebea9f82434e171aafd09a5054566fa267ebbb3
parent d9df1068
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ typedef struct ARect {
} ARect;

#ifdef __cplusplus
};
}
#endif

#endif // ANDROID_RECT_H
+24 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#define LOG_TAG "AHardwareBuffer"

#include <android/hardware_buffer.h>
#include <android/hardware_buffer_aidl.h>
#include <vndk/hardware_buffer.h>

#include <errno.h>
@@ -32,6 +34,9 @@
#include <android/hardware/graphics/common/1.1/types.h>
#include <aidl/android/hardware/graphics/common/PixelFormat.h>

// TODO: Better way to handle this
#include "../binder/ndk/parcel_internal.h"

static constexpr int kFdBufferSize = 128 * sizeof(int);  // 128 ints

using namespace android;
@@ -412,6 +417,25 @@ int AHardwareBuffer_getId(const AHardwareBuffer* buffer, uint64_t* outId) {
    return OK;
}

binder_status_t AHardwareBuffer_readFromParcel(const AParcel* _Nonnull parcel,
        AHardwareBuffer* _Nullable* _Nonnull outBuffer) {
    if (!parcel || !outBuffer) return STATUS_BAD_VALUE;
    auto buffer = sp<GraphicBuffer>::make();
    status_t status = parcel->get()->read(*buffer);
    if (status != STATUS_OK) return status;
    *outBuffer = AHardwareBuffer_from_GraphicBuffer(buffer.get());
    AHardwareBuffer_acquire(*outBuffer);
    return STATUS_OK;
}

binder_status_t AHardwareBuffer_writeToParcel(const AHardwareBuffer* _Nonnull buffer,
        AParcel* _Nonnull parcel) {
    const GraphicBuffer* gb = AHardwareBuffer_to_GraphicBuffer(buffer);
    if (!gb) return STATUS_BAD_VALUE;
    if (!parcel) return STATUS_BAD_VALUE;
    return parcel->get()->write(*gb);
}

// ----------------------------------------------------------------------------
// VNDK functions
// ----------------------------------------------------------------------------
+2 −0
Original line number Diff line number Diff line
@@ -96,6 +96,8 @@ cc_library {
        "liblog",
        "libutils",
        "libui",
        "libbinder",
        "libbinder_ndk",
        "android.hardware.graphics.common@1.1",
    ],

+151 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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.
 */

/**
 * @file hardware_buffer_aidl.h
 * @brief HardwareBuffer NDK AIDL glue code
 */

/**
 * @addtogroup AHardwareBuffer
 *
 * Parcelable support for AHardwareBuffer. Can be used with libbinder_ndk
 *
 * @{
 */

#ifndef ANDROID_HARDWARE_BUFFER_AIDL_H
#define ANDROID_HARDWARE_BUFFER_AIDL_H

#include <android/binder_parcel.h>
#include <android/hardware_buffer.h>
#include <sys/cdefs.h>

__BEGIN_DECLS

/**
 * Read an AHardwareBuffer from a AParcel. The output buffer will have an
 * initial reference acquired and will need to be released with
 * AHardwareBuffer_release.
 *
 * Available since API level 34.
 *
 * \return STATUS_OK on success
 *         STATUS_BAD_VALUE if the parcel or outBuffer is null, or if there's an
 *                          issue deserializing (eg, corrupted parcel)
 *         STATUS_BAD_TYPE if the parcel's current data position is not that of
 *                         an AHardwareBuffer type
 *         STATUS_NO_MEMORY if an allocation fails
 */
binder_status_t AHardwareBuffer_readFromParcel(const AParcel* _Nonnull parcel,
        AHardwareBuffer* _Nullable* _Nonnull outBuffer) __INTRODUCED_IN(34);

/**
 * Write an AHardwareBuffer to an AParcel.
 *
 * Available since API level 34.
 *
 * \return STATUS_OK on success.
 *         STATUS_BAD_VALUE if either buffer or parcel is null, or if the AHardwareBuffer*
 *                          fails to serialize (eg, internally corrupted)
 *         STATUS_NO_MEMORY if the parcel runs out of space to store the buffer & is
 *                          unable to allocate more
 *         STATUS_FDS_NOT_ALLOWED if the parcel does not allow storing FDs
 */
binder_status_t AHardwareBuffer_writeToParcel(const AHardwareBuffer* _Nonnull buffer,
        AParcel* _Nonnull parcel) __INTRODUCED_IN(34);

__END_DECLS

// Only enable the AIDL glue helper if this is C++
#ifdef __cplusplus

namespace aidl::android::hardware {

/**
 * Wrapper class that enables interop with AIDL NDK generation
 * Takes ownership of the AHardwareBuffer* given to it in reset() and will automatically
 * destroy it in the destructor, similar to a smart pointer container
 */
class HardwareBuffer {
public:
    HardwareBuffer() noexcept {}
    explicit HardwareBuffer(HardwareBuffer&& other) noexcept : mBuffer(other.release()) {}

    ~HardwareBuffer() {
        reset();
    }

    binder_status_t readFromParcel(const AParcel* _Nonnull parcel) {
        reset();
        return AHardwareBuffer_readFromParcel(parcel, &mBuffer);
    }

    binder_status_t writeToParcel(AParcel* _Nonnull parcel) const {
        if (!mBuffer) {
            return STATUS_BAD_VALUE;
        }
        return AHardwareBuffer_writeToParcel(mBuffer, parcel);
    }

    /**
     * Destroys any currently owned AHardwareBuffer* and takes ownership of the given
     * AHardwareBuffer*
     *
     * @param buffer The buffer to take ownership of
     */
    void reset(AHardwareBuffer* _Nullable buffer = nullptr) noexcept {
        if (mBuffer) {
            AHardwareBuffer_release(mBuffer);
            mBuffer = nullptr;
        }
        mBuffer = buffer;
    }

    inline AHardwareBuffer* _Nullable operator-> () const { return mBuffer;  }
    inline AHardwareBuffer* _Nullable get() const { return mBuffer; }
    inline explicit operator bool () const { return mBuffer != nullptr; }

    HardwareBuffer& operator=(HardwareBuffer&& other) noexcept {
        reset(other.release());
        return *this;
    }

    /**
     * Stops managing any contained AHardwareBuffer*, returning it to the caller. Ownership
     * is released.
     * @return AHardwareBuffer* or null if this was empty
     */
    [[nodiscard]] AHardwareBuffer* _Nullable release() noexcept {
        AHardwareBuffer* _Nullable ret = mBuffer;
        mBuffer = nullptr;
        return ret;
    }

private:
    HardwareBuffer(const HardwareBuffer& other) = delete;
    HardwareBuffer& operator=(const HardwareBuffer& other) = delete;

    AHardwareBuffer* _Nullable mBuffer = nullptr;
};

} // aidl::android::hardware

#endif // __cplusplus

#endif // ANDROID_HARDWARE_BUFFER_AIDL_H

/** @} */
+2 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@ LIBNATIVEWINDOW {
    AHardwareBuffer_release;
    AHardwareBuffer_sendHandleToUnixSocket;
    AHardwareBuffer_unlock;
    AHardwareBuffer_readFromParcel; # introduced=34
    AHardwareBuffer_writeToParcel; # introduced=34
    ANativeWindowBuffer_getHardwareBuffer; # llndk
    ANativeWindow_OemStorageGet; # llndk
    ANativeWindow_OemStorageSet; # llndk