diff --git a/graphics/Android.bp b/graphics/Android.bp index 4ac7766479..796ef41133 100644 --- a/graphics/Android.bp +++ b/graphics/Android.bp @@ -2,6 +2,7 @@ subdirs = [ "allocator/2.0", "allocator/2.0/default", + "allocator/2.0/vts/functional", "common/1.0", "composer/2.1", "composer/2.1/default", diff --git a/graphics/allocator/2.0/IAllocator.hal b/graphics/allocator/2.0/IAllocator.hal index 0464bcd046..9a45444874 100644 --- a/graphics/allocator/2.0/IAllocator.hal +++ b/graphics/allocator/2.0/IAllocator.hal @@ -78,6 +78,9 @@ interface IAllocator { * * @return capabilities is a list of supported capabilities. */ + @entry + @exit + @callflow(next="*") getCapabilities() generates (vec capabilities); /* @@ -86,6 +89,9 @@ interface IAllocator { * * @return debugInfo is a string of debug information. */ + @entry + @exit + @callflow(next="*") dumpDebugInfo() generates (string debugInfo); /* @@ -98,6 +104,8 @@ interface IAllocator { * NO_RESOURCES when no more descriptors can currently be created. * @return descriptor is the newly created buffer descriptor. */ + @entry + @callflow(next="*") createDescriptor(BufferDescriptorInfo descriptorInfo) generates (Error error, BufferDescriptor descriptor); @@ -108,6 +116,8 @@ interface IAllocator { * @param descriptor is the descriptor to destroy. * @return error is either NONE or BAD_DESCRIPTOR. */ + @exit + @callflow(next="*") destroyDescriptor(BufferDescriptor descriptor) generates (Error error); /* @@ -124,6 +134,7 @@ interface IAllocator { * UNSUPPORTED when any of the descriptors can never be satisfied. * UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities. */ + @callflow(next="allocate") testAllocate(vec descriptors) generates (Error error); /* @@ -147,6 +158,7 @@ interface IAllocator { * time. * @return buffers is the allocated buffers. */ + @callflow(next="exportHandle") allocate(vec descriptors) generates (Error error, vec buffers); @@ -158,6 +170,8 @@ interface IAllocator { * @return error is NONE upon success. Otherwise, * BAD_BUFFER when the buffer is invalid. */ + @exit + @callflow(next="*") free(Buffer buffer) generates (Error error); /* @@ -182,6 +196,7 @@ interface IAllocator { * NO_RESOURCES when the buffer cannot be exported at this time. * @return bufferHandle is the exported handle. */ + @callflow(next="free") exportHandle(BufferDescriptor descriptor, Buffer buffer) generates (Error error, diff --git a/graphics/allocator/2.0/vts/Allocator.vts b/graphics/allocator/2.0/vts/Allocator.vts new file mode 100644 index 0000000000..04d431417f --- /dev/null +++ b/graphics/allocator/2.0/vts/Allocator.vts @@ -0,0 +1,215 @@ +component_class: HAL_HIDL +component_type_version: 2.0 +component_name: "IAllocator" + +package: "android.hardware.graphics.allocator" + +import: "android.hardware.graphics.allocator@2.0::types" + +interface: { + attribute: { + name: "::android::hardware::graphics::allocator::V2_0::IAllocator::Capability" + type: TYPE_ENUM + enum_value: { + scalar_type: "int32_t" + + enumerator: "INVALID" + scalar_value: { + int32_t: 0 + } + enumerator: "TEST_ALLOCATE" + scalar_value: { + int32_t: 1 + } + } + } + + attribute: { + name: "::android::hardware::graphics::allocator::V2_0::IAllocator::BufferDescriptorInfo" + type: TYPE_STRUCT + struct_value: { + name: "width" + type: TYPE_SCALAR + scalar_type: "uint32_t" + } + struct_value: { + name: "height" + type: TYPE_SCALAR + scalar_type: "uint32_t" + } + struct_value: { + name: "format" + type: TYPE_ENUM + predefined_type: "::android::hardware::graphics::allocator::V2_0::PixelFormat" + } + struct_value: { + name: "producerUsageMask" + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + struct_value: { + name: "consumerUsageMask" + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + } + + api: { + name: "getCapabilities" + return_type_hidl: { + type: TYPE_VECTOR + vector_value: { + type: TYPE_ENUM + predefined_type: "::android::hardware::graphics::allocator::V2_0::IAllocator::Capability" + } + } + callflow: { + entry: true + } + callflow: { + exit: true + } + callflow: { + next: "*" + } + } + + api: { + name: "dumpDebugInfo" + return_type_hidl: { + type: TYPE_STRING + } + callflow: { + entry: true + } + callflow: { + exit: true + } + callflow: { + next: "*" + } + } + + api: { + name: "createDescriptor" + return_type_hidl: { + type: TYPE_ENUM + predefined_type: "::android::hardware::graphics::allocator::V2_0::Error" + } + return_type_hidl: { + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + arg: { + type: TYPE_STRUCT + predefined_type: "::android::hardware::graphics::allocator::V2_0::IAllocator::BufferDescriptorInfo" + } + callflow: { + entry: true + } + callflow: { + next: "*" + } + } + + api: { + name: "destroyDescriptor" + return_type_hidl: { + type: TYPE_ENUM + predefined_type: "::android::hardware::graphics::allocator::V2_0::Error" + } + arg: { + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + callflow: { + exit: true + } + callflow: { + next: "*" + } + } + + api: { + name: "testAllocate" + return_type_hidl: { + type: TYPE_ENUM + predefined_type: "::android::hardware::graphics::allocator::V2_0::Error" + } + arg: { + type: TYPE_VECTOR + vector_value: { + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + } + callflow: { + next: "allocate" + } + } + + api: { + name: "allocate" + return_type_hidl: { + type: TYPE_ENUM + predefined_type: "::android::hardware::graphics::allocator::V2_0::Error" + } + return_type_hidl: { + type: TYPE_VECTOR + vector_value: { + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + } + arg: { + type: TYPE_VECTOR + vector_value: { + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + } + callflow: { + next: "exportHandle" + } + } + + api: { + name: "free" + return_type_hidl: { + type: TYPE_ENUM + predefined_type: "::android::hardware::graphics::allocator::V2_0::Error" + } + arg: { + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + callflow: { + exit: true + } + callflow: { + next: "*" + } + } + + api: { + name: "exportHandle" + return_type_hidl: { + type: TYPE_ENUM + predefined_type: "::android::hardware::graphics::allocator::V2_0::Error" + } + return_type_hidl: { + } + arg: { + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + arg: { + type: TYPE_SCALAR + scalar_type: "uint64_t" + } + callflow: { + next: "free" + } + } + +} diff --git a/graphics/allocator/2.0/vts/functional/Android.bp b/graphics/allocator/2.0/vts/functional/Android.bp new file mode 100644 index 0000000000..e1966dcbd3 --- /dev/null +++ b/graphics/allocator/2.0/vts/functional/Android.bp @@ -0,0 +1,37 @@ +// +// Copyright (C) 2016 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. +// + +cc_test { + name: "graphics_allocator_hidl_hal_test", + gtest: true, + srcs: ["graphics_allocator_hidl_hal_test.cpp"], + shared_libs: [ + "libbase", + "liblog", + "libcutils", + "libhidlbase", + "libhidltransport", + "libhwbinder", + "libnativehelper", + "libutils", + "android.hardware.graphics.allocator@2.0", + ], + static_libs: ["libgtest"], + cflags: [ + "-O0", + "-g", + ], +} diff --git a/graphics/allocator/2.0/vts/functional/graphics_allocator_hidl_hal_test.cpp b/graphics/allocator/2.0/vts/functional/graphics_allocator_hidl_hal_test.cpp new file mode 100644 index 0000000000..54369a4ff3 --- /dev/null +++ b/graphics/allocator/2.0/vts/functional/graphics_allocator_hidl_hal_test.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2016 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_TAG "graphics_allocator_hidl_hal_test" + +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace tests { +namespace { + +using android::hardware::graphics::common::V1_0::PixelFormat; + +#define CHECK_FEATURE_OR_SKIP(FEATURE_NAME) \ + do { \ + if (!hasCapability(FEATURE_NAME)) { \ + std::cout << "[ SKIPPED ] Feature " << #FEATURE_NAME \ + << " not supported" << std::endl; \ + return; \ + } \ + } while (0) + +class TempDescriptor { + public: + TempDescriptor(const sp& allocator, + const IAllocator::BufferDescriptorInfo& info) + : mAllocator(allocator), mError(Error::NO_RESOURCES) { + mAllocator->createDescriptor( + info, [&](const auto& tmpError, const auto& tmpDescriptor) { + mError = tmpError; + mDescriptor = tmpDescriptor; + }); + } + + ~TempDescriptor() { + if (mError == Error::NONE) { + mAllocator->destroyDescriptor(mDescriptor); + } + } + + bool isValid() const { return (mError == Error::NONE); } + + operator BufferDescriptor() const { return mDescriptor; } + + private: + sp mAllocator; + Error mError; + BufferDescriptor mDescriptor; +}; + +class GraphicsAllocatorHidlTest : public ::testing::Test { + protected: + void SetUp() override { + mAllocator = IAllocator::getService("gralloc"); + ASSERT_NE(mAllocator, nullptr); + + initCapabilities(); + + mDummyDescriptorInfo.width = 64; + mDummyDescriptorInfo.height = 64; + mDummyDescriptorInfo.format = PixelFormat::RGBA_8888; + mDummyDescriptorInfo.producerUsageMask = + static_cast(ProducerUsage::CPU_WRITE); + mDummyDescriptorInfo.consumerUsageMask = + static_cast(ConsumerUsage::CPU_READ); + } + + void TearDown() override {} + + /** + * Initialize the set of supported capabilities. + */ + void initCapabilities() { + mAllocator->getCapabilities([this](const auto& capabilities) { + std::vector caps = capabilities; + mCapabilities.insert(caps.cbegin(), caps.cend()); + }); + } + + /** + * Test whether a capability is supported. + */ + bool hasCapability(IAllocator::Capability capability) const { + return (mCapabilities.count(capability) > 0); + } + + sp mAllocator; + IAllocator::BufferDescriptorInfo mDummyDescriptorInfo{}; + + private: + std::unordered_set mCapabilities; +}; + +TEST_F(GraphicsAllocatorHidlTest, GetCapabilities) { + auto ret = mAllocator->getCapabilities([](const auto& capabilities) { + std::vector caps = capabilities; + for (auto cap : caps) { + EXPECT_NE(IAllocator::Capability::INVALID, cap); + } + }); + + ASSERT_TRUE(ret.getStatus().isOk()); +} + +TEST_F(GraphicsAllocatorHidlTest, DumpDebugInfo) { + auto ret = mAllocator->dumpDebugInfo([](const auto&) { + // nothing to do + }); + + ASSERT_TRUE(ret.getStatus().isOk()); +} + +TEST_F(GraphicsAllocatorHidlTest, CreateDestroyDescriptor) { + Error error; + BufferDescriptor descriptor; + auto ret = mAllocator->createDescriptor( + mDummyDescriptorInfo, + [&](const auto& tmpError, const auto& tmpDescriptor) { + error = tmpError; + descriptor = tmpDescriptor; + }); + + ASSERT_TRUE(ret.getStatus().isOk()); + ASSERT_EQ(Error::NONE, error); + + auto err_ret = mAllocator->destroyDescriptor(descriptor); + ASSERT_TRUE(err_ret.getStatus().isOk()); + ASSERT_EQ(Error::NONE, static_cast(err_ret)); +} + +/** + * Test testAllocate with a single buffer descriptor. + */ +TEST_F(GraphicsAllocatorHidlTest, TestAllocateBasic) { + CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE); + + TempDescriptor descriptor(mAllocator, mDummyDescriptorInfo); + ASSERT_TRUE(descriptor.isValid()); + + hidl_vec descriptors; + descriptors.resize(1); + descriptors[0] = descriptor; + + auto ret = mAllocator->testAllocate(descriptors); + ASSERT_TRUE(ret.getStatus().isOk()); + + auto error = static_cast(ret); + ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED); +} + +/** + * Test testAllocate with two buffer descriptors. + */ +TEST_F(GraphicsAllocatorHidlTest, TestAllocateArray) { + CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE); + + TempDescriptor descriptor(mAllocator, mDummyDescriptorInfo); + ASSERT_TRUE(descriptor.isValid()); + + hidl_vec descriptors; + descriptors.resize(2); + descriptors[0] = descriptor; + descriptors[1] = descriptor; + + auto ret = mAllocator->testAllocate(descriptors); + ASSERT_TRUE(ret.getStatus().isOk()); + + auto error = static_cast(ret); + ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED); +} + +/** + * Test allocate/free with a single buffer descriptor. + */ +TEST_F(GraphicsAllocatorHidlTest, AllocateFreeBasic) { + TempDescriptor descriptor(mAllocator, mDummyDescriptorInfo); + ASSERT_TRUE(descriptor.isValid()); + + hidl_vec descriptors; + descriptors.resize(1); + descriptors[0] = descriptor; + + Error error; + std::vector buffers; + auto ret = mAllocator->allocate( + descriptors, [&](const auto& tmpError, const auto& tmpBuffers) { + error = tmpError; + buffers = tmpBuffers; + }); + + ASSERT_TRUE(ret.getStatus().isOk()); + ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED); + EXPECT_EQ(1u, buffers.size()); + + if (!buffers.empty()) { + auto err_ret = mAllocator->free(buffers[0]); + EXPECT_TRUE(err_ret.getStatus().isOk()); + EXPECT_EQ(Error::NONE, static_cast(err_ret)); + } +} + +/** + * Test allocate/free with an array of buffer descriptors. + */ +TEST_F(GraphicsAllocatorHidlTest, AllocateFreeArray) { + TempDescriptor descriptor1(mAllocator, mDummyDescriptorInfo); + ASSERT_TRUE(descriptor1.isValid()); + + TempDescriptor descriptor2(mAllocator, mDummyDescriptorInfo); + ASSERT_TRUE(descriptor2.isValid()); + + hidl_vec descriptors; + descriptors.resize(3); + descriptors[0] = descriptor1; + descriptors[1] = descriptor1; + descriptors[2] = descriptor2; + + Error error; + std::vector buffers; + auto ret = mAllocator->allocate( + descriptors, [&](const auto& tmpError, const auto& tmpBuffers) { + error = tmpError; + buffers = tmpBuffers; + }); + + ASSERT_TRUE(ret.getStatus().isOk()); + ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED); + EXPECT_EQ(descriptors.size(), buffers.size()); + + for (auto buf : buffers) { + auto err_ret = mAllocator->free(buf); + EXPECT_TRUE(err_ret.getStatus().isOk()); + EXPECT_EQ(Error::NONE, static_cast(err_ret)); + } +} + +TEST_F(GraphicsAllocatorHidlTest, ExportHandle) { + TempDescriptor descriptor(mAllocator, mDummyDescriptorInfo); + ASSERT_TRUE(descriptor.isValid()); + + hidl_vec descriptors; + descriptors.resize(1); + descriptors[0] = descriptor; + + Error error; + std::vector buffers; + auto ret = mAllocator->allocate( + descriptors, [&](const auto& tmpError, const auto& tmpBuffers) { + error = tmpError; + buffers = tmpBuffers; + }); + + ASSERT_TRUE(ret.getStatus().isOk()); + ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED); + ASSERT_EQ(1u, buffers.size()); + + ret = mAllocator->exportHandle( + descriptors[0], buffers[0], + [&](const auto& tmpError, const auto&) { error = tmpError; }); + EXPECT_TRUE(ret.getStatus().isOk()); + EXPECT_EQ(Error::NONE, error); + + auto err_ret = mAllocator->free(buffers[0]); + EXPECT_TRUE(err_ret.getStatus().isOk()); + EXPECT_EQ(Error::NONE, static_cast(err_ret)); +} + +} // namespace anonymous +} // namespace tests +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + int status = RUN_ALL_TESTS(); + ALOGI("Test result = %d", status); + + return status; +} diff --git a/graphics/allocator/2.0/vts/types.vts b/graphics/allocator/2.0/vts/types.vts new file mode 100644 index 0000000000..ac1bf3f501 --- /dev/null +++ b/graphics/allocator/2.0/vts/types.vts @@ -0,0 +1,231 @@ +component_class: HAL_HIDL +component_type_version: 2.0 +component_name: "types" + +package: "android.hardware.graphics.allocator" + + +attribute: { + name: "::android::hardware::graphics::allocator::V2_0::Error" + type: TYPE_ENUM + enum_value: { + scalar_type: "int32_t" + + enumerator: "NONE" + scalar_value: { + int32_t: 0 + } + enumerator: "BAD_DESCRIPTOR" + scalar_value: { + int32_t: 1 + } + enumerator: "BAD_BUFFER" + scalar_value: { + int32_t: 2 + } + enumerator: "BAD_VALUE" + scalar_value: { + int32_t: 3 + } + enumerator: "NOT_SHARED" + scalar_value: { + int32_t: 4 + } + enumerator: "NO_RESOURCES" + scalar_value: { + int32_t: 5 + } + enumerator: "UNDEFINED" + scalar_value: { + int32_t: 6 + } + enumerator: "UNSUPPORTED" + scalar_value: { + int32_t: 7 + } + } +} + +attribute: { + name: "::android::hardware::graphics::allocator::V2_0::ProducerUsage" + type: TYPE_ENUM + enum_value: { + scalar_type: "uint64_t" + + enumerator: "CPU_READ" + scalar_value: { + uint64_t: 2 + } + enumerator: "CPU_READ_OFTEN" + scalar_value: { + uint64_t: 4 + } + enumerator: "CPU_WRITE" + scalar_value: { + uint64_t: 32 + } + enumerator: "CPU_WRITE_OFTEN" + scalar_value: { + uint64_t: 64 + } + enumerator: "GPU_RENDER_TARGET" + scalar_value: { + uint64_t: 512 + } + enumerator: "PROTECTED" + scalar_value: { + uint64_t: 16384 + } + enumerator: "CAMERA" + scalar_value: { + uint64_t: 131072 + } + enumerator: "VIDEO_DECODER" + scalar_value: { + uint64_t: 4194304 + } + } +} + +attribute: { + name: "::android::hardware::graphics::allocator::V2_0::ConsumerUsage" + type: TYPE_ENUM + enum_value: { + scalar_type: "uint64_t" + + enumerator: "CPU_READ" + scalar_value: { + uint64_t: 2 + } + enumerator: "CPU_READ_OFTEN" + scalar_value: { + uint64_t: 4 + } + enumerator: "GPU_TEXTURE" + scalar_value: { + uint64_t: 256 + } + enumerator: "HWCOMPOSER" + scalar_value: { + uint64_t: 2048 + } + enumerator: "CLIENT_TARGET" + scalar_value: { + uint64_t: 4096 + } + enumerator: "CURSOR" + scalar_value: { + uint64_t: 32768 + } + enumerator: "VIDEO_ENCODER" + scalar_value: { + uint64_t: 65536 + } + enumerator: "CAMERA" + scalar_value: { + uint64_t: 262144 + } + enumerator: "RENDERSCRIPT" + scalar_value: { + uint64_t: 1048576 + } + } +} + +attribute: { + name: "::android::hardware::graphics::allocator::V2_0::PixelFormat" + type: TYPE_ENUM + enum_value: { + scalar_type: "int32_t" + + enumerator: "RGBA_8888" + scalar_value: { + int32_t: 1 + } + enumerator: "RGBX_8888" + scalar_value: { + int32_t: 2 + } + enumerator: "RGB_888" + scalar_value: { + int32_t: 3 + } + enumerator: "RGB_565" + scalar_value: { + int32_t: 4 + } + enumerator: "BGRA_8888" + scalar_value: { + int32_t: 5 + } + enumerator: "YV12" + scalar_value: { + int32_t: 842094169 + } + enumerator: "Y8" + scalar_value: { + int32_t: 538982489 + } + enumerator: "Y16" + scalar_value: { + int32_t: 540422489 + } + enumerator: "RAW16" + scalar_value: { + int32_t: 32 + } + enumerator: "RAW10" + scalar_value: { + int32_t: 37 + } + enumerator: "RAW12" + scalar_value: { + int32_t: 38 + } + enumerator: "RAW_OPAQUE" + scalar_value: { + int32_t: 36 + } + enumerator: "BLOB" + scalar_value: { + int32_t: 33 + } + enumerator: "IMPLEMENTATION_DEFINED" + scalar_value: { + int32_t: 34 + } + enumerator: "YCbCr_420_888" + scalar_value: { + int32_t: 35 + } + enumerator: "YCbCr_422_888" + scalar_value: { + int32_t: 39 + } + enumerator: "YCbCr_444_888" + scalar_value: { + int32_t: 40 + } + enumerator: "FLEX_RGB_888" + scalar_value: { + int32_t: 41 + } + enumerator: "FLEX_RGBA_8888" + scalar_value: { + int32_t: 42 + } + enumerator: "YCbCr_422_SP" + scalar_value: { + int32_t: 16 + } + enumerator: "YCrCb_420_SP" + scalar_value: { + int32_t: 17 + } + enumerator: "YCbCr_422_I" + scalar_value: { + int32_t: 20 + } + } +} +