Merge changes I45704b34,I28428e32,Iaba7b766,Icfe01188

* changes:
  renderengine: move away from "new"
  renderengine: use std::unordered_map in ProgramCache
  renderengine: remove hasExtension from GLExtensions
  renderengine: remove unused Program::dumpShader
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
new file mode 100644
index 0000000..11b1e8e
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_auto_utils.h
+ * @brief These objects provide a more C++-like thin interface to the .
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+#include <android/binder_parcel.h>
+#include <android/binder_status.h>
+
+#ifdef __cplusplus
+
+#include <cstddef>
+
+namespace android {
+
+/**
+ * Represents one strong pointer to an AIBinder object.
+ */
+class AutoAIBinder {
+public:
+    /**
+     * Takes ownership of one strong refcount of binder.
+     */
+    explicit AutoAIBinder(AIBinder* binder = nullptr) : mBinder(binder) {}
+
+    /**
+     * Convenience operator for implicitly constructing an AutoAIBinder from nullptr. This is not
+     * explicit because it is not taking ownership of anything.
+     */
+    AutoAIBinder(std::nullptr_t) : AutoAIBinder() {}
+
+    /**
+     * This will delete the underlying object if it exists. See operator=.
+     */
+    AutoAIBinder(const AutoAIBinder& other) { *this = other; }
+
+    /**
+     * This deletes the underlying object if it exists. See set.
+     */
+    ~AutoAIBinder() { set(nullptr); }
+
+    /**
+     * This takes ownership of a binder from another AIBinder object but it does not affect the
+     * ownership of that other object.
+     */
+    AutoAIBinder& operator=(const AutoAIBinder& other) {
+        AIBinder_incStrong(other.mBinder);
+        set(other.mBinder);
+        return *this;
+    }
+
+    /**
+     * Takes ownership of one strong refcount of binder
+     */
+    void set(AIBinder* binder) {
+        if (mBinder != nullptr) AIBinder_decStrong(mBinder);
+        mBinder = binder;
+    }
+
+    /**
+     * This returns the underlying binder object for transactions. If it is used to create another
+     * AutoAIBinder object, it should first be incremented.
+     */
+    AIBinder* get() const { return mBinder; }
+
+    /**
+     * This allows the value in this class to be set from beneath it. If you call this method and
+     * then change the value of T*, you must take ownership of the value you are replacing and add
+     * ownership to the object that is put in here.
+     *
+     * Recommended use is like this:
+     *   AutoAIBinder a;  // will be nullptr
+     *   SomeInitFunction(a.getR());  // value is initialized with refcount
+     *
+     * Other usecases are discouraged.
+     *
+     */
+    AIBinder** getR() { return &mBinder; }
+
+private:
+    AIBinder* mBinder = nullptr;
+};
+
+/**
+ * This baseclass owns a single object, used to make various classes RAII.
+ */
+template <typename T, void (*Destroy)(T*)>
+class AutoA {
+public:
+    /**
+     * Takes ownership of t.
+     */
+    explicit AutoA(T* t = nullptr) : mT(t) {}
+
+    /**
+     * This deletes the underlying object if it exists. See set.
+     */
+    ~AutoA() { set(nullptr); }
+
+    /**
+     * Takes ownership of t.
+     */
+    void set(T* t) {
+        Destroy(mT);
+        mT = t;
+    }
+
+    /**
+     * This returns the underlying object to be modified but does not affect ownership.
+     */
+    T* get() { return mT; }
+
+    /**
+     * This returns the const underlying object but does not affect ownership.
+     */
+    const T* get() const { return mT; }
+
+    /**
+     * This allows the value in this class to be set from beneath it. If you call this method and
+     * then change the value of T*, you must take ownership of the value you are replacing and add
+     * ownership to the object that is put in here.
+     *
+     * Recommended use is like this:
+     *   AutoA<T> a; // will be nullptr
+     *   SomeInitFunction(a.getR()); // value is initialized with refcount
+     *
+     * Other usecases are discouraged.
+     *
+     */
+    T** getR() { return &mT; }
+
+    // copy-constructing, or move/copy assignment is disallowed
+    AutoA(const AutoA&) = delete;
+    AutoA& operator=(const AutoA&) = delete;
+    AutoA& operator=(AutoA&&) = delete;
+
+    // move-constructing is okay
+    AutoA(AutoA&&) = default;
+
+private:
+    T* mT;
+};
+
+/**
+ * Convenience wrapper. See AParcel.
+ */
+class AutoAParcel : public AutoA<AParcel, AParcel_delete> {
+public:
+    /**
+     * Takes ownership of a.
+     */
+    explicit AutoAParcel(AParcel* a = nullptr) : AutoA(a) {}
+    ~AutoAParcel() {}
+    AutoAParcel(AutoAParcel&&) = default;
+};
+
+/**
+ * Convenience wrapper. See AStatus.
+ */
+class AutoAStatus : public AutoA<AStatus, AStatus_delete> {
+public:
+    /**
+     * Takes ownership of a.
+     */
+    explicit AutoAStatus(AStatus* a = nullptr) : AutoA(a) {}
+    ~AutoAStatus() {}
+    AutoAStatus(AutoAStatus&&) = default;
+
+    /**
+     * See AStatus_isOk.
+     */
+    bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+};
+
+/**
+ * Convenience wrapper. See AIBinder_DeathRecipient.
+ */
+class AutoAIBinder_DeathRecipient
+      : public AutoA<AIBinder_DeathRecipient, AIBinder_DeathRecipient_delete> {
+public:
+    /**
+     * Takes ownership of a.
+     */
+    explicit AutoAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr) : AutoA(a) {}
+    ~AutoAIBinder_DeathRecipient() {}
+    AutoAIBinder_DeathRecipient(AutoAIBinder_DeathRecipient&&) = default;
+};
+
+/**
+ * Convenience wrapper. See AIBinder_Weak.
+ */
+class AutoAIBinder_Weak : public AutoA<AIBinder_Weak, AIBinder_Weak_delete> {
+public:
+    /**
+     * Takes ownership of a.
+     */
+    explicit AutoAIBinder_Weak(AIBinder_Weak* a = nullptr) : AutoA(a) {}
+    ~AutoAIBinder_Weak() {}
+    AutoAIBinder_Weak(AutoAIBinder_Weak&&) = default;
+
+    /**
+     * See AIBinder_Weak_promote.
+     */
+    AutoAIBinder promote() { return AutoAIBinder(AIBinder_Weak_promote(get())); }
+};
+
+} // namespace android
+
+#endif // __cplusplus
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
new file mode 100644
index 0000000..d7e1566
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_interface_utils.h
+ * @brief This provides common C++ classes for common operations and as base classes for C++
+ * interfaces.
+ */
+
+#pragma once
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+
+#ifdef __cplusplus
+
+#include <memory>
+#include <mutex>
+
+namespace android {
+
+// analog using std::shared_ptr for RefBase-like semantics
+class SharedRefBase {
+public:
+    SharedRefBase() {}
+    virtual ~SharedRefBase() {}
+
+    std::shared_ptr<SharedRefBase> ref() {
+        std::shared_ptr<SharedRefBase> thiz = mThis.lock();
+
+        std::call_once(mFlagThis, [&]() { mThis = thiz = std::shared_ptr<SharedRefBase>(this); });
+
+        return thiz;
+    }
+
+    template <typename CHILD>
+    std::shared_ptr<CHILD> ref() {
+        return std::static_pointer_cast<CHILD>(ref());
+    }
+
+private:
+    std::once_flag mFlagThis;
+    std::weak_ptr<SharedRefBase> mThis;
+};
+
+// wrapper analog to IInterface
+class ICInterface : public SharedRefBase {
+public:
+    ICInterface() {}
+    virtual ~ICInterface() {}
+
+    // This either returns the single existing implementation or creates a new implementation.
+    virtual AutoAIBinder asBinder() = 0;
+};
+
+// wrapper analog to BnInterface
+template <typename INTERFACE>
+class BnCInterface : public INTERFACE {
+public:
+    BnCInterface() {}
+    virtual ~BnCInterface() {}
+
+    AutoAIBinder asBinder() override;
+
+protected:
+    // This function should only be called by asBinder. Otherwise, there is a possibility of
+    // multiple AIBinder* objects being created for the same instance of an object.
+    virtual AutoAIBinder createBinder() = 0;
+
+private:
+    std::mutex mMutex; // for asBinder
+    AutoAIBinder_Weak mWeakBinder;
+};
+
+// wrapper analog to BpInterfae
+template <typename INTERFACE>
+class BpCInterface : public INTERFACE {
+public:
+    BpCInterface(const AutoAIBinder& binder) : mBinder(binder) {}
+    virtual ~BpCInterface() {}
+
+    AutoAIBinder asBinder() override;
+
+private:
+    AutoAIBinder mBinder;
+};
+
+template <typename INTERFACE>
+AutoAIBinder BnCInterface<INTERFACE>::asBinder() {
+    std::lock_guard<std::mutex> l(mMutex);
+
+    AutoAIBinder binder;
+    if (mWeakBinder.get() != nullptr) {
+        binder.set(AIBinder_Weak_promote(mWeakBinder.get()));
+    }
+    if (binder.get() == nullptr) {
+        binder = createBinder();
+        mWeakBinder.set(AIBinder_Weak_new(binder.get()));
+    }
+
+    return binder;
+}
+
+template <typename INTERFACE>
+AutoAIBinder BpCInterface<INTERFACE>::asBinder() {
+    return mBinder;
+}
+
+#endif // __cplusplus
+
+} // namespace android
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index a3800da..0e97b50 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -88,6 +88,43 @@
 binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status)
         __INTRODUCED_IN(29);
 
