Implement allocateBuffer for BufferHubService

Return ALLOCATION_FAILED when failed to create BufferNode, NO_ERROR on
success.

Allocation and memory management logics are in BufferNode, and enforced
via the shared_ptr and clientList. Memcpy is used to convert between
AHardwareBuffer_Desc and HardwareBufferDescription (i.e. hidl_vec).

Test: BufferHubBuffer_test (passed)
Change-Id: I5e17aa7330c5f94656e62dc4bea8ab6c705ab7a4
Fix: 118614333
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 1521e1d..4c9c176 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -32,7 +32,8 @@
     name: "BufferHubBuffer_test",
     header_libs: [
         "libbufferhub_headers",
-        "libdvr_headers"
+        "libdvr_headers",
+        "libnativewindow_headers",
     ],
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 606aee60..143335a 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -18,6 +18,7 @@
 
 #include <android/frameworks/bufferhub/1.0/IBufferClient.h>
 #include <android/frameworks/bufferhub/1.0/IBufferHub.h>
+#include <android/hardware_buffer.h>
 #include <gtest/gtest.h>
 #include <hidl/ServiceManagement.h>
 #include <hwbinder/IPCThreadState.h>
@@ -41,6 +42,7 @@
 using frameworks::bufferhub::V1_0::IBufferClient;
 using frameworks::bufferhub::V1_0::IBufferHub;
 using hardware::hidl_handle;
+using hardware::graphics::common::V1_2::HardwareBufferDescription;
 using hidl::base::V1_0::IBase;
 using pdx::LocalChannelHandle;
 
@@ -124,19 +126,22 @@
     return;
 }
 
-TEST_F(BufferHubBufferTest, ConnectHidlServer) {
-    sp<IBufferHub> bufferhub = IBufferHub::getService();
-    ASSERT_NE(nullptr, bufferhub.get());
+TEST_F(BufferHubBufferTest, AllocateBuffer) {
+    // TODO(b/116681016): directly test on BufferHubBuffer instead of the service.
+    sp<IBufferHub> bufferHub = IBufferHub::getService();
+    ASSERT_NE(nullptr, bufferHub.get());
 
-    // TODO(b/116681016): Fill in real test once the interface gets implemented..
-    hidl_handle handle;
-    EXPECT_TRUE(bufferhub
-                        ->importBuffer(handle,
-                                       [](const auto& client, const auto& ret) {
-                                           EXPECT_EQ(client, nullptr);
-                                           EXPECT_EQ(ret, BufferHubStatus::NO_ERROR);
-                                       })
-                        .isOk());
+    // Stride is an output, rfu0 and rfu1 are reserved data slot for future use.
+    AHardwareBuffer_Desc aDesc = {kWidth, kHeight,        kLayerCount,  kFormat,
+                                  kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+    HardwareBufferDescription desc;
+    memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+    IBufferHub::allocateBuffer_cb callback = [](const auto& client, const auto& status) {
+        EXPECT_EQ(status, BufferHubStatus::NO_ERROR);
+        EXPECT_NE(nullptr, client.get());
+    };
+    EXPECT_TRUE(bufferHub->allocateBuffer(desc, kUserMetadataSize, callback).isOk());
 }
 
 } // namespace
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index ca65e02..871561f 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -52,6 +52,12 @@
     srcs: [
         "main_bufferhub.cpp"
     ],
+    header_libs: [
+        "libbufferhub_headers",
+        "libdvr_headers",
+        "libnativewindow_headers",
+        "libpdx_headers",
+    ],
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
         "libbufferhubservice",
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index 86598e0..b72b556 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
+#include <android/hardware_buffer.h>
 #include <bufferhub/BufferHubService.h>
+#include <log/log.h>
 
 namespace android {
 namespace frameworks {
@@ -24,11 +26,27 @@
 
 using hardware::Void;
 
-Return<void> BufferHubService::allocateBuffer(const HardwareBufferDescription& /*description*/,
-                                              const uint32_t /*userMetadataSize*/,
+Return<void> BufferHubService::allocateBuffer(const HardwareBufferDescription& description,
+                                              const uint32_t userMetadataSize,
                                               allocateBuffer_cb _hidl_cb) {
-    // TODO(b/118614333): implement buffer allocation
-    _hidl_cb(/*bufferClient=*/nullptr, /*status=*/BufferHubStatus::NO_ERROR);
+    AHardwareBuffer_Desc desc;
+    memcpy(&desc, &description, sizeof(AHardwareBuffer_Desc));
+
+    std::shared_ptr<BufferNode> node =
+            std::make_shared<BufferNode>(desc.width, desc.height, desc.layers, desc.format,
+                                         desc.usage, userMetadataSize);
+    if (node == nullptr || !node->IsValid()) {
+        ALOGE("%s: creating BufferNode failed.", __FUNCTION__);
+        _hidl_cb(/*bufferClient=*/nullptr, /*status=*/BufferHubStatus::ALLOCATION_FAILED);
+        return Void();
+    }
+
+    sp<BufferClient> client = new BufferClient(node);
+    // Add it to list for bookkeeping and dumpsys.
+    std::lock_guard<std::mutex> lock(mClientListMutex);
+    mClientList.push_back(client);
+
+    _hidl_cb(/*bufferClient=*/client, /*status=*/BufferHubStatus::NO_ERROR);
     return Void();
 }
 
diff --git a/services/bufferhub/include/bufferhub/BufferClient.h b/services/bufferhub/include/bufferhub/BufferClient.h
index 14ea95c..c6eb791 100644
--- a/services/bufferhub/include/bufferhub/BufferClient.h
+++ b/services/bufferhub/include/bufferhub/BufferClient.h
@@ -18,6 +18,7 @@
 #define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_CLIENT_H
 
 #include <android/frameworks/bufferhub/1.0/IBufferClient.h>
+#include <bufferhub/BufferNode.h>
 
 namespace android {
 namespace frameworks {
@@ -27,9 +28,19 @@
 
 using hardware::Return;
 
+// Forward declaration to avoid circular dependency
+class BufferHubService;
+
 class BufferClient : public IBufferClient {
 public:
+    // Creates a server-side buffer client from an existing BufferNode. Note that
+    // this funciton takes ownership of the shared_ptr.
+    explicit BufferClient(const std::shared_ptr<BufferNode>& node) : mBufferNode(node){};
+
     Return<void> duplicate(duplicate_cb _hidl_cb) override;
+
+private:
+    std::shared_ptr<BufferNode> mBufferNode;
 };
 
 } // namespace implementation
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
index 5e0cff0..1bbd807 100644
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ b/services/bufferhub/include/bufferhub/BufferHubService.h
@@ -17,8 +17,11 @@
 #ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
 #define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
 
-#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
+#include <mutex>
+
 #include <android/frameworks/bufferhub/1.0/IBufferHub.h>
+#include <bufferhub/BufferClient.h>
+#include <utils/Mutex.h>
 
 namespace android {
 namespace frameworks {
@@ -36,6 +39,11 @@
                                 const uint32_t userMetadataSize,
                                 allocateBuffer_cb _hidl_cb) override;
     Return<void> importBuffer(const hidl_handle& nativeHandle, importBuffer_cb _hidl_cb) override;
+
+private:
+    // List of active BufferClient for bookkeeping.
+    std::mutex mClientListMutex;
+    std::vector<sp<BufferClient>> mClientList GUARDED_BY(mClientListMutex);
 };
 
 } // namespace implementation