blob: 8de1a3eecbc2253d6678d32e20748a41a0951421 [file] [log] [blame]
/*
* Copyright (C) 2018 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 <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <limits>
#include <sstream>
#include <string>
#include <android/hardware_buffer.h>
#include <android/log.h>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
//#define LOG_NDEBUG 0
#define BAD_VALUE -EINVAL
#define INVALID_OPERATION -ENOSYS
#define NO_ERROR 0
#define LOG_TAG "AHBTest"
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
namespace {
using testing::AnyOf;
using testing::Eq;
using testing::Ge;
using testing::NotNull;
#define FORMAT_CASE(x) case AHARDWAREBUFFER_FORMAT_ ## x: os << #x ; break
void PrintAhbFormat(std::ostream& os, uint64_t format) {
switch (format) {
FORMAT_CASE(R8G8B8A8_UNORM);
FORMAT_CASE(R8G8B8X8_UNORM);
FORMAT_CASE(R8G8B8_UNORM);
FORMAT_CASE(R5G6B5_UNORM);
FORMAT_CASE(R16G16B16A16_FLOAT);
FORMAT_CASE(R10G10B10A2_UNORM);
FORMAT_CASE(BLOB);
FORMAT_CASE(D16_UNORM);
FORMAT_CASE(D24_UNORM);
FORMAT_CASE(D24_UNORM_S8_UINT);
FORMAT_CASE(D32_FLOAT);
FORMAT_CASE(D32_FLOAT_S8_UINT);
FORMAT_CASE(S8_UINT);
FORMAT_CASE(Y8Cb8Cr8_420);
FORMAT_CASE(YCbCr_P010);
FORMAT_CASE(R8_UNORM);
FORMAT_CASE(R16_UINT);
FORMAT_CASE(R16G16_UINT);
FORMAT_CASE(R10G10B10A10_UNORM);
default: os << "unknown"; break;
}
}
#define BITS_CASE(x) case AHARDWAREBUFFER_USAGE_ ## x: os << #x ; break
#define PRINT_FLAG(x) \
do { if (usage & AHARDWAREBUFFER_USAGE_ ## x) { os << #x << " "; } } while (0)
void PrintAhbUsage(std::ostream& os, uint64_t usage) {
if (usage == 0) {
os << "none";
return;
}
switch (usage & AHARDWAREBUFFER_USAGE_CPU_READ_MASK) {
BITS_CASE(CPU_READ_NEVER);
BITS_CASE(CPU_READ_RARELY);
BITS_CASE(CPU_READ_OFTEN);
default: break;
}
switch (usage & AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK) {
BITS_CASE(CPU_WRITE_NEVER);
BITS_CASE(CPU_WRITE_RARELY);
BITS_CASE(CPU_WRITE_OFTEN);
default: break;
}
PRINT_FLAG(GPU_SAMPLED_IMAGE);
PRINT_FLAG(GPU_COLOR_OUTPUT);
PRINT_FLAG(PROTECTED_CONTENT);
PRINT_FLAG(VIDEO_ENCODE);
PRINT_FLAG(SENSOR_DIRECT_DATA);
PRINT_FLAG(GPU_DATA_BUFFER);
PRINT_FLAG(GPU_CUBE_MAP);
PRINT_FLAG(GPU_MIPMAP_COMPLETE);
PRINT_FLAG(VENDOR_0);
PRINT_FLAG(VENDOR_1);
PRINT_FLAG(VENDOR_2);
PRINT_FLAG(VENDOR_3);
PRINT_FLAG(VENDOR_4);
PRINT_FLAG(VENDOR_5);
PRINT_FLAG(VENDOR_6);
PRINT_FLAG(VENDOR_7);
PRINT_FLAG(VENDOR_8);
PRINT_FLAG(VENDOR_9);
PRINT_FLAG(VENDOR_10);
PRINT_FLAG(VENDOR_11);
PRINT_FLAG(VENDOR_12);
PRINT_FLAG(VENDOR_13);
PRINT_FLAG(VENDOR_14);
PRINT_FLAG(VENDOR_15);
PRINT_FLAG(VENDOR_16);
PRINT_FLAG(VENDOR_17);
PRINT_FLAG(VENDOR_18);
PRINT_FLAG(VENDOR_19);
}
AHardwareBuffer_Desc GetDescription(AHardwareBuffer* buffer) {
AHardwareBuffer_Desc description;
AHardwareBuffer_describe(buffer, &description);
return description;
}
} // namespace
// GTest printer for AHardwareBuffer_Desc. Has to be in the global namespace.
void PrintTo(const AHardwareBuffer_Desc& desc, ::std::ostream* os) {
*os << "AHardwareBuffer_Desc " << desc.width << "x" << desc.height;
if (desc.layers > 1) {
*os << ", " << desc.layers << " layers";
}
*os << ", usage = ";
PrintAhbUsage(*os, desc.usage);
*os << ", format = ";
PrintAhbFormat(*os, desc.format);
}
// Equality operators for AHardwareBuffer_Desc. Have to be in the global namespace.
bool operator==(const AHardwareBuffer_Desc& a, const AHardwareBuffer_Desc& b) {
return a.width == b.width && a.height == b.height && a.layers == b.layers &&
a.usage == b.usage && a.format == b.format;
}
bool operator!=(const AHardwareBuffer_Desc& a, const AHardwareBuffer_Desc& b) {
return !(a == b);
}
namespace android {
// Test that passing in NULL values to allocate works as expected.
TEST(AHardwareBufferTest, AllocateFailsWithNullInput) {
AHardwareBuffer* buffer;
AHardwareBuffer_Desc desc;
memset(&desc, 0, sizeof(AHardwareBuffer_Desc));
int res = AHardwareBuffer_allocate(&desc, (AHardwareBuffer * * _Nonnull)NULL);
EXPECT_EQ(BAD_VALUE, res);
res = AHardwareBuffer_allocate((AHardwareBuffer_Desc* _Nonnull)NULL, &buffer);
EXPECT_EQ(BAD_VALUE, res);
res = AHardwareBuffer_allocate((AHardwareBuffer_Desc* _Nonnull)NULL,
(AHardwareBuffer * * _Nonnull)NULL);
EXPECT_EQ(BAD_VALUE, res);
}
// Test that passing in NULL values to allocate works as expected.
TEST(AHardwareBufferTest, BlobFormatRequiresHeight1) {
AHardwareBuffer* buffer;
AHardwareBuffer_Desc desc = {};
desc.width = 2;
desc.height = 4;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
desc.format = AHARDWAREBUFFER_FORMAT_BLOB;
int res = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(BAD_VALUE, res);
desc.height = 1;
res = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, res);
EXPECT_EQ(desc, GetDescription(buffer));
AHardwareBuffer_release(buffer);
buffer = NULL;
}
// Test that allocate can create an AHardwareBuffer correctly.
TEST(AHardwareBufferTest, AllocateSucceeds) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 2;
desc.height = 4;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
int res = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, res);
EXPECT_EQ(desc, GetDescription(buffer));
AHardwareBuffer_release(buffer);
buffer = NULL;
desc.width = 4;
desc.height = 12;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
res = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, res);
EXPECT_EQ(desc, GetDescription(buffer));
AHardwareBuffer_release(buffer);
}
// Test that allocate can create YUV AHardwareBuffers correctly.
TEST(AHardwareBufferTest, YuvAllocateSucceeds) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 16;
desc.height = 16;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
desc.format = AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
int res = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, res);
EXPECT_EQ(desc, GetDescription(buffer));
AHardwareBuffer_release(buffer);
buffer = NULL;
}
TEST(AHardwareBufferTest, DescribeSucceeds) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 2;
desc.height = 4;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
int res = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, res);
// Description of a null buffer should be all zeros.
AHardwareBuffer_Desc scratch_desc;
memset(&scratch_desc, 0, sizeof(AHardwareBuffer_Desc));
AHardwareBuffer_describe((AHardwareBuffer* _Nonnull)NULL, &scratch_desc);
EXPECT_EQ(0U, scratch_desc.width);
EXPECT_EQ(0U, scratch_desc.height);
// This shouldn't crash.
AHardwareBuffer_describe(buffer, (AHardwareBuffer_Desc* _Nonnull)NULL);
// Description of created buffer should match requsted description.
EXPECT_EQ(desc, GetDescription(buffer));
AHardwareBuffer_release(buffer);
}
struct ClientData {
int fd;
AHardwareBuffer* buffer;
ClientData(int fd_in, AHardwareBuffer* buffer_in)
: fd(fd_in), buffer(buffer_in) {}
};
static void* clientFunction(void* data) {
ClientData* pdata = reinterpret_cast<ClientData*>(data);
int err = AHardwareBuffer_sendHandleToUnixSocket(pdata->buffer, pdata->fd);
EXPECT_EQ(NO_ERROR, err);
close(pdata->fd);
return 0;
}
TEST(AHardwareBufferTest, SendAndRecvSucceeds) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 2;
desc.height = 4;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
// Test that an invalid buffer fails.
int err = AHardwareBuffer_sendHandleToUnixSocket((AHardwareBuffer* _Nonnull)NULL, 0);
EXPECT_EQ(BAD_VALUE, err);
err = 0;
err = AHardwareBuffer_sendHandleToUnixSocket(buffer, 0);
EXPECT_EQ(BAD_VALUE, err);
// Allocate the buffer.
err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, err);
int fds[2];
err = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
// Launch a client that will send the buffer back.
ClientData data(fds[1], buffer);
pthread_t thread;
EXPECT_EQ(0, pthread_create(&thread, NULL, clientFunction, &data));
// Receive the buffer.
err = AHardwareBuffer_recvHandleFromUnixSocket(fds[0], (AHardwareBuffer * * _Nonnull)NULL);
EXPECT_EQ(BAD_VALUE, err);
AHardwareBuffer* received = NULL;
err = AHardwareBuffer_recvHandleFromUnixSocket(fds[0], &received);
EXPECT_EQ(NO_ERROR, err);
EXPECT_TRUE(received != NULL);
EXPECT_EQ(desc, GetDescription(received));
void* ret_val;
EXPECT_EQ(0, pthread_join(thread, &ret_val));
EXPECT_EQ(NULL, ret_val);
close(fds[0]);
AHardwareBuffer_release(buffer);
AHardwareBuffer_release(received);
}
TEST(AHardwareBufferTest, LockAndGetInfoAndUnlockSucceed) {
AHardwareBuffer* buffer = nullptr;
AHardwareBuffer_Desc desc = {};
desc.width = 2;
desc.height = 4;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
int32_t bytesPerPixel = std::numeric_limits<int32_t>::min();
int32_t bytesPerStride = std::numeric_limits<int32_t>::min();
// Test that an invalid buffer fails.
int err =
AHardwareBuffer_lockAndGetInfo((AHardwareBuffer* _Nonnull)NULL, 0, -1, NULL,
(void** _Nonnull)NULL, &bytesPerPixel, &bytesPerStride);
EXPECT_EQ(BAD_VALUE, err);
err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, err);
void* bufferData = NULL;
// Test invalid usage flag
err = AHardwareBuffer_lockAndGetInfo(buffer, ~(AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK | AHARDWAREBUFFER_USAGE_CPU_READ_MASK), -1, NULL, &bufferData, &bytesPerPixel, &bytesPerStride);
EXPECT_EQ(BAD_VALUE, err);
err = AHardwareBuffer_lockAndGetInfo(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL, &bufferData, &bytesPerPixel, &bytesPerStride);
if (bytesPerPixel == -1 || bytesPerStride == -1) {
EXPECT_EQ(INVALID_OPERATION, err);
} else {
EXPECT_EQ(NO_ERROR, err);
EXPECT_LE(0, bytesPerPixel);
EXPECT_LE(0, bytesPerStride);
EXPECT_TRUE(bufferData != NULL);
err = AHardwareBuffer_unlock(buffer, nullptr);
EXPECT_EQ(NO_ERROR, err);
}
AHardwareBuffer_release(buffer);
}
TEST(AHardwareBufferTest, LockAndUnlockSucceed) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 2;
desc.height = 4;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
// Test that an invalid buffer fails.
int err = AHardwareBuffer_lock((AHardwareBuffer* _Nonnull)NULL, 0, -1, NULL,
(void** _Nonnull)NULL);
EXPECT_EQ(BAD_VALUE, err);
err = 0;
// Allocate the buffer.
err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, err);
void* bufferData = NULL;
err = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1,
NULL, &bufferData);
EXPECT_EQ(NO_ERROR, err);
EXPECT_TRUE(bufferData != NULL);
err = AHardwareBuffer_unlock(buffer, nullptr);
AHardwareBuffer_release(buffer);
}
TEST(AHardwareBufferTest, PlanarLockAndUnlockYuvSucceed) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 16;
desc.height = 32;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
desc.format = AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
// Test that an invalid buffer fails.
int err = AHardwareBuffer_lock((AHardwareBuffer* _Nonnull)NULL, 0, -1, NULL,
(void** _Nonnull)NULL);
EXPECT_EQ(BAD_VALUE, err);
err = 0;
// Allocate the buffer.
err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, err);
// Lock its planes
AHardwareBuffer_Planes planes;
err = AHardwareBuffer_lockPlanes(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL,
&planes);
// Make sure everything looks right
EXPECT_EQ(NO_ERROR, err);
EXPECT_EQ(3U, planes.planeCount);
EXPECT_TRUE(planes.planes[0].data != NULL);
EXPECT_EQ(1U, planes.planes[0].pixelStride);
EXPECT_TRUE(planes.planes[0].rowStride >= 16);
EXPECT_TRUE(planes.planes[1].data != NULL);
EXPECT_THAT(planes.planes[1].pixelStride, AnyOf(Eq(1U), Eq(2U)));
EXPECT_TRUE(planes.planes[1].rowStride >= 8);
EXPECT_TRUE(planes.planes[2].data != NULL);
EXPECT_THAT(planes.planes[2].pixelStride, AnyOf(Eq(1U), Eq(2U)));
EXPECT_TRUE(planes.planes[2].rowStride >= 8);
// Unlock
err = AHardwareBuffer_unlock(buffer, nullptr);
EXPECT_EQ(NO_ERROR, err);
AHardwareBuffer_release(buffer);
}
TEST(AHardwareBufferTest, PlanarLockAndUnlockYuvP010Succeed) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 32;
desc.height = 32;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
desc.format = AHARDWAREBUFFER_FORMAT_YCbCr_P010;
if (!AHardwareBuffer_isSupported(&desc)) {
ALOGI("Test skipped: AHARDWAREBUFFER_FORMAT_YCbCr_P010 not supported.");
return;
}
// Allocate the buffer.
int err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, err);
// Lock its planes
AHardwareBuffer_Planes planes;
err = AHardwareBuffer_lockPlanes(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL,
&planes);
// Make sure everything looks right
EXPECT_EQ(NO_ERROR, err);
EXPECT_EQ(3U, planes.planeCount);
const uint32_t yPlaneWidth = desc.width;
const uint32_t cPlaneWidth = desc.width / 2;
const uint32_t bytesPerPixel = 2;
EXPECT_THAT(planes.planes[0].data, NotNull());
EXPECT_THAT(planes.planes[0].pixelStride, Eq(bytesPerPixel));
EXPECT_THAT(planes.planes[0].rowStride, Ge(yPlaneWidth * bytesPerPixel));
EXPECT_THAT(planes.planes[1].data, NotNull());
EXPECT_THAT(planes.planes[1].pixelStride, Eq(bytesPerPixel * /*interleaved=*/2));
EXPECT_THAT(planes.planes[1].rowStride, Ge(cPlaneWidth * bytesPerPixel));
EXPECT_THAT(planes.planes[2].data, NotNull());
EXPECT_THAT(planes.planes[2].pixelStride, Eq(bytesPerPixel * /*interleaved=*/2));
EXPECT_THAT(planes.planes[2].rowStride, Ge(cPlaneWidth * bytesPerPixel));
// Unlock
err = AHardwareBuffer_unlock(buffer, nullptr);
EXPECT_EQ(NO_ERROR, err);
AHardwareBuffer_release(buffer);
}
TEST(AHardwareBufferTest, PlanarLockAndUnlockRgbaSucceed) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 16;
desc.height = 32;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
// Test that an invalid buffer fails.
int err = AHardwareBuffer_lock((AHardwareBuffer* _Nonnull)NULL, 0, -1, NULL,
(void** _Nonnull)NULL);
EXPECT_EQ(BAD_VALUE, err);
err = 0;
// Allocate the buffer.
err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, err);
// Lock its planes
AHardwareBuffer_Planes planes;
err = AHardwareBuffer_lockPlanes(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL,
&planes);
// Make sure everything looks right
EXPECT_EQ(NO_ERROR, err);
EXPECT_EQ(1U, planes.planeCount);
EXPECT_TRUE(planes.planes[0].data != NULL);
EXPECT_EQ(4U, planes.planes[0].pixelStride);
EXPECT_TRUE(planes.planes[0].rowStride >= 64);
// Unlock
err = AHardwareBuffer_unlock(buffer, nullptr);
EXPECT_EQ(NO_ERROR, err);
AHardwareBuffer_release(buffer);
}
TEST(AHardwareBufferTest, ProtectedContentAndCpuReadIncompatible) {
AHardwareBuffer* buffer = NULL;
AHardwareBuffer_Desc desc = {};
desc.width = 120;
desc.height = 240;
desc.layers = 1;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
// Allocation of a CPU-readable buffer should succeed...
int err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_EQ(NO_ERROR, err);
AHardwareBuffer_release(buffer);
buffer = nullptr;
// ...but not if it's a protected buffer.
desc.usage =
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_NE(NO_ERROR, err);
desc.usage =
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
err = AHardwareBuffer_allocate(&desc, &buffer);
EXPECT_NE(NO_ERROR, err);
}
TEST(AHardwareBufferTest, GetIdSucceed) {
AHardwareBuffer* buffer1 = nullptr;
uint64_t id1 = 0;
const AHardwareBuffer_Desc desc = {
.width = 4,
.height = 4,
.layers = 1,
.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
};
int err = AHardwareBuffer_allocate(&desc, &buffer1);
EXPECT_EQ(NO_ERROR, err);
EXPECT_NE(nullptr, buffer1);
EXPECT_EQ(0, AHardwareBuffer_getId(buffer1, &id1));
EXPECT_NE(id1, 0ULL);
AHardwareBuffer* buffer2 = nullptr;
uint64_t id2 = 0;
err = AHardwareBuffer_allocate(&desc, &buffer2);
EXPECT_EQ(NO_ERROR, err);
EXPECT_NE(nullptr, buffer2);
EXPECT_EQ(0, AHardwareBuffer_getId(buffer2, &id2));
EXPECT_NE(id2, 0ULL);
EXPECT_NE(id1, id2);
}
} // namespace android