+/**
+ * Writes string value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length)
+        __INTRODUCED_IN(29);
+
+/**
+ * This is called to allocate a buffer
+ *
+ * The length here includes the space required to insert a '\0' for a properly formed c-str. If the
+ * buffer returned from this function is retStr, it will be filled by AParcel_readString with the
+ * data from the remote process, and it will be filled such that retStr[length] == '\0'.
+ *
+ * If allocation fails, null should be returned.
+ */
+typedef void* (*AParcel_string_reallocator)(void* stringData, size_t length);
+
+/**
+ * This is called to get the buffer from a stringData object.
+ */
+typedef char* (*AParcel_string_getter)(void* stringData);
+
+/**
+ * Reads and allocates string value from the next location in a non-null parcel.
+ *
+ * Data is passed to the string allocator once the string size is known. This data should be used to
+ * point to some kind of string data. For instance, it could be a char*, and the string allocator
+ * could be realloc. Then the getter would simply be a cast to char*. In more complicated cases,
+ * stringData could be a structure containing additional string data.
+ *
+ * If this function returns a success, the buffer returned by allocator when passed stringData will
+ * contain a null-terminated c-str read from the binder.
+ */
+binder_status_t AParcel_readString(const AParcel* parcel, AParcel_string_reallocator reallocator,
+                                   AParcel_string_getter getter, void** stringData)
+        __INTRODUCED_IN(29);
+
 // @START
 /**
  * Writes int32_t value to the next location in a non-null parcel.
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
new file mode 100644
index 0000000..7b261d6
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_parcel_utils.h
+ * @brief A collection of helper wrappers for AParcel.
+ */
+
+#pragma once
+
+#include <android/binder_parcel.h>
+
+#ifdef __cplusplus
+
+#include <string>
+
+/**
+ * Takes a std::string and reallocates it to the specified length. For use with AParcel_readString.
+ * See use below in AParcel_readString.
+ */
+static inline void* AParcel_std_string_reallocator(void* stringData, size_t length) {
+    std::string* str = static_cast<std::string*>(stringData);
+    str->resize(length - 1);
+    return stringData;
+}
+
+/**
+ * Takes a std::string and returns the inner char*.
+ */
+static inline char* AParcel_std_string_getter(void* stringData) {
+    std::string* str = static_cast<std::string*>(stringData);
+    return &(*str)[0];
+}
+
+/**
+ * Convenience API for writing a std::string.
+ */
+static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
+    return AParcel_writeString(parcel, str.c_str(), str.size());
+}
+
+/**
+ * Convenience API for reading a std::string.
+ */
+static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
+    void* stringData = static_cast<void*>(str);
+    return AParcel_readString(parcel, AParcel_std_string_reallocator, AParcel_std_string_getter,
+                              &stringData);
+}
+
+#endif // __cplusplus
+
+/** @} */
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 4f486c9..2a1bff1 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -32,6 +32,7 @@
     AParcel_readInt64;
     AParcel_readNullableStrongBinder;
     AParcel_readStatusHeader;
