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

Commit ead3d6ee authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

AHB: add AHardwareBuffer_getId API in ndk

Add this api to ndk so that there's a reliable system-wide unique id for
caching.

libui is not linkable from sphal so vendors cannot convert an AHB into
GraphicBuffer to call getId(). This change solves the problem.

This change has been forced to refactor the existing docs and
annotations due to -Wnullability-completeness.

Bug: 162425097
Bug: 163615119
Test: atest libnativewindow_test:AHardwareBufferTest#GetIdTest
Change-Id: I91043b96b83bc9a896c361385581e9620fe373c3
parent 9058b8fe
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -397,6 +397,16 @@ int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) {
    return 0;
}

int AHardwareBuffer_getId(const AHardwareBuffer* buffer, uint64_t* outId) {
    if (!buffer || !outId) return BAD_VALUE;

    const GraphicBuffer* gb = AHardwareBuffer_to_GraphicBuffer(buffer);
    if (!gb) return BAD_VALUE;

    *outId = gb->getId();

    return OK;
}

// ----------------------------------------------------------------------------
// VNDK functions
+97 −71
Original line number Diff line number Diff line
@@ -45,14 +45,14 @@
#ifndef ANDROID_HARDWARE_BUFFER_H
#define ANDROID_HARDWARE_BUFFER_H

#include <android/rect.h>
#include <inttypes.h>

#include <sys/cdefs.h>

#include <android/rect.h>

__BEGIN_DECLS

// clang-format off

/**
 * Buffer pixel formats.
 */
@@ -313,7 +313,7 @@ typedef struct AHardwareBuffer_Desc {
 * Holds data for a single image plane.
 */
typedef struct AHardwareBuffer_Plane {
    void*       data;        ///< Points to first byte in plane
    void*    _Nullable data; ///< Points to first byte in plane
    uint32_t pixelStride;    ///< Distance in bytes from the color channel of one pixel to the next
    uint32_t rowStride;      ///< Distance in bytes from the first value of one row of the image to
                             ///  the first value of the next row.
@@ -332,6 +332,8 @@ typedef struct AHardwareBuffer_Planes {
 */
typedef struct AHardwareBuffer AHardwareBuffer;

// clang-format on

#if __ANDROID_API__ >= 26

/**
@@ -347,8 +349,8 @@ typedef struct AHardwareBuffer AHardwareBuffer;
 * \return 0 on success, or an error number of the allocation fails for
 * any reason. The returned buffer has a reference count of 1.
 */
int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
        AHardwareBuffer** outBuffer) __INTRODUCED_IN(26);
int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* _Nonnull desc,
                             AHardwareBuffer* _Nullable* _Nonnull outBuffer) __INTRODUCED_IN(26);
/**
 * Acquire a reference on the given AHardwareBuffer object.
 *
@@ -357,7 +359,7 @@ int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
 *
 * Available since API level 26.
 */
void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
void AHardwareBuffer_acquire(AHardwareBuffer* _Nonnull buffer) __INTRODUCED_IN(26);

/**
 * Remove a reference that was previously acquired with
@@ -365,7 +367,7 @@ void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
 *
 * Available since API level 26.
 */
void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
void AHardwareBuffer_release(AHardwareBuffer* _Nonnull buffer) __INTRODUCED_IN(26);

/**
 * Return a description of the AHardwareBuffer in the passed
@@ -373,8 +375,8 @@ void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
 *
 * Available since API level 26.
 */
void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
        AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26);
void AHardwareBuffer_describe(const AHardwareBuffer* _Nonnull buffer,
                              AHardwareBuffer_Desc* _Nonnull outDesc) __INTRODUCED_IN(26);

/**
 * Lock the AHardwareBuffer for direct CPU access.
@@ -428,38 +430,9 @@ void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
 * has more than one layer. Error number if the lock fails for any other
 * reason.
 */
int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage,
        int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26);

/**
 * Lock a potentially multi-planar AHardwareBuffer for direct CPU access.
 *
 * This function is similar to AHardwareBuffer_lock, but can lock multi-planar
 * formats. The locked planes are returned in the \a outPlanes argument. Note,
 * that multi-planar should not be confused with multi-layer images, which this
 * locking function does not support.
 *
 * YUV formats are always represented by three separate planes of data, one for
 * each color plane. The order of planes in the array is guaranteed such that
 * plane #0 is always Y, plane #1 is always U (Cb), and plane #2 is always V
 * (Cr). All other formats are represented by a single plane.
 *
 * Additional information always accompanies the buffers, describing the row
 * stride and the pixel stride for each plane.
 *
 * In case the buffer cannot be locked, \a outPlanes will contain zero planes.
 *
 * See the AHardwareBuffer_lock documentation for all other locking semantics.
 *
 * Available since API level 29.
 *
 * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
 * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
 * has more than one layer. Error number if the lock fails for any other
 * reason.
 */
