Refactor BufferHubBuffer to use hwbinder

Entirely move BufferHubBuffer off pdx dependency and using hwbinder
backend and rewrite test cases to fit in current behavior.

Remove duplicated test cases in buffer_hub-test. Commented out
BufferHubBuffer related parts and remove related include and using
statement.

Add hidl interface dependency to libs/gui build file to avoid compile
errors.

Test: BufferHub_test, GraphicBuffer_test, buffer_hub-test
Bug: 116681016
Change-Id: I9d8f734f681e04d3d50b7a02c27b17df8c66cbad
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index d1c732b..3521e89 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -121,6 +121,7 @@
     ],
 
     shared_libs: [
+        "android.frameworks.bufferhub@1.0",
         "android.hardware.graphics.common@1.1",
         "libbase",
         "libsync",
@@ -153,6 +154,7 @@
                 "BufferHubProducer.cpp",
             ],
             exclude_shared_libs: [
+                "android.frameworks.bufferhub@1.0",
                 "libbufferhub",
                 "libbufferhubqueue",
                 "libpdx_default_transport",
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 956465c..d089bf6 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -77,6 +77,7 @@
     ],
 
     shared_libs: [
+        "android.frameworks.bufferhub@1.0",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.mapper@2.0",
@@ -93,7 +94,6 @@
         "libutils",
         "libutilscallstack",
         "liblog",
-        "libpdx_default_transport",  // TODO(b/112338294): Remove this once BufferHub moved to use Binder.
     ],
 
     export_shared_lib_headers: [
@@ -121,6 +121,7 @@
                 "libnativewindow_headers",
             ],
             exclude_shared_libs: [
+                "android.frameworks.bufferhub@1.0",
                 "libpdx_default_transport",
             ],
         },
@@ -148,9 +149,6 @@
         "libhardware_headers",
         "libui_headers",
     ],
