Merge changes Iad7bf035,I870e08c6

* changes:
  VNDK ANativeWindow API - step 2
  VNDK ANativeWindow API
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 39e0ba3..4740202 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -16,6 +16,7 @@
     name: "lshal",
     shared_libs: [
         "libbase",
+        "libcutils",
         "libutils",
         "libhidlbase",
         "libhidltransport",
@@ -24,6 +25,7 @@
         "android.hidl.manager@1.0",
     ],
     srcs: [
-        "Lshal.cpp"
+        "Lshal.cpp",
+        "PipeRelay.cpp"
     ],
 }
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index a5cac15..420ec3c 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -25,13 +25,17 @@
 #include <sstream>
 #include <regex>
 
+#include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hidl/ServiceManagement.h>
 #include <hidl-util/FQName.h>
+#include <private/android_filesystem_config.h>
+#include <sys/stat.h>
 #include <vintf/HalManifest.h>
 #include <vintf/parse_xml.h>
 
+#include "PipeRelay.h"
 #include "Timeout.h"
 
 using ::android::hardware::hidl_string;
@@ -357,6 +361,52 @@
     }
 }
 
+// A unique_ptr type using a custom deleter function.
+template<typename T>
+using deleted_unique_ptr = std::unique_ptr<T, std::function<void(T *)> >;
+
+void Lshal::emitDebugInfo(
+        const sp<IServiceManager> &serviceManager,
+        const std::string &interfaceName,
+        const std::string &instanceName) const {
+    using android::hidl::base::V1_0::IBase;
+
+    hardware::Return<sp<IBase>> retBase =
+        serviceManager->get(interfaceName, instanceName);
+
+    sp<IBase> base;
+    if (!retBase.isOk() || (base = retBase) == nullptr) {
+        // There's a small race, where a service instantiated while collecting
+        // the list of services has by now terminated, so this isn't anything
+        // to be concerned about.
+        return;
+    }
+
+    PipeRelay relay(mOut.buf());
+
+    if (relay.initCheck() != OK) {
+        LOG(ERROR) << "PipeRelay::initCheck() FAILED w/ " << relay.initCheck();
+        return;
+    }
+
+    deleted_unique_ptr<native_handle_t> fdHandle(
+        native_handle_create(1 /* numFds */, 0 /* numInts */),
+        native_handle_delete);
+
+    fdHandle->data[0] = relay.fd();
+
+    hardware::hidl_vec<hardware::hidl_string> options;
+    hardware::Return<void> ret = base->debug(fdHandle.get(), options);
+
+    if (!ret.isOk()) {
+        LOG(ERROR)
+            << interfaceName
+            << "::debug(...) FAILED. (instance "
+            << instanceName
+            << ")";
+    }
+}
+
 void Lshal::dumpTable() {
     mServicesTable.description =
             "All binderized services (registered services through hwservicemanager)";
@@ -374,6 +424,16 @@
         mOut << std::left;
         printLine("Interface", "Transport", "Arch", "Server", "Server CMD",
                   "PTR", "Clients", "Clients CMD");
+
+        // We're only interested in dumping debug info for already
+        // instantiated services. There's little value in dumping the
+        // debug info for a service we create on the fly, so we only operate
+        // on the "mServicesTable".
+        sp<IServiceManager> serviceManager;
+        if (mEmitDebugInfo && &table == &mServicesTable) {
+            serviceManager = ::android::hardware::defaultServiceManager();
+        }
+
         for (const auto &entry : table) {
             printLine(entry.interfaceName,
                     entry.transport,
@@ -383,6 +443,11 @@
                     entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress),
                     join(entry.clientPids, " "),
                     join(entry.clientCmdlines, ";"));
+
+            if (serviceManager != nullptr) {
+                auto pair = splitFirst(entry.interfaceName, '/');
+                emitDebugInfo(serviceManager, pair.first, pair.second);
+            }
         }
         mOut << std::endl;
     });
@@ -626,6 +691,7 @@
         {"address",   no_argument,       0, 'a' },
         {"clients",   no_argument,       0, 'c' },
         {"cmdline",   no_argument,       0, 'm' },
+        {"debug",     optional_argument, 0, 'd' },
 
         // long options without short alternatives
         {"sort",      required_argument, 0, 's' },
@@ -638,7 +704,7 @@
     optind = 1;
     for (;;) {
         // using getopt_long in case we want to add other options in the future
-        c = getopt_long(argc, argv, "hitrpacm", longOptions, &optionIndex);
+        c = getopt_long(argc, argv, "hitrpacmd", longOptions, &optionIndex);
         if (c == -1) {
             break;
         }
@@ -694,6 +760,20 @@
             mEnableCmdlines = true;
             break;
         }
+        case 'd': {
+            mEmitDebugInfo = true;
+
+            if (optarg) {
+                mFileOutput = new std::ofstream{optarg};
+                mOut = mFileOutput;
+                if (!mFileOutput.buf().is_open()) {
+                    mErr << "Could not open file '" << optarg << "'." << std::endl;
+                    return IO_ERROR;
+                }
+                chown(optarg, AID_SHELL, AID_SHELL);
+            }
+            break;
+        }
         case 'h': // falls through
         default: // see unrecognized options
             usage();
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index c9c6660..a21e86c 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -77,6 +77,11 @@
     void forEachTable(const std::function<void(Table &)> &f);
     void forEachTable(const std::function<void(const Table &)> &f) const;
 
+    void emitDebugInfo(
+            const sp<hidl::manager::V1_0::IServiceManager> &serviceManager,
+            const std::string &interfaceName,
+            const std::string &instanceName) const;
+
     Table mServicesTable{};
     Table mPassthroughRefTable{};
     Table mImplementationsTable{};
@@ -88,6 +93,10 @@
     TableEntrySelect mSelectedColumns = 0;
     // If true, cmdlines will be printed instead of pid.
     bool mEnableCmdlines = false;
+
+    // If true, calls IBase::debug(...) on each service.
+    bool mEmitDebugInfo = false;
+
     bool mVintf = false;
     // If an entry does not exist, need to ask /proc/{pid}/cmdline to get it.
     // If an entry exist but is an empty string, process might have died.
