Create GraphicBuffer backed by BufferHubBuffer

The newly created GraphicBuffer shall own the BufferHubBuffer object
through out its life cycle.

Bug: 70912269
Bug: 111976433
Test: GraphicBuffer_test
Change-Id: I698573e26f85dd40d30c267aeea545e65a7e2a8b
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 0a0c8ca..f770975 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -109,6 +109,7 @@
     // bufferhub is not used when building libgui for vendors
     target: {
         vendor: {
+            cflags: ["-DLIBUI_IN_VNDK"],
             exclude_srcs: [
                 "BufferHubBuffer.cpp",
                 "BufferHubMetadata.cpp",
@@ -116,6 +117,7 @@
             exclude_header_libs: [
                 "libbufferhub_headers",
                 "libdvr_headers",
+                "libnativewindow_headers",
             ],
             exclude_shared_libs: [
                 "libpdx_default_transport",
@@ -128,6 +130,7 @@
         "libbufferhub_headers",
         "libdvr_headers",
         "libnativebase_headers",
+        "libnativewindow_headers",
         "libhardware_headers",
         "libui_headers",
         "libpdx_headers",
@@ -155,6 +158,7 @@
     vendor_available: true,
     target: {
         vendor: {
+            cflags: ["-DLIBUI_IN_VNDK"],
             override_export_include_dirs: ["include_vndk"],
         },
     },
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index dd79775..e747ee1 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -160,6 +160,16 @@
     // GraphicBuffer instance can be created in future.
     mBufferHandle = bufferTraits.take_buffer_handle();
 
+    // Populate buffer desc based on buffer traits.
+    mBufferDesc.width = bufferTraits.width();
+    mBufferDesc.height = bufferTraits.height();
+    mBufferDesc.layers = bufferTraits.layer_count();
+    mBufferDesc.format = bufferTraits.format();
+    mBufferDesc.usage = bufferTraits.usage();
+    mBufferDesc.stride = bufferTraits.stride();
+    mBufferDesc.rfu0 = 0U;
+    mBufferDesc.rfu1 = 0U;
+
     // If all imports succeed, replace the previous buffer and id.
     mId = bufferId;
     mClientStateMask = bufferTraits.client_state_mask();
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 29deb01..e606e26 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -22,6 +22,10 @@
 
 #include <grallocusage/GrallocUsageConversion.h>
 
+#ifndef LIBUI_IN_VNDK
+#include <ui/BufferHubBuffer.h>
+#endif // LIBUI_IN_VNDK
+
 #include <ui/Gralloc2.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/GraphicBufferMapper.h>
@@ -89,6 +93,21 @@
                                 inUsage, inStride);
 }
 
+#ifndef LIBUI_IN_VNDK
+GraphicBuffer::GraphicBuffer(std::unique_ptr<BufferHubBuffer> buffer) : GraphicBuffer() {
+    if (buffer == nullptr) {
+        mInitCheck = BAD_VALUE;
+        return;
+    }
+
+    mInitCheck = initWithHandle(buffer->DuplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE,
+                                buffer->desc().width, buffer->desc().height,
+                                static_cast<PixelFormat>(buffer->desc().format),
+                                buffer->desc().layers, buffer->desc().usage, buffer->desc().stride);
+    mBufferHubBuffer = std::move(buffer);
+}
+#endif // LIBUI_IN_VNDK
+
 GraphicBuffer::~GraphicBuffer()
 {
     if (handle) {
@@ -483,6 +502,12 @@
     return NO_ERROR;
 }
 
+#ifndef LIBUI_IN_VNDK
+bool GraphicBuffer::isBufferHubBuffer() const {
+    return mBufferHubBuffer != nullptr;
+}
+#endif // LIBUI_IN_VNDK
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index daf6192..6850b43 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -38,6 +38,7 @@
 #include <private/dvr/native_handle_wrapper.h>
 #pragma clang diagnostic pop
 
+#include <android/hardware_buffer.h>
 #include <ui/BufferHubMetadata.h>
 
 namespace android {
@@ -62,9 +63,9 @@
     // Allocates a standalone BufferHubBuffer not associated with any producer consumer set.
     static std::unique_ptr<BufferHubBuffer> Create(uint32_t width, uint32_t height,
                                                    uint32_t layerCount, uint32_t format,
-                                                   uint64_t usage, size_t mUserMetadataSize) {
+                                                   uint64_t usage, size_t userMetadataSize) {
         return std::unique_ptr<BufferHubBuffer>(
-                new BufferHubBuffer(width, height, layerCount, format, usage, mUserMetadataSize));
+                new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
     }
 
     // Imports the given channel handle to a BufferHubBuffer, taking ownership.
@@ -79,6 +80,9 @@
     // bufferhubd share the same buffer id.
     int id() const { return mId; }
 
+    // Returns the buffer description, which is guaranteed to be faithful values from bufferhubd.
+    const AHardwareBuffer_Desc& desc() const { return mBufferDesc; }
+
     const native_handle_t* DuplicateHandle() { return mBufferHandle.DuplicateHandle(); }
 
     // Returns the current value of MetadataHeader::buffer_state.
@@ -118,7 +122,7 @@
 
 private:
     BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
-                    uint64_t usage, size_t mUserMetadataSize);
+                    uint64_t usage, size_t userMetadataSize);
 
     BufferHubBuffer(pdx::LocalChannelHandle mChannelHandle);
 
@@ -128,6 +132,9 @@
     int mId = -1;
     uint64_t mClientStateMask = 0;
 
+    // Stores ground truth of the buffer.
+    AHardwareBuffer_Desc mBufferDesc;
+
     // Wrapps the gralloc buffer handle of this buffer.
     dvr::NativeHandleWrapper<pdx::LocalHandle> mBufferHandle;
 
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index fe6229a..81f6cd9 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -34,6 +34,10 @@
 
 namespace android {
 
+#ifndef LIBUI_IN_VNDK
+class BufferHubBuffer;
+#endif // LIBUI_IN_VNDK
+
 class GraphicBufferMapper;
 
 // ===========================================================================
@@ -133,6 +137,11 @@
     GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
             uint32_t inUsage, std::string requestorName = "<Unknown>");
 
+#ifndef LIBUI_IN_VNDK
+    // Create a GraphicBuffer from an existing BufferHubBuffer.
+    GraphicBuffer(std::unique_ptr<BufferHubBuffer> buffer);
+#endif // LIBUI_IN_VNDK
+
     // return status
     status_t initCheck() const;
 
@@ -188,6 +197,11 @@
     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);
 
+#ifndef LIBUI_IN_VNDK
+    // Returns whether this GraphicBuffer is backed by BufferHubBuffer.
+    bool isBufferHubBuffer() const;
+#endif // LIBUI_IN_VNDK
+
 private:
     ~GraphicBuffer();
 
@@ -237,6 +251,11 @@
     // match the BufferQueue's internal generation number (set through
     // IGBP::setGenerationNumber), attempts to attach the buffer will fail.
     uint32_t mGenerationNumber;
+
+#ifndef LIBUI_IN_VNDK
+    // Stores a BufferHubBuffer that handles buffer signaling, identification.
+    std::unique_ptr<BufferHubBuffer> mBufferHubBuffer;
+#endif // LIBUI_IN_VNDK
 };
 
 }; // namespace android
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 4c9c176..b7ad4e5 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -29,6 +29,22 @@
 }
 
 cc_test {
+    name: "GraphicBuffer_test",
+    header_libs: [
+        "libbufferhub_headers",
+        "libdvr_headers",
+        "libnativewindow_headers",
+    ],
+    shared_libs: [
+        "libpdx_default_transport",
+        "libui",
+        "libutils",
+    ],
+    srcs: ["GraphicBuffer_test.cpp"],
+    cflags: ["-Wall", "-Werror"],
+}
+
+cc_test {
     name: "BufferHubBuffer_test",
     header_libs: [
         "libbufferhub_headers",
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
new file mode 100644
index 0000000..95ca2c1
--- /dev/null
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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/BufferHubBuffer.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, CreateFromBufferHubBuffer) {
+    std::unique_ptr<BufferHubBuffer> b1 =
+            BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
+                                    kTestUsage, /*userMetadataSize=*/0);
+    EXPECT_TRUE(b1->IsValid());
+
+    sp<GraphicBuffer> gb(new GraphicBuffer(std::move(b1)));
+    EXPECT_TRUE(gb->isBufferHubBuffer());
+
+    EXPECT_EQ(gb->getWidth(), kTestWidth);
+    EXPECT_EQ(gb->getHeight(), kTestHeight);
+    EXPECT_EQ(static_cast<uint32_t>(gb->getPixelFormat()), kTestFormat);
+    EXPECT_EQ(gb->getUsage(), kTestUsage);
+    EXPECT_EQ(gb->getLayerCount(), kTestLayerCount);
+}
+
+} // namespace android