-
-    // TODO(b/117568153): Temporarily opt out using libcrt.
-    no_libcrt: true,
 }
 
 cc_library_headers {
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 1184960..c70f188 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -14,150 +14,190 @@
  * limitations under the License.
  */
 
-// We would eliminate the clang warnings introduced by libdpx.
-// TODO(b/112338294): Remove those once BufferHub moved to use Binder
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
-#pragma clang diagnostic ignored "-Wgnu-case-range"
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
-#pragma clang diagnostic ignored "-Wnested-anon-types"
-#pragma clang diagnostic ignored "-Wpacked"
-#pragma clang diagnostic ignored "-Wshadow"
-#pragma clang diagnostic ignored "-Wsign-conversion"
-#pragma clang diagnostic ignored "-Wswitch-enum"
-#pragma clang diagnostic ignored "-Wundefined-func-template"
-#pragma clang diagnostic ignored "-Wunused-template"
-#pragma clang diagnostic ignored "-Wweak-vtables"
-#include <pdx/default_transport/client_channel.h>
-#include <pdx/default_transport/client_channel_factory.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/bufferhub_rpc.h>
-#pragma clang diagnostic pop
-
 #include <poll.h>
 
 #include <android-base/unique_fd.h>
+#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
+#include <log/log.h>
 #include <ui/BufferHubBuffer.h>
 #include <ui/BufferHubDefs.h>
+#include <utils/Trace.h>
 
-using android::base::unique_fd;
-using android::dvr::BufferTraits;
-using android::dvr::DetachedBufferRPC;
-using android::dvr::NativeHandleWrapper;
-
-// TODO(b/112338294): Remove PDX dependencies from libui.
-using android::pdx::LocalChannelHandle;
-using android::pdx::LocalHandle;
-using android::pdx::Status;
-using android::pdx::default_transport::ClientChannel;
-using android::pdx::default_transport::ClientChannelFactory;
+using ::android::base::unique_fd;
+using ::android::BufferHubDefs::AnyClientAcquired;
+using ::android::BufferHubDefs::AnyClientGained;
+using ::android::BufferHubDefs::IsClientAcquired;
+using ::android::BufferHubDefs::IsClientGained;
+using ::android::BufferHubDefs::IsClientPosted;
+using ::android::BufferHubDefs::IsClientReleased;
+using ::android::frameworks::bufferhub::V1_0::BufferHubStatus;
+using ::android::frameworks::bufferhub::V1_0::BufferTraits;
+using ::android::frameworks::bufferhub::V1_0::IBufferClient;
+using ::android::frameworks::bufferhub::V1_0::IBufferHub;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::graphics::common::V1_2::HardwareBufferDescription;
 
 namespace android {
 
-namespace {
-
-// TODO(b/112338294): Remove this string literal after refactoring BufferHub
-// to use Binder.
-static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
-
-using BufferHubDefs::AnyClientAcquired;
-using BufferHubDefs::AnyClientGained;
-using BufferHubDefs::IsClientAcquired;
-using BufferHubDefs::IsClientGained;
-using BufferHubDefs::IsClientPosted;
-using BufferHubDefs::IsClientReleased;
-using BufferHubDefs::kHighBitsMask;
-
-} // namespace
-
-BufferHubClient::BufferHubClient() : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
-
-BufferHubClient::BufferHubClient(LocalChannelHandle mChannelHandle)
-      : Client(ClientChannel::Create(std::move(mChannelHandle))) {}
-
-BufferHubClient::~BufferHubClient() {}
-
-bool BufferHubClient::IsValid() const {
-    return IsConnected() && GetChannelHandle().valid();
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Create(uint32_t width, uint32_t height,
+                                                         uint32_t layerCount, uint32_t format,
+                                                         uint64_t usage, size_t userMetadataSize) {
+    auto buffer = std::unique_ptr<BufferHubBuffer>(
+            new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
+    return buffer->IsValid() ? std::move(buffer) : nullptr;
 }
 
-LocalChannelHandle BufferHubClient::TakeChannelHandle() {
-    if (IsConnected()) {
-        return std::move(GetChannelHandle());
-    } else {
-        return {};
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Import(const native_handle_t* token) {
+    if (token == nullptr) {
+        ALOGE("%s: token cannot be nullptr!", __FUNCTION__);
+        return nullptr;
     }
+
+    auto buffer = std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(token));
+    return buffer->IsValid() ? std::move(buffer) : nullptr;
 }
 
 BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
-                                 uint32_t format, uint64_t usage, size_t mUserMetadataSize) {
+                                 uint32_t format, uint64_t usage, size_t userMetadataSize) {
     ATRACE_CALL();
-    ALOGD("%s: width=%u height=%u layerCount=%u, format=%u usage=%" PRIx64 " mUserMetadataSize=%zu",
-          __FUNCTION__, width, height, layerCount, format, usage, mUserMetadataSize);
+    ALOGD("%s: width=%u height=%u layerCount=%u, format=%u "
+          "usage=%" PRIx64 " mUserMetadataSize=%zu",
+          __FUNCTION__, width, height, layerCount, format, usage, userMetadataSize);
 
-    auto status =
-            mClient.InvokeRemoteMethod<DetachedBufferRPC::Create>(width, height, layerCount, format,
-                                                                  usage, mUserMetadataSize);
-    if (!status) {
-        ALOGE("%s: Failed to create detached buffer: %s", __FUNCTION__,
-              status.GetErrorMessage().c_str());
-        mClient.Close(-status.error());
+    sp<IBufferHub> bufferhub = IBufferHub::getService();
+    if (bufferhub.get() == nullptr) {
+        ALOGE("%s: BufferHub service not found!", __FUNCTION__);
+        return;
     }
 
-    const int ret = ImportGraphicBuffer();
-    if (ret < 0) {
-        ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-ret));
-        mClient.Close(ret);
+    AHardwareBuffer_Desc aDesc = {width, height,         layerCount,   format,
+                                  usage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+    HardwareBufferDescription desc;
+    memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+    BufferHubStatus ret;
+    sp<IBufferClient> client;
+    BufferTraits bufferTraits;
+    IBufferHub::allocateBuffer_cb alloc_cb = [&](const auto& status, const auto& outClient,
+                                                 const auto& traits) {
+        ret = status;
+        client = std::move(outClient);
+        bufferTraits = std::move(traits);
+    };
+
+    if (!bufferhub->allocateBuffer(desc, static_cast<uint32_t>(userMetadataSize), alloc_cb)
+                 .isOk()) {
+        ALOGE("%s: allocateBuffer transaction failed!", __FUNCTION__);
+        return;
+    } else if (ret != BufferHubStatus::NO_ERROR) {
+        ALOGE("%s: allocateBuffer failed with error %u.", __FUNCTION__, ret);
+        return;
+    } else if (client == nullptr) {
+        ALOGE("%s: allocateBuffer got null BufferClient.", __FUNCTION__);
+        return;
+    }
+
+    const int importRet = initWithBufferTraits(bufferTraits);
+    if (importRet < 0) {
+        ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
+        client->close();
+    }
+    mBufferClient = std::move(client);
+}
+
+BufferHubBuffer::BufferHubBuffer(const native_handle_t* token) {
+    sp<IBufferHub> bufferhub = IBufferHub::getService();
+    if (bufferhub.get() == nullptr) {
+        ALOGE("%s: BufferHub service not found!", __FUNCTION__);
+        return;
+    }
+
+    BufferHubStatus ret;
+    sp<IBufferClient> client;
+    BufferTraits bufferTraits;
+    IBufferHub::importBuffer_cb import_cb = [&](const auto& status, const auto& outClient,
+                                                const auto& traits) {
+        ret = status;
+        client = std::move(outClient);
+        bufferTraits = std::move(traits);
+    };
+
+    // hidl_handle(native_handle_t*) simply creates a raw pointer reference withouth ownership
+    // transfer.
+    if (!bufferhub->importBuffer(hidl_handle(token), import_cb).isOk()) {
+        ALOGE("%s: importBuffer transaction failed!", __FUNCTION__);
+        return;
+    } else if (ret != BufferHubStatus::NO_ERROR) {
+        ALOGE("%s: importBuffer failed with error %u.", __FUNCTION__, ret);
+        return;
+    } else if (client == nullptr) {
+        ALOGE("%s: importBuffer got null BufferClient.", __FUNCTION__);
+        return;
+    }
+
+    const int importRet = initWithBufferTraits(bufferTraits);
+    if (importRet < 0) {
+        ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
+        client->close();
+    }
+    mBufferClient = std::move(client);
+}
+
+BufferHubBuffer::~BufferHubBuffer() {
+    // Close buffer client to avoid possible race condition: user could first duplicate and hold
+    // token with the original buffer gone, and then try to import the token. The close function
+    // will explicitly invalidate the token to avoid this.
+    if (mBufferClient != nullptr) {
+        if (!mBufferClient->close().isOk()) {
+            ALOGE("%s: close BufferClient transaction failed!", __FUNCTION__);
+        }
     }
 }
 
-BufferHubBuffer::BufferHubBuffer(LocalChannelHandle mChannelHandle)
-      : mClient(std::move(mChannelHandle)) {
-    const int ret = ImportGraphicBuffer();
-    if (ret < 0) {
-        ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-ret));
-        mClient.Close(ret);
-    }
-}
-
-int BufferHubBuffer::ImportGraphicBuffer() {
+int BufferHubBuffer::initWithBufferTraits(const BufferTraits& bufferTraits) {
     ATRACE_CALL();
 
-    auto status = mClient.InvokeRemoteMethod<DetachedBufferRPC::Import>();
-    if (!status) {
-        ALOGE("%s: Failed to import GraphicBuffer: %s", __FUNCTION__,
-              status.GetErrorMessage().c_str());
-        return -status.error();
+    if (bufferTraits.bufferInfo.getNativeHandle() == nullptr) {
+        ALOGE("%s: missing buffer info handle.", __FUNCTION__);
+        return -EINVAL;
     }
 
-    BufferTraits<LocalHandle> bufferTraits = status.take();
-    if (bufferTraits.id() < 0) {
-        ALOGE("%s: Received an invalid id!", __FUNCTION__);
-        return -EIO;
+    if (bufferTraits.bufferHandle.getNativeHandle() == nullptr) {
+        ALOGE("%s: missing gralloc handle.", __FUNCTION__);
+        return -EINVAL;
     }
 
-    // Stash the buffer id to replace the value in mId.
-    const int bufferId = bufferTraits.id();
+    int bufferId = bufferTraits.bufferInfo->data[1];
+    if (bufferId < 0) {
+        ALOGE("%s: Received an invalid (negative) id!", __FUNCTION__);
+        return -EINVAL;
+    }
 
-    // Import the metadata.
-    LocalHandle metadataHandle = bufferTraits.take_metadata_handle();
-    unique_fd metadataFd(metadataHandle.Release());
-    mMetadata = BufferHubMetadata::Import(std::move(metadataFd));
+    uint32_t clientBitMask;
+    memcpy(&clientBitMask, &bufferTraits.bufferInfo->data[2], sizeof(clientBitMask));
+    if (clientBitMask == 0U) {
+        ALOGE("%s: Received a invalid client state mask!", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    // Import the metadata. Dup since hidl_handle owns the fd
+    unique_fd ashmemFd(dup(bufferTraits.bufferInfo->data[0]));
+    mMetadata = BufferHubMetadata::Import(std::move(ashmemFd));
 
     if (!mMetadata.IsValid()) {
         ALOGE("%s: invalid metadata.", __FUNCTION__);
-        return -ENOMEM;
+        return -EINVAL;
     }
 
-    if (mMetadata.metadata_size() != bufferTraits.metadata_size()) {
-        ALOGE("%s: metadata buffer too small: %zu, expected: %" PRIu64 ".", __FUNCTION__,
-              mMetadata.metadata_size(), bufferTraits.metadata_size());
-        return -ENOMEM;
+    uint32_t userMetadataSize;
+    memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[3], sizeof(userMetadataSize));
+    if (mMetadata.user_metadata_size() != userMetadataSize) {
+        ALOGE("%s: user metadata size not match: expected %u, actual %zu.", __FUNCTION__,
+              userMetadataSize, mMetadata.user_metadata_size());
+        return -EINVAL;
     }
 
-    size_t metadataSize = static_cast<size_t>(bufferTraits.metadata_size());
+    size_t metadataSize = static_cast<size_t>(mMetadata.metadata_size());
     if (metadataSize < BufferHubDefs::kMetadataHeaderSize) {
         ALOGE("%s: metadata too small: %zu", __FUNCTION__, metadataSize);
         return -EINVAL;
@@ -178,24 +218,14 @@
 
     // Import the buffer: We only need to hold on the native_handle_t here so that
     // GraphicBuffer instance can be created in future.
-    mBufferHandle = bufferTraits.take_buffer_handle();
+    mBufferHandle = std::move(bufferTraits.bufferHandle);
+    memcpy(&mBufferDesc, &bufferTraits.bufferDesc, sizeof(AHardwareBuffer_Desc));
 
-    // 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();
+    mClientStateMask = clientBitMask;
 
     // TODO(b/112012161) Set up shared fences.
-    ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, id(),
+    ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, mId,
           buffer_state_->load(std::memory_order_acquire));
     return 0;
 }
@@ -225,7 +255,7 @@
 
 int BufferHubBuffer::Post() {
     uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
-    uint32_t updated_buffer_state = (~mClientStateMask) & kHighBitsMask;
+    uint32_t updated_buffer_state = (~mClientStateMask) & BufferHubDefs::kHighBitsMask;
     do {
         if (!IsClientGained(current_buffer_state, mClientStateMask)) {
             ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
@@ -283,24 +313,42 @@
     return 0;
 }
 
-int BufferHubBuffer::Poll(int timeoutMs) {
-    ATRACE_CALL();
-
-    pollfd p = {mClient.event_fd(), POLLIN, 0};
-    return poll(&p, 1, timeoutMs);
+bool BufferHubBuffer::IsValid() const {
+    // TODO(b/68770788): check eventFd once implemented
+    return mBufferHandle.getNativeHandle() != nullptr && mId >= 0 && mClientStateMask != 0U &&
+            mMetadata.IsValid() && mBufferClient != nullptr;
 }
 
-Status<LocalChannelHandle> BufferHubBuffer::Duplicate() {
-    ATRACE_CALL();
-    ALOGD("%s: id=%d.", __FUNCTION__, mId);
+// TODO(b/68770788): implement Poll() once we have event fd
+int BufferHubBuffer::Poll(int /* timeoutMs */) {
+    return -ENOSYS;
+}
 
-    auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
-
-    if (!statusOrHandle.ok()) {
-        ALOGE("%s: Failed to duplicate buffer (id=%d): %s.", __FUNCTION__, mId,
-              statusOrHandle.GetErrorMessage().c_str());
+native_handle_t* BufferHubBuffer::Duplicate() {
+    if (mBufferClient == nullptr) {
+        ALOGE("%s: missing BufferClient!", __FUNCTION__);
+        return nullptr;
     }
-    return statusOrHandle;
+
+    hidl_handle token;
+    BufferHubStatus ret;
+    IBufferClient::duplicate_cb dup_cb = [&](const auto& outToken, const auto& status) {
+        token = std::move(outToken);
+        ret = status;
+    };
+
+    if (!mBufferClient->duplicate(dup_cb).isOk()) {
+        ALOGE("%s: duplicate transaction failed!", __FUNCTION__);
+        return nullptr;
+    } else if (ret != BufferHubStatus::NO_ERROR) {
+        ALOGE("%s: duplicate failed with error %u.", __FUNCTION__, ret);
+        return nullptr;
+    } else if (token.getNativeHandle() == nullptr) {
+        ALOGE("%s: duplicate got null token.", __FUNCTION__);
+        return nullptr;
+    }
+
+    return native_handle_clone(token.getNativeHandle());
 }
 
 } // namespace android
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index 90dd391..44dfa95 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -17,73 +17,43 @@
 #ifndef ANDROID_BUFFER_HUB_BUFFER_H_
 #define ANDROID_BUFFER_HUB_BUFFER_H_
 
-// We would eliminate the clang warnings introduced by libdpx.
-// TODO(b/112338294): Remove those once BufferHub moved to use Binder
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
-#pragma clang diagnostic ignored "-Wgnu-case-range"
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
-#pragma clang diagnostic ignored "-Wnested-anon-types"
-#pragma clang diagnostic ignored "-Wpacked"
-#pragma clang diagnostic ignored "-Wshadow"
-#pragma clang diagnostic ignored "-Wsign-conversion"
-#pragma clang diagnostic ignored "-Wswitch-enum"
-#pragma clang diagnostic ignored "-Wundefined-func-template"
-#pragma clang diagnostic ignored "-Wunused-template"
-#pragma clang diagnostic ignored "-Wweak-vtables"
-#include <pdx/client.h>
-#include <private/dvr/native_handle_wrapper.h>
-#pragma clang diagnostic pop
-
+#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
 #include <android/hardware_buffer.h>
+#include <cutils/native_handle.h>
 #include <ui/BufferHubDefs.h>
 #include <ui/BufferHubMetadata.h>
 
 namespace android {
 
-class BufferHubClient : public pdx::Client {
-public:
-    BufferHubClient();
-    virtual ~BufferHubClient();
-    explicit BufferHubClient(pdx::LocalChannelHandle mChannelHandle);
-
-    bool IsValid() const;
-    pdx::LocalChannelHandle TakeChannelHandle();
-
-    using pdx::Client::Close;
-    using pdx::Client::event_fd;
-    using pdx::Client::GetChannel;
-    using pdx::Client::InvokeRemoteMethod;
-};
-
 class BufferHubBuffer {
 public:
-    // Allocates a standalone BufferHubBuffer not associated with any producer consumer set.
+    // Allocates a standalone BufferHubBuffer.
     static std::unique_ptr<BufferHubBuffer> Create(uint32_t width, uint32_t height,
                                                    uint32_t layerCount, uint32_t format,
-                                                   uint64_t usage, size_t userMetadataSize) {
-        return std::unique_ptr<BufferHubBuffer>(
-                new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
-    }
+                                                   uint64_t usage, size_t userMetadataSize);
 
-    // Imports the given channel handle to a BufferHubBuffer, taking ownership.
-    static std::unique_ptr<BufferHubBuffer> Import(pdx::LocalChannelHandle mChannelHandle) {
-        return std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(std::move(mChannelHandle)));
-    }
+    // Imports the given token to a BufferHubBuffer. Not taking ownership of the token. Caller
+    // should close and destroy the token after calling this function regardless of output.
+    // TODO(b/122543147): use a movable wrapper for token
+    static std::unique_ptr<BufferHubBuffer> Import(const native_handle_t* token);
 
     BufferHubBuffer(const BufferHubBuffer&) = delete;
     void operator=(const BufferHubBuffer&) = delete;
 
+    virtual ~BufferHubBuffer();
+
     // Gets ID of the buffer client. All BufferHubBuffer clients derived from the same buffer in
-    // bufferhubd share the same buffer id.
+    // BufferHub share the same buffer id.
     int id() const { return mId; }
 
-    // Returns the buffer description, which is guaranteed to be faithful values from bufferhubd.
+    // Returns the buffer description, which is guaranteed to be faithful values from BufferHub.
     const AHardwareBuffer_Desc& desc() const { return mBufferDesc; }
 
-    const native_handle_t* DuplicateHandle() { return mBufferHandle.DuplicateHandle(); }
+    // Duplicate the underlying Gralloc buffer handle. Caller is responsible to free the handle
+    // after use.
+    native_handle_t* DuplicateHandle() {
+        return native_handle_clone(mBufferHandle.getNativeHandle());
+    }
 
     // Returns the current value of MetadataHeader::buffer_state.
     uint32_t buffer_state() {
@@ -96,12 +66,12 @@
 
     size_t user_metadata_size() const { return mMetadata.user_metadata_size(); }
 
-    // Returns true if the buffer holds an open PDX channels towards bufferhubd.
-    bool IsConnected() const { return mClient.IsValid(); }
+    // Returns true if the BufferClient is still alive.
+    bool IsConnected() const { return mBufferClient->ping().isOk(); }
 
-    // Returns true if the buffer holds an valid native buffer handle that's availble for the client
-    // to read from and/or write into.
-    bool IsValid() const { return mBufferHandle.IsValid(); }
+    // Returns true if the buffer is valid: non-null buffer handle, valid id, valid client bit mask,
+    // valid metadata and valid buffer client
+    bool IsValid() const;
 
     // Gains the buffer for exclusive write permission. Read permission is implied once a buffer is
     // gained.
@@ -124,33 +94,27 @@
     // current cycle of the usage of the buffer.
     int Release();
 
-    // Returns the event mask for all the events that are pending on this buffer (see sys/poll.h for
-    // all possible bits).
-    pdx::Status<int> GetEventMask(int events) {
-        if (auto* channel = mClient.GetChannel()) {
-            return channel->GetEventMask(events);
-        } else {
-            return pdx::ErrorStatus(EINVAL);
-        }
-    }
-
     // Polls the fd for |timeoutMs| milliseconds (-1 for infinity).
     int Poll(int timeoutMs);
 
-    // Creates a BufferHubBuffer client from an existing one. The new client will
-    // share the same underlying gralloc buffer and ashmem region for metadata.
-    pdx::Status<pdx::LocalChannelHandle> Duplicate();
+    // Creates a token that stands for this BufferHubBuffer client and could be used for Import to
+    // create another BufferHubBuffer. The new BufferHubBuffer will share the same underlying
+    // gralloc buffer and ashmem region for metadata. Note that the caller owns the token and
+    // should free it after use.
+    // Returns a valid token on success, nullptr on failure.
+    // TODO(b/122543147): use a movable wrapper for token
+    native_handle_t* Duplicate();
 
 private:
     BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
                     uint64_t usage, size_t userMetadataSize);
 
-    BufferHubBuffer(pdx::LocalChannelHandle mChannelHandle);
+    BufferHubBuffer(const native_handle_t* token);
 
-    int ImportGraphicBuffer();
+    int initWithBufferTraits(const frameworks::bufferhub::V1_0::BufferTraits& bufferTraits);
 
     // Global id for the buffer that is consistent across processes.
-    int mId = -1;
+    int mId = 0;
 
     // Client state mask of this BufferHubBuffer object. It is unique amoung all
     // clients/users of the buffer.
@@ -159,8 +123,8 @@
     // Stores ground truth of the buffer.
     AHardwareBuffer_Desc mBufferDesc;
 
-    // Wrapps the gralloc buffer handle of this buffer.
-    dvr::NativeHandleWrapper<pdx::LocalHandle> mBufferHandle;
+    // Wraps the gralloc buffer handle of this buffer.
+    hardware::hidl_handle mBufferHandle;
 
     // An ashmem-based metadata object. The same shared memory are mapped to the
     // bufferhubd daemon and all buffer clients.
@@ -170,8 +134,8 @@
     std::atomic<uint32_t>* fence_state_ = nullptr;
     std::atomic<uint32_t>* active_clients_bit_mask_ = nullptr;
 
-    // PDX backend.
-    BufferHubClient mClient;
+    // HwBinder backend
+    sp<frameworks::bufferhub::V1_0::IBufferClient> mBufferClient;
 };
 
 } // namespace android
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index a670b3c..665469e 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -31,12 +31,14 @@
 cc_test {
     name: "GraphicBuffer_test",
     header_libs: [
-        "libbufferhub_headers",
         "libdvr_headers",
         "libnativewindow_headers",
     ],
     shared_libs: [
-        "libpdx_default_transport",
+        "android.frameworks.bufferhub@1.0",
+        "libcutils",
+        "libhidlbase",
+        "libhwbinder",
         "libui",
         "libutils",
     ],
@@ -47,7 +49,6 @@
 cc_test {
     name: "BufferHub_test",
     header_libs: [
-        "libbufferhub_headers",
         "libdvr_headers",
         "libnativewindow_headers",
     ],
@@ -60,7 +61,6 @@
         "libhidlbase",
         "libhwbinder",
         "liblog",
-        "libpdx_default_transport",
         "libui",
         "libutils"
     ],
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 69b9590..cd744cd 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -16,10 +16,9 @@
 
 #define LOG_TAG "BufferHubBufferTest"
 
-#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
-#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
 #include <android/hardware_buffer.h>
 #include <cutils/native_handle.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <hidl/ServiceManagement.h>
 #include <hwbinder/IPCThreadState.h>
@@ -29,36 +28,38 @@
 
 namespace {
 
+using ::android::BufferHubDefs::AnyClientAcquired;
+using ::android::BufferHubDefs::AnyClientGained;
+using ::android::BufferHubDefs::AnyClientPosted;
+using ::android::BufferHubDefs::IsBufferReleased;
+using ::android::BufferHubDefs::IsClientAcquired;
+using ::android::BufferHubDefs::IsClientGained;
+using ::android::BufferHubDefs::IsClientPosted;
+using ::android::BufferHubDefs::IsClientReleased;
+using ::android::BufferHubDefs::kMetadataHeaderSize;
+using ::testing::IsNull;
+using ::testing::NotNull;
+
 const int kWidth = 640;
 const int kHeight = 480;
 const int kLayerCount = 1;
 const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
 const int kUsage = 0;
-const size_t kUserMetadataSize = 0;
-
-using BufferHubDefs::AnyClientAcquired;
-using BufferHubDefs::AnyClientGained;
-using BufferHubDefs::AnyClientPosted;
-using BufferHubDefs::IsBufferReleased;
-using BufferHubDefs::IsClientAcquired;
-using BufferHubDefs::IsClientGained;
-using BufferHubDefs::IsClientPosted;
-using BufferHubDefs::IsClientReleased;
-using BufferHubDefs::kFirstClientBitMask;
-using BufferHubDefs::kMetadataHeaderSize;
-using frameworks::bufferhub::V1_0::BufferHubStatus;
-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;
+const AHardwareBuffer_Desc kDesc = {kWidth, kHeight,        kLayerCount,  kFormat,
+                                    kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+const size_t kUserMetadataSize = 1;
 
 class BufferHubBufferTest : public ::testing::Test {
 protected:
     void SetUp() override { android::hardware::ProcessState::self()->startThreadPool(); }
 };
 
+bool cmpAHardwareBufferDesc(const AHardwareBuffer_Desc& desc, const AHardwareBuffer_Desc& other) {
+    // Not comparing stride because it's unknown before allocation
+    return desc.format == other.format && desc.height == other.height &&
+            desc.layers == other.layers && desc.usage == other.usage && desc.width == other.width;
+}
+
 class BufferHubBufferStateTransitionTest : public BufferHubBufferTest {
 protected:
     void SetUp() override {
@@ -78,91 +79,126 @@
 
 void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() {
     b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
+    ASSERT_THAT(b1, NotNull());
     b1ClientMask = b1->client_state_mask();
     ASSERT_NE(b1ClientMask, 0U);
-    auto statusOrHandle = b1->Duplicate();
-    ASSERT_TRUE(statusOrHandle);
-    LocalChannelHandle h2 = statusOrHandle.take();
-    b2 = BufferHubBuffer::Import(std::move(h2));
+
+    native_handle_t* token = b1->Duplicate();
+    ASSERT_THAT(token, NotNull());
+
+    // TODO(b/122543147): use a movalbe wrapper for token
+    b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
+    ASSERT_THAT(b2, NotNull());
+
     b2ClientMask = b2->client_state_mask();
     ASSERT_NE(b2ClientMask, 0U);
     ASSERT_NE(b2ClientMask, b1ClientMask);
 }
 
-TEST_F(BufferHubBufferTest, CreateBufferHubBufferFails) {
+TEST_F(BufferHubBufferTest, CreateBufferFails) {
     // Buffer Creation will fail: BLOB format requires height to be 1.
     auto b1 = BufferHubBuffer::Create(kWidth, /*height=*/2, kLayerCount,
                                       /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage, kUserMetadataSize);
 
-    EXPECT_FALSE(b1->IsConnected());
-    EXPECT_FALSE(b1->IsValid());
+    EXPECT_THAT(b1, IsNull());
 
     // Buffer Creation will fail: user metadata size too large.
     auto b2 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                       /*userMetadataSize=*/std::numeric_limits<size_t>::max());
 
-    EXPECT_FALSE(b2->IsConnected());
-    EXPECT_FALSE(b2->IsValid());
+    EXPECT_THAT(b2, IsNull());
 
     // Buffer Creation will fail: user metadata size too large.
     const size_t userMetadataSize = std::numeric_limits<size_t>::max() - kMetadataHeaderSize;
     auto b3 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                       userMetadataSize);
 
-    EXPECT_FALSE(b3->IsConnected());
-    EXPECT_FALSE(b3->IsValid());
+    EXPECT_THAT(b3, IsNull());
 }
 
-TEST_F(BufferHubBufferTest, CreateBufferHubBuffer) {
+TEST_F(BufferHubBufferTest, CreateBuffer) {
     auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                       kUserMetadataSize);
+    ASSERT_THAT(b1, NotNull());
     EXPECT_TRUE(b1->IsConnected());
     EXPECT_TRUE(b1->IsValid());
-    EXPECT_NE(b1->id(), 0);
+    EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), kDesc));
+    EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
 }
 
-TEST_F(BufferHubBufferTest, DuplicateBufferHubBuffer) {
+TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) {
     auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                       kUserMetadataSize);
-    int id1 = b1->id();
-    uint32_t bufferStateMask1 = b1->client_state_mask();
-    EXPECT_NE(bufferStateMask1, 0U);
+    ASSERT_THAT(b1, NotNull());
     EXPECT_TRUE(b1->IsValid());
-    EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
 
-    auto statusOrHandle = b1->Duplicate();
-    EXPECT_TRUE(statusOrHandle);
+    native_handle_t* token = b1->Duplicate();
+    EXPECT_TRUE(token);
 
     // The detached buffer should still be valid.
     EXPECT_TRUE(b1->IsConnected());
     EXPECT_TRUE(b1->IsValid());
 
-    // Gets the channel handle for the duplicated buffer.
-    LocalChannelHandle h2 = statusOrHandle.take();
-    EXPECT_TRUE(h2.valid());
+    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
 
-    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(h2));
-    EXPECT_FALSE(h2.valid());
-    ASSERT_TRUE(b2 != nullptr);
+    ASSERT_THAT(b2, NotNull());
     EXPECT_TRUE(b2->IsValid());
-    EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
 
-    int id2 = b2->id();
-    uint32_t bufferStateMask2 = b2->client_state_mask();
-    EXPECT_NE(bufferStateMask2, 0U);
+    EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), b2->desc()));
+    EXPECT_EQ(b1->user_metadata_size(), b2->user_metadata_size());
 
     // These two buffer instances are based on the same physical buffer under the
     // hood, so they should share the same id.
-    EXPECT_EQ(id1, id2);
+    EXPECT_EQ(b1->id(), b2->id());
     // We use client_state_mask() to tell those two instances apart.
-    EXPECT_NE(bufferStateMask1, bufferStateMask2);
+    EXPECT_NE(b1->client_state_mask(), b2->client_state_mask());
 
     // Both buffer instances should be in released state currently.
     EXPECT_TRUE(IsBufferReleased(b1->buffer_state()));
     EXPECT_TRUE(IsBufferReleased(b2->buffer_state()));
+}
 
-    // TODO(b/112338294): rewrite test after migration
-    return;
+TEST_F(BufferHubBufferTest, ImportFreedBuffer) {
+    auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+                                      kUserMetadataSize);
+    ASSERT_THAT(b1, NotNull());
+    EXPECT_TRUE(b1->IsValid());
+
+    native_handle_t* token = b1->Duplicate();
+    EXPECT_TRUE(token);
+
+    // Explicitly destroy b1. Backend buffer should be freed and token becomes invalid
+    b1.reset();
+
+    // TODO(b/122543147): use a movalbe wrapper for token
+    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
+
+    // Import should fail with INVALID_TOKEN
+    EXPECT_THAT(b2, IsNull());
+}
+
+// nullptr must not crash the service
+TEST_F(BufferHubBufferTest, ImportNullToken) {
+    auto b1 = BufferHubBuffer::Import(nullptr);
+    EXPECT_THAT(b1, IsNull());
+}
+
+// TODO(b/118180214): remove the comment after ag/5856474 landed
+// This test has a very little chance to fail (number of existing tokens / 2 ^ 32)
+TEST_F(BufferHubBufferTest, ImportInvalidToken) {
+    native_handle_t* token = native_handle_create(/*numFds=*/0, /*numInts=*/1);
+    token->data[0] = 0;
+
+    auto b1 = BufferHubBuffer::Import(token);
+    native_handle_delete(token);
+
+    EXPECT_THAT(b1, IsNull());
 }
 
 TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) {
@@ -357,13 +393,20 @@
     std::unique_ptr<BufferHubBuffer> b1 =
             BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                     kUserMetadataSize);
+    ASSERT_THAT(b1, NotNull());
     ASSERT_EQ(b1->Gain(), 0);
 
     // Create a consumer of the buffer and test if the consumer can acquire the
     // buffer if producer posts.
-    auto statusOrHandle = b1->Duplicate();
-    ASSERT_TRUE(statusOrHandle);
-    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(statusOrHandle.take()));
+    // TODO(b/122543147): use a movalbe wrapper for token
+    native_handle_t* token = b1->Duplicate();
+    ASSERT_TRUE(token);
+
+    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
+
+    ASSERT_THAT(b2, NotNull());
     ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
 
     ASSERT_EQ(b1->Post(), 0);
@@ -380,13 +423,20 @@
 
     // Create a consumer of the buffer and test if the consumer can acquire the
     // buffer if producer posts.
-    auto statusOrHandle = b1->Duplicate();
-    ASSERT_TRUE(statusOrHandle);
-    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(statusOrHandle.take()));
+    // TODO(b/122543147): use a movalbe wrapper for token
+    native_handle_t* token = b1->Duplicate();
+    ASSERT_TRUE(token);
+
+    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
+
+    ASSERT_THAT(b2, NotNull());
     ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
 
     EXPECT_EQ(b2->Acquire(), 0);
 }
 
 } // namespace
+
 } // namespace android
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index 81ab3ac..5b46454 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -39,7 +39,7 @@
     std::unique_ptr<BufferHubBuffer> b1 =
             BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
                                     kTestUsage, /*userMetadataSize=*/0);