int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage,
        int32_t fence, const ARect* rect, AHardwareBuffer_Planes* outPlanes) __INTRODUCED_IN(29);
int AHardwareBuffer_lock(AHardwareBuffer* _Nonnull buffer, uint64_t usage, int32_t fence,
                         const ARect* _Nullable rect, void* _Nullable* _Nonnull outVirtualAddress)
        __INTRODUCED_IN(26);

/**
 * Unlock the AHardwareBuffer from direct CPU access.
@@ -479,7 +452,8 @@ int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage,
 * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if
 * the unlock fails for any reason.
 */
int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED_IN(26);
int AHardwareBuffer_unlock(AHardwareBuffer* _Nonnull buffer, int32_t* _Nullable fence)
        __INTRODUCED_IN(26);

/**
 * Send the AHardwareBuffer to an AF_UNIX socket.
@@ -489,7 +463,8 @@ int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED
 * \return 0 on success, -EINVAL if \a buffer is NULL, or an error
 * number if the operation fails for any reason.
 */
int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd) __INTRODUCED_IN(26);
int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* _Nonnull buffer, int socketFd)
        __INTRODUCED_IN(26);

/**
 * Receive an AHardwareBuffer from an AF_UNIX socket.
@@ -499,12 +474,45 @@ int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int so
 * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
 * number if the operation fails for any reason.
 */
int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26);
int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd,
                                             AHardwareBuffer* _Nullable* _Nonnull outBuffer)
        __INTRODUCED_IN(26);

#endif // __ANDROID_API__ >= 26

#if __ANDROID_API__ >= 29

/**
 * Lock a potentially multi-planar AHardwareBuffer for direct CPU access.
 *
 * This function is similar to AHardwareBuffer_lock, but can lock multi-planar
 * formats. The locked planes are returned in the \a outPlanes argument. Note,
 * that multi-planar should not be confused with multi-layer images, which this
 * locking function does not support.
 *
 * YUV formats are always represented by three separate planes of data, one for
 * each color plane. The order of planes in the array is guaranteed such that
 * plane #0 is always Y, plane #1 is always U (Cb), and plane #2 is always V
 * (Cr). All other formats are represented by a single plane.
 *
 * Additional information always accompanies the buffers, describing the row
 * stride and the pixel stride for each plane.
 *
 * In case the buffer cannot be locked, \a outPlanes will contain zero planes.
 *
 * See the AHardwareBuffer_lock documentation for all other locking semantics.
 *
 * Available since API level 29.
 *
 * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
 * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
 * has more than one layer. Error number if the lock fails for any other
 * reason.
 */
int AHardwareBuffer_lockPlanes(AHardwareBuffer* _Nonnull buffer, uint64_t usage, int32_t fence,
                               const ARect* _Nullable rect,
                               AHardwareBuffer_Planes* _Nonnull outPlanes) __INTRODUCED_IN(29);

/**
 * Test whether the given format and usage flag combination is
 * allocatable.
@@ -524,7 +532,7 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out
 * \return 1 if the format and usage flag combination is allocatable,
 *     0 otherwise.
 */
int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_IN(29);
int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* _Nonnull desc) __INTRODUCED_IN(29);

/**
 * Lock an AHardwareBuffer for direct CPU access.
@@ -537,11 +545,29 @@ int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_I
 *
 * Available since API level 29.
 */
int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
        int32_t fence, const ARect* rect, void** outVirtualAddress,
        int32_t* outBytesPerPixel, int32_t* outBytesPerStride) __INTRODUCED_IN(29);
int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* _Nonnull buffer, uint64_t usage, int32_t fence,
                                   const ARect* _Nullable rect,
                                   void* _Nullable* _Nonnull outVirtualAddress,
                                   int32_t* _Nonnull outBytesPerPixel,
                                   int32_t* _Nonnull outBytesPerStride) __INTRODUCED_IN(29);

#endif // __ANDROID_API__ >= 29

#if __ANDROID_API__ >= 31

/**
 * Get the system wide unique id for an AHardwareBuffer.
 *
 * Available since API level 31.
 *
 * \return 0 on success, -EINVAL if \a buffer or \a outId is NULL, or an error number if the
 * operation fails for any reason.
 */
int AHardwareBuffer_getId(const AHardwareBuffer* _Nonnull buffer, uint64_t* _Nonnull outId)
        __INTRODUCED_IN(31);

#endif // __ANDROID_API__ >= 31

__END_DECLS

#endif // ANDROID_HARDWARE_BUFFER_H
+16 −6
Original line number Diff line number Diff line
@@ -24,7 +24,14 @@