diff --git a/cmds/lshal/PipeRelay.cpp b/cmds/lshal/PipeRelay.cpp
new file mode 100644
index 0000000..c7b29df
--- /dev/null
+++ b/cmds/lshal/PipeRelay.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "PipeRelay.h"
+
+#include <sys/socket.h>
+#include <utils/Thread.h>
+
+namespace android {
+namespace lshal {
+
+struct PipeRelay::RelayThread : public Thread {
+    explicit RelayThread(int fd, std::ostream &os);
+
+    bool threadLoop() override;
+
+private:
+    int mFd;
+    std::ostream &mOutStream;
+
+    DISALLOW_COPY_AND_ASSIGN(RelayThread);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os)
+    : mFd(fd),
+      mOutStream(os) {
+}
+
+bool PipeRelay::RelayThread::threadLoop() {
+    char buffer[1024];
+    ssize_t n = read(mFd, buffer, sizeof(buffer));
+
+    if (n <= 0) {
+        return false;
+    }
+
+    mOutStream.write(buffer, n);
+
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+PipeRelay::PipeRelay(std::ostream &os)
+    : mOutStream(os),
+      mInitCheck(NO_INIT) {
+    int res = socketpair(AF_UNIX, SOCK_STREAM, 0 /* protocol */, mFds);
+
+    if (res < 0) {
+        mInitCheck = -errno;
+        return;
+    }
+
+    mThread = new RelayThread(mFds[0], os);
+    mInitCheck = mThread->run("RelayThread");
+}
+
+// static
+void PipeRelay::CloseFd(int *fd) {
+    if (*fd >= 0) {
+        close(*fd);
+        *fd = -1;
+    }
+}
+
+PipeRelay::~PipeRelay() {
+    if (mFds[1] >= 0) {
+        shutdown(mFds[1], SHUT_WR);
+    }
+
+    if (mFds[0] >= 0) {
+        shutdown(mFds[0], SHUT_RD);
+    }
+
+    if (mThread != NULL) {
+        mThread->join();
+        mThread.clear();
+    }
+
+    CloseFd(&mFds[1]);
+    CloseFd(&mFds[0]);
+}
+
+status_t PipeRelay::initCheck() const {
+    return mInitCheck;
+}
+
+int PipeRelay::fd() const {
+    return mFds[1];
+}
+
+}  // namespace lshal
+}  // namespace android
diff --git a/cmds/lshal/PipeRelay.h b/cmds/lshal/PipeRelay.h
new file mode 100644
index 0000000..76b2b23
--- /dev/null
+++ b/cmds/lshal/PipeRelay.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
+
+#define FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
+
+#include <android-base/macros.h>
+#include <ostream>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+namespace lshal {
+
+/* Creates an AF_UNIX socketpair and spawns a thread that relays any data
+ * written to the "write"-end of the pair to the specified output stream "os".
+ */
+struct PipeRelay {
+    explicit PipeRelay(std::ostream &os);
+    ~PipeRelay();
+
+    status_t initCheck() const;
+
+    // Returns the file descriptor corresponding to the "write"-end of the
+    // connection.
+    int fd() const;
+
+private:
+    struct RelayThread;
+
+    std::ostream &mOutStream;
+    status_t mInitCheck;
+    int mFds[2];
+    sp<RelayThread> mThread;
+
+    static void CloseFd(int *fd);
+
+    DISALLOW_COPY_AND_ASSIGN(PipeRelay);
+};
+
+}  // namespace lshal
+}  // namespace android
+
+#endif  // FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
+
diff --git a/include/gfx/SafeLog.h b/include/gfx/SafeLog.h
deleted file mode 100644
index e45e541..0000000
--- a/include/gfx/SafeLog.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Weverything"
-#include <fmt/format.h>
-#include <log/log.h>
-#pragma clang diagnostic pop
-
-#include <type_traits>
-
-namespace android {
-namespace gfx {
-
-/* SafeLog is a mix-in that can be used to easily add typesafe logging using fmtlib to any class.
- * To use it, inherit from it using CRTP and implement the getLogTag method.
- *
- * For example:
- *
- * class Frobnicator : private SafeLog<Frobnicator> {
- *     friend class SafeLog<Frobnicator>;  // Allows getLogTag to be private
- *
- *   public:
- *     void frobnicate(int32_t i);
- *
- *   private:
- *     // SafeLog does member access on the object calling alog*, so this tag can theoretically vary
- *     // by instance unless getLogTag is made static
- *     const char* getLogTag() { return "Frobnicator"; }
- * };
- *
- * void Frobnicator::frobnicate(int32_t i) {
- *     // Logs something like "04-16 21:35:46.811  3513  3513 I Frobnicator: frobnicating 42"
- *     alogi("frobnicating {}", i);
- * }
- *
- * See http://fmtlib.net for more information on the formatting API.
- */
-
-template <typename T>
-class SafeLog {
-  protected:
-    template <typename... Args>
-#if LOG_NDEBUG
-    void alogv(Args&&... /*unused*/) const {
-    }
-#else
-    void alogv(Args&&... args) const {
-        alog<ANDROID_LOG_VERBOSE>(std::forward<Args>(args)...);
-    }
-#endif
-
-    template <typename... Args>
-    void alogd(Args&&... args) const {
-        alog<ANDROID_LOG_DEBUG>(std::forward<Args>(args)...);
-    }
-
-    template <typename... Args>
-    void alogi(Args&&... args) const {
-        alog<ANDROID_LOG_INFO>(std::forward<Args>(args)...);
-    }
-
-    template <typename... Args>
-    void alogw(Args&&... args) const {
-        alog<ANDROID_LOG_WARN>(std::forward<Args>(args)...);
-    }
-
-    template <typename... Args>
-    void aloge(Args&&... args) const {
-        alog<ANDROID_LOG_ERROR>(std::forward<Args>(args)...);
-    }
-
-  private:
-    // Suppresses clang-tidy check cppcoreguidelines-pro-bounds-array-to-pointer-decay
-    template <size_t strlen, typename... Args>
-    void write(fmt::MemoryWriter* writer, const char (&str)[strlen], Args&&... args) const {
-        writer->write(static_cast<const char*>(str), std::forward<Args>(args)...);
-    }
-
-    template <int priority, typename... Args>
-    void alog(Args&&... args) const {
-        static_assert(std::is_base_of<SafeLog<T>, T>::value, "Can't convert to SafeLog pointer");
-        fmt::MemoryWriter writer;
-        write(&writer, std::forward<Args>(args)...);
-        auto derivedThis = static_cast<const T*>(this);
-        android_writeLog(priority, derivedThis->getLogTag(), writer.c_str());
-    }
-};
-
-}  // namespace gfx
-}  // namespace android
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index e068469..452bad0 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -15,7 +15,6 @@
 sourceFiles = [
     "buffer_hub_client.cpp",
     "buffer_hub_rpc.cpp",
-    "dvr_buffer.cpp",
     "ion_buffer.cpp",
 ]
 
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 1c8f2c0..2d96638 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -43,7 +43,7 @@
 cc_library {
     name: "libbufferhubqueue",
     cflags = [
-        "-DLOGTAG=\"libbufferhubqueue\"",
+        "-DLOG_TAG=\"libbufferhubqueue\"",
         "-DTRACE=0",
     ],
     srcs: sourceFiles,
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index feaf3d7..f786356 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -329,6 +329,9 @@
     return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
   }
 
