diff options
| -rw-r--r-- | libs/ui/GraphicBufferAllocator.cpp | 12 | ||||
| -rw-r--r-- | libs/ui/include/ui/GraphicBufferAllocator.h | 2 | ||||
| -rw-r--r-- | libs/ui/tests/Android.bp | 20 | ||||
| -rw-r--r-- | libs/ui/tests/GraphicBufferAllocator_test.cpp | 102 | ||||
| -rw-r--r-- | libs/ui/tests/mock/MockGrallocAllocator.cpp | 27 | ||||
| -rw-r--r-- | libs/ui/tests/mock/MockGrallocAllocator.h | 44 |
6 files changed, 205 insertions, 2 deletions
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 9c7d1fda90..a664c71cfd 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -132,6 +132,16 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, status_t error = mAllocator->allocate(width, height, format, layerCount, usage, 1, stride, handle); + size_t bufSize; + + // if stride has no meaning or is too large, + // approximate size with the input width instead + if (std::numeric_limits<size_t>::max() / height / (*stride) < static_cast<size_t>(bpp)) { + bufSize = static_cast<size_t>(width) * height * bpp; + } else { + bufSize = static_cast<size_t>((*stride)) * height * bpp; + } + if (error == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); @@ -142,7 +152,7 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, rec.format = format; rec.layerCount = layerCount; rec.usage = usage; - rec.size = static_cast<size_t>(height * (*stride) * bpp); + rec.size = bufSize; rec.requestorName = std::move(requestorName); list.add(*handle, rec); diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h index 25d4512859..324d9e143b 100644 --- a/libs/ui/include/ui/GraphicBufferAllocator.h +++ b/libs/ui/include/ui/GraphicBufferAllocator.h @@ -54,7 +54,7 @@ public: void dump(std::string& res) const; static void dumpToSystemLog(); -private: +protected: struct alloc_rec_t { uint32_t width; uint32_t height; diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 373fa4f221..15f4b6407c 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -29,6 +29,26 @@ cc_test { } cc_test { + name: "GraphicBufferAllocator_test", + header_libs: [ + "libdvr_headers", + "libnativewindow_headers", + ], + static_libs: [ + "libgmock", + ], + shared_libs: [ + "liblog", + "libui", + ], + srcs: [ + "GraphicBufferAllocator_test.cpp", + "mock/MockGrallocAllocator.cpp", + ], + cflags: ["-Wall", "-Werror"], +} + +cc_test { name: "GraphicBuffer_test", header_libs: [ "libdvr_headers", diff --git a/libs/ui/tests/GraphicBufferAllocator_test.cpp b/libs/ui/tests/GraphicBufferAllocator_test.cpp new file mode 100644 index 0000000000..4bbc54993c --- /dev/null +++ b/libs/ui/tests/GraphicBufferAllocator_test.cpp @@ -0,0 +1,102 @@ +/* + * Copyright 2019 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 "GraphicBufferAllocatorTest" + +#include <ui/GraphicBuffer.h> +#include <ui/GraphicBufferAllocator.h> +#include <ui/PixelFormat.h> + +#include <gtest/gtest.h> + +#include "mock/MockGrallocAllocator.h" + +#include <algorithm> +#include <limits> + +namespace android { + +namespace { + +constexpr uint32_t kTestWidth = 1024; +constexpr uint32_t kTestHeight = 1; +constexpr uint32_t kTestLayerCount = 1; +constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN; + +} // namespace + +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; + +class TestableGraphicBufferAllocator : public GraphicBufferAllocator { +public: + TestableGraphicBufferAllocator() { + mAllocator = std::make_unique<const mock::MockGrallocAllocator>(); + } + void setUpAllocateExpectations(status_t err, uint32_t stride) { + std::cout << "Setting expected stride to " << stride << std::endl; + EXPECT_CALL(*(reinterpret_cast<const mock::MockGrallocAllocator*>(mAllocator.get())), + allocate) + .WillOnce(DoAll(SetArgPointee<6>(stride), Return(err))); + } + std::unique_ptr<const GrallocAllocator>& getAllocator() { return mAllocator; } +}; + +class GraphicBufferAllocatorTest : public testing::Test { +public: + GraphicBufferAllocatorTest() : mAllocator() {} + const TestableGraphicBufferAllocator& getAllocator() { return mAllocator; } + +protected: + TestableGraphicBufferAllocator mAllocator; +}; + +TEST_F(GraphicBufferAllocatorTest, AllocateNoError) { + mAllocator.setUpAllocateExpectations(NO_ERROR, kTestWidth); + android::PixelFormat format = PIXEL_FORMAT_RGBA_8888; + uint32_t stride = 0; + buffer_handle_t handle; + status_t err = mAllocator.allocate(kTestWidth, kTestHeight, format, kTestLayerCount, kTestUsage, + &handle, &stride, 0, "GraphicBufferAllocatorTest"); + ASSERT_EQ(NO_ERROR, err); + ASSERT_EQ(kTestWidth, stride); +} + +TEST_F(GraphicBufferAllocatorTest, AllocateBadStride) { + uint32_t height = std::numeric_limits<uint32_t>::max(); + uint32_t bpp = 4; + android::PixelFormat format = PIXEL_FORMAT_RGBA_8888; + + if (std::numeric_limits<size_t>::max() / height / bpp >= std::numeric_limits<uint32_t>::max()) { + std::cout << "stride cannot cause overflow" << std::endl; + GTEST_SUCCEED() << "stride cannot cause overflow"; + return; + } + uint32_t width = std::numeric_limits<size_t>::max() / height / bpp; + + uint32_t expectedStride = std::numeric_limits<uint32_t>::max(); + + mAllocator.setUpAllocateExpectations(NO_ERROR, expectedStride); + uint32_t stride = 0; + buffer_handle_t handle; + // an overflow would cause a crash + status_t err = mAllocator.allocate(width, height, format, kTestLayerCount, kTestUsage, &handle, + &stride, 0, "GraphicBufferAllocatorTest"); + ASSERT_EQ(NO_ERROR, err); + ASSERT_EQ(expectedStride, stride); +} +} // namespace android diff --git a/libs/ui/tests/mock/MockGrallocAllocator.cpp b/libs/ui/tests/mock/MockGrallocAllocator.cpp new file mode 100644 index 0000000000..d71e25fc08 --- /dev/null +++ b/libs/ui/tests/mock/MockGrallocAllocator.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019 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 "MockGrallocAllocator.h" + +namespace android { + +namespace mock { + +MockGrallocAllocator::MockGrallocAllocator() = default; +MockGrallocAllocator::~MockGrallocAllocator() = default; + +} // namespace mock +} // namespace android diff --git a/libs/ui/tests/mock/MockGrallocAllocator.h b/libs/ui/tests/mock/MockGrallocAllocator.h new file mode 100644 index 0000000000..22c80a4638 --- /dev/null +++ b/libs/ui/tests/mock/MockGrallocAllocator.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include <gmock/gmock.h> + +#include <ui/Gralloc.h> + +namespace android { + +class GraphicBuffer; + +namespace mock { + +class MockGrallocAllocator : public GrallocAllocator { +public: + MockGrallocAllocator(); + ~MockGrallocAllocator() override; + + MOCK_METHOD(bool, isLoaded, (), (const, override)); + MOCK_METHOD(std::string, dumpDebugInfo, (), (const, override)); + MOCK_METHOD(status_t, allocate, + (uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount, + uint64_t usage, uint32_t bufferCount, uint32_t* outStride, + buffer_handle_t* outBufferHandles), + (const, override)); +}; + +} // namespace mock +} // namespace android |