+    AParcel_readString;
     AParcel_readStrongBinder;
     AParcel_readUint32;
     AParcel_readUint64;
@@ -43,6 +44,7 @@
     AParcel_writeInt32;
     AParcel_writeInt64;
     AParcel_writeStatusHeader;
+    AParcel_writeString;
     AParcel_writeStrongBinder;
     AParcel_writeUint32;
     AParcel_writeUint64;
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 385e898..3e03e90 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -20,7 +20,11 @@
 #include "ibinder_internal.h"
 #include "status_internal.h"
 
+#include <limits>
+
+#include <android-base/logging.h>
 #include <binder/Parcel.h>
+#include <utils/Unicode.h>
 
 using ::android::IBinder;
 using ::android::Parcel;
@@ -69,6 +73,67 @@
     return ret;
 }
 
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length) {
+    const uint8_t* str8 = (uint8_t*)string;
+
+    const ssize_t len16 = utf8_to_utf16_length(str8, length);
+
+    if (len16 < 0 || len16 >= std::numeric_limits<int32_t>::max()) {
+        LOG(WARNING) << __func__ << ": Invalid string length: " << len16;
+        return STATUS_BAD_VALUE;
+    }
+
+    status_t err = parcel->get()->writeInt32(len16);
+    if (err) {
+        return PruneStatusT(err);
+    }
+
+    void* str16 = parcel->get()->writeInplace((len16 + 1) * sizeof(char16_t));
+    if (str16 == nullptr) {
+        return STATUS_NO_MEMORY;
+    }
+
+    utf8_to_utf16(str8, length, (char16_t*)str16, (size_t)len16 + 1);
+
+    return STATUS_OK;
+}
+
+binder_status_t AParcel_readString(const AParcel* parcel, AParcel_string_reallocator reallocator,
+                                   AParcel_string_getter getter, void** stringData) {
+    size_t len16;
+    const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
+
+    if (str16 == nullptr) {
+        LOG(WARNING) << __func__ << ": Failed to read string in place.";
+        return STATUS_UNEXPECTED_NULL;
+    }
+
+    ssize_t len8;
+
+    if (len16 == 0) {
+        len8 = 1;
+    } else {
+        len8 = utf16_to_utf8_length(str16, len16) + 1;
+    }
+
+    if (len8 <= 0 || len8 >= std::numeric_limits<int32_t>::max()) {
+        LOG(WARNING) << __func__ << ": Invalid string length: " << len8;
+        return STATUS_BAD_VALUE;
+    }
+
+    *stringData = reallocator(*stringData, len8);
+    char* str8 = getter(*stringData);
+
+    if (str8 == nullptr) {
+        LOG(WARNING) << __func__ << ": AParcel_string_allocator failed to allocate.";
+        return STATUS_NO_MEMORY;
+    }
+
+    utf16_to_utf8(str16, len16, str8, len8);
+
+    return STATUS_OK;
+}
+
 // See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
 // libbinder and this library.
 // @START
diff --git a/libs/binder/ndk/status.cpp b/libs/binder/ndk/status.cpp
index e0ae469..1f75b0b 100644
--- a/libs/binder/ndk/status.cpp
+++ b/libs/binder/ndk/status.cpp
@@ -27,11 +27,11 @@
 }
 
 AStatus* AStatus_fromExceptionCode(binder_exception_t exception) {
-    return new AStatus(Status::fromExceptionCode(exception));
+    return new AStatus(Status::fromExceptionCode(PruneException(exception)));
 }
 
 AStatus* AStatus_fromExceptionCodeWithMessage(binder_exception_t exception, const char* message) {
-    return new AStatus(Status::fromExceptionCode(exception, message));
+    return new AStatus(Status::fromExceptionCode(PruneException(exception), message));
 }
 
 AStatus* AStatus_fromServiceSpecificError(int32_t serviceSpecific) {
@@ -43,7 +43,7 @@
 }
 
 AStatus* AStatus_fromStatus(binder_status_t status) {
-    return new AStatus(Status::fromStatusT(status));
+    return new AStatus(Status::fromStatusT(PruneStatusT(status)));
 }
 
 bool AStatus_isOk(const AStatus* status) {
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
index 3fc096a..22bf1e5 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -131,3 +131,6 @@
     EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName2));
     EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
 }
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 93091e3..d174d35 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -14,7 +14,6 @@
 
 sourceFiles = [
     "buffer_hub_base.cpp",
-    "buffer_hub_client.cpp",
     "buffer_hub_metadata.cpp",
     "buffer_hub_rpc.cpp",
     "consumer_buffer.cpp",
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 11b2211..cf4a0e9 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -21,9 +21,9 @@
 
 using android::GraphicBuffer;
 using android::sp;
-using android::dvr::BufferConsumer;
-using android::dvr::BufferProducer;
+using android::dvr::ConsumerBuffer;
 using android::dvr::DetachedBuffer;
+using android::dvr::ProducerBuffer;
 using android::dvr::BufferHubDefs::IsBufferAcquired;
 using android::dvr::BufferHubDefs::IsBufferGained;
 using android::dvr::BufferHubDefs::IsBufferPosted;
@@ -48,15 +48,15 @@
 using LibBufferHubTest = ::testing::Test;
 
 TEST_F(LibBufferHubTest, TestBasicUsage) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
   // Check that consumers can spawn other consumers.
-  std::unique_ptr<BufferConsumer> c2 =
-      BufferConsumer::Import(c->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c2 =
+      ConsumerBuffer::Import(c->CreateConsumer());
   ASSERT_TRUE(c2.get() != nullptr);
 
   // Producer state mask is unique, i.e. 1.
@@ -110,11 +110,11 @@
 }
 
 TEST_F(LibBufferHubTest, TestEpoll) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   LocalHandle epoll_fd{epoll_create1(EPOLL_CLOEXEC)};
@@ -177,15 +177,15 @@
 }
 
 TEST_F(LibBufferHubTest, TestStateMask) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
 
   // It's ok to create up to kMaxConsumerCount consumer buffers.
   uint64_t buffer_state_bits = p->buffer_state_bit();
