summaryrefslogtreecommitdiff
path: root/libs/ui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ui')
-rw-r--r--libs/ui/Android.bp20
-rw-r--r--libs/ui/DebugUtils.cpp104
-rw-r--r--libs/ui/Fence.cpp18
-rw-r--r--libs/ui/Gralloc2.cpp138
-rw-r--r--libs/ui/GraphicBuffer.cpp45
-rw-r--r--libs/ui/GraphicBufferMapper.cpp34
-rw-r--r--libs/ui/HdrCapabilities.cpp7
-rw-r--r--libs/ui/Region.cpp11
-rw-r--r--libs/ui/include/ui/DebugUtils.h6
-rw-r--r--libs/ui/include/ui/DetachedBufferHandle.h52
-rw-r--r--libs/ui/include/ui/Fence.h8
-rw-r--r--libs/ui/include/ui/Gralloc2.h22
-rw-r--r--libs/ui/include/ui/GraphicBuffer.h21
-rw-r--r--libs/ui/include/ui/GraphicBufferMapper.h6
-rw-r--r--libs/ui/include/ui/GraphicTypes.h34
-rw-r--r--libs/ui/include/ui/HdrCapabilities.h7
-rw-r--r--libs/ui/include/ui/Rect.h3
l---------libs/ui/include_vndk/ui/ANativeObjectBase.h1
l---------libs/ui/include_vndk/ui/BufferQueueDefs.h1
l---------libs/ui/include_vndk/ui/ColorSpace.h1
l---------libs/ui/include_vndk/ui/DebugUtils.h1
l---------libs/ui/include_vndk/ui/DisplayInfo.h1
l---------libs/ui/include_vndk/ui/DisplayStatInfo.h1
l---------libs/ui/include_vndk/ui/Fence.h1
l---------libs/ui/include_vndk/ui/FenceTime.h1
l---------libs/ui/include_vndk/ui/FloatRect.h1
l---------libs/ui/include_vndk/ui/FrameStats.h1
l---------libs/ui/include_vndk/ui/Gralloc2.h1
l---------libs/ui/include_vndk/ui/GraphicBuffer.h1
l---------libs/ui/include_vndk/ui/GraphicBufferAllocator.h1
l---------libs/ui/include_vndk/ui/GraphicBufferMapper.h1
l---------libs/ui/include_vndk/ui/GraphicTypes.h1
l---------libs/ui/include_vndk/ui/HdrCapabilities.h1
l---------libs/ui/include_vndk/ui/PixelFormat.h1
l---------libs/ui/include_vndk/ui/Point.h1
l---------libs/ui/include_vndk/ui/Rect.h1
l---------libs/ui/include_vndk/ui/Region.h1
l---------libs/ui/include_vndk/ui/UiConfig.h1
-rw-r--r--libs/ui/tests/Android.bp7
-rw-r--r--libs/ui/tests/GraphicBuffer_test.cpp64
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