diff options
Diffstat (limited to 'libs/ui')
40 files changed, 545 insertions, 83 deletions
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index 438fd2a0f7..d25ad1a46d 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -48,7 +48,7 @@ cc_library_shared { ], sanitize: { - //misc_undefined: ["integer"], + integer_overflow: true, }, srcs: [ @@ -74,7 +74,9 @@ cc_library_shared { shared_libs: [ "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.common@1.1", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", "android.hardware.configstore@1.0", "android.hardware.configstore-utils", "libbase", @@ -89,6 +91,10 @@ cc_library_shared { "liblog", ], + export_shared_lib_headers: [ + "android.hardware.graphics.common@1.1", + ], + static_libs: [ "libarect", "libgrallocusage", @@ -96,20 +102,23 @@ cc_library_shared { ], header_libs: [ + "libbase_headers", "libnativebase_headers", "libhardware_headers", + "libui_headers", + "libpdx_headers", ], - export_include_dirs: ["include"], - export_static_lib_headers: [ "libarect", "libmath", ], export_header_lib_headers: [ + "libbase_headers", "libnativebase_headers", "libhardware_headers", + "libui_headers", ], } @@ -117,6 +126,11 @@ cc_library_headers { name: "libui_headers", export_include_dirs: ["include"], vendor_available: true, + target: { + vendor: { + override_export_include_dirs: ["include_vndk"], + }, + }, } subdirs = [ diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp index 2d72944665..61df02d41d 100644 --- a/libs/ui/DebugUtils.cpp +++ b/libs/ui/DebugUtils.cpp @@ -22,6 +22,8 @@ #include <string> using android::base::StringPrintf; +using android::ui::ColorMode; +using android::ui::RenderIntent; std::string decodeStandard(android_dataspace dataspace) { const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK); @@ -74,7 +76,7 @@ std::string decodeStandard(android_dataspace dataspace) { case HAL_DATASPACE_SRGB: return std::string("(deprecated) sRGB"); - case HAL_DATASPACE_V0_BT709: + case HAL_DATASPACE_BT709: return std::string("(deprecated) BT709"); case HAL_DATASPACE_ARBITRARY: @@ -84,7 +86,7 @@ std::string decodeStandard(android_dataspace dataspace) { // Fallthrough default: return android::base::StringPrintf("Unknown deprecated dataspace code %d", - dataspaceSelect); + dataspace); } } @@ -98,7 +100,7 @@ std::string decodeTransfer(android_dataspace dataspace) { case HAL_DATASPACE_JFIF: case HAL_DATASPACE_BT601_625: case HAL_DATASPACE_BT601_525: - case HAL_DATASPACE_V0_BT709: + case HAL_DATASPACE_BT709: return std::string("SMPTE_170M"); case HAL_DATASPACE_SRGB_LINEAR: @@ -159,8 +161,8 @@ std::string decodeRange(android_dataspace dataspace) { case HAL_DATASPACE_BT601_625: case HAL_DATASPACE_BT601_525: - case HAL_DATASPACE_V0_BT709: - return std::string("Limited range)"); + case HAL_DATASPACE_BT709: + return std::string("Limited range"); case HAL_DATASPACE_ARBITRARY: case HAL_DATASPACE_UNKNOWN: @@ -197,42 +199,78 @@ std::string dataspaceDetails(android_dataspace dataspace) { decodeRange(dataspace).c_str()); } -std::string decodeColorMode(android_color_mode colorMode) { +std::string decodeColorMode(ColorMode colorMode) { switch (colorMode) { - case HAL_COLOR_MODE_NATIVE: - return std::string("HAL_COLOR_MODE_NATIVE"); + case ColorMode::NATIVE: + return std::string("ColorMode::NATIVE"); - case HAL_COLOR_MODE_STANDARD_BT601_625: - return std::string("HAL_COLOR_MODE_BT601_625"); + case ColorMode::STANDARD_BT601_625: + return std::string("ColorMode::BT601_625"); - case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED: - return std::string("HAL_COLOR_MODE_BT601_625_UNADJUSTED"); + case ColorMode::STANDARD_BT601_625_UNADJUSTED: + return std::string("ColorMode::BT601_625_UNADJUSTED"); - case HAL_COLOR_MODE_STANDARD_BT601_525: - return std::string("HAL_COLOR_MODE_BT601_525"); + case ColorMode::STANDARD_BT601_525: + return std::string("ColorMode::BT601_525"); - case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED: - return std::string("HAL_COLOR_MODE_BT601_525_UNADJUSTED"); + case ColorMode::STANDARD_BT601_525_UNADJUSTED: + return std::string("ColorMode::BT601_525_UNADJUSTED"); - case HAL_COLOR_MODE_STANDARD_BT709: - return std::string("HAL_COLOR_MODE_BT709"); + case ColorMode::STANDARD_BT709: + return std::string("ColorMode::BT709"); - case HAL_COLOR_MODE_DCI_P3: - return std::string("HAL_COLOR_MODE_DCI_P3"); + case ColorMode::DCI_P3: + return std::string("ColorMode::DCI_P3"); - case HAL_COLOR_MODE_SRGB: - return std::string("HAL_COLOR_MODE_SRGB"); + case ColorMode::SRGB: + return std::string("ColorMode::SRGB"); - case HAL_COLOR_MODE_ADOBE_RGB: - return std::string("HAL_COLOR_MODE_ADOBE_RGB"); + case ColorMode::ADOBE_RGB: + return std::string("ColorMode::ADOBE_RGB"); - case HAL_COLOR_MODE_DISPLAY_P3: - return std::string("HAL_COLOR_MODE_DISPLAY_P3"); + case ColorMode::DISPLAY_P3: + return std::string("ColorMode::DISPLAY_P3"); + + case ColorMode::BT2020: + return std::string("ColorMode::BT2020"); + + case ColorMode::BT2100_PQ: + return std::string("ColorMode::BT2100_PQ"); + + case ColorMode::BT2100_HLG: + return std::string("ColorMode::BT2100_HLG"); } return android::base::StringPrintf("Unknown color mode %d", colorMode); } +std::string decodeColorTransform(android_color_transform colorTransform) { + switch (colorTransform) { + case HAL_COLOR_TRANSFORM_IDENTITY: + return std::string("Identity"); + + case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX: + return std::string("Arbitrary matrix"); + + case HAL_COLOR_TRANSFORM_VALUE_INVERSE: + return std::string("Inverse value"); + + case HAL_COLOR_TRANSFORM_GRAYSCALE: + return std::string("Grayscale"); + + case HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA: + return std::string("Correct protanopia"); + + case HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA: + return std::string("Correct deuteranopia"); + + case HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA: + return std::string("Correct tritanopia"); + } + + return android::base::StringPrintf("Unknown color transform %d", colorTransform); +} + // Converts a PixelFormat to a human-readable string. Max 11 chars. // (Could use a table of prefab String8 objects.) std::string decodePixelFormat(android::PixelFormat format) { @@ -266,6 +304,20 @@ std::string decodePixelFormat(android::PixelFormat format) { } } +std::string decodeRenderIntent(RenderIntent renderIntent) { + switch(renderIntent) { + case RenderIntent::COLORIMETRIC: + return std::string("RenderIntent::COLORIMETRIC"); + case RenderIntent::ENHANCE: + return std::string("RenderIntent::ENHANCE"); + case RenderIntent::TONE_MAP_COLORIMETRIC: + return std::string("RenderIntent::TONE_MAP_COLORIMETRIC"); + case RenderIntent::TONE_MAP_ENHANCE: + return std::string("RenderIntent::TONE_MAP_ENHANCE"); + } + return std::string("Unknown RenderIntent"); +} + std::string to_string(const android::Rect& rect) { return StringPrintf("(%4d,%4d,%4d,%4d)", rect.left, rect.top, rect.right, rect.bottom); } diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp index eb88be117a..ed7ccb0bed 100644 --- a/libs/ui/Fence.cpp +++ b/libs/ui/Fence.cpp @@ -37,18 +37,12 @@ namespace android { const sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence); -Fence::Fence() : - mFenceFd(-1) { -} - Fence::Fence(int fenceFd) : mFenceFd(fenceFd) { } -Fence::~Fence() { - if (mFenceFd != -1) { - close(mFenceFd); - } +Fence::Fence(base::unique_fd fenceFd) : + mFenceFd(std::move(fenceFd)) { } status_t Fence::wait(int timeout) { @@ -68,7 +62,7 @@ status_t Fence::waitForever(const char* logname) { int warningTimeout = 3000; int err = sync_wait(mFenceFd, warningTimeout); if (err < 0 && errno == ETIME) { - ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd, + ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd.get(), warningTimeout); err = sync_wait(mFenceFd, TIMEOUT_NEVER); } @@ -94,7 +88,7 @@ sp<Fence> Fence::merge(const char* name, const sp<Fence>& f1, if (result == -1) { status_t err = -errno; ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)", - name, f1->mFenceFd, f2->mFenceFd, + name, f1->mFenceFd.get(), f2->mFenceFd.get(), strerror(-err), err); return NO_FENCE; } @@ -117,7 +111,7 @@ nsecs_t Fence::getSignalTime() const { struct sync_file_info* finfo = sync_file_info(mFenceFd); if (finfo == NULL) { - ALOGE("sync_file_info returned NULL for fd %d", mFenceFd); + ALOGE("sync_file_info returned NULL for fd %d", mFenceFd.get()); return SIGNAL_TIME_INVALID; } if (finfo->status != 1) { @@ -181,7 +175,7 @@ status_t Fence::unflatten(void const*& buffer, size_t& size, int const*& fds, si } if (numFds) { - mFenceFd = *fds++; + mFenceFd.reset(*fds++); count--; } diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp index 0eb08e59a9..37cf617374 100644 --- a/libs/ui/Gralloc2.cpp +++ b/libs/ui/Gralloc2.cpp @@ -20,6 +20,7 @@ #include <hwbinder/IPCThreadState.h> #include <ui/Gralloc2.h> +#include <inttypes.h> #include <log/log.h> #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wzero-length-array" @@ -30,35 +31,104 @@ namespace android { namespace Gralloc2 { +namespace { + static constexpr Error kTransactionError = Error::NO_RESOURCES; +uint64_t getValid10UsageBits() { + static const uint64_t valid10UsageBits = []() -> uint64_t { + using hardware::graphics::common::V1_0::BufferUsage; + uint64_t bits = 0; + for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) { + bits = bits | bit; + } + // TODO(b/72323293, b/72703005): Remove these additional bits + bits = bits | (1 << 10) | (1 << 13); + + return bits; + }(); + return valid10UsageBits; +} + +uint64_t getValid11UsageBits() { + static const uint64_t valid11UsageBits = []() -> uint64_t { + using hardware::graphics::common::V1_1::BufferUsage; + uint64_t bits = 0; + for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) { + bits = bits | bit; + } + return bits; + }(); + return valid11UsageBits; +} + +} // anonymous namespace + void Mapper::preload() { android::hardware::preloadPassthroughService<hardware::graphics::mapper::V2_0::IMapper>(); } Mapper::Mapper() { - mMapper = IMapper::getService(); - if (mMapper == nullptr || mMapper->isRemote()) { + mMapper = hardware::graphics::mapper::V2_0::IMapper::getService(); + if (mMapper == nullptr) { + LOG_ALWAYS_FATAL("gralloc-mapper is missing"); + } + if (mMapper->isRemote()) { LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode"); } + + // IMapper 2.1 is optional + mMapperV2_1 = IMapper::castFrom(mMapper); +} + +Gralloc2::Error Mapper::validateBufferDescriptorInfo( + const IMapper::BufferDescriptorInfo& descriptorInfo) const { + uint64_t validUsageBits = getValid10UsageBits(); + if (mMapperV2_1 != nullptr) { + validUsageBits = validUsageBits | getValid11UsageBits(); + } + + if (descriptorInfo.usage & ~validUsageBits) { + ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64, + descriptorInfo.usage & ~validUsageBits); + return Error::BAD_VALUE; + } + return Error::NONE; } Error Mapper::createDescriptor( const IMapper::BufferDescriptorInfo& descriptorInfo, BufferDescriptor* outDescriptor) const { - Error error; - auto ret = mMapper->createDescriptor(descriptorInfo, - [&](const auto& tmpError, const auto& tmpDescriptor) - { - error = tmpError; - if (error != Error::NONE) { - return; - } + Error error = validateBufferDescriptorInfo(descriptorInfo); + if (error != Error::NONE) { + return error; + } - *outDescriptor = tmpDescriptor; - }); + auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor) + { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outDescriptor = tmpDescriptor; + }; + + hardware::Return<void> ret; + if (mMapperV2_1 != nullptr) { + ret = mMapperV2_1->createDescriptor_2_1(descriptorInfo, hidl_cb); + } else { + const hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo info = { + descriptorInfo.width, + descriptorInfo.height, + descriptorInfo.layerCount, + static_cast<hardware::graphics::common::V1_0::PixelFormat>(descriptorInfo.format), + descriptorInfo.usage, + }; + ret = mMapper->createDescriptor(info, hidl_cb); + } return (ret.isOk()) ? error : kTransactionError; } @@ -91,6 +161,50 @@ void Mapper::freeBuffer(buffer_handle_t bufferHandle) const buffer, error); } +Error Mapper::validateBufferSize(buffer_handle_t bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, + uint32_t stride) const +{ + if (mMapperV2_1 == nullptr) { + return Error::NONE; + } + + auto buffer = const_cast<native_handle_t*>(bufferHandle); + auto ret = mMapperV2_1->validateBufferSize(buffer, descriptorInfo, stride); + + return (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError; +} + +void Mapper::getTransportSize(buffer_handle_t bufferHandle, + uint32_t* outNumFds, uint32_t* outNumInts) const +{ + *outNumFds = uint32_t(bufferHandle->numFds); + *outNumInts = uint32_t(bufferHandle->numInts); + + if (mMapperV2_1 == nullptr) { + return; + } + + Error error; + auto buffer = const_cast<native_handle_t*>(bufferHandle); + auto ret = mMapperV2_1->getTransportSize(buffer, + [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outNumFds = tmpNumFds; + *outNumInts = tmpNumInts; + }); + + if (!ret.isOk()) { + error = kTransactionError; + } + ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", + buffer, error); +} + Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const IMapper::Rect& accessRegion, int acquireFence, void** outData) const diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index c8805000a4..254038b0ad 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -22,6 +22,7 @@ #include <grallocusage/GrallocUsageConversion.h> +#include <ui/DetachedBufferHandle.h> #include <ui/Gralloc2.h> #include <ui/GraphicBufferAllocator.h> #include <ui/GraphicBufferMapper.h> @@ -170,6 +171,8 @@ status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight, inUsage, &handle, &outStride, mId, std::move(requestorName)); if (err == NO_ERROR) { + mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts); + width = static_cast<int>(inWidth); height = static_cast<int>(inHeight); format = inFormat; @@ -199,7 +202,8 @@ status_t GraphicBuffer::initWithHandle(const native_handle_t* handle, if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) { buffer_handle_t importedHandle; - status_t err = mBufferMapper.importBuffer(handle, &importedHandle); + status_t err = mBufferMapper.importBuffer(handle, width, height, + layerCount, format, usage, stride, &importedHandle); if (err != NO_ERROR) { initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0); @@ -212,6 +216,7 @@ status_t GraphicBuffer::initWithHandle(const native_handle_t* handle, } handle = importedHandle; + mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts); } ANativeWindowBuffer::handle = handle; @@ -323,11 +328,11 @@ status_t GraphicBuffer::unlockAsync(int *fenceFd) } size_t GraphicBuffer::getFlattenedSize() const { - return static_cast<size_t>(13 + (handle ? handle->numInts : 0)) * sizeof(int); + return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int); } size_t GraphicBuffer::getFdCount() const { - return static_cast<size_t>(handle ? handle->numFds : 0); + return static_cast<size_t>(handle ? mTransportNumFds : 0); } status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { @@ -353,18 +358,18 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& buf[12] = int(usage >> 32); // high 32-bits if (handle) { - buf[10] = handle->numFds; - buf[11] = handle->numInts; - memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int)); + buf[10] = int32_t(mTransportNumFds); + buf[11] = int32_t(mTransportNumInts); + memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int)); memcpy(buf + 13, handle->data + handle->numFds, - static_cast<size_t>(handle->numInts) * sizeof(int)); + static_cast<size_t>(mTransportNumInts) * sizeof(int)); } buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded); size -= sizeNeeded; if (handle) { - fds += handle->numFds; - count -= static_cast<size_t>(handle->numFds); + fds += mTransportNumFds; + count -= static_cast<size_t>(mTransportNumFds); } return NO_ERROR; @@ -457,7 +462,8 @@ status_t GraphicBuffer::unflatten( if (handle != 0) { buffer_handle_t importedHandle; - status_t err = mBufferMapper.importBuffer(handle, &importedHandle); + status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height), + uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle); if (err != NO_ERROR) { width = height = stride = format = usage_deprecated = 0; layerCount = 0; @@ -470,6 +476,7 @@ status_t GraphicBuffer::unflatten( native_handle_close(handle); native_handle_delete(const_cast<native_handle_t*>(handle)); handle = importedHandle; + mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts); } buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); @@ -480,6 +487,24 @@ status_t GraphicBuffer::unflatten( return NO_ERROR; } +bool GraphicBuffer::isDetachedBuffer() const { + return mDetachedBufferHandle && mDetachedBufferHandle->isValid(); +} + +status_t GraphicBuffer::setDetachedBufferHandle(std::unique_ptr<DetachedBufferHandle> channel) { + if (isDetachedBuffer()) { + ALOGW("setDetachedBuffer: there is already a BufferHub channel associated with this " + "GraphicBuffer. Replacing the old one."); + } + + mDetachedBufferHandle = std::move(channel); + return NO_ERROR; +} + +std::unique_ptr<DetachedBufferHandle> GraphicBuffer::takeDetachedBufferHandle() { + return std::move(mDetachedBufferHandle); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index d85448968a..2d8e5824b0 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -52,17 +52,43 @@ GraphicBufferMapper::GraphicBufferMapper() } status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle, + uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, uint32_t stride, buffer_handle_t* outHandle) { ATRACE_CALL(); + buffer_handle_t bufferHandle; Gralloc2::Error error = mMapper->importBuffer( - hardware::hidl_handle(rawHandle), outHandle); + hardware::hidl_handle(rawHandle), &bufferHandle); + if (error != Gralloc2::Error::NONE) { + ALOGW("importBuffer(%p) failed: %d", rawHandle, error); + return static_cast<status_t>(error); + } + + Gralloc2::IMapper::BufferDescriptorInfo info = {}; + info.width = width; + info.height = height; + info.layerCount = layerCount; + info.format = static_cast<Gralloc2::PixelFormat>(format); + info.usage = usage; + + error = mMapper->validateBufferSize(bufferHandle, info, stride); + if (error != Gralloc2::Error::NONE) { + ALOGE("validateBufferSize(%p) failed: %d", rawHandle, error); + freeBuffer(bufferHandle); + return static_cast<status_t>(error); + } - ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d", - rawHandle, error); + *outHandle = bufferHandle; - return static_cast<status_t>(error); + return NO_ERROR; +} + +void GraphicBufferMapper::getTransportSize(buffer_handle_t handle, + uint32_t* outTransportNumFds, uint32_t* outTransportNumInts) +{ + mMapper->getTransportSize(handle, outTransportNumFds, outTransportNumInts); } status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle) diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp index 755e60c82e..a36911d1cf 100644 --- a/libs/ui/HdrCapabilities.cpp +++ b/libs/ui/HdrCapabilities.cpp @@ -27,13 +27,12 @@ HdrCapabilities::~HdrCapabilities() = default; HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) = default; HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) = default; - size_t HdrCapabilities::getFlattenedSize() const { return sizeof(mMaxLuminance) + sizeof(mMaxAverageLuminance) + sizeof(mMinLuminance) + sizeof(int32_t) + - mSupportedHdrTypes.size() * sizeof(int32_t); + mSupportedHdrTypes.size() * sizeof(ui::Hdr); } status_t HdrCapabilities::flatten(void* buffer, size_t size) const { @@ -48,7 +47,7 @@ status_t HdrCapabilities::flatten(void* buffer, size_t size) const { reinterpret_cast<float&>(buf[2]) = mMinLuminance; buf[3] = static_cast<int32_t>(mSupportedHdrTypes.size()); for (size_t i = 0, c = mSupportedHdrTypes.size(); i < c; ++i) { - buf[4 + i] = mSupportedHdrTypes[i]; + buf[4 + i] = static_cast<int32_t>(mSupportedHdrTypes[i]); } return NO_ERROR; } @@ -78,7 +77,7 @@ status_t HdrCapabilities::unflatten(void const* buffer, size_t size) { if (itemCount) { mSupportedHdrTypes.resize(itemCount); for (size_t i = 0; i < itemCount; ++i) { - mSupportedHdrTypes[i] = buf[4 + i]; + mSupportedHdrTypes[i] = static_cast<ui::Hdr>(buf[4 + i]); } } return NO_ERROR; diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index b53c563624..fe4ae6c414 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -513,6 +513,12 @@ void Region::rasterizer::flushSpan() bool Region::validate(const Region& reg, const char* name, bool silent) { + if (reg.mStorage.isEmpty()) { + ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name); + // return immediately as the code below assumes mStorage is non-empty + return false; + } + bool result = true; const_iterator cur = reg.begin(); const_iterator const tail = reg.end(); @@ -832,6 +838,11 @@ Region::const_iterator Region::begin() const { } Region::const_iterator Region::end() const { + // Workaround for b/77643177 + // mStorage should never be empty, but somehow it is and it's causing + // an abort in ubsan + if (mStorage.isEmpty()) return mStorage.array(); + size_t numRects = isRect() ? 1 : mStorage.size() - 1; return mStorage.array() + numRects; } diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h index dad9446b3a..92b2bfb282 100644 --- a/libs/ui/include/ui/DebugUtils.h +++ b/libs/ui/include/ui/DebugUtils.h @@ -16,7 +16,7 @@ #pragma once -#include <system/graphics.h> +#include <ui/GraphicTypes.h> #include <ui/PixelFormat.h> #include <string> @@ -29,6 +29,8 @@ std::string decodeStandard(android_dataspace dataspace); std::string decodeTransfer(android_dataspace dataspace); std::string decodeRange(android_dataspace dataspace); std::string dataspaceDetails(android_dataspace dataspace); -std::string decodeColorMode(android_color_mode colormode); +std::string decodeColorMode(android::ui::ColorMode colormode); +std::string decodeColorTransform(android_color_transform colorTransform); std::string decodePixelFormat(android::PixelFormat format); +std::string decodeRenderIntent(android::ui::RenderIntent renderIntent); std::string to_string(const android::Rect& rect); diff --git a/libs/ui/include/ui/DetachedBufferHandle.h b/libs/ui/include/ui/DetachedBufferHandle.h new file mode 100644 index 0000000000..f3c328d52b --- /dev/null +++ b/libs/ui/include/ui/DetachedBufferHandle.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef ANDROID_DETACHED_BUFFER_HUB_HANDLE_H +#define ANDROID_DETACHED_BUFFER_HUB_HANDLE_H + +#include <pdx/channel_handle.h> + +#include <memory> + +namespace android { + +// A wrapper that holds a pdx::LocalChannelHandle object. From the handle, a BufferHub buffer can be +// created. Current implementation assumes that the underlying transport is using libpdx (thus +// holding a pdx::LocalChannelHandle object), but future implementation can change it to a Binder +// backend if ever needed. +class DetachedBufferHandle { +public: + static std::unique_ptr<DetachedBufferHandle> Create(pdx::LocalChannelHandle handle) { + return std::unique_ptr<DetachedBufferHandle>(new DetachedBufferHandle(std::move(handle))); + } + + // Accessors to get or take the internal pdx::LocalChannelHandle. + pdx::LocalChannelHandle& handle() { return mHandle; } + const pdx::LocalChannelHandle& handle() const { return mHandle; } + + // Returns whether the DetachedBufferHandle holds a BufferHub channel. + bool isValid() const { return mHandle.valid(); } + +private: + // Constructs a DetachedBufferHandle from a pdx::LocalChannelHandle. + explicit DetachedBufferHandle(pdx::LocalChannelHandle handle) : mHandle(std::move(handle)) {} + + pdx::LocalChannelHandle mHandle; +}; + +} // namespace android + +#endif // ANDROID_DETACHED_BUFFER_HUB_HANDLE_H diff --git a/libs/ui/include/ui/Fence.h b/libs/ui/include/ui/Fence.h index 37811bcd7c..ec67fa972c 100644 --- a/libs/ui/include/ui/Fence.h +++ b/libs/ui/include/ui/Fence.h @@ -19,6 +19,7 @@ #include <stdint.h> +#include <android-base/unique_fd.h> #include <utils/Flattenable.h> #include <utils/RefBase.h> #include <utils/Timers.h> @@ -49,12 +50,13 @@ public: // Construct a new Fence object with an invalid file descriptor. This // should be done when the Fence object will be set up by unflattening // serialized data. - Fence(); + Fence() = default; // Construct a new Fence object to manage a given fence file descriptor. // When the new Fence object is destructed the file descriptor will be // closed. explicit Fence(int fenceFd); + explicit Fence(base::unique_fd fenceFd); // Not copyable or movable. Fence(const Fence& rhs) = delete; @@ -136,9 +138,9 @@ public: private: // Only allow instantiation using ref counting. friend class LightRefBase<Fence>; - ~Fence(); + ~Fence() = default; - int mFenceFd; + base::unique_fd mFenceFd; }; }; // namespace android diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h index 8aee16033a..5a8dbda5d3 100644 --- a/libs/ui/include/ui/Gralloc2.h +++ b/libs/ui/include/ui/Gralloc2.h @@ -20,7 +20,9 @@ #include <string> #include <android/hardware/graphics/allocator/2.0/IAllocator.h> +#include <android/hardware/graphics/common/1.1/types.h> #include <android/hardware/graphics/mapper/2.0/IMapper.h> +#include <android/hardware/graphics/mapper/2.1/IMapper.h> #include <utils/StrongPointer.h> namespace android { @@ -28,11 +30,11 @@ namespace android { namespace Gralloc2 { using hardware::graphics::allocator::V2_0::IAllocator; -using hardware::graphics::common::V1_0::BufferUsage; -using hardware::graphics::common::V1_0::PixelFormat; +using hardware::graphics::common::V1_1::BufferUsage; +using hardware::graphics::common::V1_1::PixelFormat; +using hardware::graphics::mapper::V2_1::IMapper; using hardware::graphics::mapper::V2_0::BufferDescriptor; using hardware::graphics::mapper::V2_0::Error; -using hardware::graphics::mapper::V2_0::IMapper; using hardware::graphics::mapper::V2_0::YCbCrLayout; // A wrapper to IMapper @@ -55,6 +57,13 @@ public: void freeBuffer(buffer_handle_t bufferHandle) const; + Error validateBufferSize(buffer_handle_t bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, + uint32_t stride) const; + + void getTransportSize(buffer_handle_t bufferHandle, + uint32_t* outNumFds, uint32_t* outNumInts) const; + // The ownership of acquireFence is always transferred to the callee, even // on errors. Error lock(buffer_handle_t bufferHandle, uint64_t usage, @@ -72,7 +81,12 @@ public: int unlock(buffer_handle_t bufferHandle) const; private: - sp<IMapper> mMapper; + // Determines whether the passed info is compatible with the mapper. + Error validateBufferDescriptorInfo( + const IMapper::BufferDescriptorInfo& descriptorInfo) const; + + sp<hardware::graphics::mapper::V2_0::IMapper> mMapper; + sp<IMapper> mMapperV2_1; }; // A wrapper to IAllocator diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 95c2d2272e..cc38982e64 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -34,6 +34,7 @@ namespace android { +class DetachedBufferHandle; class GraphicBufferMapper; // =========================================================================== @@ -190,6 +191,11 @@ public: status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); + // Sets and takes DetachedBuffer. Should only be called from BufferHub. + bool isDetachedBuffer() const; + status_t setDetachedBufferHandle(std::unique_ptr<DetachedBufferHandle> detachedBuffer); + std::unique_ptr<DetachedBufferHandle> takeDetachedBufferHandle(); + private: ~GraphicBuffer(); @@ -230,12 +236,27 @@ private: GraphicBufferMapper& mBufferMapper; ssize_t mInitCheck; + // numbers of fds/ints in native_handle_t to flatten + uint32_t mTransportNumFds; + uint32_t mTransportNumInts; + uint64_t mId; // Stores the generation number of this buffer. If this number does not // match the BufferQueue's internal generation number (set through // IGBP::setGenerationNumber), attempts to attach the buffer will fail. uint32_t mGenerationNumber; + + // Stores a BufferHub handle that can be used to re-attach this GraphicBuffer back into a + // BufferHub producer/consumer set. In terms of GraphicBuffer's relationship with BufferHub, + // there are three different modes: + // 1. Legacy mode: GraphicBuffer is not backed by BufferHub and mDetachedBufferHandle must be + // invalid. + // 2. Detached mode: GraphicBuffer is backed by BufferHub, but not part of a producer/consumer + // set. In this mode, mDetachedBufferHandle must be valid. + // 3. Attached mode: GraphicBuffer is backed by BufferHub and it's part of a producer/consumer + // set. In this mode, mDetachedBufferHandle must be invalid. + std::unique_ptr<DetachedBufferHandle> mDetachedBufferHandle; }; }; // namespace android diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h index 06961b11b5..7cf003dcba 100644 --- a/libs/ui/include/ui/GraphicBufferMapper.h +++ b/libs/ui/include/ui/GraphicBufferMapper.h @@ -22,6 +22,7 @@ #include <memory> +#include <ui/PixelFormat.h> #include <utils/Singleton.h> @@ -49,10 +50,15 @@ public: // The imported outHandle must be freed with freeBuffer when no longer // needed. rawHandle is owned by the caller. status_t importBuffer(buffer_handle_t rawHandle, + uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, uint32_t stride, buffer_handle_t* outHandle); status_t freeBuffer(buffer_handle_t handle); + void getTransportSize(buffer_handle_t handle, + uint32_t* outTransportNumFds, uint32_t* outTransportNumInts); + status_t lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr); diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h new file mode 100644 index 0000000000..0fa819dce8 --- /dev/null +++ b/libs/ui/include/ui/GraphicTypes.h @@ -0,0 +1,34 @@ +/* + * Copyright 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. + */ + +#pragma once + +#include <android/hardware/graphics/common/1.1/types.h> +#include <system/graphics.h> + +// android::ui::* in this header file will alias different types as +// the HIDL interface is updated. +namespace android { +namespace ui { + +using android::hardware::graphics::common::V1_0::Hdr; +using android::hardware::graphics::common::V1_1::ColorMode; +using android::hardware::graphics::common::V1_1::Dataspace; +using android::hardware::graphics::common::V1_1::PixelFormat; +using android::hardware::graphics::common::V1_1::RenderIntent; + +} // namespace ui +} // namespace android diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h index 925aa1b7b3..4e98c283d1 100644 --- a/libs/ui/include/ui/HdrCapabilities.h +++ b/libs/ui/include/ui/HdrCapabilities.h @@ -21,6 +21,7 @@ #include <vector> +#include <ui/GraphicTypes.h> #include <utils/Flattenable.h> namespace android { @@ -28,7 +29,7 @@ namespace android { class HdrCapabilities : public LightFlattenable<HdrCapabilities> { public: - HdrCapabilities(const std::vector<int32_t /*android_hdr_t*/>& types, + HdrCapabilities(const std::vector<ui::Hdr>& types, float maxLuminance, float maxAverageLuminance, float minLuminance) : mSupportedHdrTypes(types), mMaxLuminance(maxLuminance), @@ -47,7 +48,7 @@ public: ~HdrCapabilities(); - const std::vector<int32_t /*android_hdr_t*/>& getSupportedHdrTypes() const { + const std::vector<ui::Hdr>& getSupportedHdrTypes() const { return mSupportedHdrTypes; } float getDesiredMaxLuminance() const { return mMaxLuminance; } @@ -61,7 +62,7 @@ public: status_t unflatten(void const* buffer, size_t size); private: - std::vector<int32_t /*android_hdr_t*/> mSupportedHdrTypes; + std::vector<ui::Hdr> mSupportedHdrTypes; float mMaxLuminance; float mMaxAverageLuminance; float mMinLuminance; diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h index c099a026aa..0bec0b7f78 100644 --- a/libs/ui/include/ui/Rect.h +++ b/libs/ui/include/ui/Rect.h @@ -95,15 +95,18 @@ public: } // rectangle's width + __attribute__((no_sanitize("signed-integer-overflow"))) inline int32_t getWidth() const { return right - left; } // rectangle's height + __attribute__((no_sanitize("signed-integer-overflow"))) inline int32_t getHeight() const { return bottom - top; } + __attribute__((no_sanitize("signed-integer-overflow"))) inline Rect getBounds() const { return Rect(right - left, bottom - top); } diff --git a/libs/ui/include_vndk/ui/ANativeObjectBase.h b/libs/ui/include_vndk/ui/ANativeObjectBase.h new file mode 120000 index 0000000000..4dab8d8b8b --- /dev/null +++ b/libs/ui/include_vndk/ui/ANativeObjectBase.h @@ -0,0 +1 @@ +../../include/ui/ANativeObjectBase.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/BufferQueueDefs.h b/libs/ui/include_vndk/ui/BufferQueueDefs.h new file mode 120000 index 0000000000..c886ed858e --- /dev/null +++ b/libs/ui/include_vndk/ui/BufferQueueDefs.h @@ -0,0 +1 @@ +../../include/ui/BufferQueueDefs.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/ColorSpace.h b/libs/ui/include_vndk/ui/ColorSpace.h new file mode 120000 index 0000000000..ddf70d5bdf --- /dev/null +++ b/libs/ui/include_vndk/ui/ColorSpace.h @@ -0,0 +1 @@ +../../include/ui/ColorSpace.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/DebugUtils.h b/libs/ui/include_vndk/ui/DebugUtils.h new file mode 120000 index 0000000000..8461bb39c3 --- /dev/null +++ b/libs/ui/include_vndk/ui/DebugUtils.h @@ -0,0 +1 @@ +../../include/ui/DebugUtils.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/DisplayInfo.h b/libs/ui/include_vndk/ui/DisplayInfo.h new file mode 120000 index 0000000000..75f14cf66d --- /dev/null +++ b/libs/ui/include_vndk/ui/DisplayInfo.h @@ -0,0 +1 @@ +../../include/ui/DisplayInfo.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/DisplayStatInfo.h b/libs/ui/include_vndk/ui/DisplayStatInfo.h new file mode 120000 index 0000000000..6689ad3162 --- /dev/null +++ b/libs/ui/include_vndk/ui/DisplayStatInfo.h @@ -0,0 +1 @@ +../../include/ui/DisplayStatInfo.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/Fence.h b/libs/ui/include_vndk/ui/Fence.h new file mode 120000 index 0000000000..b110201354 --- /dev/null +++ b/libs/ui/include_vndk/ui/Fence.h @@ -0,0 +1 @@ +../../include/ui/Fence.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/FenceTime.h b/libs/ui/include_vndk/ui/FenceTime.h new file mode 120000 index 0000000000..01a6ff21d1 --- /dev/null +++ b/libs/ui/include_vndk/ui/FenceTime.h @@ -0,0 +1 @@ +../../include/ui/FenceTime.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/FloatRect.h b/libs/ui/include_vndk/ui/FloatRect.h new file mode 120000 index 0000000000..a5262118f7 --- /dev/null +++ b/libs/ui/include_vndk/ui/FloatRect.h @@ -0,0 +1 @@ +../../include/ui/FloatRect.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/FrameStats.h b/libs/ui/include_vndk/ui/FrameStats.h new file mode 120000 index 0000000000..e68e5c843f --- /dev/null +++ b/libs/ui/include_vndk/ui/FrameStats.h @@ -0,0 +1 @@ +../../include/ui/FrameStats.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/Gralloc2.h b/libs/ui/include_vndk/ui/Gralloc2.h new file mode 120000 index 0000000000..66098c4edb --- /dev/null +++ b/libs/ui/include_vndk/ui/Gralloc2.h @@ -0,0 +1 @@ +../../include/ui/Gralloc2.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/GraphicBuffer.h b/libs/ui/include_vndk/ui/GraphicBuffer.h new file mode 120000 index 0000000000..445eae5395 --- /dev/null +++ b/libs/ui/include_vndk/ui/GraphicBuffer.h @@ -0,0 +1 @@ +../../include/ui/GraphicBuffer.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/GraphicBufferAllocator.h b/libs/ui/include_vndk/ui/GraphicBufferAllocator.h new file mode 120000 index 0000000000..96345330f1 --- /dev/null +++ b/libs/ui/include_vndk/ui/GraphicBufferAllocator.h @@ -0,0 +1 @@ +../../include/ui/GraphicBufferAllocator.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/GraphicBufferMapper.h b/libs/ui/include_vndk/ui/GraphicBufferMapper.h new file mode 120000 index 0000000000..c3b3a7c61d --- /dev/null +++ b/libs/ui/include_vndk/ui/GraphicBufferMapper.h @@ -0,0 +1 @@ +../../include/ui/GraphicBufferMapper.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/GraphicTypes.h b/libs/ui/include_vndk/ui/GraphicTypes.h new file mode 120000 index 0000000000..b1859e0f51 --- /dev/null +++ b/libs/ui/include_vndk/ui/GraphicTypes.h @@ -0,0 +1 @@ +../../include/ui/GraphicTypes.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/HdrCapabilities.h b/libs/ui/include_vndk/ui/HdrCapabilities.h new file mode 120000 index 0000000000..a240828c8c --- /dev/null +++ b/libs/ui/include_vndk/ui/HdrCapabilities.h @@ -0,0 +1 @@ +../../include/ui/HdrCapabilities.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/PixelFormat.h b/libs/ui/include_vndk/ui/PixelFormat.h new file mode 120000 index 0000000000..0aba056f58 --- /dev/null +++ b/libs/ui/include_vndk/ui/PixelFormat.h @@ -0,0 +1 @@ +../../include/ui/PixelFormat.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/Point.h b/libs/ui/include_vndk/ui/Point.h new file mode 120000 index 0000000000..0aeda3e97e --- /dev/null +++ b/libs/ui/include_vndk/ui/Point.h @@ -0,0 +1 @@ +../../include/ui/Point.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/Rect.h b/libs/ui/include_vndk/ui/Rect.h new file mode 120000 index 0000000000..01ed6891e9 --- /dev/null +++ b/libs/ui/include_vndk/ui/Rect.h @@ -0,0 +1 @@ +../../include/ui/Rect.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/Region.h b/libs/ui/include_vndk/ui/Region.h new file mode 120000 index 0000000000..3f829bfad0 --- /dev/null +++ b/libs/ui/include_vndk/ui/Region.h @@ -0,0 +1 @@ +../../include/ui/Region.h
\ No newline at end of file diff --git a/libs/ui/include_vndk/ui/UiConfig.h b/libs/ui/include_vndk/ui/UiConfig.h new file mode 120000 index 0000000000..f580ce1095 --- /dev/null +++ b/libs/ui/include_vndk/ui/UiConfig.h @@ -0,0 +1 @@ +../../include/ui/UiConfig.h
\ No newline at end of file diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 08067fcf5d..aef6428cc8 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -27,3 +27,10 @@ cc_test { srcs: ["colorspace_test.cpp"], cflags: ["-Wall", "-Werror"], } + +cc_test { + name: "GraphicBuffer_test", + shared_libs: ["libpdx_default_transport", "libui", "libutils"], + srcs: ["GraphicBuffer_test.cpp"], + cflags: ["-Wall", "-Werror"], +} diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp new file mode 100644 index 0000000000..eb679ac236 --- /dev/null +++ b/libs/ui/tests/GraphicBuffer_test.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 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. + */ + +#define LOG_TAG "GraphicBufferTest" + +#include <ui/DetachedBufferHandle.h> +#include <ui/GraphicBuffer.h> + +#include <gtest/gtest.h> + +namespace android { + +namespace { + +constexpr uint32_t kTestWidth = 1024; +constexpr uint32_t kTestHeight = 1; +constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB; +constexpr uint32_t kTestLayerCount = 1; +constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN; + +} // namespace + +class GraphicBufferTest : public testing::Test {}; + +TEST_F(GraphicBufferTest, DetachedBuffer) { + sp<GraphicBuffer> buffer( + new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount, kTestUsage)); + + // Currently a newly allocated GraphicBuffer is in legacy mode, i.e. not associated with + // BufferHub. But this may change in the future. + EXPECT_FALSE(buffer->isDetachedBuffer()); + + pdx::LocalChannelHandle channel{nullptr, 1234}; + EXPECT_TRUE(channel.valid()); + + std::unique_ptr<DetachedBufferHandle> handle = DetachedBufferHandle::Create(std::move(channel)); + EXPECT_FALSE(channel.valid()); + EXPECT_TRUE(handle->isValid()); + EXPECT_TRUE(handle->handle().valid()); + + buffer->setDetachedBufferHandle(std::move(handle)); + EXPECT_TRUE(handle == nullptr); + EXPECT_TRUE(buffer->isDetachedBuffer()); + + handle = buffer->takeDetachedBufferHandle(); + EXPECT_TRUE(handle != nullptr); + EXPECT_TRUE(handle->isValid()); + EXPECT_FALSE(buffer->isDetachedBuffer()); +} + +} // namespace android |