__BEGIN_DECLS

const native_handle_t* AHardwareBuffer_getNativeHandle(const AHardwareBuffer* buffer);
/**
 * Get the native handle from an AHardwareBuffer.
 *
 * \return a non-NULL native handle on success, NULL if \a buffer is nullptr or the operation fails
 * for any reason.
 */
const native_handle_t* _Nullable AHardwareBuffer_getNativeHandle(
        const AHardwareBuffer* _Nonnull buffer);

enum CreateFromHandleMethod {
    // enum values chosen to match internal GraphicBuffer::HandleWrapMethod
@@ -33,9 +40,9 @@ enum CreateFromHandleMethod {
};

/**
 * Create a AHardwareBuffer from a native handle.
 * Create an AHardwareBuffer from a native handle.
 *
 * This function wraps a native handle in a AHardwareBuffer suitable for use by applications or
 * This function wraps a native handle in an AHardwareBuffer suitable for use by applications or
 * other parts of the system. The contents of desc will be returned by AHardwareBuffer_describe().
 *
 * If method is AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_REGISTER, the handle is assumed to be
@@ -44,10 +51,13 @@ enum CreateFromHandleMethod {
 *
 * If method is AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, the handle will be cloned and the
 * clone registered. The AHardwareBuffer will own the cloned handle but not the original.
 *
 * \return 0 on success, -EINVAL if \a desc or \a handle or outBuffer is NULL, or an error number if
 * the operation fails for any reason.
 */
int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc,
                                     const native_handle_t* handle, int32_t method,
                                     AHardwareBuffer** outBuffer);
int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* _Nonnull desc,
                                     const native_handle_t* _Nonnull handle, int32_t method,
                                     AHardwareBuffer* _Nullable* _Nonnull outBuffer);

/**
 * Buffer pixel formats.
+1 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ LIBNATIVEWINDOW {
    AHardwareBuffer_allocate;
    AHardwareBuffer_createFromHandle; # llndk # apex
    AHardwareBuffer_describe;
    AHardwareBuffer_getId; # introduced=31
    AHardwareBuffer_getNativeHandle; # llndk # apex
    AHardwareBuffer_isSupported; # introduced=29
    AHardwareBuffer_lock;
+43 −4
Original line number Diff line number Diff line
@@ -17,12 +17,11 @@
#define LOG_TAG "AHardwareBuffer_test"
//#define LOG_NDEBUG 0

#include <android/hardware_buffer.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <android/hardware/graphics/common/1.0/types.h>
#include <vndk/hardware_buffer.h>

#include <gtest/gtest.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <ui/GraphicBuffer.h>
#include <vndk/hardware_buffer.h>

using namespace android;
using android::hardware::graphics::common::V1_0::BufferUsage;
@@ -131,3 +130,43 @@ TEST(AHardwareBufferTest, GetCreateHandleTest) {
    AHardwareBuffer_release(buffer);
    AHardwareBuffer_release(otherBuffer);
}

TEST(AHardwareBufferTest, GetIdTest) {
    const uint32_t testWidth = 4;
    const uint32_t testHeight = 4;
    const uint32_t testLayers = 1;

    AHardwareBuffer* ahb1 = nullptr;
    uint64_t id1 = 0;
    const AHardwareBuffer_Desc desc = {
            .width = testWidth,
            .height = testHeight,
            .layers = testLayers,
            .format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
            .usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
    };
    int res = AHardwareBuffer_allocate(&desc, &ahb1);
    EXPECT_EQ(NO_ERROR, res);
    EXPECT_NE(nullptr, ahb1);
    EXPECT_EQ(0, AHardwareBuffer_getId(ahb1, &id1));
    const GraphicBuffer* gb1 = AHardwareBuffer_to_GraphicBuffer(ahb1);
    EXPECT_NE(nullptr, gb1);
    EXPECT_EQ(id1, gb1->getId());
    EXPECT_NE(id1, 0);

    sp<GraphicBuffer> gb2(new GraphicBuffer(testWidth,
                                            testHeight,
                                            PIXEL_FORMAT_RGBA_8888,
                                            testLayers,
                                            GraphicBuffer::USAGE_SW_READ_RARELY,
                                            std::string("test")));
    EXPECT_NE(nullptr, gb2.get());
    const AHardwareBuffer* ahb2 = AHardwareBuffer_from_GraphicBuffer(gb2.get());
    EXPECT_NE(nullptr, ahb2);
    uint64_t id2 = 0;
    EXPECT_EQ(0, AHardwareBuffer_getId(ahb2, &id2));
    EXPECT_EQ(id2, gb2->getId());
    EXPECT_NE(id2, 0);

    EXPECT_NE(id1, id2);
}
Loading