-    EXPECT_NE(b1, nullptr);
+    ASSERT_NE(b1, nullptr);
     EXPECT_TRUE(b1->IsValid());
 
     sp<GraphicBuffer> gb(new GraphicBuffer(std::move(b1)));
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 487a604..ed5a992 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -5,7 +5,6 @@
 #include <private/dvr/producer_buffer.h>
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
-#include <ui/BufferHubBuffer.h>
 #include <ui/BufferHubDefs.h>
 
 #include <mutex>
@@ -20,9 +19,6 @@
     return result;                            \
   })()
 
-using android::BufferHubBuffer;
-using android::GraphicBuffer;
-using android::sp;
 using android::BufferHubDefs::AnyClientAcquired;
 using android::BufferHubDefs::AnyClientGained;
 using android::BufferHubDefs::AnyClientPosted;
@@ -31,19 +27,15 @@
 using android::BufferHubDefs::IsClientPosted;
 using android::BufferHubDefs::IsClientReleased;
 using android::BufferHubDefs::kFirstClientBitMask;
-using android::BufferHubDefs::kMetadataHeaderSize;
 using android::dvr::ConsumerBuffer;
 using android::dvr::ProducerBuffer;
-using android::pdx::LocalChannelHandle;
 using android::pdx::LocalHandle;
 using android::pdx::Status;
 
 const int kWidth = 640;
 const int kHeight = 480;