+  std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
+                                          size_t meta_size,
+                                          LocalHandle* acquire_fence);
  private:
   friend BASE;
 
@@ -344,13 +347,27 @@
                     LocalHandle* acquire_fence) override;
 
   int OnBufferAllocated() override;
-
-  std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
-                                          size_t meta_size,
-                                          LocalHandle* acquire_fence);
 };
 
 }  // namespace dvr
 }  // namespace android
 
+// Concrete C type definition for DVR API.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct DvrWriteBufferQueue {
+  std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+};
+
+struct DvrReadBufferQueue {
+  std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue_;
+};
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
 #endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index b8a0da3..865573c 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -24,6 +24,7 @@
     static_libs: static_libraries,
     shared_libs: shared_libraries,
     cflags: [
+        "-DLOG_TAG=\"buffer_hub_queue-test\"",
         "-DTRACE=0",
         "-O0",
         "-g",
@@ -37,6 +38,7 @@
     static_libs: static_libraries,
     shared_libs: shared_libraries,
     cflags: [
+        "-DLOG_TAG=\"buffer_hub_queue_producer-test\"",
         "-DTRACE=0",
         "-O0",
         "-g",
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index f3c71b5..de2a56e 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -15,7 +15,6 @@
 sourceFiles = [
     "native_buffer_queue.cpp",
     "display_client.cpp",
-    "display_manager_client.cpp",
     "display_manager_client_impl.cpp",
     "display_rpc.cpp",
     "dummy_native_window.cpp",
@@ -24,7 +23,6 @@
     "late_latch.cpp",
     "video_mesh_surface_client.cpp",
     "vsync_client.cpp",
-    "vsync_client_api.cpp",
     "screenshot_client.cpp",
     "frame_history.cpp",
 ]
diff --git a/libs/vr/libdisplay/graphics.cpp b/libs/vr/libdisplay/graphics.cpp
index 3713389..2abdf8e 100644
--- a/libs/vr/libdisplay/graphics.cpp
+++ b/libs/vr/libdisplay/graphics.cpp
@@ -17,7 +17,6 @@
 #include <private/dvr/clock_ns.h>
 #include <private/dvr/debug.h>
 #include <private/dvr/display_types.h>
-#include <private/dvr/dvr_buffer.h>
 #include <private/dvr/frame_history.h>
 #include <private/dvr/gl_fenced_flush.h>
 #include <private/dvr/graphics/vr_gl_extensions.h>
@@ -1575,14 +1574,3 @@
     };
   }
 }
-
-extern "C" int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
-  auto client = android::dvr::DisplayClient::Create();
-  if (!client) {
-    ALOGE("Failed to create display client!");
-    return -ECOMM;
-  }
-
-  *pose_buffer = CreateDvrReadBufferFromBufferConsumer(client->GetPoseBuffer());
-  return 0;
-}
diff --git a/libs/vr/libdisplay/include/dvr/graphics.h b/libs/vr/libdisplay/include/dvr/graphics.h
index fc51d52..ac8b27f 100644
--- a/libs/vr/libdisplay/include/dvr/graphics.h
+++ b/libs/vr/libdisplay/include/dvr/graphics.h
@@ -442,9 +442,6 @@
                                         const int eye,
                                         const float* transform);
 
-// Get a pointer to the global pose buffer.
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
-
 __END_DECLS
 
 #endif  // DVR_GRAPHICS_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/vsync_client.h b/libs/vr/libdisplay/include/private/dvr/vsync_client.h
index 32fa40f..1eeb80e 100644
--- a/libs/vr/libdisplay/include/private/dvr/vsync_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/vsync_client.h
@@ -4,7 +4,6 @@
 #include <stdint.h>
 
 #include <pdx/client.h>
-#include <private/dvr/vsync_client_api.h>
 
 struct dvr_vsync_client {};
 
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
new file mode 100644
index 0000000..5449cb5
--- /dev/null
+++ b/libs/vr/libdvr/Android.mk
@@ -0,0 +1,54 @@
+# Copyright (C) 2017 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.
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libdvr
+LOCAL_MODULE_OWNER := google
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+
+LOCAL_CFLAGS += \
+    -fvisibility=hidden \
+    -D DVR_EXPORT='__attribute__ ((visibility ("default")))'
+
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH)/include \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+    $(LOCAL_PATH)/include \
+
+LOCAL_SRC_FILES := \
+    display_manager_client.cpp \
+    dvr_api.cpp \
+    dvr_buffer.cpp \
+    dvr_buffer_queue.cpp \
+    dvr_surface.cpp \
+    vsync_client_api.cpp \
+
+LOCAL_STATIC_LIBRARIES := \
+    libbufferhub \
+    libbufferhubqueue \
+    libdisplay \
+    libvrsensor \
+    libvirtualtouchpadclient \
+
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.graphics.bufferqueue@1.0 \
+    android.hidl.token@1.0-utils \
+    libandroid_runtime \
+    libbase \
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/vr/libdisplay/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
similarity index 97%
rename from libs/vr/libdisplay/display_manager_client.cpp
rename to libs/vr/libdvr/display_manager_client.cpp
index d60d35b..7cbfc21 100644
--- a/libs/vr/libdisplay/display_manager_client.cpp
+++ b/libs/vr/libdvr/display_manager_client.cpp
@@ -1,8 +1,8 @@
-#include "include/private/dvr/display_manager_client.h"
+#include "include/dvr/display_manager_client.h"
 