-  std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
+  std::array<std::unique_ptr<ConsumerBuffer>, kMaxConsumerCount> cs;
   for (size_t i = 0; i < kMaxConsumerCount; i++) {
-    cs[i] = BufferConsumer::Import(p->CreateConsumer());
+    cs[i] = ConsumerBuffer::Import(p->CreateConsumer());
     ASSERT_TRUE(cs[i].get() != nullptr);
     // Expect all buffers have unique state mask.
     EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
@@ -201,7 +201,7 @@
   for (size_t i = 0; i < kMaxConsumerCount; i++) {
     buffer_state_bits &= ~cs[i]->buffer_state_bit();
     cs[i] = nullptr;
-    cs[i] = BufferConsumer::Import(p->CreateConsumer());
+    cs[i] = ConsumerBuffer::Import(p->CreateConsumer());
     ASSERT_TRUE(cs[i].get() != nullptr);
     // The released state mask will be reused.
     EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
@@ -211,11 +211,11 @@
 }
 
 TEST_F(LibBufferHubTest, TestStateTransitions) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   uint64_t context;
@@ -263,11 +263,11 @@
 }
 
 TEST_F(LibBufferHubTest, TestAsyncStateTransitions) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   DvrNativeBufferMetadata metadata;
@@ -334,7 +334,7 @@
 }
 
 TEST_F(LibBufferHubTest, TestZeroConsumer) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
 
@@ -350,21 +350,21 @@
   EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
 
   // A new consumer should still be able to acquire the buffer immediately.
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
   EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
   EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
 }
 
 TEST_F(LibBufferHubTest, TestMaxConsumers) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
 
-  std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
+  std::array<std::unique_ptr<ConsumerBuffer>, kMaxConsumerCount> cs;
   for (size_t i = 0; i < kMaxConsumerCount; i++) {
-    cs[i] = BufferConsumer::Import(p->CreateConsumer());
+    cs[i] = ConsumerBuffer::Import(p->CreateConsumer());
     ASSERT_TRUE(cs[i].get() != nullptr);
     EXPECT_TRUE(IsBufferGained(cs[i]->buffer_state()));
   }
@@ -400,13 +400,13 @@
 }
 
 TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
   EXPECT_TRUE(IsBufferGained(p->buffer_state()));
 
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
   EXPECT_TRUE(IsBufferGained(c->buffer_state()));
 
@@ -422,7 +422,7 @@
 }
 
 TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferPosted) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
   EXPECT_TRUE(IsBufferGained(p->buffer_state()));
@@ -435,8 +435,8 @@
   EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
 
   // Newly created consumer should be automatically sigalled.
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
   EXPECT_TRUE(IsBufferPosted(c->buffer_state()));
   EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
@@ -444,12 +444,12 @@
 }
 
 TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
 
-  std::unique_ptr<BufferConsumer> c1 =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c1 =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c1.get() != nullptr);
 
   DvrNativeBufferMetadata metadata;
@@ -470,8 +470,8 @@
 
   // Create another consumer immediately after the release, should not make the
   // buffer un-released.
-  std::unique_ptr<BufferConsumer> c2 =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c2 =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c2.get() != nullptr);
 
   EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
@@ -484,11 +484,11 @@
     int64_t field1;
     int64_t field2;
   };
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   Metadata m = {1, 3};
@@ -515,11 +515,11 @@
     int64_t field2;
     int64_t field3;
   };
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   // It is illegal to post metadata larger than originally requested during
@@ -544,11 +544,11 @@
     int64_t field2;
     int64_t field3;
   };
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   Metadata m = {1, 3};
@@ -569,11 +569,11 @@
 }
 
 TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   int64_t sequence = 3;
@@ -584,11 +584,11 @@
 }
 
 TEST_F(LibBufferHubTest, TestWithNoMeta) {
-  std::unique_ptr<BufferProducer> p =
-      BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
+  std::unique_ptr<ProducerBuffer> p =
+      ProducerBuffer::Create(kWidth, kHeight, kFormat, kUsage);
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   LocalHandle fence;
@@ -598,11 +598,11 @@
 }
 
 TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) {
-  std::unique_ptr<BufferProducer> p =
-      BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
+  std::unique_ptr<ProducerBuffer> p =
+      ProducerBuffer::Create(kWidth, kHeight, kFormat, kUsage);
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   int64_t sequence = 3;
@@ -619,11 +619,11 @@
 }  // namespace
 
 TEST_F(LibBufferHubTest, TestAcquireFence) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, /*metadata_size=*/0);
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
   DvrNativeBufferMetadata meta;
@@ -680,11 +680,11 @@
 }
 
 TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
-  std::unique_ptr<BufferConsumer> c1 =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c1 =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c1.get() != nullptr);
   const uint64_t consumer_state_bit1 = c1->buffer_state_bit();
 