-const int kLayerCount = 1;
 const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
 const int kUsage = 0;
-const size_t kUserMetadataSize = 0;
 // Maximum number of consumers for the buffer that only has one producer in the
 // test.
 const size_t kMaxConsumerCount =
@@ -808,7 +800,7 @@
   // TODO(b/112338294) rewrite test after migration
   return;
 
-  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
+  /* std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   std::unique_ptr<ConsumerBuffer> c =
       ConsumerBuffer::Import(p->CreateConsumer());
@@ -876,49 +868,14 @@
   EXPECT_TRUE(d->IsConnected());
   EXPECT_TRUE(d->IsValid());
 
-  EXPECT_EQ(d->id(), p_id);
-}
-
-TEST_F(LibBufferHubTest, TestCreateBufferHubBufferFails) {
-  // Buffer Creation will fail: BLOB format requires height to be 1.
-  auto b1 = BufferHubBuffer::Create(kWidth, /*height=2*/ 2, kLayerCount,
-                                    /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage,
-                                    kUserMetadataSize);
-
-  EXPECT_FALSE(b1->IsConnected());
-  EXPECT_FALSE(b1->IsValid());
-
-  // Buffer Creation will fail: user metadata size too large.
-  auto b2 = BufferHubBuffer::Create(
-      kWidth, kHeight, kLayerCount, kFormat, kUsage,
-      /*user_metadata_size=*/std::numeric_limits<size_t>::max());
-
-  EXPECT_FALSE(b2->IsConnected());
-  EXPECT_FALSE(b2->IsValid());
-
-  // Buffer Creation will fail: user metadata size too large.
-  auto b3 = BufferHubBuffer::Create(
-      kWidth, kHeight, kLayerCount, kFormat, kUsage,
-      /*user_metadata_size=*/std::numeric_limits<size_t>::max() -
-          kMetadataHeaderSize);
-
-  EXPECT_FALSE(b3->IsConnected());
-  EXPECT_FALSE(b3->IsValid());
-}
-
-TEST_F(LibBufferHubTest, TestCreateBufferHubBuffer) {
-  auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
-                                    kUsage, kUserMetadataSize);
-  EXPECT_TRUE(b1->IsConnected());
-  EXPECT_TRUE(b1->IsValid());
-  EXPECT_NE(b1->id(), 0);
+  EXPECT_EQ(d->id(), p_id); */
 }
 
 TEST_F(LibBufferHubTest, TestDetach) {
   // TODO(b/112338294) rewrite test after migration
   return;
 
-  std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
+  /* std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p1.get() != nullptr);
   int p1_id = p1->id();
@@ -936,47 +893,5 @@
   EXPECT_FALSE(h1.valid());
   EXPECT_TRUE(b1->IsValid());
   int b1_id = b1->id();
-  EXPECT_EQ(b1_id, p1_id);
-}
-
-TEST_F(LibBufferHubTest, TestDuplicateBufferHubBuffer) {
-  auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
-                                    kUsage, kUserMetadataSize);
-  int b1_id = b1->id();
-  EXPECT_TRUE(b1->IsValid());
-  EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
-  EXPECT_NE(b1->client_state_mask(), 0U);
-
-  auto status_or_handle = b1->Duplicate();
-  EXPECT_TRUE(status_or_handle);
-
-  // The detached buffer should still be valid.
-  EXPECT_TRUE(b1->IsConnected());
-  EXPECT_TRUE(b1->IsValid());
-
-  // Gets the channel handle for the duplicated buffer.
-  LocalChannelHandle h2 = status_or_handle.take();
-  EXPECT_TRUE(h2.valid());
-
-  std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(h2));
-  EXPECT_FALSE(h2.valid());
-  ASSERT_TRUE(b2 != nullptr);
-  EXPECT_TRUE(b2->IsValid());
-  EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
-  EXPECT_NE(b2->client_state_mask(), 0U);
-
-  int b2_id = b2->id();
-
-  // These two buffer instances are based on the same physical buffer under the
-  // hood, so they should share the same id.
-  EXPECT_EQ(b1_id, b2_id);
-  // We use client_state_mask() to tell those two instances apart.
-  EXPECT_NE(b1->client_state_mask(), b2->client_state_mask());
-
-  // Both buffer instances should be in gained state.
-  EXPECT_TRUE(IsBufferReleased(b1->buffer_state()));
-  EXPECT_TRUE(IsBufferReleased(b2->buffer_state()));
-
-  // TODO(b/112338294) rewrite test after migration
-  return;
+  EXPECT_EQ(b1_id, p1_id); */
 }