+#include <dvr/dvr_buffer.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/display_manager_client_impl.h>
-#include <private/dvr/dvr_buffer.h>
 
 using android::dvr::DisplaySurfaceAttributeEnum;
 
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
new file mode 100644
index 0000000..4dd49da
--- /dev/null
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -0,0 +1,106 @@
+#include "include/dvr/dvr_api.h"
+
+#include <errno.h>
+
+// Headers from libdvr
+#include <dvr/display_manager_client.h>
+#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_surface.h>
+#include <dvr/vsync_client_api.h>
+
+// Headers not yet moved into libdvr.
+// TODO(jwcai) Move these once their callers are moved into Google3.
+#include <dvr/pose_client.h>
+#include <dvr/virtual_touchpad_client.h>
+
+extern "C" {
+
+DVR_EXPORT int dvrGetApi(void* api, size_t struct_size, int version) {
+  if (version == 1) {
+    if (struct_size != sizeof(DvrApi_v1)) {
+      return -EINVAL;
+    }
+    DvrApi_v1* dvr_api = static_cast<DvrApi_v1*>(api);
+
+    // display_manager_client.h
+    dvr_api->display_manager_client_create_ = dvrDisplayManagerClientCreate;
+    dvr_api->display_manager_client_destroy_ = dvrDisplayManagerClientDestroy;
+    dvr_api->display_manager_client_get_surface_list_ =
+        dvrDisplayManagerClientGetSurfaceList;
+    dvr_api->display_manager_client_surface_list_destroy_ =
+        dvrDisplayManagerClientSurfaceListDestroy;
+    dvr_api->display_manager_setup_pose_buffer_ =
+        dvrDisplayManagerSetupPoseBuffer;
+    dvr_api->display_manager_client_surface_list_get_size_ =
+        dvrDisplayManagerClientSurfaceListGetSize;
+    dvr_api->display_manager_client_surface_list_get_surface_id_ =
+        dvrDisplayManagerClientSurfaceListGetSurfaceId;
+    dvr_api->display_manager_client_get_surface_buffer_list_ =
+        dvrDisplayManagerClientGetSurfaceBuffers;
+    dvr_api->display_manager_client_surface_buffer_list_destroy_ =
+        dvrDisplayManagerClientSurfaceBuffersDestroy;
+    dvr_api->display_manager_client_surface_buffer_list_get_size_ =
+        dvrDisplayManagerClientSurfaceBuffersGetSize;
+    dvr_api->display_manager_client_surface_buffer_list_get_fd_ =
+        dvrDisplayManagerClientSurfaceBuffersGetFd;
+
+    // dvr_buffer.h
+    dvr_api->write_buffer_destroy_ = dvrWriteBufferDestroy;
+    dvr_api->write_buffer_get_blob_fds_ = dvrWriteBufferGetBlobFds;
+    dvr_api->write_buffer_get_AHardwareBuffer_ =
+        dvrWriteBufferGetAHardwareBuffer;
+    dvr_api->write_buffer_post_ = dvrWriteBufferPost;
+    dvr_api->write_buffer_gain_ = dvrWriteBufferGain;
+    dvr_api->write_buffer_gain_async_ = dvrWriteBufferGainAsync;
+
+    dvr_api->read_buffer_destroy_ = dvrReadBufferDestroy;
+    dvr_api->read_buffer_get_blob_fds_ = dvrReadBufferGetBlobFds;
+    dvr_api->read_buffer_get_AHardwareBuffer_ = dvrReadBufferGetAHardwareBuffer;
+    dvr_api->read_buffer_acquire_ = dvrReadBufferAcquire;
+    dvr_api->read_buffer_release_ = dvrReadBufferRelease;
+    dvr_api->read_buffer_release_async_ = dvrReadBufferReleaseAsync;
+
+    // dvr_buffer_queue.h
+    dvr_api->write_buffer_queue_destroy_ = dvrWriteBufferQueueDestroy;
+    dvr_api->write_buffer_queue_get_capacity_ = dvrWriteBufferQueueGetCapacity;
+    dvr_api->write_buffer_queue_get_external_surface_ =
+        dvrWriteBufferQueueGetExternalSurface;
+    dvr_api->write_buffer_queue_create_read_queue_ =
+        dvrWriteBufferQueueCreateReadQueue;
+    dvr_api->write_buffer_queue_dequeue_ = dvrWriteBufferQueueDequeue;
+    dvr_api->read_buffer_queue_destroy_ = dvrReadBufferQueueDestroy;
+    dvr_api->read_buffer_queue_get_capacity_ = dvrReadBufferQueueGetCapacity;
+    dvr_api->read_buffer_queue_create_read_queue_ =
+        dvrReadBufferQueueCreateReadQueue;
+    dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
+
+    // dvr_surface.h
+    dvr_api->get_pose_buffer_ = dvrGetPoseBuffer;
+
+    // vsync_client_api.h
+    dvr_api->vsync_client_create_ = dvr_vsync_client_create;
+    dvr_api->vsync_client_destroy_ = dvr_vsync_client_destroy;
+    dvr_api->vsync_client_get_sched_info_ = dvr_vsync_client_get_sched_info;
+
+    // pose_client.h
+    dvr_api->pose_client_create_ = dvrPoseCreate;
+    dvr_api->pose_client_destroy_ = dvrPoseDestroy;
+    dvr_api->pose_get_ = dvrPoseGet;
+    dvr_api->pose_get_vsync_count_ = dvrPoseGetVsyncCount;
+    dvr_api->pose_get_controller_ = dvrPoseGetController;
+
+    // virtual_touchpad_client.h
+    dvr_api->virtual_touchpad_create_ = dvrVirtualTouchpadCreate;
+    dvr_api->virtual_touchpad_destroy_ = dvrVirtualTouchpadDestroy;
+    dvr_api->virtual_touchpad_attach_ = dvrVirtualTouchpadAttach;
+    dvr_api->virtual_touchpad_detach_ = dvrVirtualTouchpadDetach;
+    dvr_api->virtual_touchpad_touch_ = dvrVirtualTouchpadTouch;
+    dvr_api->virtual_touchpad_button_state_ = dvrVirtualTouchpadButtonState;
+
+    return 0;
+  }
+  return -EINVAL;
+}
+
+}  // extern "C"
diff --git a/libs/vr/libbufferhub/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
similarity index 91%
rename from libs/vr/libbufferhub/dvr_buffer.cpp
rename to libs/vr/libdvr/dvr_buffer.cpp
index 3eb611f..25128a6 100644
--- a/libs/vr/libbufferhub/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -1,16 +1,17 @@
+#include "include/dvr/dvr_buffer.h"
+
 #include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/dvr_buffer.h>
 #include <ui/GraphicBuffer.h>
 
 using namespace android;
 
 struct DvrWriteBuffer {
-  std::unique_ptr<dvr::BufferProducer> write_buffer_;
+  std::shared_ptr<dvr::BufferProducer> write_buffer_;
   sp<GraphicBuffer> graphic_buffer_;
 };
 
 struct DvrReadBuffer {
-  std::unique_ptr<dvr::BufferConsumer> read_buffer_;
+  std::shared_ptr<dvr::BufferConsumer> read_buffer_;
   sp<GraphicBuffer> graphic_buffer_;
 };
 