@@ -699,8 +699,8 @@
   c1 = nullptr;
   EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
 
-  std::unique_ptr<BufferConsumer> c2 =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c2 =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c2.get() != nullptr);
   const uint64_t consumer_state_bit2 = c2->buffer_state_bit();
   EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
@@ -715,8 +715,8 @@
   EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
 
   // But if another consumer is created in released state.
-  std::unique_ptr<BufferConsumer> c3 =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c3 =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c3.get() != nullptr);
   const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
   EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
@@ -729,10 +729,13 @@
 }
 
 TEST_F(LibBufferHubTest, TestDetachBufferFromProducer) {
-  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+  // TODO(b/112338294) rewrite test after migration
+  return;
+
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
-  std::unique_ptr<BufferConsumer> c =
-      BufferConsumer::Import(p->CreateConsumer());
+  std::unique_ptr<ConsumerBuffer> c =
+      ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(p.get() != nullptr);
   ASSERT_TRUE(c.get() != nullptr);
 
@@ -834,6 +837,9 @@
 }
 
 TEST_F(LibBufferHubTest, TestPromoteDetachedBuffer) {
+  // TODO(b/112338294) rewrite test after migration
+  return;
+
   auto b1 = DetachedBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
                                    kUsage, kUserMetadataSize);
   int b1_id = b1->id();
@@ -856,7 +862,7 @@
   LocalChannelHandle h1 = status_or_handle.take();
   EXPECT_TRUE(h1.valid());
 
-  std::unique_ptr<BufferProducer> p1 = BufferProducer::Import(std::move(h1));
+  std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Import(std::move(h1));
   EXPECT_FALSE(h1.valid());
   ASSERT_TRUE(p1 != nullptr);
   int p1_id = p1->id();
