| /* |
| * 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 |