@@ -18,14 +19,14 @@
 namespace dvr {
 
 DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
-    std::unique_ptr<dvr::BufferProducer> buffer_producer) {
+    const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
   DvrWriteBuffer* write_buffer = new DvrWriteBuffer;
   write_buffer->write_buffer_ = std::move(buffer_producer);
   return write_buffer;
 }
 
 DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
-    std::unique_ptr<dvr::BufferConsumer> buffer_consumer) {
+    const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
   DvrReadBuffer* read_buffer = new DvrReadBuffer;
   read_buffer->read_buffer_ = std::move(buffer_consumer);
   return read_buffer;
@@ -85,6 +86,8 @@
   return client->write_buffer_->GainAsync();
 }
 
+void dvrReadBufferDestroy(DvrReadBuffer* client) { delete client; }
+
 void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
                              size_t max_fds_count) {
   client->read_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
new file mode 100644
index 0000000..b0b5a2a
--- /dev/null
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -0,0 +1,146 @@
+#include "include/dvr/dvr_buffer_queue.h"
+
+#include <gui/Surface.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/buffer_hub_queue_producer.h>
+
+#include <android_runtime/android_view_Surface.h>
+
+#define CHECK_PARAM(param)                                               \
+  LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
+                      __FUNCTION__)
+
+using namespace android;
+
+extern "C" {
+
+void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
+  delete write_queue;
+}
+
+size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
+  CHECK_PARAM(write_queue);
+  return write_queue->producer_queue_->capacity();
+}
+
+void* dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+                                            JNIEnv* env) {
+  CHECK_PARAM(env);
+  CHECK_PARAM(write_queue);
+
+  std::shared_ptr<dvr::BufferHubQueueCore> core =
+      dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+
+  return android_view_Surface_createFromIGraphicBufferProducer(
+      env, new dvr::BufferHubQueueProducer(core));
+}
+
+int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
+                                       DvrReadBufferQueue** out_read_queue) {
+  CHECK_PARAM(write_queue);
+  CHECK_PARAM(write_queue->producer_queue_);
+  CHECK_PARAM(out_read_queue);
+
+  auto read_queue = std::make_unique<DvrReadBufferQueue>();
+  read_queue->consumer_queue_ =
+      write_queue->producer_queue_->CreateConsumerQueue();
+  if (read_queue->consumer_queue_ == nullptr) {
+    ALOGE(
+        "dvrWriteBufferQueueCreateReadQueue: Failed to create consumer queue "
+        "from DvrWriteBufferQueue[%p].",
+        write_queue);
+    return -ENOMEM;
+  }
+
+  *out_read_queue = read_queue.release();
+  return 0;
+}
+
+int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
+                                  DvrWriteBuffer** out_buffer,
+                                  int* out_fence_fd) {
+  CHECK_PARAM(write_queue);
+  CHECK_PARAM(write_queue->producer_queue_);
+  CHECK_PARAM(out_buffer);
+  CHECK_PARAM(out_fence_fd);
+
+  size_t slot;
+  pdx::LocalHandle release_fence;
+  std::shared_ptr<dvr::BufferProducer> buffer =
+      write_queue->producer_queue_->Dequeue(timeout, &slot, &release_fence);
+  if (buffer == nullptr) {
+    ALOGE("dvrWriteBufferQueueDequeue: Failed to dequeue buffer.");
+    return -ENOMEM;
+  }
+
+  *out_buffer = CreateDvrWriteBufferFromBufferProducer(buffer);
+  *out_fence_fd = release_fence.Release();
+  return 0;
+}
+
+// ReadBufferQueue
+void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) {
+  delete read_queue;
+}
+
+size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
+  CHECK_PARAM(read_queue);
+
+  return read_queue->consumer_queue_->capacity();
+}
+
+int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
+                                      DvrReadBufferQueue** out_read_queue) {
+  CHECK_PARAM(read_queue);
+  CHECK_PARAM(read_queue->consumer_queue_);
+  CHECK_PARAM(out_read_queue);
+
+  auto new_read_queue = std::make_unique<DvrReadBufferQueue>();
+  new_read_queue->consumer_queue_ =
+      read_queue->consumer_queue_->CreateConsumerQueue();
+  if (new_read_queue->consumer_queue_ == nullptr) {
+    ALOGE(
+        "dvrReadBufferQueueCreateReadQueue: Failed to create consumer queue "
+        "from DvrReadBufferQueue[%p].",
+        read_queue);
+    return -ENOMEM;
+  }
+
+  *out_read_queue = new_read_queue.release();
+  return 0;
+}
+
+int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
+                              DvrReadBuffer** out_buffer, int* out_fence_fd,
+                              void* out_meta, size_t meta_size_bytes) {
+  CHECK_PARAM(read_queue);
+  CHECK_PARAM(read_queue->consumer_queue_);
+  CHECK_PARAM(out_buffer);
+  CHECK_PARAM(out_fence_fd);
+  CHECK_PARAM(out_meta);
+
+  if (meta_size_bytes != read_queue->consumer_queue_->metadata_size()) {
+    ALOGE(
+        "dvrReadBufferQueueDequeue: Invalid metadata size, expected (%zu), "
+        "but actual (%zu).",
+        read_queue->consumer_queue_->metadata_size(), meta_size_bytes);
+    return -EINVAL;
+  }
+
+  size_t slot;
+  pdx::LocalHandle acquire_fence;
+  std::shared_ptr<dvr::BufferConsumer> buffer =
+      read_queue->consumer_queue_->Dequeue(timeout, &slot, out_meta,
+                                           meta_size_bytes, &acquire_fence);
+
+  if (buffer == nullptr) {
+    ALOGE("dvrReadBufferQueueGainBuffer: Failed to dequeue buffer.");
+    return -ENOMEM;
+  }
+
+  *out_buffer = CreateDvrReadBufferFromBufferConsumer(buffer);
+  *out_fence_fd = acquire_fence.Release();
+  return 0;
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
new file mode 100644
index 0000000..2abbe63
--- /dev/null
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -0,0 +1,20 @@
+#include "include/dvr/dvr_surface.h"
+
+#include <private/dvr/display_client.h>
+
+using namespace android;
+
+extern "C" {
+
+int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
+  auto client = android::dvr::DisplayClient::Create();
+  if (!client) {
+    ALOGE("Failed to create display client!");
+    return -ECOMM;
+  }
+
+  *pose_buffer = CreateDvrReadBufferFromBufferConsumer(client->GetPoseBuffer());
+  return 0;
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/include/CPPLINT.cfg b/libs/vr/libdvr/include/CPPLINT.cfg
new file mode 100644
index 0000000..2f8a3c0
--- /dev/null
+++ b/libs/vr/libdvr/include/CPPLINT.cfg
@@ -0,0 +1 @@
+filter=-build/header_guard
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
similarity index 100%
rename from libs/vr/libdisplay/include/private/dvr/display_manager_client.h
rename to libs/vr/libdvr/include/dvr/display_manager_client.h
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
new file mode 100644
index 0000000..6fd50ee
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -0,0 +1,220 @@
+#ifndef ANDROID_DVR_API_H_
+#define ANDROID_DVR_API_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DvrPoseAsync DvrPoseAsync;
+
+typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
+typedef struct DvrDisplayManagerClientSurfaceList
+    DvrDisplayManagerClientSurfaceList;
+typedef struct DvrDisplayManagerClientSurfaceBuffers
+    DvrDisplayManagerClientSurfaceBuffers;
+typedef struct DvrPose DvrPose;
+typedef struct dvr_vsync_client dvr_vsync_client;
+typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
+
+typedef DvrDisplayManagerClient* (*DisplayManagerClientCreatePtr)(void);
+typedef void (*DisplayManagerClientDestroyPtr)(DvrDisplayManagerClient* client);
+
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct AHardwareBuffer AHardwareBuffer;
+
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+// display_manager_client.h
+typedef int (*DisplayManagerClientGetSurfaceListPtr)(
+    DvrDisplayManagerClient* client,
+    DvrDisplayManagerClientSurfaceList** surface_list);
+typedef void (*DisplayManagerClientSurfaceListDestroyPtr)(
+    DvrDisplayManagerClientSurfaceList* surface_list);
+typedef DvrWriteBuffer* (*DisplayManagerSetupPoseBufferPtr)(
+    DvrDisplayManagerClient* client, size_t extended_region_size,
+    uint64_t usage0, uint64_t usage1);
+typedef size_t (*DisplayManagerClientSurfaceListGetSizePtr)(
+    DvrDisplayManagerClientSurfaceList* surface_list);
+typedef int (*DisplayManagerClientSurfaceListGetSurfaceIdPtr)(
+    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
+typedef int (*DisplayManagerClientGetSurfaceBufferListPtr)(
+    DvrDisplayManagerClient* client, int surface_id,
+    DvrDisplayManagerClientSurfaceBuffers** surface_buffers);
+typedef void (*DisplayManagerClientSurfaceBufferListDestroyPtr)(
+    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
+typedef size_t (*DisplayManagerClientSurfaceBufferListGetSizePtr)(
+    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
+typedef int (*DisplayManagerClientSurfaceBufferListGetFdPtr)(
+    DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index);
+
+// dvr_buffer.h
+typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
+typedef void (*DvrWriteBufferGetBlobFdsPtr)(DvrWriteBuffer* client, int* fds,
+                                            size_t* fds_count,
+                                            size_t max_fds_count);
+typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
+    DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
+                                     const void* meta, size_t meta_size_bytes);
+typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* client,
+                                     int* release_fence_fd);
+typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
+
+typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
+typedef void (*DvrReadBufferGetBlobFdsPtr)(DvrReadBuffer* client, int* fds,
+                                           size_t* fds_count,
+                                           size_t max_fds_count);
+typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
+    DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
+                                       int* ready_fence_fd, void* meta,
+                                       size_t meta_size_bytes);
+typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
+                                       int release_fence_fd);
+typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
+
+// dvr_buffer_queue.h
+typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
+typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
+    DvrWriteBufferQueue* write_queue);
+typedef void* (*DvrWriteBufferQueueGetExternalSurfacePtr)(
+    DvrWriteBufferQueue* write_queue, JNIEnv* env);
+typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
+    DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
+typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
+                                             int timeout,
+                                             DvrWriteBuffer** out_buffer,
+                                             int* out_fence_fd);
+typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue);
+typedef size_t (*DvrReadBufferQueueGetCapacityPtr)(
+    DvrReadBufferQueue* read_queue);
+typedef int (*DvrReadBufferQueueCreateReadQueuePtr)(
+    DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue);
+typedef int (*DvrReadBufferQueueDequeuePtr)(DvrReadBufferQueue* read_queue,
+                                            int timeout,
+                                            DvrReadBuffer** out_buffer,
+                                            int* out_fence_fd, void* out_meta,
+                                            size_t meta_size_bytes);
+
+// dvr_surface.h
+typedef int (*DvrGetPoseBufferPtr)(DvrReadBuffer** pose_buffer);
+
+// vsync_client_api.h
+typedef dvr_vsync_client* (*VSyncClientCreatePtr)();
+typedef void (*VSyncClientDestroyPtr)(dvr_vsync_client* client);
+typedef int (*VSyncClientGetSchedInfoPtr)(dvr_vsync_client* client,
+                                          int64_t* vsync_period_ns,
+                                          int64_t* next_timestamp_ns,
+                                          uint32_t* next_vsync_count);
+
+// pose_client.h
+typedef DvrPose* (*PoseClientCreatePtr)(void);
+typedef void (*PoseClientDestroyPtr)(DvrPose* client);
+typedef int (*PoseGetPtr)(DvrPose* client, uint32_t vsync_count,
+                          DvrPoseAsync* out_pose);
+typedef uint32_t (*PoseGetVsyncCountPtr)(DvrPose* client);
+typedef int (*PoseGetControllerPtr)(DvrPose* client, int32_t controller_id,
+                                    uint32_t vsync_count,
+                                    DvrPoseAsync* out_pose);
+
+// virtual_touchpad_client.h
+typedef DvrVirtualTouchpad* (*VirtualTouchpadCreatePtr)(void);
+typedef void (*VirtualTouchpadDestroyPtr)(DvrVirtualTouchpad* client);
+typedef int (*VirtualTouchpadAttachPtr)(DvrVirtualTouchpad* client);
+typedef int (*VirtualTouchpadDetachPtr)(DvrVirtualTouchpad* client);
+typedef int (*VirtualTouchpadTouchPtr)(DvrVirtualTouchpad* client, int touchpad,
+                                       float x, float y, float pressure);
+typedef int (*VirtualTouchpadButtonStatePtr)(DvrVirtualTouchpad* client,
+                                             int touchpad, int buttons);
+
+struct DvrApi_v1 {
+  // Display manager client
+  DisplayManagerClientCreatePtr display_manager_client_create_;
+  DisplayManagerClientDestroyPtr display_manager_client_destroy_;
+  DisplayManagerClientGetSurfaceListPtr
+      display_manager_client_get_surface_list_;
+  DisplayManagerClientSurfaceListDestroyPtr
+      display_manager_client_surface_list_destroy_;
+  DisplayManagerSetupPoseBufferPtr display_manager_setup_pose_buffer_;
+  DisplayManagerClientSurfaceListGetSizePtr
+      display_manager_client_surface_list_get_size_;
+  DisplayManagerClientSurfaceListGetSurfaceIdPtr
+      display_manager_client_surface_list_get_surface_id_;
+  DisplayManagerClientGetSurfaceBufferListPtr
+      display_manager_client_get_surface_buffer_list_;
+  DisplayManagerClientSurfaceBufferListDestroyPtr
+      display_manager_client_surface_buffer_list_destroy_;
+  DisplayManagerClientSurfaceBufferListGetSizePtr
+      display_manager_client_surface_buffer_list_get_size_;
+  DisplayManagerClientSurfaceBufferListGetFdPtr
+      display_manager_client_surface_buffer_list_get_fd_;
+
+  // Write buffer
+  DvrWriteBufferDestroyPtr write_buffer_destroy_;
+  DvrWriteBufferGetBlobFdsPtr write_buffer_get_blob_fds_;
+  DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_AHardwareBuffer_;
+  DvrWriteBufferPostPtr write_buffer_post_;
+  DvrWriteBufferGainPtr write_buffer_gain_;
+  DvrWriteBufferGainAsyncPtr write_buffer_gain_async_;
+
+  // Read buffer
+  DvrReadBufferDestroyPtr read_buffer_destroy_;
+  DvrReadBufferGetBlobFdsPtr read_buffer_get_blob_fds_;
+  DvrReadBufferGetAHardwareBufferPtr read_buffer_get_AHardwareBuffer_;
+  DvrReadBufferAcquirePtr read_buffer_acquire_;
+  DvrReadBufferReleasePtr read_buffer_release_;
+  DvrReadBufferReleaseAsyncPtr read_buffer_release_async_;
+
+  // Write buffer queue
+  DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy_;
+  DvrWriteBufferQueueGetCapacityPtr write_buffer_queue_get_capacity_;
+  DvrWriteBufferQueueGetExternalSurfacePtr
+      write_buffer_queue_get_external_surface_;
+  DvrWriteBufferQueueCreateReadQueuePtr write_buffer_queue_create_read_queue_;
+  DvrWriteBufferQueueDequeuePtr write_buffer_queue_dequeue_;
+
+  // Read buffer queue
+  DvrReadBufferQueueDestroyPtr read_buffer_queue_destroy_;
+  DvrReadBufferQueueGetCapacityPtr read_buffer_queue_get_capacity_;
+  DvrReadBufferQueueCreateReadQueuePtr read_buffer_queue_create_read_queue_;
+  DvrReadBufferQueueDequeuePtr read_buffer_queue_dequeue;
+
+  // V-Sync client
+  VSyncClientCreatePtr vsync_client_create_;
+  VSyncClientDestroyPtr vsync_client_destroy_;
+  VSyncClientGetSchedInfoPtr vsync_client_get_sched_info_;
+
+  // Display surface
+  DvrGetPoseBufferPtr get_pose_buffer_;
+
+  // Pose client
+  PoseClientCreatePtr pose_client_create_;
+  PoseClientDestroyPtr pose_client_destroy_;
+  PoseGetPtr pose_get_;
+  PoseGetVsyncCountPtr pose_get_vsync_count_;
+  PoseGetControllerPtr pose_get_controller_;
+
+  // Virtual touchpad client
+  VirtualTouchpadCreatePtr virtual_touchpad_create_;
+  VirtualTouchpadDestroyPtr virtual_touchpad_destroy_;
+  VirtualTouchpadAttachPtr virtual_touchpad_attach_;
+  VirtualTouchpadDetachPtr virtual_touchpad_detach_;
+  VirtualTouchpadTouchPtr virtual_touchpad_touch_;
+  VirtualTouchpadButtonStatePtr virtual_touchpad_button_state_;
+};
+
+int dvrGetApi(void* api, size_t struct_size, int version);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // ANDROID_DVR_API_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
similarity index 90%
rename from libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h
rename to libs/vr/libdvr/include/dvr/dvr_buffer.h
index c14b1a3..bbfbb00 100644
--- a/libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -25,6 +25,7 @@
 int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
 
 // Read buffer