@@ -867,7 +873,10 @@
 }
 
 TEST_F(LibBufferHubTest, TestDetachThenPromote) {
-  std::unique_ptr<BufferProducer> p1 = BufferProducer::Create(
+  // TODO(b/112338294) rewrite test after migration
+  return;
+
+  std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p1.get() != nullptr);
   int p1_id = p1->id();
@@ -896,7 +905,7 @@
   LocalChannelHandle h2 = status_or_handle.take();
   EXPECT_TRUE(h2.valid());
 
-  std::unique_ptr<BufferProducer> p2 = BufferProducer::Import(std::move(h2));
+  std::unique_ptr<ProducerBuffer> p2 = ProducerBuffer::Import(std::move(h2));
   EXPECT_FALSE(h2.valid());
   ASSERT_TRUE(p2 != nullptr);
   int p2_id = p2->id();
@@ -942,6 +951,9 @@
   EXPECT_TRUE(IsBufferGained(b1->buffer_state()));
   EXPECT_TRUE(IsBufferGained(b2->buffer_state()));
 
+  // TODO(b/112338294) rewrite test after migration
+  return;
+
   // Promote the detached buffer should fail as b1 is no longer the exclusive
   // owner of the buffer..
   status_or_handle = b1->Promote();
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
deleted file mode 100644
index 3f20024..0000000
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <mutex>
-
-#include <log/log.h>
-#include <pdx/default_transport/client_channel.h>
-#include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <utils/Trace.h>
-
-using android::pdx::LocalChannelHandle;
-using android::pdx::default_transport::ClientChannel;
-using android::pdx::default_transport::ClientChannelFactory;
-
-namespace android {
-namespace dvr {
-
-BufferHubClient::BufferHubClient()
-    : Client(ClientChannelFactory::Create(BufferHubRPC::kClientPath)) {}
-
-BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle)
-    : Client(ClientChannel::Create(std::move(channel_handle))) {}
-
-bool BufferHubClient::IsValid() const {
-  return IsConnected() && GetChannelHandle().valid();
-}
-
-LocalChannelHandle BufferHubClient::TakeChannelHandle() {
-  if (IsConnected()) {
-    return std::move(GetChannelHandle());
-  } else {
-    return {};
-  }
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libbufferhub/detached_buffer.cpp b/libs/vr/libbufferhub/detached_buffer.cpp
index 7716cfa..420ce24 100644
--- a/libs/vr/libbufferhub/detached_buffer.cpp
+++ b/libs/vr/libbufferhub/detached_buffer.cpp
@@ -1,6 +1,8 @@
-#include <private/dvr/detached_buffer.h>
-
+#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>
+#include <private/dvr/detached_buffer.h>
 #include <ui/DetachedBufferHandle.h>
 
 #include <poll.h>
@@ -8,10 +10,30 @@
 using android::pdx::LocalChannelHandle;
 using android::pdx::LocalHandle;
 using android::pdx::Status;
+using android::pdx::default_transport::ClientChannel;
+using android::pdx::default_transport::ClientChannelFactory;
 
 namespace android {
 namespace dvr {
 
+BufferHubClient::BufferHubClient()
+    : Client(ClientChannelFactory::Create(BufferHubRPC::kClientPath)) {}
+
+BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle)
+    : Client(ClientChannel::Create(std::move(channel_handle))) {}
+
+bool BufferHubClient::IsValid() const {
+  return IsConnected() && GetChannelHandle().valid();
+}
+
+LocalChannelHandle BufferHubClient::TakeChannelHandle() {
+  if (IsConnected()) {
+    return std::move(GetChannelHandle());
+  } else {
+    return {};
+  }
+}
+
 DetachedBuffer::DetachedBuffer(uint32_t width, uint32_t height,
                                uint32_t layer_count, uint32_t format,
                                uint64_t usage, size_t user_metadata_size) {
@@ -133,6 +155,10 @@
 }
 
 Status<LocalChannelHandle> DetachedBuffer::Promote() {
+  // TODO(b/112338294) remove after migrate producer buffer to binder
+  ALOGW("DetachedBuffer::Promote: not supported operation during migration");
+  return {};
+
   ATRACE_NAME("DetachedBuffer::Promote");
   ALOGD_IF(TRACE, "DetachedBuffer::Promote: id=%d.", id_);
 
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index 7b317d1..1daeed9 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -1,30 +1,10 @@
 #ifndef ANDROID_DVR_BUFFER_HUB_CLIENT_H_
 #define ANDROID_DVR_BUFFER_HUB_CLIENT_H_
 
-#include <pdx/channel_handle.h>
-#include <pdx/client.h>
+// TODO(b/116855254): This header is completely deprecated and replaced by
+// consumer_buffer.h and producer_buffer.h. Remove this file once all references
+// to it has been removed.
 #include <private/dvr/consumer_buffer.h>
 #include <private/dvr/producer_buffer.h>
 
-namespace android {
-namespace dvr {
-
-class BufferHubClient : public pdx::Client {
- public:
-  BufferHubClient();
-  explicit BufferHubClient(pdx::LocalChannelHandle channel_handle);
-
-  bool IsValid() const;
-  pdx::LocalChannelHandle TakeChannelHandle();
-
-  using pdx::Client::Close;
-  using pdx::Client::GetChannel;
-  using pdx::Client::InvokeRemoteMethod;
-  using pdx::Client::IsConnected;
-  using pdx::Client::event_fd;
-};
-
-}  // namespace dvr
-}  // namespace android
-
 #endif  // ANDROID_DVR_BUFFER_HUB_CLIENT_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
index e795f3b..d280d94 100644
--- a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
@@ -1,11 +1,28 @@
 #ifndef ANDROID_DVR_DETACHED_BUFFER_H_
 #define ANDROID_DVR_DETACHED_BUFFER_H_
 
-#include <private/dvr/buffer_hub_client.h>
+#include <pdx/client.h>
+#include <private/dvr/buffer_hub_defs.h>
+#include <private/dvr/buffer_hub_metadata.h>
+#include <private/dvr/ion_buffer.h>
 
 namespace android {
 namespace dvr {
 
+class BufferHubClient : public pdx::Client {
+ public:
+  BufferHubClient();
+  explicit BufferHubClient(pdx::LocalChannelHandle channel_handle);
+
+  bool IsValid() const;
+  pdx::LocalChannelHandle TakeChannelHandle();
+
+  using pdx::Client::Close;
+  using pdx::Client::event_fd;
+  using pdx::Client::GetChannel;
+  using pdx::Client::InvokeRemoteMethod;
+};
+
 class DetachedBuffer {
  public:
   // Allocates a standalone DetachedBuffer not associated with any producer
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index c4f1a3b..7b6f77a 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -222,6 +222,10 @@
 }
 
 Status<LocalChannelHandle> ProducerBuffer::Detach() {
+  // TODO(b/112338294) remove after migrate producer buffer to binder
+  ALOGW("ProducerBuffer::Detach: not supported operation during migration");
+  return {};
+
   uint64_t buffer_state = buffer_state_->load();
   if (!BufferHubDefs::IsBufferGained(buffer_state)) {
     // Can only detach a ProducerBuffer when it's in gained state.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9be18fb..8afd3b3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -118,6 +118,12 @@
         c->detachLayer(this);
     }
 
+    for (auto& point : mRemoteSyncPoints) {
+        point->setTransactionApplied();
+    }
+    for (auto& point : mLocalSyncPoints) {
+        point->setFrameAvailable();
+    }
     mFrameTracker.logAndResetStats(mName);
 }
 
@@ -135,6 +141,8 @@
 void Layer::onRemovedFromCurrentState() {
     // the layer is removed from SF mCurrentState to mLayersPendingRemoval
 
+    mPendingRemoval = true;
+
     if (mCurrentState.zOrderRelativeOf != nullptr) {
         sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
         if (strongRelative != nullptr) {
@@ -143,7 +151,7 @@
         }
         mCurrentState.zOrderRelativeOf = nullptr;
     }
-    
+
     for (const auto& child : mCurrentChildren) {
         child->onRemovedFromCurrentState();
     }
@@ -155,13 +163,8 @@
 
     destroyAllHwcLayers();
 
-    mRemoved = true;
-
-    for (auto& point : mRemoteSyncPoints) {
-        point->setTransactionApplied();
-    }
-    for (auto& point : mLocalSyncPoints) {
-        point->setFrameAvailable();
+    for (const auto& child : mCurrentChildren) {
+        child->onRemoved();
     }
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f2cda03..3eb8327 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -345,7 +345,7 @@
     virtual bool isCreatedFromMainThread() const { return false; }
 
 
-    bool isRemoved() const { return mRemoved; }
+    bool isPendingRemoval() const { return mPendingRemoval; }
 
     void writeToProto(LayerProto* layerInfo,
                       LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
@@ -594,12 +594,12 @@
      */
     class LayerCleaner {
         sp<SurfaceFlinger> mFlinger;
-        sp<Layer> mLayer;
+        wp<Layer> mLayer;
 
     protected:
         ~LayerCleaner() {
             // destroy client resources
-            mFlinger->removeLayer(mLayer, true);
+            mFlinger->onLayerDestroyed(mLayer);
         }
 
     public:
@@ -744,7 +744,7 @@
     // Whether filtering is needed b/c of the drawingstate
     bool mNeedsFiltering{false};
 
-    bool mRemoved{false};
+    bool mPendingRemoval{false};
 
     // page-flip thread (currently main thread)
     bool mProtectedByApp{false}; // application requires protected path to external sink
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2199ce1..37b32ed 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2852,7 +2852,6 @@
             recordBufferingStats(l->getName().string(),
                     l->getOccupancyHistory(true));
             l->onRemoved();
-            mNumLayers -= 1;
         }
         mLayersPendingRemoval.clear();
     }
@@ -3284,7 +3283,7 @@
         if (parent == nullptr) {
             mCurrentState.layersSortedByZ.add(lbc);
         } else {
-            if (parent->isRemoved()) {
+            if (parent->isPendingRemoval()) {
                 ALOGE("addClientLayer called with a removed parent");
                 return NAME_NOT_FOUND;
             }
@@ -3316,7 +3315,7 @@
 
 status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp<Layer>& layer,
                                            bool topLevelOnly) {
-    if (layer->isRemoved()) {
+    if (layer->isPendingRemoval()) {
         return NO_ERROR;
     }
 
@@ -3326,14 +3325,39 @@
         if (topLevelOnly) {
             return NO_ERROR;
         }
+
+        sp<Layer> ancestor = p;
+        while (ancestor->getParent() != nullptr) {
+            ancestor = ancestor->getParent();
+        }
+        if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
+            ALOGE("removeLayer called with a layer whose parent has been removed");
+            return NAME_NOT_FOUND;
+        }
+
         index = p->removeChild(layer);
     } else {
         index = mCurrentState.layersSortedByZ.remove(layer);
     }
 
+    // As a matter of normal operation, the LayerCleaner will produce a second
+    // attempt to remove the surface. The Layer will be kept alive in mDrawingState
+    // so we will succeed in promoting it, but it's already been removed
+    // from mCurrentState. As long as we can find it in mDrawingState we have no problem
+    // otherwise something has gone wrong and we are leaking the layer.
+    if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
+        ALOGE("Failed to find layer (%s) in layer parent (%s).",
+                layer->getName().string(),
+                (p != nullptr) ? p->getName().string() : "no-parent");
+        return BAD_VALUE;
+    } else if (index < 0) {
+        return NO_ERROR;
+    }
+
     layer->onRemovedFromCurrentState();
     mLayersPendingRemoval.add(layer);
     mLayersRemoved = true;
+    mNumLayers -= 1 + layer->getChildrenCount();
     setTransactionFlags(eTransactionNeeded);
     return NO_ERROR;
 }
@@ -3536,7 +3560,7 @@
         return 0;
     }
 
-    if (layer->isRemoved()) {
+    if (layer->isPendingRemoval()) {
         ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string());
         return 0;
     }
@@ -3744,7 +3768,7 @@
         return;
     }
 
-    if (layer->isRemoved()) {
+    if (layer->isPendingRemoval()) {
         ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string());
         return;
     }
@@ -3921,6 +3945,19 @@
     return err;
 }
 
+status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
+{
+    // called by ~LayerCleaner() when all references to the IBinder (handle)
+    // are gone
+    sp<Layer> l = layer.promote();
+    if (l == nullptr) {
+        // The layer has already been removed, carry on
+        return NO_ERROR;
+    }
+    // If we have a parent, then we can continue to live as long as it does.
+    return removeLayer(l, true);
+}
+
 // ---------------------------------------------------------------------------
 
 void SurfaceFlinger::onInitializeDisplays() {
@@ -5294,7 +5331,7 @@
     auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
     auto parent = layerHandle->owner.promote();
 
-    if (parent == nullptr || parent->isRemoved()) {
+    if (parent == nullptr || parent->isPendingRemoval()) {
         ALOGE("captureLayers called with a removed parent");
         return NAME_NOT_FOUND;
     }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9f6eb21..a0f7c75 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -561,6 +561,11 @@
     // ISurfaceComposerClient::destroySurface()
     status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
 
+    // called when all clients have released all their references to
+    // this layer meaning it is entirely safe to destroy all
+    // resources associated to this layer.
+    status_t onLayerDestroyed(const wp<Layer>& layer);
+
     // remove a layer from SurfaceFlinger immediately
     status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false);
     status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false);
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 34d0fd7..8bd5fcb 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*"
+            "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*"
         }
 }
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 0bf54d5..3166a8c 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2582,37 +2582,6 @@
     }
 }
 
-TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
-    sp<SurfaceControl> mGrandChild =
-        mClient->createSurface(String8("Grand Child"), 10, 10,
-                PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
-    fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
-
-    {
-        SCOPED_TRACE("Grandchild visible");
-        ScreenCapture::captureScreen(&mCapture);
-        mCapture->checkPixel(64, 64, 111, 111, 111);
-    }
-
-    mChild->clear();
-
-    {
-        SCOPED_TRACE("After destroying child");
-        ScreenCapture::captureScreen(&mCapture);
-        mCapture->expectFGColor(64, 64);
-    }
-
-    asTransaction([&](Transaction& t) {
-         t.reparent(mGrandChild, mFGSurfaceControl->getHandle());
-    });
-
-    {
-        SCOPED_TRACE("After reparenting grandchild");
-        ScreenCapture::captureScreen(&mCapture);
-        mCapture->checkPixel(64, 64, 111, 111, 111);
-    }
-}
-
 TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
     sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
     sp<SurfaceControl> mChildNewClient =
diff --git a/services/vr/bufferhubd/buffer_hub_binder.cpp b/services/vr/bufferhubd/buffer_hub_binder.cpp
index def15f1..26de45d 100644
--- a/services/vr/bufferhubd/buffer_hub_binder.cpp
+++ b/services/vr/bufferhubd/buffer_hub_binder.cpp
@@ -1,33 +1,62 @@
 #include <stdio.h>
 
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
 #include <log/log.h>
 #include <private/dvr/buffer_hub_binder.h>
 
 namespace android {
 namespace dvr {
 
-status_t BufferHubBinderService::start() {
-  ProcessState::self()->startThreadPool();
+status_t BufferHubBinderService::start(
+    const std::shared_ptr<BufferHubService>& pdx_service) {
   IPCThreadState::self()->disableBackgroundScheduling(true);
-  status_t result = BinderService<BufferHubBinderService>::publish();
-  if (result != OK) {
+
+  BufferHubBinderService* service = new BufferHubBinderService();
+  service->pdx_service_ = pdx_service;
+
+  // Not using BinderService::publish because need to get an instance of this
+  // class (above). Following code is the same as
+  // BinderService::publishAndJoinThreadPool
+  sp<IServiceManager> sm = defaultServiceManager();
+  status_t result = sm->addService(
+      String16(getServiceName()), service,
+      /*allowIsolated =*/false,
+      /*dump flags =*/IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+  if (result != NO_ERROR) {
     ALOGE("Publishing bufferhubd failed with error %d", result);
     return result;
   }
 
+  sp<ProcessState> process_self(ProcessState::self());
+  process_self->startThreadPool();
+
   return result;
 }
 
-status_t BufferHubBinderService::dump(int fd, const Vector<String16> & /* args */) {
-  // TODO(b/115435506): not implemented yet
-  FILE *out = fdopen(dup(fd), "w");
+status_t BufferHubBinderService::dump(int fd, const Vector<String16>& args) {
+  FILE* out = fdopen(dup(fd), "w");
 
-  fprintf(out, "BufferHubBinderService::dump(): Not Implemented.\n");
+  // Currently not supporting args, so notify the user.
+  if (!args.isEmpty()) {
+    fprintf(out,
+            "Note: dumpsys bufferhubd currently does not support args."
+            "Input arguments are ignored.\n");
+  }
+
+  // TODO(b/116526156): output real data in this class once we have it
+  if (pdx_service_) {
+    // BufferHubService::Dumpstate(size_t) is not actually using the param
+    // So just using 0 as the length
+    fprintf(out, "%s", pdx_service_->DumpState(0).c_str());
+  } else {
+    fprintf(out, "PDX service not registered or died.\n");
+  }
 
   fclose(out);
   return NO_ERROR;
 }
 
-
 }  // namespace dvr
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp
index 0ca7edc..3e10b26 100644
--- a/services/vr/bufferhubd/bufferhubd.cpp
+++ b/services/vr/bufferhubd/bufferhubd.cpp
@@ -10,7 +10,7 @@
 
 int main(int, char**) {
   int ret = -1;
-  std::shared_ptr<android::pdx::Service> service;
+  std::shared_ptr<android::dvr::BufferHubService> pdx_service;
   std::unique_ptr<android::pdx::ServiceDispatcher> dispatcher;
 
   // We need to be able to create endpoints with full perms.
@@ -33,15 +33,16 @@
   else
     ALOGI("New nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max);
 
-  CHECK_ERROR(android::dvr::BufferHubBinderService::start() != android::OK,
-              error, "Failed to create bufferhub binder service\n");
-
   dispatcher = android::pdx::ServiceDispatcher::Create();
   CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher\n");
 
-  service = android::dvr::BufferHubService::Create();
-  CHECK_ERROR(!service, error, "Failed to create bufferhubd service\n");
-  dispatcher->AddService(service);
+  pdx_service = android::dvr::BufferHubService::Create();
+  CHECK_ERROR(!pdx_service, error, "Failed to create bufferhub pdx service\n");
+  dispatcher->AddService(pdx_service);
+
+  ret = android::dvr::BufferHubBinderService::start(pdx_service);
+  CHECK_ERROR(ret != android::NO_ERROR, error,
+              "Failed to create bufferhub binder service\n");
 
   ret = dvrSetSchedulerClass(0, "graphics");
   CHECK_ERROR(ret < 0, error, "Failed to set thread priority");
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
index c0281fd..b47c34b 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
@@ -2,22 +2,27 @@
 #define ANDROID_DVR_BUFFER_HUB_BINDER_H
 
 #include <binder/BinderService.h>
+#include <private/dvr/buffer_hub.h>
 
 #include "android/dvr/BnBufferHub.h"
 
 namespace android {
 namespace dvr {
 
-class BufferHubBinderService : public BinderService<BufferHubBinderService>, public BnBufferHub {
+class BufferHubBinderService : public BinderService<BufferHubBinderService>,
+                               public BnBufferHub {
  public:
-  static status_t start();
+  static status_t start(const std::shared_ptr<BufferHubService>& pdx_service);
   static const char* getServiceName() { return "bufferhubd"; }
   // Dump bufferhub related information to given fd (usually stdout)
   // usage: adb shell dumpsys bufferhubd
-  virtual status_t dump(int fd, const Vector<String16> &args) override;
+  virtual status_t dump(int fd, const Vector<String16>& args) override;
+
+ private:
+  std::shared_ptr<BufferHubService> pdx_service_;
 };
 
 }  // namespace dvr
 }  // namespace android
 
-#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
\ No newline at end of file
+#endif  // ANDROID_DVR_BUFFER_HUB_BINDER_H
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
index 4d1d43f..92bda78 100644
--- a/services/vr/bufferhubd/tests/Android.bp
+++ b/services/vr/bufferhubd/tests/Android.bp
@@ -6,11 +6,18 @@
         "-DTRACE=0",
         "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
     ],
-    static_libs: ["libbufferhubd"],
+    header_libs: ["libdvr_headers"],
+    static_libs: [
+        "libbufferhub",
+        "libbufferhubd",
+        "libgmock",
+    ],
     shared_libs: [
         "libbase",
         "libbinder",
         "liblog",
+        "libpdx_default_transport",
+        "libui",
         "libutils",
     ],
 }
\ No newline at end of file
diff --git a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
index e3f2825..67ac1cb 100644
--- a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
+++ b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
@@ -1,6 +1,7 @@
-#include <private/dvr/buffer_hub_binder.h>
-
+#include <binder/IServiceManager.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include <private/dvr/buffer_hub_binder.h>
 
 namespace android {
 namespace dvr {
@@ -12,8 +13,12 @@
 };
 
 TEST_F(BufferHubBinderServiceTest, TestInitialize) {
-  // Test if start binder server returns OK
-  EXPECT_EQ(BufferHubBinderService::start(), OK);
+  // Create a new service will kill the current one.
+  // So just check if Binder service is running
+  sp<IServiceManager> sm = defaultServiceManager();
+  sp<IBinder> service =
+      sm->checkService(String16(BufferHubBinderService::getServiceName()));
+  EXPECT_THAT(service, ::testing::Ne(nullptr));
 }
 
 }  // namespace