+void dvrReadBufferDestroy(DvrReadBuffer* client);
 void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
                              size_t max_fds_count);
 int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
@@ -45,9 +46,9 @@
 class BufferConsumer;
 
 DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
-    std::unique_ptr<BufferProducer> buffer_producer);
+    const std::shared_ptr<BufferProducer>& buffer_producer);
 DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
-    std::unique_ptr<BufferConsumer> buffer_consumer);
+    const std::shared_ptr<BufferConsumer>& buffer_consumer);
 
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
new file mode 100644
index 0000000..86b3ae2
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -0,0 +1,41 @@
+#ifndef ANDROID_DVR_BUFFER_QUEUE_H_
+#define ANDROID_DVR_BUFFER_QUEUE_H_
+
+#include <dvr/dvr_buffer.h>
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+// WriteBufferQueue
+void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
+size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+
+// Returns ANativeWindow in the form of jobject. Can be casted to ANativeWindow
+// using ANativeWindow_fromSurface NDK API.
+void* dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+                                            JNIEnv* env);
+
+int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
+                                       DvrReadBufferQueue** out_read_queue);
+int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
+                               DvrWriteBuffer** out_buffer, int* out_fence_fd);
+
+// ReadeBufferQueue
+void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
+size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
+                                      DvrReadBufferQueue** out_read_queue);
+int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
+                              DvrReadBuffer** out_buffer, int* out_fence_fd,
+                              void* out_meta, size_t meta_size_bytes);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // ANDROID_DVR_BUFFER_QUEUE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
new file mode 100644
index 0000000..fa8d228
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -0,0 +1,17 @@
+#ifndef ANDROID_DVR_SURFACE_H_
+#define ANDROID_DVR_SURFACE_H_
+
+#include <dvr/dvr_buffer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Get a pointer to the global pose buffer.
+int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // ANDROID_DVR_SURFACE_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/vsync_client_api.h b/libs/vr/libdvr/include/dvr/vsync_client_api.h
similarity index 100%
rename from libs/vr/libdisplay/include/private/dvr/vsync_client_api.h
rename to libs/vr/libdvr/include/dvr/vsync_client_api.h
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
new file mode 100644
index 0000000..158d58f
--- /dev/null
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -0,0 +1,29 @@
+LOCAL_PATH := $(call my-dir)
+
+shared_libraries := \
+    libbase \
+    libbinder \
+    libcutils \
+    libgui \
+    liblog \
+    libhardware \
+    libui \
+    libutils \
+
+static_libraries := \
+    libdvr \
+    libbufferhubqueue \
+    libbufferhub \
+    libchrome \
+    libdvrcommon \
+    libpdx_default_transport \
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp
+LOCAL_STATIC_LIBRARIES := $(static_libraries)
+LOCAL_SHARED_LIBRARIES := $(shared_libraries)
+LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
+LOCAL_CFLAGS := -DLOG_TAG=\"dvr_buffer_queue-test\" -DTRACE=0 -O0 -g
+LOCAL_MODULE := dvr_buffer_queue-test
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
new file mode 100644
index 0000000..f344a24
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -0,0 +1,149 @@
+#include <dvr/dvr_buffer_queue.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+static constexpr int kBufferWidth = 100;
+static constexpr int kBufferHeight = 1;
+static constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
+static constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
+static constexpr int kBufferSliceCount = 1;  // number of slices in each buffer
+static constexpr size_t kQueueCapacity = 3;
+
+typedef uint64_t TestMeta;
+
+class DvrBufferQueueTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    write_queue_ = new DvrWriteBufferQueue;
+    write_queue_->producer_queue_ = ProducerQueue::Create<TestMeta>(0, 0, 0, 0);
+    ASSERT_NE(nullptr, write_queue_->producer_queue_);
+  }
+
+  void TearDown() override {
+    if (write_queue_ != nullptr) {
+      dvrWriteBufferQueueDestroy(write_queue_);
+      write_queue_ = nullptr;
+    }
+  }
+
+  void AllocateBuffers(size_t buffer_count) {
+    size_t out_slot;
+    for (size_t i = 0; i < buffer_count; i++) {
+      int ret = write_queue_->producer_queue_->AllocateBuffer(
+          kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage,
+          kBufferSliceCount, &out_slot);
+      ASSERT_EQ(0, ret);
+    }
+  }
+
+  DvrWriteBufferQueue* write_queue_{nullptr};
+};
+
+TEST_F(DvrBufferQueueTest, TestWrite_QueueDestroy) {
+  dvrWriteBufferQueueDestroy(write_queue_);
+  write_queue_ = nullptr;
+}
+
+TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) {
+  AllocateBuffers(kQueueCapacity);
+  size_t capacity = dvrWriteBufferQueueGetCapacity(write_queue_);
+
+  ALOGD_IF(TRACE, "TestWrite_QueueGetCapacity, capacity=%zu", capacity);
+  ASSERT_EQ(kQueueCapacity, capacity);
+}
+
+TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) {
+  DvrReadBufferQueue* read_queue = nullptr;
+  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, read_queue);
+
+  dvrReadBufferQueueDestroy(read_queue);
+}
+
+TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) {
+  DvrReadBufferQueue* read_queue1 = nullptr;
+  DvrReadBufferQueue* read_queue2 = nullptr;
+  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);
+
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, read_queue1);
+
+  ret = dvrReadBufferQueueCreateReadQueue(read_queue1, &read_queue2);
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, read_queue2);
+  ASSERT_NE(read_queue1, read_queue2);
+
+  dvrReadBufferQueueDestroy(read_queue1);
+  dvrReadBufferQueueDestroy(read_queue2);
+}
+
+TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
+  static constexpr int kTimeout = 0;
+  DvrReadBufferQueue* read_queue = nullptr;
+  DvrReadBuffer* rb = nullptr;
+  DvrWriteBuffer* wb = nullptr;
+  int fence_fd = -1;
+
+  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, read_queue);
+
+  AllocateBuffers(kQueueCapacity);
+
+  // Gain buffer for writing.
+  ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, &wb, &fence_fd);
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, wb);
+  ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
+           wb, fence_fd);
+  pdx::LocalHandle release_fence(fence_fd);
+
+  // Post buffer to the read_queue.
+  TestMeta seq = 42U;
+  ret = dvrWriteBufferPost(wb, /* fence */ -1, &seq, sizeof(seq));
+  ASSERT_EQ(0, ret);
+  dvrWriteBufferDestroy(wb);
+  wb = nullptr;
+
+  // Acquire buffer for reading.
+  TestMeta acquired_seq = 0U;
+  ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, &rb, &fence_fd,
+                                  &acquired_seq, sizeof(acquired_seq));
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, rb);
+  ASSERT_EQ(seq, acquired_seq);
+  ALOGD_IF(TRACE,
+           "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
+           fence_fd);
+  pdx::LocalHandle acquire_fence(fence_fd);
+
+  // Release buffer to the write_queue.
+  ret = dvrReadBufferRelease(rb, -1);
+  ASSERT_EQ(0, ret);
+  dvrReadBufferDestroy(rb);
+  rb = nullptr;
+
+  // TODO(b/34387835) Currently buffer allocation has to happen after all queues
+  // are initialized.
+  size_t capacity = dvrReadBufferQueueGetCapacity(read_queue);
+
+  ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, capacity=%zu", capacity);
+  ASSERT_EQ(kQueueCapacity, capacity);
+
+  dvrReadBufferQueueDestroy(read_queue);
+}
+
+}  // namespace
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libdisplay/vsync_client_api.cpp b/libs/vr/libdvr/vsync_client_api.cpp
similarity index 93%
rename from libs/vr/libdisplay/vsync_client_api.cpp
rename to libs/vr/libdvr/vsync_client_api.cpp
index 00af525..dbddd3d 100644
--- a/libs/vr/libdisplay/vsync_client_api.cpp
+++ b/libs/vr/libdvr/vsync_client_api.cpp
@@ -1,4 +1,4 @@
-#include "include/private/dvr/vsync_client_api.h"
+#include "include/dvr/vsync_client_api.h"
 
 #include <private/dvr/vsync_client.h>