Merge "Use IVrComposerClient interface to expose the VR HWC client"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 054b00e..457d203 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <zlib.h>
 
+#include <fstream>
 #include <memory>
 
 #include <binder/IBinder.h>
@@ -172,6 +173,7 @@
         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
         { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
         { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
+        { REQ,      "events/lowmemorykiller/enable" },
     } },
     { "regulators",  "Voltage and Current Regulators", 0, {
         { REQ,      "events/regulator/enable" },
@@ -181,9 +183,9 @@
         { REQ,      "events/binder/binder_transaction_received/enable" },
     } },
     { "binder_lock", "Binder global lock trace", 0, {
-        { REQ,      "events/binder/binder_lock/enable" },
-        { REQ,      "events/binder/binder_locked/enable" },
-        { REQ,      "events/binder/binder_unlock/enable" },
+        { OPT,      "events/binder/binder_lock/enable" },
+        { OPT,      "events/binder/binder_locked/enable" },
+        { OPT,      "events/binder/binder_unlock/enable" },
     } },
     { "pagecache",  "Page cache", 0, {
         { REQ,      "events/filemap/enable" },
@@ -371,7 +373,7 @@
                     ok = true;
                 }
             } else {
-                ok |= fileIsWritable(path);
+                ok = true;
             }
         }
     }
@@ -434,56 +436,31 @@
     return writeStr(k_traceBufferSizePath, str);
 }
 
-// Read the trace_clock sysfs file and return true if it matches the requested
-// value.  The trace_clock file format is:
-// local [global] counter uptime perf
-static bool isTraceClock(const char *mode)
-{
-    int fd = open((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
-    if (fd == -1) {
-        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath,
-            strerror(errno), errno);
-        return false;
-    }
-
-    char buf[4097];
-    ssize_t n = read(fd, buf, 4096);
-    close(fd);
-    if (n == -1) {
-        fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
-            strerror(errno), errno);
-        return false;
-    }
-    buf[n] = '\0';
-
-    char *start = strchr(buf, '[');
-    if (start == NULL) {
-        return false;
-    }
-    start++;
-
-    char *end = strchr(start, ']');
-    if (end == NULL) {
-        return false;
-    }
-    *end = '\0';
-
-    return strcmp(mode, start) == 0;
-}
-
-// Enable or disable the kernel's use of the global clock.  Disabling the global
-// clock will result in the kernel using a per-CPU local clock.
+// Set the clock to the best available option while tracing. Use 'boot' if it's
+// available; otherwise, use 'mono'. If neither are available use 'global'.
 // Any write to the trace_clock sysfs file will reset the buffer, so only
 // update it if the requested value is not the current value.
-static bool setGlobalClockEnable(bool enable)
+static bool setClock()
 {
-    const char *clock = enable ? "global" : "local";
+    std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
+    std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
+        std::istreambuf_iterator<char>());
 
-    if (isTraceClock(clock)) {
-        return true;
+    std::string newClock;
+    if (clockStr.find("boot") != std::string::npos) {
+        newClock = "boot";
+    } else if (clockStr.find("mono") != std::string::npos) {
+        newClock = "mono";
+    } else {
+        newClock = "global";
     }
 
-    return writeStr(k_traceClockPath, clock);
+    size_t begin = clockStr.find("[") + 1;
+    size_t end = clockStr.find("]");
+    if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
+        return true;
+    }
+    return writeStr(k_traceClockPath, newClock.c_str());
 }
 
 static bool setPrintTgidEnableIfPresent(bool enable)
@@ -776,7 +753,7 @@
     ok &= setCategoriesEnableFromFile(g_categoriesFile);
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
-    ok &= setGlobalClockEnable(true);
+    ok &= setClock();
     ok &= setPrintTgidEnableIfPresent(true);
     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
 
@@ -848,7 +825,6 @@
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
     setTraceBufferSizeKB(1);
-    setGlobalClockEnable(false);
     setPrintTgidEnableIfPresent(false);
     setKernelTraceFuncs(NULL);
 }
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index cef41be..1e0f6f8 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -51,6 +51,8 @@
     chown root shell /sys/kernel/tracing/events/binder/binder_locked/enable
     chown root shell /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
     chown root shell /sys/kernel/tracing/events/binder/binder_unlock/enable
+    chown root shell /sys/kernel/debug/tracing/events/lowmemorykiller/enable
+    chown root shell /sys/kernel/tracing/events/lowmemorykiller/enable
 
     chown root shell /sys/kernel/debug/tracing/tracing_on
     chown root shell /sys/kernel/tracing/tracing_on
@@ -119,6 +121,8 @@
     chmod 0664 /sys/kernel/tracing/events/i2c/smbus_result/enable
     chmod 0664 /sys/kernel/debug/tracing/events/i2c/smbus_reply/enable
     chmod 0664 /sys/kernel/tracing/events/i2c/smbus_reply/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/lowmemorykiller/enable
+    chmod 0664 /sys/kernel/tracing/events/lowmemorykiller/enable
 
     # Tracing disabled by default
     write /sys/kernel/debug/tracing/tracing_on 0
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 73d274f..7e05d72 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -123,6 +123,13 @@
 {
     signal(SIGPIPE, SIG_IGN);
     sp<ProcessState> proc = ProcessState::self();
+    // setThreadPoolMaxThreadCount(0) actually tells the kernel it's
+    // not allowed to spawn any additional threads, but we still spawn
+    // a binder thread from userspace when we call startThreadPool().
+    // This is safe because we only have 2 callbacks, neither of which
+    // block.
+    // See b/36066697 for rationale
+    proc->setThreadPoolMaxThreadCount(0);
     proc->startThreadPool();
 
     sp<IServiceManager> sm = defaultServiceManager();
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 6e89f3a..b8e56e3 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -2007,8 +2007,6 @@
 
     int idmap_fd = -1;
     char idmap_path[PATH_MAX];
-    struct stat target_apk_stat, overlay_apk_stat, idmap_stat;
-    bool outdated = false;
 
     if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
                 idmap_path, sizeof(idmap_path)) == -1) {
@@ -2016,22 +2014,8 @@
         goto fail;
     }
 
-    if (stat(idmap_path, &idmap_stat) < 0 ||
-            stat(target_apk, &target_apk_stat) < 0 ||
-            stat(overlay_apk, &overlay_apk_stat) < 0) {
-        outdated = true;
-    } else if (idmap_stat.st_mtime < target_apk_stat.st_mtime ||
-            idmap_stat.st_mtime < overlay_apk_stat.st_mtime) {
-        outdated = true;
-    }
-
-    if (outdated) {
-        unlink(idmap_path);
-        idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644);
-    } else {
-        idmap_fd = open(idmap_path, O_RDWR);
-    }
-
+    unlink(idmap_path);
+    idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644);
     if (idmap_fd < 0) {
         ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno));
         goto fail;
@@ -2045,11 +2029,6 @@
         goto fail;
     }
 
-    if (!outdated) {
-        close(idmap_fd);
-        return ok();
-    }
-
     pid_t pid;
     pid = fork();
     if (pid == 0) {
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 5a78d78..7419eb4 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1763,10 +1763,20 @@
             result = false;
             continue;
         }
+
+        // Delete oat/vdex/art files.
         result = unlink_if_exists(oat_path) && result;
         result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
         result = unlink_if_exists(create_image_filename(oat_path)) && result;
 
+        // Delete profiles.
+        std::string current_profile = create_current_profile_path(
+                multiuser_get_user_id(uid), dex_path, /*is_secondary*/true);
+        std::string reference_profile = create_reference_profile_path(
+                dex_path, /*is_secondary*/true);
+        result = unlink_if_exists(current_profile) && result;
+        result = unlink_if_exists(reference_profile) && result;
+
         // Try removing the directories as well, they might be empty.
         result = rmdir_if_empty(oat_isa_dir) && result;
         result = rmdir_if_empty(oat_dir) && result;
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 43d0780..68cb0d7 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -64,6 +64,25 @@
 namespace android {
 namespace installd {
 
+// Check expected values for dexopt flags. If you need to change this:
+//
+//   RUN AN A/B OTA TO MAKE SURE THINGS STILL WORK!
+//
+// You most likely need to increase the protocol version and all that entails!
+
+static_assert(DEXOPT_PUBLIC         == 1 << 1, "DEXOPT_PUBLIC unexpected.");
+static_assert(DEXOPT_DEBUGGABLE     == 1 << 2, "DEXOPT_DEBUGGABLE unexpected.");
+static_assert(DEXOPT_BOOTCOMPLETE   == 1 << 3, "DEXOPT_BOOTCOMPLETE unexpected.");
+static_assert(DEXOPT_PROFILE_GUIDED == 1 << 4, "DEXOPT_PROFILE_GUIDED unexpected.");
+static_assert(DEXOPT_SECONDARY_DEX  == 1 << 5, "DEXOPT_SECONDARY_DEX unexpected.");
+static_assert(DEXOPT_FORCE          == 1 << 6, "DEXOPT_FORCE unexpected.");
+static_assert(DEXOPT_STORAGE_CE     == 1 << 7, "DEXOPT_STORAGE_CE unexpected.");
+static_assert(DEXOPT_STORAGE_DE     == 1 << 8, "DEXOPT_STORAGE_DE unexpected.");
+
+static_assert(DEXOPT_MASK           == 0x1fe, "DEXOPT_MASK unexpected.");
+
+
+
 template<typename T>
 static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
     return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index df4941c..67b5b46 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_binary {
-    name: "lshal",
+cc_library_shared {
+    name: "liblshal",
     shared_libs: [
         "libbase",
         "libcutils",
@@ -24,7 +24,44 @@
         "libvintf",
     ],
     srcs: [
+        "DebugCommand.cpp",
         "Lshal.cpp",
-        "PipeRelay.cpp"
+        "ListCommand.cpp",
+        "PipeRelay.cpp",
+        "utils.cpp",
     ],
 }
+
+cc_defaults {
+    name: "lshal_defaults",
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "liblshal",
+        "libutils",
+    ]
+}
+
+cc_binary {
+    name: "lshal",
+    defaults: ["lshal_defaults"],
+    srcs: [
+        "main.cpp"
+    ]
+}
+
+cc_test {
+    name: "lshal_test",
+    defaults: ["lshal_defaults"],
+    gtest: true,
+    static_libs: [
+        "libgmock"
+    ],
+    shared_libs: [
+        "android.hardware.tests.baz@1.0"
+    ],
+    srcs: [
+        "test.cpp"
+    ]
+}
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
new file mode 100644
index 0000000..672cad6
--- /dev/null
+++ b/cmds/lshal/DebugCommand.cpp
@@ -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.
+ */
+
+#include "DebugCommand.h"
+
+#include "Lshal.h"
+
+namespace android {
+namespace lshal {
+
+DebugCommand::DebugCommand(Lshal &lshal) : mLshal(lshal) {
+}
+
+Status DebugCommand::parseArgs(const std::string &command, const Arg &arg) {
+    if (optind >= arg.argc) {
+        mLshal.usage(command);
+        return USAGE;
+    }
+    mInterfaceName = arg.argv[optind];
+    ++optind;
+    for (; optind < arg.argc; ++optind) {
+        mOptions.push_back(arg.argv[optind]);
+    }
+    return OK;
+}
+
+Status DebugCommand::main(const std::string &command, const Arg &arg) {
+    Status status = parseArgs(command, arg);
+    if (status != OK) {
+        return status;
+    }
+    auto pair = splitFirst(mInterfaceName, '/');
+    return mLshal.emitDebugInfo(
+            pair.first, pair.second.empty() ? "default" : pair.second, mOptions,
+            mLshal.out().buf(),
+            mLshal.err());
+}
+
+}  // namespace lshal
+}  // namespace android
+
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
new file mode 100644
index 0000000..fa0f0fa
--- /dev/null
+++ b/cmds/lshal/DebugCommand.h
@@ -0,0 +1,49 @@
+/*
+ * 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 FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
+
+#include <string>
+
+#include <android-base/macros.h>
+
+#include "utils.h"
+
+namespace android {
+namespace lshal {
+
+class Lshal;
+
+class DebugCommand {
+public:
+    DebugCommand(Lshal &lshal);
+    Status main(const std::string &command, const Arg &arg);
+private:
+    Status parseArgs(const std::string &command, const Arg &arg);
+
+    Lshal &mLshal;
+    std::string mInterfaceName;
+    std::vector<std::string> mOptions;
+
+    DISALLOW_COPY_AND_ASSIGN(DebugCommand);
+};
+
+
+}  // namespace lshal
+}  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
new file mode 100644
index 0000000..38b406c
--- /dev/null
+++ b/cmds/lshal/ListCommand.cpp
@@ -0,0 +1,716 @@
+/*
+ * 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 "ListCommand.h"
+
+#include <getopt.h>
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <regex>
+
+#include <android-base/parseint.h>
+#include <android/hidl/manager/1.0/IServiceManager.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 "Lshal.h"
+#include "PipeRelay.h"
+#include "Timeout.h"
+#include "utils.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hidl::manager::V1_0::IServiceManager;
+
+namespace android {
+namespace lshal {
+
+ListCommand::ListCommand(Lshal &lshal) : mLshal(lshal), mErr(lshal.err()), mOut(lshal.out()) {
+}
+
+std::string getCmdline(pid_t pid) {
+    std::ifstream ifs("/proc/" + std::to_string(pid) + "/cmdline");
+    std::string cmdline;
+    if (!ifs.is_open()) {
+        return "";
+    }
+    ifs >> cmdline;
+    return cmdline;
+}
+
+const std::string &ListCommand::getCmdline(pid_t pid) {
+    auto pair = mCmdlines.find(pid);
+    if (pair != mCmdlines.end()) {
+        return pair->second;
+    }
+    mCmdlines[pid] = ::android::lshal::getCmdline(pid);
+    return mCmdlines[pid];
+}
+
+void ListCommand::removeDeadProcesses(Pids *pids) {
+    static const pid_t myPid = getpid();
+    pids->erase(std::remove_if(pids->begin(), pids->end(), [this](auto pid) {
+        return pid == myPid || this->getCmdline(pid).empty();
+    }), pids->end());
+}
+
+bool ListCommand::getReferencedPids(
+        pid_t serverPid, std::map<uint64_t, Pids> *objects) const {
+
+    std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid));
+    if (!ifs.is_open()) {
+        return false;
+    }
+
+    static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
+
+    std::string line;
+    std::smatch match;
+    while(getline(ifs, line)) {
+        if (!std::regex_search(line, match, prefix)) {
+            // the line doesn't start with the correct prefix
+            continue;
+        }
+        std::string ptrString = "0x" + match.str(2); // use number after c
+        uint64_t ptr;
+        if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
+            // Should not reach here, but just be tolerant.
+            mErr << "Could not parse number " << ptrString << std::endl;
+            continue;
+        }
+        const std::string proc = " proc ";
+        auto pos = line.rfind(proc);
+        if (pos != std::string::npos) {
+            for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) {
+                int32_t pid;
+                if (!::android::base::ParseInt(pidStr, &pid)) {
+                    mErr << "Could not parse number " << pidStr << std::endl;
+                    continue;
+                }
+                (*objects)[ptr].push_back(pid);
+            }
+        }
+    }
+    return true;
+}
+
+// Must process hwbinder services first, then passthrough services.
+void ListCommand::forEachTable(const std::function<void(Table &)> &f) {
+    f(mServicesTable);
+    f(mPassthroughRefTable);
+    f(mImplementationsTable);
+}
+void ListCommand::forEachTable(const std::function<void(const Table &)> &f) const {
+    f(mServicesTable);
+    f(mPassthroughRefTable);
+    f(mImplementationsTable);
+}
+
+void ListCommand::postprocess() {
+    forEachTable([this](Table &table) {
+        if (mSortColumn) {
+            std::sort(table.begin(), table.end(), mSortColumn);
+        }
+        for (TableEntry &entry : table) {
+            entry.serverCmdline = getCmdline(entry.serverPid);
+            removeDeadProcesses(&entry.clientPids);
+            for (auto pid : entry.clientPids) {
+                entry.clientCmdlines.push_back(this->getCmdline(pid));
+            }
+        }
+    });
+    // use a double for loop here because lshal doesn't care about efficiency.
+    for (TableEntry &packageEntry : mImplementationsTable) {
+        std::string packageName = packageEntry.interfaceName;
+        FQName fqPackageName{packageName.substr(0, packageName.find("::"))};
+        if (!fqPackageName.isValid()) {
+            continue;
+        }
+        for (TableEntry &interfaceEntry : mPassthroughRefTable) {
+            if (interfaceEntry.arch != ARCH_UNKNOWN) {
+                continue;
+            }
+            FQName interfaceName{splitFirst(interfaceEntry.interfaceName, '/').first};
+            if (!interfaceName.isValid()) {
+                continue;
+            }
+            if (interfaceName.getPackageAndVersion() == fqPackageName) {
+                interfaceEntry.arch = packageEntry.arch;
+            }
+        }
+    }
+}
+
+void ListCommand::printLine(
+        const std::string &interfaceName,
+        const std::string &transport,
+        const std::string &arch,
+        const std::string &server,
+        const std::string &serverCmdline,
+        const std::string &address, const std::string &clients,
+        const std::string &clientCmdlines) const {
+    if (mSelectedColumns & ENABLE_INTERFACE_NAME)
+        mOut << std::setw(80) << interfaceName << "\t";
+    if (mSelectedColumns & ENABLE_TRANSPORT)
+        mOut << std::setw(10) << transport << "\t";
+    if (mSelectedColumns & ENABLE_ARCH)
+        mOut << std::setw(5) << arch << "\t";
+    if (mSelectedColumns & ENABLE_SERVER_PID) {
+        if (mEnableCmdlines) {
+            mOut << std::setw(15) << serverCmdline << "\t";
+        } else {
+            mOut << std::setw(5)  << server << "\t";
+        }
+    }
+    if (mSelectedColumns & ENABLE_SERVER_ADDR)
+        mOut << std::setw(16) << address << "\t";
+    if (mSelectedColumns & ENABLE_CLIENT_PIDS) {
+        if (mEnableCmdlines) {
+            mOut << std::setw(0)  << clientCmdlines;
+        } else {
+            mOut << std::setw(0)  << clients;
+        }
+    }
+    mOut << std::endl;
+}
+
+void ListCommand::dumpVintf() const {
+    mOut << "<!-- " << std::endl
+         << "    This is a skeleton device manifest. Notes: " << std::endl
+         << "    1. android.hidl.*, android.frameworks.*, android.system.* are not included." << std::endl
+         << "    2. If a HAL is supported in both hwbinder and passthrough transport, " << std::endl
+         << "       only hwbinder is shown." << std::endl
+         << "    3. It is likely that HALs in passthrough transport does not have" << std::endl
+         << "       <interface> declared; users will have to write them by hand." << std::endl
+         << "    4. sepolicy version is set to 0.0. It is recommended that the entry" << std::endl
+         << "       is removed from the manifest file and written by assemble_vintf" << std::endl
+         << "       at build time." << std::endl
+         << "-->" << std::endl;
+
+    vintf::HalManifest manifest;
+    forEachTable([this, &manifest] (const Table &table) {
+        for (const TableEntry &entry : table) {
+
+            std::string fqInstanceName = entry.interfaceName;
+
+            if (&table == &mImplementationsTable) {
+                // Quick hack to work around *'s
+                replaceAll(&fqInstanceName, '*', 'D');
+            }
+            auto splittedFqInstanceName = splitFirst(fqInstanceName, '/');
+            FQName fqName(splittedFqInstanceName.first);
+            if (!fqName.isValid()) {
+                mErr << "Warning: '" << splittedFqInstanceName.first
+                     << "' is not a valid FQName." << std::endl;
+                continue;
+            }
+            // Strip out system libs.
+            if (fqName.inPackage("android.hidl") ||
+                fqName.inPackage("android.frameworks") ||
+                fqName.inPackage("android.system")) {
+                continue;
+            }
+            std::string interfaceName =
+                    &table == &mImplementationsTable ? "" : fqName.name();
+            std::string instanceName =
+                    &table == &mImplementationsTable ? "" : splittedFqInstanceName.second;
+
+            vintf::Version version{fqName.getPackageMajorVersion(),
+                                   fqName.getPackageMinorVersion()};
+            vintf::Transport transport;
+            vintf::Arch arch;
+            if (entry.transport == "hwbinder") {
+                transport = vintf::Transport::HWBINDER;
+                arch = vintf::Arch::ARCH_EMPTY;
+            } else if (entry.transport == "passthrough") {
+                transport = vintf::Transport::PASSTHROUGH;
+                switch (entry.arch) {
+                    case lshal::ARCH32:
+                        arch = vintf::Arch::ARCH_32;    break;
+                    case lshal::ARCH64:
+                        arch = vintf::Arch::ARCH_64;    break;
+                    case lshal::ARCH_BOTH:
+                        arch = vintf::Arch::ARCH_32_64; break;
+                    case lshal::ARCH_UNKNOWN: // fallthrough
+                    default:
+                        mErr << "Warning: '" << fqName.package()
+                             << "' doesn't have bitness info, assuming 32+64." << std::endl;
+                        arch = vintf::Arch::ARCH_32_64;
+                }
+            } else {
+                mErr << "Warning: '" << entry.transport << "' is not a valid transport." << std::endl;
+                continue;
+            }
+
+            bool done = false;
+            for (vintf::ManifestHal *hal : manifest.getHals(fqName.package())) {
+                if (hal->transport() != transport) {
+                    if (transport != vintf::Transport::PASSTHROUGH) {
+                        mErr << "Fatal: should not reach here. Generated result may be wrong."
+                             << std::endl;
+                    }
+                    done = true;
+                    break;
+                }
+                if (hal->hasVersion(version)) {
+                    if (&table != &mImplementationsTable) {
+                        hal->interfaces[interfaceName].name = interfaceName;
+                        hal->interfaces[interfaceName].instances.insert(instanceName);
+                    }
+                    done = true;
+                    break;
+                }
+            }
+            if (done) {
+                continue; // to next TableEntry
+            }
+            decltype(vintf::ManifestHal::interfaces) interfaces;
+            if (&table != &mImplementationsTable) {
+                interfaces[interfaceName].name = interfaceName;
+                interfaces[interfaceName].instances.insert(instanceName);
+            }
+            if (!manifest.add(vintf::ManifestHal{
+                    .format = vintf::HalFormat::HIDL,
+                    .name = fqName.package(),
+                    .versions = {version},
+                    .transportArch = {transport, arch},
+                    .interfaces = interfaces})) {
+                mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
+            }
+        }
+    });
+    mOut << vintf::gHalManifestConverter(manifest);
+}
+
+static const std::string &getArchString(Architecture arch) {
+    static const std::string sStr64 = "64";
+    static const std::string sStr32 = "32";
+    static const std::string sStrBoth = "32+64";
+    static const std::string sStrUnknown = "";
+    switch (arch) {
+        case ARCH64:
+            return sStr64;
+        case ARCH32:
+            return sStr32;
+        case ARCH_BOTH:
+            return sStrBoth;
+        case ARCH_UNKNOWN: // fall through
+        default:
+            return sStrUnknown;
+    }
+}
+
+static Architecture fromBaseArchitecture(::android::hidl::base::V1_0::DebugInfo::Architecture a) {
+    switch (a) {
+        case ::android::hidl::base::V1_0::DebugInfo::Architecture::IS_64BIT:
+            return ARCH64;
+        case ::android::hidl::base::V1_0::DebugInfo::Architecture::IS_32BIT:
+            return ARCH32;
+        case ::android::hidl::base::V1_0::DebugInfo::Architecture::UNKNOWN: // fallthrough
+        default:
+            return ARCH_UNKNOWN;
+    }
+}
+
+void ListCommand::dumpTable() {
+    mServicesTable.description =
+            "All binderized services (registered services through hwservicemanager)";
+    mPassthroughRefTable.description =
+            "All interfaces that getService() has ever return as a passthrough interface;\n"
+            "PIDs / processes shown below might be inaccurate because the process\n"
+            "might have relinquished the interface or might have died.\n"
+            "The Server / Server CMD column can be ignored.\n"
+            "The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
+            "the library and successfully fetched the passthrough implementation.";
+    mImplementationsTable.description =
+            "All available passthrough implementations (all -impl.so files)";
+    forEachTable([this] (const Table &table) {
+        if (!mNeat) {
+            mOut << table.description << std::endl;
+        }
+        mOut << std::left;
+        if (!mNeat) {
+            printLine("Interface", "Transport", "Arch", "Server", "Server CMD",
+                      "PTR", "Clients", "Clients CMD");
+        }
+
+        for (const auto &entry : table) {
+            printLine(entry.interfaceName,
+                    entry.transport,
+                    getArchString(entry.arch),
+                    entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid),
+                    entry.serverCmdline,
+                    entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress),
+                    join(entry.clientPids, " "),
+                    join(entry.clientCmdlines, ";"));
+
+            // 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".
+            if (mEmitDebugInfo && &table == &mServicesTable) {
+                auto pair = splitFirst(entry.interfaceName, '/');
+                mLshal.emitDebugInfo(pair.first, pair.second, {}, mOut.buf(),
+                        NullableOStream<std::ostream>(nullptr));
+            }
+        }
+        if (!mNeat) {
+            mOut << std::endl;
+        }
+    });
+
+}
+
+void ListCommand::dump() {
+    if (mVintf) {
+        dumpVintf();
+        if (!!mFileOutput) {
+            mFileOutput.buf().close();
+            delete &mFileOutput.buf();
+            mFileOutput = nullptr;
+        }
+        mOut = std::cout;
+    } else {
+        dumpTable();
+    }
+}
+
+void ListCommand::putEntry(TableEntrySource source, TableEntry &&entry) {
+    Table *table = nullptr;
+    switch (source) {
+        case HWSERVICEMANAGER_LIST :
+            table = &mServicesTable; break;
+        case PTSERVICEMANAGER_REG_CLIENT :
+            table = &mPassthroughRefTable; break;
+        case LIST_DLLIB :
+            table = &mImplementationsTable; break;
+        default:
+            mErr << "Error: Unknown source of entry " << source << std::endl;
+    }
+    if (table) {
+        table->entries.push_back(std::forward<TableEntry>(entry));
+    }
+}
+
+Status ListCommand::fetchAllLibraries(const sp<IServiceManager> &manager) {
+    using namespace ::android::hardware;
+    using namespace ::android::hidl::manager::V1_0;
+    using namespace ::android::hidl::base::V1_0;
+    auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) {
+        std::map<std::string, TableEntry> entries;
+        for (const auto &info : infos) {
+            std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" +
+                    std::string{info.instanceName.c_str()};
+            entries.emplace(interfaceName, TableEntry{
+                .interfaceName = interfaceName,
+                .transport = "passthrough",
+                .serverPid = NO_PID,
+                .serverObjectAddress = NO_PTR,
+                .clientPids = {},
+                .arch = ARCH_UNKNOWN
+            }).first->second.arch |= fromBaseArchitecture(info.arch);
+        }
+        for (auto &&pair : entries) {
+            putEntry(LIST_DLLIB, std::move(pair.second));
+        }
+    });
+    if (!ret.isOk()) {
+        mErr << "Error: Failed to call list on getPassthroughServiceManager(): "
+             << ret.description() << std::endl;
+        return DUMP_ALL_LIBS_ERROR;
+    }
+    return OK;
+}
+
+Status ListCommand::fetchPassthrough(const sp<IServiceManager> &manager) {
+    using namespace ::android::hardware;
+    using namespace ::android::hardware::details;
+    using namespace ::android::hidl::manager::V1_0;
+    using namespace ::android::hidl::base::V1_0;
+    auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) {
+        for (const auto &info : infos) {
+            if (info.clientPids.size() <= 0) {
+                continue;
+            }
+            putEntry(PTSERVICEMANAGER_REG_CLIENT, {
+                .interfaceName =
+                        std::string{info.interfaceName.c_str()} + "/" +
+                        std::string{info.instanceName.c_str()},
+                .transport = "passthrough",
+                .serverPid = info.clientPids.size() == 1 ? info.clientPids[0] : NO_PID,
+                .serverObjectAddress = NO_PTR,
+                .clientPids = info.clientPids,
+                .arch = fromBaseArchitecture(info.arch)
+            });
+        }
+    });
+    if (!ret.isOk()) {
+        mErr << "Error: Failed to call debugDump on defaultServiceManager(): "
+             << ret.description() << std::endl;
+        return DUMP_PASSTHROUGH_ERROR;
+    }
+    return OK;
+}
+
+Status ListCommand::fetchBinderized(const sp<IServiceManager> &manager) {
+    using namespace ::std;
+    using namespace ::android::hardware;
+    using namespace ::android::hidl::manager::V1_0;
+    using namespace ::android::hidl::base::V1_0;
+    const std::string mode = "hwbinder";
+
+    hidl_vec<hidl_string> fqInstanceNames;
+    // copying out for timeoutIPC
+    auto listRet = timeoutIPC(manager, &IServiceManager::list, [&] (const auto &names) {
+        fqInstanceNames = names;
+    });
+    if (!listRet.isOk()) {
+        mErr << "Error: Failed to list services for " << mode << ": "
+             << listRet.description() << std::endl;
+        return DUMP_BINDERIZED_ERROR;
+    }
+
+    Status status = OK;
+    // server pid, .ptr value of binder object, child pids
+    std::map<std::string, DebugInfo> allDebugInfos;
+    std::map<pid_t, std::map<uint64_t, Pids>> allPids;
+    for (const auto &fqInstanceName : fqInstanceNames) {
+        const auto pair = splitFirst(fqInstanceName, '/');
+        const auto &serviceName = pair.first;
+        const auto &instanceName = pair.second;
+        auto getRet = timeoutIPC(manager, &IServiceManager::get, serviceName, instanceName);
+        if (!getRet.isOk()) {
+            mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
+                 << "cannot be fetched from service manager:"
+                 << getRet.description() << std::endl;
+            status |= DUMP_BINDERIZED_ERROR;
+            continue;
+        }
+        sp<IBase> service = getRet;
+        if (service == nullptr) {
+            mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
+                 << "cannot be fetched from service manager (null)"
+                 << std::endl;
+            status |= DUMP_BINDERIZED_ERROR;
+            continue;
+        }
+        auto debugRet = timeoutIPC(service, &IBase::getDebugInfo, [&] (const auto &debugInfo) {
+            allDebugInfos[fqInstanceName] = debugInfo;
+            if (debugInfo.pid >= 0) {
+                allPids[static_cast<pid_t>(debugInfo.pid)].clear();
+            }
+        });
+        if (!debugRet.isOk()) {
+            mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
+                 << "debugging information cannot be retrieved:"
+                 << debugRet.description() << std::endl;
+            status |= DUMP_BINDERIZED_ERROR;
+        }
+    }
+    for (auto &pair : allPids) {
+        pid_t serverPid = pair.first;
+        if (!getReferencedPids(serverPid, &allPids[serverPid])) {
+            mErr << "Warning: no information for PID " << serverPid
+                      << ", are you root?" << std::endl;
+            status |= DUMP_BINDERIZED_ERROR;
+        }
+    }
+    for (const auto &fqInstanceName : fqInstanceNames) {
+        auto it = allDebugInfos.find(fqInstanceName);
+        if (it == allDebugInfos.end()) {
+            putEntry(HWSERVICEMANAGER_LIST, {
+                .interfaceName = fqInstanceName,
+                .transport = mode,
+                .serverPid = NO_PID,
+                .serverObjectAddress = NO_PTR,
+                .clientPids = {},
+                .arch = ARCH_UNKNOWN
+            });
+            continue;
+        }
+        const DebugInfo &info = it->second;
+        putEntry(HWSERVICEMANAGER_LIST, {
+            .interfaceName = fqInstanceName,
+            .transport = mode,
+            .serverPid = info.pid,
+            .serverObjectAddress = info.ptr,
+            .clientPids = info.pid == NO_PID || info.ptr == NO_PTR
+                    ? Pids{} : allPids[info.pid][info.ptr],
+            .arch = fromBaseArchitecture(info.arch),
+        });
+    }
+    return status;
+}
+
+Status ListCommand::fetch() {
+    Status status = OK;
+    auto bManager = mLshal.serviceManager();
+    if (bManager == nullptr) {
+        mErr << "Failed to get defaultServiceManager()!" << std::endl;
+        status |= NO_BINDERIZED_MANAGER;
+    } else {
+        status |= fetchBinderized(bManager);
+        // Passthrough PIDs are registered to the binderized manager as well.
+        status |= fetchPassthrough(bManager);
+    }
+
+    auto pManager = mLshal.passthroughManager();
+    if (pManager == nullptr) {
+        mErr << "Failed to get getPassthroughServiceManager()!" << std::endl;
+        status |= NO_PASSTHROUGH_MANAGER;
+    } else {
+        status |= fetchAllLibraries(pManager);
+    }
+    return status;
+}
+
+Status ListCommand::parseArgs(const std::string &command, const Arg &arg) {
+    static struct option longOptions[] = {
+        // long options with short alternatives
+        {"help",      no_argument,       0, 'h' },
+        {"interface", no_argument,       0, 'i' },
+        {"transport", no_argument,       0, 't' },
+        {"arch",      no_argument,       0, 'r' },
+        {"pid",       no_argument,       0, 'p' },
+        {"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' },
+        {"init-vintf",optional_argument, 0, 'v' },
+        {"neat",      no_argument,       0, 'n' },
+        { 0,          0,                 0,  0  }
+    };
+
+    int optionIndex;
+    int c;
+    // Lshal::parseArgs has set optind to the next option to parse
+    for (;;) {
+        // using getopt_long in case we want to add other options in the future
+        c = getopt_long(arg.argc, arg.argv,
+                "hitrpacmd", longOptions, &optionIndex);
+        if (c == -1) {
+            break;
+        }
+        switch (c) {
+        case 's': {
+            if (strcmp(optarg, "interface") == 0 || strcmp(optarg, "i") == 0) {
+                mSortColumn = TableEntry::sortByInterfaceName;
+            } else if (strcmp(optarg, "pid") == 0 || strcmp(optarg, "p") == 0) {
+                mSortColumn = TableEntry::sortByServerPid;
+            } else {
+                mErr << "Unrecognized sorting column: " << optarg << std::endl;
+                mLshal.usage(command);
+                return USAGE;
+            }
+            break;
+        }
+        case 'v': {
+            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;
+                }
+            }
+            mVintf = true;
+        }
+        case 'i': {
+            mSelectedColumns |= ENABLE_INTERFACE_NAME;
+            break;
+        }
+        case 't': {
+            mSelectedColumns |= ENABLE_TRANSPORT;
+            break;
+        }
+        case 'r': {
+            mSelectedColumns |= ENABLE_ARCH;
+            break;
+        }
+        case 'p': {
+            mSelectedColumns |= ENABLE_SERVER_PID;
+            break;
+        }
+        case 'a': {
+            mSelectedColumns |= ENABLE_SERVER_ADDR;
+            break;
+        }
+        case 'c': {
+            mSelectedColumns |= ENABLE_CLIENT_PIDS;
+            break;
+        }
+        case 'm': {
+            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 'n': {
+            mNeat = true;
+            break;
+        }
+        case 'h': // falls through
+        default: // see unrecognized options
+            mLshal.usage(command);
+            return USAGE;
+        }
+    }
+    if (optind < arg.argc) {
+        // see non option
+        mErr << "Unrecognized option `" << arg.argv[optind] << "`" << std::endl;
+    }
+
+    if (mSelectedColumns == 0) {
+        mSelectedColumns = ENABLE_INTERFACE_NAME | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS;
+    }
+    return OK;
+}
+
+Status ListCommand::main(const std::string &command, const Arg &arg) {
+    Status status = parseArgs(command, arg);
+    if (status != OK) {
+        return status;
+    }
+    status = fetch();
+    postprocess();
+    dump();
+    return status;
+}
+
+}  // namespace lshal
+}  // namespace android
+
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
new file mode 100644
index 0000000..f367d7f
--- /dev/null
+++ b/cmds/lshal/ListCommand.h
@@ -0,0 +1,106 @@
+/*
+ * 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 FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
+
+#include <stdint.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <android-base/macros.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+
+#include "NullableOStream.h"
+#include "TableEntry.h"
+#include "utils.h"
+
+namespace android {
+namespace lshal {
+
+class Lshal;
+
+class ListCommand {
+public:
+    ListCommand(Lshal &lshal);
+    Status main(const std::string &command, const Arg &arg);
+private:
+    Status parseArgs(const std::string &command, const Arg &arg);
+    Status fetch();
+    void postprocess();
+    void dump();
+    void putEntry(TableEntrySource source, TableEntry &&entry);
+    Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
+    Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
+    Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
+    bool getReferencedPids(
+        pid_t serverPid, std::map<uint64_t, Pids> *objects) const;
+    void dumpTable();
+    void dumpVintf() const;
+    void printLine(
+            const std::string &interfaceName,
+            const std::string &transport,
+            const std::string &arch,
+            const std::string &server,
+            const std::string &serverCmdline,
+            const std::string &address, const std::string &clients,
+            const std::string &clientCmdlines) const ;
+    // Return /proc/{pid}/cmdline if it exists, else empty string.
+    const std::string &getCmdline(pid_t pid);
+    // Call getCmdline on all pid in pids. If it returns empty string, the process might
+    // have died, and the pid is removed from pids.
+    void removeDeadProcesses(Pids *pids);
+    void forEachTable(const std::function<void(Table &)> &f);
+    void forEachTable(const std::function<void(const Table &)> &f) const;
+
+    Lshal &mLshal;
+
+    Table mServicesTable{};
+    Table mPassthroughRefTable{};
+    Table mImplementationsTable{};
+
+    NullableOStream<std::ostream> mErr;
+    NullableOStream<std::ostream> mOut;
+    NullableOStream<std::ofstream> mFileOutput = nullptr;
+    TableEntryCompare mSortColumn = nullptr;
+    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;
+
+    // If true, output in VINTF format.
+    bool mVintf = false;
+
+    // If true, explanatory text are not emitted.
+    bool mNeat = 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.
+    // If an entry exist and not empty, it contains the cached content of /proc/{pid}/cmdline.
+    std::map<pid_t, std::string> mCmdlines;
+
+    DISALLOW_COPY_AND_ASSIGN(ListCommand);
+};
+
+
+}  // namespace lshal
+}  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 2fc3715..9db42f1 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,399 +14,155 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "lshal"
+#include <android-base/logging.h>
+
 #include "Lshal.h"
 
-#include <getopt.h>
+#include <set>
+#include <string>
 
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <map>
-#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 "DebugCommand.h"
+#include "ListCommand.h"
 #include "PipeRelay.h"
-#include "Timeout.h"
-
-using ::android::hardware::hidl_string;
-using ::android::hidl::manager::V1_0::IServiceManager;
 
 namespace android {
 namespace lshal {
 
-template <typename A>
-std::string join(const A &components, const std::string &separator) {
-    std::stringstream out;
-    bool first = true;
-    for (const auto &component : components) {
-        if (!first) {
-            out << separator;
-        }
-        out << component;
+using ::android::hidl::manager::V1_0::IServiceManager;
 
-        first = false;
+Lshal::Lshal()
+    : mOut(std::cout), mErr(std::cerr),
+      mServiceManager(::android::hardware::defaultServiceManager()),
+      mPassthroughManager(::android::hardware::getPassthroughServiceManager()) {
+}
+
+Lshal::Lshal(std::ostream &out, std::ostream &err,
+            sp<hidl::manager::V1_0::IServiceManager> serviceManager,
+            sp<hidl::manager::V1_0::IServiceManager> passthroughManager)
+    : mOut(out), mErr(err),
+      mServiceManager(serviceManager),
+      mPassthroughManager(passthroughManager) {
+
+}
+
+void Lshal::usage(const std::string &command) const {
+    static const std::string helpSummary =
+            "lshal: List and debug HALs.\n"
+            "\n"
+            "commands:\n"
+            "    help            Print help message\n"
+            "    list            list HALs\n"
+            "    debug           debug a specified HAL\n"
+            "\n"
+            "If no command is specified, `list` is the default.\n";
+
+    static const std::string list =
+            "list:\n"
+            "    lshal\n"
+            "    lshal list\n"
+            "        List all hals with default ordering and columns (`lshal list -ipc`)\n"
+            "    lshal list [-h|--help]\n"
+            "        -h, --help: Print help message for list (`lshal help list`)\n"
+            "    lshal [list] [--interface|-i] [--transport|-t] [-r|--arch]\n"
+            "            [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]\n"
+            "            [--sort={interface|i|pid|p}] [--init-vintf[=<output file>]]\n"
+            "            [--debug|-d[=<output file>]]\n"
+            "        -i, --interface: print the interface name column\n"
+            "        -n, --instance: print the instance name column\n"
+            "        -t, --transport: print the transport mode column\n"
+            "        -r, --arch: print if the HAL is in 64-bit or 32-bit\n"
+            "        -p, --pid: print the server PID, or server cmdline if -m is set\n"
+            "        -a, --address: print the server object address column\n"
+            "        -c, --clients: print the client PIDs, or client cmdlines if -m is set\n"
+            "        -m, --cmdline: print cmdline instead of PIDs\n"
+            "        -d[=<output file>], --debug[=<output file>]: emit debug info from \n"
+            "                IBase::debug with empty options\n"
+            "        --sort=i, --sort=interface: sort by interface name\n"
+            "        --sort=p, --sort=pid: sort by server pid\n"
+            "        --init-vintf=<output file>: form a skeleton HAL manifest to specified\n"
+            "                      file, or stdout if no file specified.\n";
+
+    static const std::string debug =
+            "debug:\n"
+            "    lshal debug <interface> [options [options [...]]] \n"
+            "        Print debug information of a specified interface.\n"
+            "        <inteface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
+            "            If instance name is missing `default` is used.\n"
+            "        options: space separated options to IBase::debug.\n";
+
+    static const std::string help =
+            "help:\n"
+            "    lshal -h\n"
+            "    lshal --help\n"
+            "    lshal help\n"
+            "        Print this help message\n"
+            "    lshal help list\n"
+            "        Print help message for list\n"
+            "    lshal help debug\n"
+            "        Print help message for debug\n";
+
+    if (command == "list") {
+        mErr << list;
+        return;
     }
-    return out.str();
-}
-
-static std::string toHexString(uint64_t t) {
-    std::ostringstream os;
-    os << std::hex << std::setfill('0') << std::setw(16) << t;
-    return os.str();
-}
-
-template<typename String>
-static std::pair<String, String> splitFirst(const String &s, char c) {
-    const char *pos = strchr(s.c_str(), c);
-    if (pos == nullptr) {
-        return {s, {}};
-    }
-    return {String(s.c_str(), pos - s.c_str()), String(pos + 1)};
-}
-
-static std::vector<std::string> split(const std::string &s, char c) {
-    std::vector<std::string> components{};
-    size_t startPos = 0;
-    size_t matchPos;
-    while ((matchPos = s.find(c, startPos)) != std::string::npos) {
-        components.push_back(s.substr(startPos, matchPos - startPos));
-        startPos = matchPos + 1;
+    if (command == "debug") {
+        mErr << debug;
+        return;
     }
 
-    if (startPos <= s.length()) {
-        components.push_back(s.substr(startPos));
-    }
-    return components;
-}
-
-static void replaceAll(std::string *s, char from, char to) {
-    for (size_t i = 0; i < s->size(); ++i) {
-        if (s->at(i) == from) {
-            s->at(i) = to;
-        }
-    }
-}
-
-std::string getCmdline(pid_t pid) {
-    std::ifstream ifs("/proc/" + std::to_string(pid) + "/cmdline");
-    std::string cmdline;
-    if (!ifs.is_open()) {
-        return "";
-    }
-    ifs >> cmdline;
-    return cmdline;
-}
-
-const std::string &Lshal::getCmdline(pid_t pid) {
-    auto pair = mCmdlines.find(pid);
-    if (pair != mCmdlines.end()) {
-        return pair->second;
-    }
-    mCmdlines[pid] = ::android::lshal::getCmdline(pid);
-    return mCmdlines[pid];
-}
-
-void Lshal::removeDeadProcesses(Pids *pids) {
-    static const pid_t myPid = getpid();
-    std::remove_if(pids->begin(), pids->end(), [this](auto pid) {
-        return pid == myPid || this->getCmdline(pid).empty();
-    });
-}
-
-bool Lshal::getReferencedPids(
-        pid_t serverPid, std::map<uint64_t, Pids> *objects) const {
-
-    std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid));
-    if (!ifs.is_open()) {
-        return false;
-    }
-
-    static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
-
-    std::string line;
-    std::smatch match;
-    while(getline(ifs, line)) {
-        if (!std::regex_search(line, match, prefix)) {
-            // the line doesn't start with the correct prefix
-            continue;
-        }
-        std::string ptrString = "0x" + match.str(2); // use number after c
-        uint64_t ptr;
-        if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
-            // Should not reach here, but just be tolerant.
-            mErr << "Could not parse number " << ptrString << std::endl;
-            continue;
-        }
-        const std::string proc = " proc ";
-        auto pos = line.rfind(proc);
-        if (pos != std::string::npos) {
-            for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) {
-                int32_t pid;
-                if (!::android::base::ParseInt(pidStr, &pid)) {
-                    mErr << "Could not parse number " << pidStr << std::endl;
-                    continue;
-                }
-                (*objects)[ptr].push_back(pid);
-            }
-        }
-    }
-    return true;
-}
-
-// Must process hwbinder services first, then passthrough services.
-void Lshal::forEachTable(const std::function<void(Table &)> &f) {
-    f(mServicesTable);
-    f(mPassthroughRefTable);
-    f(mImplementationsTable);
-}
-void Lshal::forEachTable(const std::function<void(const Table &)> &f) const {
-    f(mServicesTable);
-    f(mPassthroughRefTable);
-    f(mImplementationsTable);
-}
-
-void Lshal::postprocess() {
-    forEachTable([this](Table &table) {
-        if (mSortColumn) {
-            std::sort(table.begin(), table.end(), mSortColumn);
-        }
-        for (TableEntry &entry : table) {
-            entry.serverCmdline = getCmdline(entry.serverPid);
-            removeDeadProcesses(&entry.clientPids);
-            for (auto pid : entry.clientPids) {
-                entry.clientCmdlines.push_back(this->getCmdline(pid));
-            }
-        }
-    });
-    // use a double for loop here because lshal doesn't care about efficiency.
-    for (TableEntry &packageEntry : mImplementationsTable) {
-        std::string packageName = packageEntry.interfaceName;
-        FQName fqPackageName{packageName.substr(0, packageName.find("::"))};
-        if (!fqPackageName.isValid()) {
-            continue;
-        }
-        for (TableEntry &interfaceEntry : mPassthroughRefTable) {
-            if (interfaceEntry.arch != ARCH_UNKNOWN) {
-                continue;
-            }
-            FQName interfaceName{splitFirst(interfaceEntry.interfaceName, '/').first};
-            if (!interfaceName.isValid()) {
-                continue;
-            }
-            if (interfaceName.getPackageAndVersion() == fqPackageName) {
-                interfaceEntry.arch = packageEntry.arch;
-            }
-        }
-    }
-}
-
-void Lshal::printLine(
-        const std::string &interfaceName,
-        const std::string &transport,
-        const std::string &arch,
-        const std::string &server,
-        const std::string &serverCmdline,
-        const std::string &address, const std::string &clients,
-        const std::string &clientCmdlines) const {
-    if (mSelectedColumns & ENABLE_INTERFACE_NAME)
-        mOut << std::setw(80) << interfaceName << "\t";
-    if (mSelectedColumns & ENABLE_TRANSPORT)
-        mOut << std::setw(10) << transport << "\t";
-    if (mSelectedColumns & ENABLE_ARCH)
-        mOut << std::setw(5) << arch << "\t";
-    if (mSelectedColumns & ENABLE_SERVER_PID) {
-        if (mEnableCmdlines) {
-            mOut << std::setw(15) << serverCmdline << "\t";
-        } else {
-            mOut << std::setw(5)  << server << "\t";
-        }
-    }
-    if (mSelectedColumns & ENABLE_SERVER_ADDR)
-        mOut << std::setw(16) << address << "\t";
-    if (mSelectedColumns & ENABLE_CLIENT_PIDS) {
-        if (mEnableCmdlines) {
-            mOut << std::setw(0)  << clientCmdlines;
-        } else {
-            mOut << std::setw(0)  << clients;
-        }
-    }
-    mOut << std::endl;
-}
-
-void Lshal::dumpVintf() const {
-    mOut << "<!-- " << std::endl
-         << "    This is a skeleton device manifest. Notes: " << std::endl
-         << "    1. android.hidl.*, android.frameworks.*, android.system.* are not included." << std::endl
-         << "    2. If a HAL is supported in both hwbinder and passthrough transport, " << std::endl
-         << "       only hwbinder is shown." << std::endl
-         << "    3. It is likely that HALs in passthrough transport does not have" << std::endl
-         << "       <interface> declared; users will have to write them by hand." << std::endl
-         << "    4. sepolicy version is set to 0.0. It is recommended that the entry" << std::endl
-         << "       is removed from the manifest file and written by assemble_vintf" << std::endl
-         << "       at build time." << std::endl
-         << "-->" << std::endl;
-
-    vintf::HalManifest manifest;
-    forEachTable([this, &manifest] (const Table &table) {
-        for (const TableEntry &entry : table) {
-
-            std::string fqInstanceName = entry.interfaceName;
-
-            if (&table == &mImplementationsTable) {
-                // Quick hack to work around *'s
-                replaceAll(&fqInstanceName, '*', 'D');
-            }
-            auto splittedFqInstanceName = splitFirst(fqInstanceName, '/');
-            FQName fqName(splittedFqInstanceName.first);
-            if (!fqName.isValid()) {
-                mErr << "Warning: '" << splittedFqInstanceName.first
-                     << "' is not a valid FQName." << std::endl;
-                continue;
-            }
-            // Strip out system libs.
-            if (fqName.inPackage("android.hidl") ||
-                fqName.inPackage("android.frameworks") ||
-                fqName.inPackage("android.system")) {
-                continue;
-            }
-            std::string interfaceName =
-                    &table == &mImplementationsTable ? "" : fqName.name();
-            std::string instanceName =
-                    &table == &mImplementationsTable ? "" : splittedFqInstanceName.second;
-
-            vintf::Version version{fqName.getPackageMajorVersion(),
-                                   fqName.getPackageMinorVersion()};
-            vintf::Transport transport;
-            vintf::Arch arch;
-            if (entry.transport == "hwbinder") {
-                transport = vintf::Transport::HWBINDER;
-                arch = vintf::Arch::ARCH_EMPTY;
-            } else if (entry.transport == "passthrough") {
-                transport = vintf::Transport::PASSTHROUGH;
-                switch (entry.arch) {
-                    case lshal::ARCH32:
-                        arch = vintf::Arch::ARCH_32;    break;
-                    case lshal::ARCH64:
-                        arch = vintf::Arch::ARCH_64;    break;
-                    case lshal::ARCH_BOTH:
-                        arch = vintf::Arch::ARCH_32_64; break;
-                    case lshal::ARCH_UNKNOWN: // fallthrough
-                    default:
-                        mErr << "Warning: '" << fqName.package()
-                             << "' doesn't have bitness info, assuming 32+64." << std::endl;
-                        arch = vintf::Arch::ARCH_32_64;
-                }
-            } else {
-                mErr << "Warning: '" << entry.transport << "' is not a valid transport." << std::endl;
-                continue;
-            }
-
-            bool done = false;
-            for (vintf::ManifestHal *hal : manifest.getHals(fqName.package())) {
-                if (hal->transport() != transport) {
-                    if (transport != vintf::Transport::PASSTHROUGH) {
-                        mErr << "Fatal: should not reach here. Generated result may be wrong."
-                             << std::endl;
-                    }
-                    done = true;
-                    break;
-                }
-                if (hal->hasVersion(version)) {
-                    if (&table != &mImplementationsTable) {
-                        hal->interfaces[interfaceName].name = interfaceName;
-                        hal->interfaces[interfaceName].instances.insert(instanceName);
-                    }
-                    done = true;
-                    break;
-                }
-            }
-            if (done) {
-                continue; // to next TableEntry
-            }
-            decltype(vintf::ManifestHal::interfaces) interfaces;
-            if (&table != &mImplementationsTable) {
-                interfaces[interfaceName].name = interfaceName;
-                interfaces[interfaceName].instances.insert(instanceName);
-            }
-            if (!manifest.add(vintf::ManifestHal{
-                    .format = vintf::HalFormat::HIDL,
-                    .name = fqName.package(),
-                    .versions = {version},
-                    .transportArch = {transport, arch},
-                    .interfaces = interfaces})) {
-                mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
-            }
-        }
-    });
-    mOut << vintf::gHalManifestConverter(manifest);
-}
-
-static const std::string &getArchString(Architecture arch) {
-    static const std::string sStr64 = "64";
-    static const std::string sStr32 = "32";
-    static const std::string sStrBoth = "32+64";
-    static const std::string sStrUnknown = "";
-    switch (arch) {
-        case ARCH64:
-            return sStr64;
-        case ARCH32:
-            return sStr32;
-        case ARCH_BOTH:
-            return sStrBoth;
-        case ARCH_UNKNOWN: // fall through
-        default:
-            return sStrUnknown;
-    }
-}
-
-static Architecture fromBaseArchitecture(::android::hidl::base::V1_0::DebugInfo::Architecture a) {
-    switch (a) {
-        case ::android::hidl::base::V1_0::DebugInfo::Architecture::IS_64BIT:
-            return ARCH64;
-        case ::android::hidl::base::V1_0::DebugInfo::Architecture::IS_32BIT:
-            return ARCH32;
-        case ::android::hidl::base::V1_0::DebugInfo::Architecture::UNKNOWN: // fallthrough
-        default:
-            return ARCH_UNKNOWN;
-    }
+    mErr << helpSummary << "\n" << list << "\n" << debug << "\n" << help;
 }
 
 // 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,
+static hardware::hidl_vec<hardware::hidl_string> convert(const std::vector<std::string> &v) {
+    hardware::hidl_vec<hardware::hidl_string> hv;
+    hv.resize(v.size());
+    for (size_t i = 0; i < v.size(); ++i) {
+        hv[i].setToExternal(v[i].c_str(), v[i].size());
+    }
+    return hv;
+}
+
+Status Lshal::emitDebugInfo(
         const std::string &interfaceName,
-        const std::string &instanceName) const {
+        const std::string &instanceName,
+        const std::vector<std::string> &options,
+        std::ostream &out,
+        NullableOStream<std::ostream> err) const {
     using android::hidl::base::V1_0::IBase;
 
-    hardware::Return<sp<IBase>> retBase =
-        serviceManager->get(interfaceName, instanceName);
+    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;
+    if (!retBase.isOk()) {
+        std::string msg = "Cannot get " + interfaceName + "/" + instanceName + ": "
+                + retBase.description();
+        err << msg << std::endl;
+        LOG(ERROR) << msg;
+        return TRANSACTION_ERROR;
     }
 
-    PipeRelay relay(mOut.buf());
+    sp<IBase> base = retBase;
+    if (base == nullptr) {
+        std::string msg = interfaceName + "/" + instanceName + " does not exist, or "
+                + "no permission to connect.";
+        err << msg << std::endl;
+        LOG(ERROR) << msg;
+        return NO_INTERFACE;
+    }
+
+    PipeRelay relay(out);
 
     if (relay.initCheck() != OK) {
-        LOG(ERROR) << "PipeRelay::initCheck() FAILED w/ " << relay.initCheck();
-        return;
+        std::string msg = "PipeRelay::initCheck() FAILED w/ " + std::to_string(relay.initCheck());
+        err << msg << std::endl;
+        LOG(ERROR) << msg;
+        return IO_ERROR;
     }
 
     deleted_unique_ptr<native_handle_t> fdHandle(
@@ -415,408 +171,40 @@
 
     fdHandle->data[0] = relay.fd();
 
-    hardware::hidl_vec<hardware::hidl_string> options;
-    hardware::Return<void> ret = base->debug(fdHandle.get(), options);
+    hardware::Return<void> ret = base->debug(fdHandle.get(), convert(options));
 
     if (!ret.isOk()) {
-        LOG(ERROR)
-            << interfaceName
-            << "::debug(...) FAILED. (instance "
-            << instanceName
-            << ")";
-    }
-}
-
-void Lshal::dumpTable() {
-    mServicesTable.description =
-            "All binderized services (registered services through hwservicemanager)";
-    mPassthroughRefTable.description =
-            "All interfaces that getService() has ever return as a passthrough interface;\n"
-            "PIDs / processes shown below might be inaccurate because the process\n"
-            "might have relinquished the interface or might have died.\n"
-            "The Server / Server CMD column can be ignored.\n"
-            "The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
-            "the library and successfully fetched the passthrough implementation.";
-    mImplementationsTable.description =
-            "All available passthrough implementations (all -impl.so files)";
-    forEachTable([this] (const Table &table) {
-        mOut << table.description << std::endl;
-        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,
-                    getArchString(entry.arch),
-                    entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid),
-                    entry.serverCmdline,
-                    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;
-    });
-
-}
-
-void Lshal::dump() {
-    if (mVintf) {
-        dumpVintf();
-        if (!!mFileOutput) {
-            mFileOutput.buf().close();
-            delete &mFileOutput.buf();
-            mFileOutput = nullptr;
-        }
-        mOut = std::cout;
-    } else {
-        dumpTable();
-    }
-}
-
-void Lshal::putEntry(TableEntrySource source, TableEntry &&entry) {
-    Table *table = nullptr;
-    switch (source) {
-        case HWSERVICEMANAGER_LIST :
-            table = &mServicesTable; break;
-        case PTSERVICEMANAGER_REG_CLIENT :
-            table = &mPassthroughRefTable; break;
-        case LIST_DLLIB :
-            table = &mImplementationsTable; break;
-        default:
-            mErr << "Error: Unknown source of entry " << source << std::endl;
-    }
-    if (table) {
-        table->entries.push_back(std::forward<TableEntry>(entry));
-    }
-}
-
-Status Lshal::fetchAllLibraries(const sp<IServiceManager> &manager) {
-    using namespace ::android::hardware;
-    using namespace ::android::hidl::manager::V1_0;
-    using namespace ::android::hidl::base::V1_0;
-    auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) {
-        std::map<std::string, TableEntry> entries;
-        for (const auto &info : infos) {
-            std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" +
-                    std::string{info.instanceName.c_str()};
-            entries.emplace(interfaceName, TableEntry{
-                .interfaceName = interfaceName,
-                .transport = "passthrough",
-                .serverPid = NO_PID,
-                .serverObjectAddress = NO_PTR,
-                .clientPids = {},
-                .arch = ARCH_UNKNOWN
-            }).first->second.arch |= fromBaseArchitecture(info.arch);
-        }
-        for (auto &&pair : entries) {
-            putEntry(LIST_DLLIB, std::move(pair.second));
-        }
-    });
-    if (!ret.isOk()) {
-        mErr << "Error: Failed to call list on getPassthroughServiceManager(): "
-             << ret.description() << std::endl;
-        return DUMP_ALL_LIBS_ERROR;
+        std::string msg = "debug() FAILED on " + interfaceName + "/" + instanceName + ": "
+                + ret.description();
+        err << msg << std::endl;
+        LOG(ERROR) << msg;
+        return TRANSACTION_ERROR;
     }
     return OK;
 }
 
-Status Lshal::fetchPassthrough(const sp<IServiceManager> &manager) {
-    using namespace ::android::hardware;
-    using namespace ::android::hardware::details;
-    using namespace ::android::hidl::manager::V1_0;
-    using namespace ::android::hidl::base::V1_0;
-    auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) {
-        for (const auto &info : infos) {
-            if (info.clientPids.size() <= 0) {
-                continue;
-            }
-            putEntry(PTSERVICEMANAGER_REG_CLIENT, {
-                .interfaceName =
-                        std::string{info.interfaceName.c_str()} + "/" +
-                        std::string{info.instanceName.c_str()},
-                .transport = "passthrough",
-                .serverPid = info.clientPids.size() == 1 ? info.clientPids[0] : NO_PID,
-                .serverObjectAddress = NO_PTR,
-                .clientPids = info.clientPids,
-                .arch = fromBaseArchitecture(info.arch)
-            });
-        }
-    });
-    if (!ret.isOk()) {
-        mErr << "Error: Failed to call debugDump on defaultServiceManager(): "
-             << ret.description() << std::endl;
-        return DUMP_PASSTHROUGH_ERROR;
-    }
-    return OK;
-}
-
-Status Lshal::fetchBinderized(const sp<IServiceManager> &manager) {
-    using namespace ::std;
-    using namespace ::android::hardware;
-    using namespace ::android::hidl::manager::V1_0;
-    using namespace ::android::hidl::base::V1_0;
-    const std::string mode = "hwbinder";
-
-    hidl_vec<hidl_string> fqInstanceNames;
-    // copying out for timeoutIPC
-    auto listRet = timeoutIPC(manager, &IServiceManager::list, [&] (const auto &names) {
-        fqInstanceNames = names;
-    });
-    if (!listRet.isOk()) {
-        mErr << "Error: Failed to list services for " << mode << ": "
-             << listRet.description() << std::endl;
-        return DUMP_BINDERIZED_ERROR;
-    }
-
-    Status status = OK;
-    // server pid, .ptr value of binder object, child pids
-    std::map<std::string, DebugInfo> allDebugInfos;
-    std::map<pid_t, std::map<uint64_t, Pids>> allPids;
-    for (const auto &fqInstanceName : fqInstanceNames) {
-        const auto pair = splitFirst(fqInstanceName, '/');
-        const auto &serviceName = pair.first;
-        const auto &instanceName = pair.second;
-        auto getRet = timeoutIPC(manager, &IServiceManager::get, serviceName, instanceName);
-        if (!getRet.isOk()) {
-            mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
-                 << "cannot be fetched from service manager:"
-                 << getRet.description() << std::endl;
-            status |= DUMP_BINDERIZED_ERROR;
-            continue;
-        }
-        sp<IBase> service = getRet;
-        if (service == nullptr) {
-            mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
-                 << "cannot be fetched from service manager (null)";
-            status |= DUMP_BINDERIZED_ERROR;
-            continue;
-        }
-        auto debugRet = timeoutIPC(service, &IBase::getDebugInfo, [&] (const auto &debugInfo) {
-            allDebugInfos[fqInstanceName] = debugInfo;
-            if (debugInfo.pid >= 0) {
-                allPids[static_cast<pid_t>(debugInfo.pid)].clear();
-            }
-        });
-        if (!debugRet.isOk()) {
-            mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
-                 << "debugging information cannot be retrieved:"
-                 << debugRet.description() << std::endl;
-            status |= DUMP_BINDERIZED_ERROR;
-        }
-    }
-    for (auto &pair : allPids) {
-        pid_t serverPid = pair.first;
-        if (!getReferencedPids(serverPid, &allPids[serverPid])) {
-            mErr << "Warning: no information for PID " << serverPid
-                      << ", are you root?" << std::endl;
-            status |= DUMP_BINDERIZED_ERROR;
-        }
-    }
-    for (const auto &fqInstanceName : fqInstanceNames) {
-        auto it = allDebugInfos.find(fqInstanceName);
-        if (it == allDebugInfos.end()) {
-            putEntry(HWSERVICEMANAGER_LIST, {
-                .interfaceName = fqInstanceName,
-                .transport = mode,
-                .serverPid = NO_PID,
-                .serverObjectAddress = NO_PTR,
-                .clientPids = {},
-                .arch = ARCH_UNKNOWN
-            });
-            continue;
-        }
-        const DebugInfo &info = it->second;
-        putEntry(HWSERVICEMANAGER_LIST, {
-            .interfaceName = fqInstanceName,
-            .transport = mode,
-            .serverPid = info.pid,
-            .serverObjectAddress = info.ptr,
-            .clientPids = info.pid == NO_PID || info.ptr == NO_PTR
-                    ? Pids{} : allPids[info.pid][info.ptr],
-            .arch = fromBaseArchitecture(info.arch),
-        });
-    }
-    return status;
-}
-
-Status Lshal::fetch() {
-    Status status = OK;
-    auto bManager = ::android::hardware::defaultServiceManager();
-    if (bManager == nullptr) {
-        mErr << "Failed to get defaultServiceManager()!" << std::endl;
-        status |= NO_BINDERIZED_MANAGER;
-    } else {
-        status |= fetchBinderized(bManager);
-        // Passthrough PIDs are registered to the binderized manager as well.
-        status |= fetchPassthrough(bManager);
-    }
-
-    auto pManager = ::android::hardware::getPassthroughServiceManager();
-    if (pManager == nullptr) {
-        mErr << "Failed to get getPassthroughServiceManager()!" << std::endl;
-        status |= NO_PASSTHROUGH_MANAGER;
-    } else {
-        status |= fetchAllLibraries(pManager);
-    }
-    return status;
-}
-
-void Lshal::usage() const {
-    mErr
-        << "usage: lshal" << std::endl
-        << "           Dump all hals with default ordering and columns [-ipc]." << std::endl
-        << "       lshal [--interface|-i] [--transport|-t] [-r|--arch]" << std::endl
-        << "             [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]" << std::endl
-        << "             [--sort={interface|i|pid|p}] [--init-vintf[=path]]" << std::endl
-        << "           -i, --interface: print the interface name column" << std::endl
-        << "           -n, --instance: print the instance name column" << std::endl
-        << "           -t, --transport: print the transport mode column" << std::endl
-        << "           -r, --arch: print if the HAL is in 64-bit or 32-bit" << std::endl
-        << "           -p, --pid: print the server PID, or server cmdline if -m is set" << std::endl
-        << "           -a, --address: print the server object address column" << std::endl
-        << "           -c, --clients: print the client PIDs, or client cmdlines if -m is set"
-                                                                              << std::endl
-        << "           -m, --cmdline: print cmdline instead of PIDs" << std::endl
-        << "           -d, --debug: emit debug info from IBase::debug" << std::endl
-        << "           --sort=i, --sort=interface: sort by interface name" << std::endl
-        << "           --sort=p, --sort=pid: sort by server pid" << std::endl
-        << "           --init-vintf=path: form a skeleton HAL manifest to specified file " << std::endl
-        << "                         (stdout if no file specified)" << std::endl
-        << "       lshal [-h|--help]" << std::endl
-        << "           -h, --help: show this help information." << std::endl;
-}
-
-Status Lshal::parseArgs(int argc, char **argv) {
-    static struct option longOptions[] = {
-        // long options with short alternatives
-        {"help",      no_argument,       0, 'h' },
-        {"interface", no_argument,       0, 'i' },
-        {"transport", no_argument,       0, 't' },
-        {"arch",      no_argument,       0, 'r' },
-        {"pid",       no_argument,       0, 'p' },
-        {"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' },
-        {"init-vintf",optional_argument, 0, 'v' },
-        { 0,          0,                 0,  0  }
-    };
-
-    int optionIndex;
-    int c;
+Status Lshal::parseArgs(const Arg &arg) {
+    static std::set<std::string> sAllCommands{"list", "debug", "help"};
     optind = 1;
-    for (;;) {
-        // using getopt_long in case we want to add other options in the future
-        c = getopt_long(argc, argv, "hitrpacmd", longOptions, &optionIndex);
-        if (c == -1) {
-            break;
-        }
-        switch (c) {
-        case 's': {
-            if (strcmp(optarg, "interface") == 0 || strcmp(optarg, "i") == 0) {
-                mSortColumn = TableEntry::sortByInterfaceName;
-            } else if (strcmp(optarg, "pid") == 0 || strcmp(optarg, "p") == 0) {
-                mSortColumn = TableEntry::sortByServerPid;
-            } else {
-                mErr << "Unrecognized sorting column: " << optarg << std::endl;
-                usage();
-                return USAGE;
-            }
-            break;
-        }
-        case 'v': {
-            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;
-                }
-            }
-            mVintf = true;
-        }
-        case 'i': {
-            mSelectedColumns |= ENABLE_INTERFACE_NAME;
-            break;
-        }
-        case 't': {
-            mSelectedColumns |= ENABLE_TRANSPORT;
-            break;
-        }
-        case 'r': {
-            mSelectedColumns |= ENABLE_ARCH;
-            break;
-        }
-        case 'p': {
-            mSelectedColumns |= ENABLE_SERVER_PID;
-            break;
-        }
-        case 'a': {
-            mSelectedColumns |= ENABLE_SERVER_ADDR;
-            break;
-        }
-        case 'c': {
-            mSelectedColumns |= ENABLE_CLIENT_PIDS;
-            break;
-        }
-        case 'm': {
-            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();
-            return USAGE;
-        }
+    if (optind >= arg.argc) {
+        // no options at all.
+        return OK;
+    }
+    mCommand = arg.argv[optind];
+    if (sAllCommands.find(mCommand) != sAllCommands.end()) {
+        ++optind;
+        return OK; // mCommand is set correctly
     }
 
-    if (mSelectedColumns == 0) {
-        mSelectedColumns = ENABLE_INTERFACE_NAME | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS;
+    if (mCommand.size() > 0 && mCommand[0] == '-') {
+        // first argument is an option, set command to "" (which is recognized as "list")
+        mCommand = "";
+        return OK;
     }
-    return OK;
-}
 
-int Lshal::main(int argc, char **argv) {
-    Status status = parseArgs(argc, argv);
-    if (status != OK) {
-        return status;
-    }
-    status = fetch();
-    postprocess();
-    dump();
-    return status;
+    mErr << arg.argv[0] << ": unrecognized option `" << arg.argv[optind] << "`" << std::endl;
+    usage();
+    return USAGE;
 }
 
 void signalHandler(int sig) {
@@ -826,10 +214,43 @@
     }
 }
 
+Status Lshal::main(const Arg &arg) {
+    // Allow SIGINT to terminate all threads.
+    signal(SIGINT, signalHandler);
+
+    Status status = parseArgs(arg);
+    if (status != OK) {
+        return status;
+    }
+    if (mCommand == "help") {
+        usage(optind < arg.argc ? arg.argv[optind] : "");
+        return USAGE;
+    }
+    // Default command is list
+    if (mCommand == "list" || mCommand == "") {
+        return ListCommand{*this}.main(mCommand, arg);
+    }
+    if (mCommand == "debug") {
+        return DebugCommand{*this}.main(mCommand, arg);
+    }
+    usage();
+    return USAGE;
+}
+
+NullableOStream<std::ostream> Lshal::err() const {
+    return mErr;
+}
+NullableOStream<std::ostream> Lshal::out() const {
+    return mOut;
+}
+
+const sp<IServiceManager> &Lshal::serviceManager() const {
+    return mServiceManager;
+}
+
+const sp<IServiceManager> &Lshal::passthroughManager() const {
+    return mPassthroughManager;
+}
+
 }  // namespace lshal
 }  // namespace android
-
-int main(int argc, char **argv) {
-    signal(SIGINT, ::android::lshal::signalHandler);
-    return ::android::lshal::Lshal{}.main(argc, argv);
-}
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index a21e86c..00db5d0 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -17,94 +17,51 @@
 #ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
 #define FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
 
-#include <stdint.h>
-
-#include <fstream>
+#include <iostream>
 #include <string>
-#include <vector>
 
+#include <android-base/macros.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
+#include <utils/StrongPointer.h>
 
 #include "NullableOStream.h"
-#include "TableEntry.h"
+#include "utils.h"
 
 namespace android {
 namespace lshal {
 
-enum : unsigned int {
-    OK                                      = 0,
-    USAGE                                   = 1 << 0,
-    NO_BINDERIZED_MANAGER                   = 1 << 1,
-    NO_PASSTHROUGH_MANAGER                  = 1 << 2,
-    DUMP_BINDERIZED_ERROR                   = 1 << 3,
-    DUMP_PASSTHROUGH_ERROR                  = 1 << 4,
-    DUMP_ALL_LIBS_ERROR                     = 1 << 5,
-    IO_ERROR                                = 1 << 6,
-};
-using Status = unsigned int;
-
 class Lshal {
 public:
-    int main(int argc, char **argv);
+    Lshal();
+    Lshal(std::ostream &out, std::ostream &err,
+            sp<hidl::manager::V1_0::IServiceManager> serviceManager,
+            sp<hidl::manager::V1_0::IServiceManager> passthroughManager);
+    Status main(const Arg &arg);
+    void usage(const std::string &command = "") const;
+    NullableOStream<std::ostream> err() const;
+    NullableOStream<std::ostream> out() const;
+    const sp<hidl::manager::V1_0::IServiceManager> &serviceManager() const;
+    const sp<hidl::manager::V1_0::IServiceManager> &passthroughManager() const;
 
+    Status emitDebugInfo(
+            const std::string &interfaceName,
+            const std::string &instanceName,
+            const std::vector<std::string> &options,
+            std::ostream &out,
+            NullableOStream<std::ostream> err) const;
 private:
-    Status parseArgs(int argc, char **argv);
-    Status fetch();
-    void postprocess();
-    void dump();
-    void usage() const;
-    void putEntry(TableEntrySource source, TableEntry &&entry);
-    Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
-    Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
-    Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
-    bool getReferencedPids(
-        pid_t serverPid, std::map<uint64_t, Pids> *objects) const;
-    void dumpTable();
-    void dumpVintf() const;
-    void printLine(
-            const std::string &interfaceName,
-            const std::string &transport,
-            const std::string &arch,
-            const std::string &server,
-            const std::string &serverCmdline,
-            const std::string &address, const std::string &clients,
-            const std::string &clientCmdlines) const ;
-    // Return /proc/{pid}/cmdline if it exists, else empty string.
-    const std::string &getCmdline(pid_t pid);
-    // Call getCmdline on all pid in pids. If it returns empty string, the process might
-    // have died, and the pid is removed from pids.
-    void removeDeadProcesses(Pids *pids);
-    void forEachTable(const std::function<void(Table &)> &f);
-    void forEachTable(const std::function<void(const Table &)> &f) const;
+    Status parseArgs(const Arg &arg);
+    std::string mCommand;
+    Arg mCmdArgs;
+    NullableOStream<std::ostream> mOut;
+    NullableOStream<std::ostream> mErr;
 
-    void emitDebugInfo(
-            const sp<hidl::manager::V1_0::IServiceManager> &serviceManager,
-            const std::string &interfaceName,
-            const std::string &instanceName) const;
+    sp<hidl::manager::V1_0::IServiceManager> mServiceManager;
+    sp<hidl::manager::V1_0::IServiceManager> mPassthroughManager;
 
-    Table mServicesTable{};
-    Table mPassthroughRefTable{};
-    Table mImplementationsTable{};
-
-    NullableOStream<std::ostream> mErr = std::cerr;
-    NullableOStream<std::ostream> mOut = std::cout;
-    NullableOStream<std::ofstream> mFileOutput = nullptr;
-    TableEntryCompare mSortColumn = nullptr;
-    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.
-    // If an entry exist and not empty, it contains the cached content of /proc/{pid}/cmdline.
-    std::map<pid_t, std::string> mCmdlines;
+    DISALLOW_COPY_AND_ASSIGN(Lshal);
 };
 
-
 }  // namespace lshal
 }  // namespace android
 
diff --git a/cmds/lshal/main.cpp b/cmds/lshal/main.cpp
new file mode 100644
index 0000000..366c938
--- /dev/null
+++ b/cmds/lshal/main.cpp
@@ -0,0 +1,22 @@
+/*
+ * 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 "Lshal.h"
+
+int main(int argc, char **argv) {
+    using namespace ::android::lshal;
+    return Lshal{}.main(Arg{argc, argv});
+}
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
new file mode 100644
index 0000000..972d508
--- /dev/null
+++ b/cmds/lshal/test.cpp
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Lshal"
+#include <android-base/logging.h>
+
+#include <sstream>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <android/hardware/tests/baz/1.0/IQuux.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "Lshal.h"
+
+#define NELEMS(array)   static_cast<int>(sizeof(array) / sizeof(array[0]))
+
+using namespace testing;
+
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hidl::manager::V1_0::IServiceNotification;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace baz {
+namespace V1_0 {
+namespace implementation {
+struct Quux : android::hardware::tests::baz::V1_0::IQuux {
+    ::android::hardware::Return<void> debug(const hidl_handle& hh, const hidl_vec<hidl_string>& options) override {
+        const native_handle_t *handle = hh.getNativeHandle();
+        if (handle->numFds < 1) {
+            return Void();
+        }
+        int fd = handle->data[0];
+        std::string content{descriptor};
+        for (const auto &option : options) {
+            content += "\n";
+            content += option.c_str();
+        }
+        ssize_t written = write(fd, content.c_str(), content.size());
+        if (written != (ssize_t)content.size()) {
+            LOG(WARNING) << "SERVER(Quux) debug writes " << written << " bytes < "
+                    << content.size() << " bytes, errno = " << errno;
+        }
+        return Void();
+    }
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace baz
+} // namespace tests
+} // namespace hardware
+
+namespace lshal {
+
+
+class MockServiceManager : public IServiceManager {
+public:
+    template<typename T>
+    using R = ::android::hardware::Return<T>;
+    using String = const hidl_string&;
+    ~MockServiceManager() = default;
+
+#define MOCK_METHOD_CB(name) MOCK_METHOD1(name, R<void>(IServiceManager::name##_cb))
+
+    MOCK_METHOD2(get, R<sp<IBase>>(String, String));
+    MOCK_METHOD2(add, R<bool>(String, const sp<IBase>&));
+    MOCK_METHOD2(getTransport, R<IServiceManager::Transport>(String, String));
+    MOCK_METHOD_CB(list);
+    MOCK_METHOD2(listByInterface, R<void>(String, listByInterface_cb));
+    MOCK_METHOD3(registerForNotifications, R<bool>(String, String, const sp<IServiceNotification>&));
+    MOCK_METHOD_CB(debugDump);
+    MOCK_METHOD2(registerPassthroughClient, R<void>(String, String));
+    MOCK_METHOD_CB(interfaceChain);
+    MOCK_METHOD2(debug, R<void>(const hidl_handle&, const hidl_vec<hidl_string>&));
+    MOCK_METHOD_CB(interfaceDescriptor);
+    MOCK_METHOD_CB(getHashChain);
+    MOCK_METHOD0(setHalInstrumentation, R<void>());
+    MOCK_METHOD2(linkToDeath, R<bool>(const sp<hidl_death_recipient>&, uint64_t));
+    MOCK_METHOD0(ping, R<void>());
+    MOCK_METHOD_CB(getDebugInfo);
+    MOCK_METHOD0(notifySyspropsChanged, R<void>());
+    MOCK_METHOD1(unlinkToDeath, R<bool>(const sp<hidl_death_recipient>&));
+
+};
+
+class LshalTest : public ::testing::Test {
+public:
+    void SetUp() override {
+        using ::android::hardware::tests::baz::V1_0::IQuux;
+        using ::android::hardware::tests::baz::V1_0::implementation::Quux;
+
+        err.str("");
+        out.str("");
+        serviceManager = new testing::NiceMock<MockServiceManager>();
+        ON_CALL(*serviceManager, get(_, _)).WillByDefault(Invoke(
+            [](const auto &iface, const auto &inst) -> ::android::hardware::Return<sp<IBase>> {
+                if (iface == IQuux::descriptor && inst == "default")
+                    return new Quux();
+                return nullptr;
+            }));
+    }
+    void TearDown() override {}
+
+    std::stringstream err;
+    std::stringstream out;
+    sp<MockServiceManager> serviceManager;
+};
+
+TEST_F(LshalTest, Debug) {
+    const char *args[] = {
+        "lshal", "debug", "android.hardware.tests.baz@1.0::IQuux/default", "foo", "bar"
+    };
+    EXPECT_EQ(0u, Lshal(out, err, serviceManager, serviceManager)
+            .main({NELEMS(args), const_cast<char **>(args)}));
+    EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz@1.0::IQuux\nfoo\nbar"));
+    EXPECT_THAT(err.str(), IsEmpty());
+}
+
+TEST_F(LshalTest, Debug2) {
+    const char *args[] = {
+        "lshal", "debug", "android.hardware.tests.baz@1.0::IQuux", "baz", "quux"
+    };
+    EXPECT_EQ(0u, Lshal(out, err, serviceManager, serviceManager)
+            .main({NELEMS(args), const_cast<char **>(args)}));
+    EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz@1.0::IQuux\nbaz\nquux"));
+    EXPECT_THAT(err.str(), IsEmpty());
+}
+
+TEST_F(LshalTest, Debug3) {
+    const char *args[] = {
+        "lshal", "debug", "android.hardware.tests.doesnotexist@1.0::IDoesNotExist",
+    };
+    EXPECT_NE(0u, Lshal(out, err, serviceManager, serviceManager)
+            .main({NELEMS(args), const_cast<char **>(args)}));
+    EXPECT_THAT(err.str(), HasSubstr("does not exist"));
+}
+
+} // namespace lshal
+} // namespace android
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleMock(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/cmds/lshal/utils.cpp b/cmds/lshal/utils.cpp
new file mode 100644
index 0000000..5550721
--- /dev/null
+++ b/cmds/lshal/utils.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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 "utils.h"
+
+namespace android {
+namespace lshal {
+
+std::string toHexString(uint64_t t) {
+    std::ostringstream os;
+    os << std::hex << std::setfill('0') << std::setw(16) << t;
+    return os.str();
+}
+
+std::vector<std::string> split(const std::string &s, char c) {
+    std::vector<std::string> components{};
+    size_t startPos = 0;
+    size_t matchPos;
+    while ((matchPos = s.find(c, startPos)) != std::string::npos) {
+        components.push_back(s.substr(startPos, matchPos - startPos));
+        startPos = matchPos + 1;
+    }
+
+    if (startPos <= s.length()) {
+        components.push_back(s.substr(startPos));
+    }
+    return components;
+}
+
+void replaceAll(std::string *s, char from, char to) {
+    for (size_t i = 0; i < s->size(); ++i) {
+        if (s->at(i) == from) {
+            s->at(i) = to;
+        }
+    }
+}
+
+}  // namespace lshal
+}  // namespace android
+
diff --git a/cmds/lshal/utils.h b/cmds/lshal/utils.h
new file mode 100644
index 0000000..45b922c
--- /dev/null
+++ b/cmds/lshal/utils.h
@@ -0,0 +1,82 @@
+/*
+ * 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 FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
+
+#include <iomanip>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <vector>
+
+namespace android {
+namespace lshal {
+
+enum : unsigned int {
+    OK                                      = 0,
+    USAGE                                   = 1 << 0,
+    NO_BINDERIZED_MANAGER                   = 1 << 1,
+    NO_PASSTHROUGH_MANAGER                  = 1 << 2,
+    DUMP_BINDERIZED_ERROR                   = 1 << 3,
+    DUMP_PASSTHROUGH_ERROR                  = 1 << 4,
+    DUMP_ALL_LIBS_ERROR                     = 1 << 5,
+    IO_ERROR                                = 1 << 6,
+    NO_INTERFACE                            = 1 << 7,
+    TRANSACTION_ERROR                       = 1 << 8,
+};
+using Status = unsigned int;
+
+struct Arg {
+    int argc;
+    char **argv;
+};
+
+template <typename A>
+std::string join(const A &components, const std::string &separator) {
+    std::stringstream out;
+    bool first = true;
+    for (const auto &component : components) {
+        if (!first) {
+            out << separator;
+        }
+        out << component;
+
+        first = false;
+    }
+    return out.str();
+}
+
+std::string toHexString(uint64_t t);
+
+template<typename String>
+std::pair<String, String> splitFirst(const String &s, char c) {
+    const char *pos = strchr(s.c_str(), c);
+    if (pos == nullptr) {
+        return {s, {}};
+    }
+    return {String(s.c_str(), pos - s.c_str()), String(pos + 1)};
+}
+
+std::vector<std::string> split(const std::string &s, char c);
+
+void replaceAll(std::string *s, char from, char to);
+
+}  // namespace lshal
+}  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
diff --git a/include/ui b/include/ui
new file mode 120000
index 0000000..2fb3147
--- /dev/null
+++ b/include/ui
@@ -0,0 +1 @@
+../libs/ui/include/ui
\ No newline at end of file
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 6fefb38..aec8f10 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2547,16 +2547,8 @@
             objectsSize = 0;
         } else {
             while (objectsSize > 0) {
-                if (mObjects[objectsSize-1] < desired) {
-                    // Check for an object being sliced
-                    if (desired < mObjects[objectsSize-1] + sizeof(flat_binder_object)) {
-                        ALOGE("Attempt to shrink Parcel would slice an objects allocated memory");
-                        return UNKNOWN_ERROR + 0xBADF10;
-                    }
+                if (mObjects[objectsSize-1] < desired)
                     break;
-                }
-                // STOPSHIP: Above code to be replaced with following commented code:
-                // if (mObjects[objectsSize-1] + sizeof(flat_binder_object) <= desired) break;
                 objectsSize--;
             }
         }
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 0276008..39b5829 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -23,6 +23,11 @@
 #include <log/log.h>
 #include <nativeloader/dlext_namespaces.h>
 
+// TODO(b/37049319) Get this from a header once one exists
+extern "C" {
+  android_namespace_t* android_get_exported_namespace(const char*);
+}
+
 namespace android {
 
 /*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
@@ -43,33 +48,19 @@
 android_namespace_t* GraphicsEnv::getDriverNamespace() {
     static std::once_flag once;
     std::call_once(once, [this]() {
-        // TODO; In the next version of Android, all graphics drivers will be
-        // loaded into a custom namespace. To minimize risk for this release,
-        // only updated drivers use a custom namespace.
-        //
-        // Additionally, the custom namespace will be
-        // ANDROID_NAMESPACE_TYPE_ISOLATED, and will only have access to a
-        // subset of the system.
         if (mDriverPath.empty())
             return;
-
-        char defaultPath[PATH_MAX];
-        android_get_LD_LIBRARY_PATH(defaultPath, sizeof(defaultPath));
-        size_t defaultPathLen = strlen(defaultPath);
-
-        std::string path;
-        path.reserve(mDriverPath.size() + 1 + defaultPathLen);
-        path.append(mDriverPath);
-        path.push_back(':');
-        path.append(defaultPath, defaultPathLen);
-
-        mDriverNamespace = android_create_namespace(
-                "gfx driver",
-                nullptr,                    // ld_library_path
-                path.c_str(),               // default_library_path
-                ANDROID_NAMESPACE_TYPE_SHARED,
-                nullptr,                    // permitted_when_isolated_path
-                nullptr);                   // parent
+        // If the sphal namespace isn't configured for a device, don't support updatable drivers.
+        // We need a parent namespace to inherit the default search path from.
+        auto sphalNamespace = android_get_exported_namespace("sphal");
+        if (!sphalNamespace) return;
+        mDriverNamespace = android_create_namespace("gfx driver",
+                                                    nullptr,             // ld_library_path
+                                                    mDriverPath.c_str(), // default_library_path
+                                                    ANDROID_NAMESPACE_TYPE_SHARED |
+                                                            ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                                    nullptr, // permitted_when_isolated_path
+                                                    sphalNamespace);
     });
     return mDriverNamespace;
 }
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index b891c2a..bb703da 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -112,54 +112,60 @@
 void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
     Mutex::Autolock lock(mMutex);
 
-    String8 fifo;
+    outResult->appendFormat("%s- BufferQueue ", prefix.string());
+    outResult->appendFormat("mMaxAcquiredBufferCount=%d mMaxDequeuedBufferCount=%d\n",
+                            mMaxAcquiredBufferCount, mMaxDequeuedBufferCount);
+    outResult->appendFormat("%s  mDequeueBufferCannotBlock=%d mAsyncMode=%d\n", prefix.string(),
+                            mDequeueBufferCannotBlock, mAsyncMode);
+    outResult->appendFormat("%s  default-size=[%dx%d] default-format=%d ", prefix.string(),
+                            mDefaultWidth, mDefaultHeight, mDefaultBufferFormat);
+    outResult->appendFormat("transform-hint=%02x frame-counter=%" PRIu64, mTransformHint,
+                            mFrameCounter);
+
+    outResult->appendFormat("\n%sFIFO(%zu):\n", prefix.string(), mQueue.size());
     Fifo::const_iterator current(mQueue.begin());
     while (current != mQueue.end()) {
-        fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
-                "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
-                current->mSlot, current->mGraphicBuffer.get(),
-                current->mCrop.left, current->mCrop.top, current->mCrop.right,
-                current->mCrop.bottom, current->mTransform, current->mTimestamp,
-                BufferItem::scalingModeName(current->mScalingMode));
+        double timestamp = current->mTimestamp / 1e9;
+        outResult->appendFormat("%s  %02d:%p ", prefix.string(), current->mSlot,
+                                current->mGraphicBuffer.get());
+        outResult->appendFormat("crop=[%d,%d,%d,%d] ", current->mCrop.left, current->mCrop.top,
+                                current->mCrop.right, current->mCrop.bottom);
+        outResult->appendFormat("xform=0x%02x time=%.4f scale=%s\n", current->mTransform, timestamp,
+                                BufferItem::scalingModeName(current->mScalingMode));
         ++current;
     }
 
-    outResult->appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
-            "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
-            "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
-            "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix.string(),
-            mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
-            mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
-            mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
-            fifo.string());
-
+    outResult->appendFormat("%sSlots:\n", prefix.string());
     for (int s : mActiveBuffers) {
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
         // A dequeued buffer might be null if it's still being allocated
         if (buffer.get()) {
-            outResult->appendFormat("%s%s[%02d:%p] state=%-8s, %p "
-                    "[%4ux%4u:%4u,%3X]\n", prefix.string(),
-                    (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
-                    buffer.get(), mSlots[s].mBufferState.string(),
-                    buffer->handle, buffer->width, buffer->height,
-                    buffer->stride, buffer->format);
+            outResult->appendFormat("%s %s[%02d:%p] ", prefix.string(),
+                                    (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
+                                    buffer.get());
+            outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
+                                    buffer->handle, mSlots[s].mFrameNumber);
+            outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
+                                    buffer->stride, buffer->format);
         } else {
-            outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
-                    buffer.get(), mSlots[s].mBufferState.string());
+            outResult->appendFormat("%s  [%02d:%p] ", prefix.string(), s, buffer.get());
+            outResult->appendFormat("state=%-8s frame=%" PRIu64 "\n",
+                                    mSlots[s].mBufferState.string(), mSlots[s].mFrameNumber);
         }
     }
     for (int s : mFreeBuffers) {
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
-        outResult->appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
-                prefix.string(), s, buffer.get(), mSlots[s].mBufferState.string(),
-                buffer->handle, buffer->width, buffer->height, buffer->stride,
-                buffer->format);
+        outResult->appendFormat("%s  [%02d:%p] ", prefix.string(), s, buffer.get());
+        outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
+                                buffer->handle, mSlots[s].mFrameNumber);
+        outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
+                                buffer->stride, buffer->format);
     }
 
     for (int s : mFreeSlots) {
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
-        outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
-                buffer.get(), mSlots[s].mBufferState.string());
+        outResult->appendFormat("%s  [%02d:%p] state=%-8s\n", prefix.string(), s, buffer.get(),
+                                mSlots[s].mBufferState.string());
     }
 }
 
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 2f8e637..8481b50 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -27,6 +27,7 @@
 #include <binder/Parcel.h>
 #include <binder/IInterface.h>
 
+#include <gui/BufferQueueDefs.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/IProducerListener.h>
 
@@ -220,8 +221,16 @@
         if (result != NO_ERROR) {
             return result;
         }
+
         *slot = reply.readInt32();
         result = reply.readInt32();
+        if (result == NO_ERROR &&
+                (*slot < 0 || *slot >= BufferQueueDefs::NUM_BUFFER_SLOTS)) {
+            ALOGE("attachBuffer returned invalid slot %d", *slot);
+            android_errorWriteLog(0x534e4554, "37478824");
+            return UNKNOWN_ERROR;
+        }
+
         return result;
     }
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index a6d9e66..83ebbe8 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -476,6 +476,9 @@
 
     {
         Mutex::Autolock lock(mMutex);
+        if (mReportRemovedBuffers) {
+            mRemovedBuffers.clear();
+        }
 
         reqWidth = mReqWidth ? mReqWidth : mUserWidth;
         reqHeight = mReqHeight ? mReqHeight : mUserHeight;
@@ -513,6 +516,12 @@
         return result;
     }
 
+    if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
+        ALOGE("dequeueBuffer: IGraphicBufferProducer returned invalid slot number %d", buf);
+        android_errorWriteLog(0x534e4554, "36991414"); // SafetyNet logging
+        return FAILED_TRANSACTION;
+    }
+
     Mutex::Autolock lock(mMutex);
 
     sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
@@ -530,7 +539,6 @@
 
     if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
         if (mReportRemovedBuffers && (gbuf != nullptr)) {
-            mRemovedBuffers.clear();
             mRemovedBuffers.push_back(gbuf);
         }
         result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
@@ -1202,6 +1210,9 @@
     }
 
     Mutex::Autolock lock(mMutex);
+    if (mReportRemovedBuffers) {
+        mRemovedBuffers.clear();
+    }
 
     sp<GraphicBuffer> buffer(NULL);
     sp<Fence> fence(NULL);
@@ -1218,13 +1229,9 @@
         *outFence = Fence::NO_FENCE;
     }
 
-    if (mReportRemovedBuffers) {
-        mRemovedBuffers.clear();
-    }
-
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         if (mSlots[i].buffer != NULL &&
-                mSlots[i].buffer->handle == buffer->handle) {
+                mSlots[i].buffer->getId() == buffer->getId()) {
             if (mReportRemovedBuffers) {
                 mRemovedBuffers.push_back(mSlots[i].buffer);
             }
@@ -1241,6 +1248,9 @@
     ALOGV("Surface::attachBuffer");
 
     Mutex::Autolock lock(mMutex);
+    if (mReportRemovedBuffers) {
+        mRemovedBuffers.clear();
+    }
 
     sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
     uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
@@ -1254,7 +1264,6 @@
         return result;
     }
     if (mReportRemovedBuffers && (mSlots[attachedSlot].buffer != nullptr)) {
-        mRemovedBuffers.clear();
         mRemovedBuffers.push_back(mSlots[attachedSlot].buffer);
     }
     mSlots[attachedSlot].buffer = graphicBuffer;
@@ -1509,6 +1518,9 @@
         const Region& reg,
         int *dstFenceFd)
 {
+    if (dst->getId() == src->getId())
+        return OK;
+
     // src and dst with, height and format must be identical. no verification
     // is done here.
     status_t err;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 08d6715..fcaa23a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -24,6 +24,7 @@
 #include <cutils/properties.h>
 #include <gui/BufferItemConsumer.h>
 #include <gui/IDisplayEventConnection.h>
+#include <gui/IProducerListener.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
@@ -320,6 +321,77 @@
     ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
 }
 
+TEST_F(SurfaceTest, GetAndFlushRemovedBuffers) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+    consumer->consumerConnect(dummyConsumer, false);
+    consumer->setConsumerName(String8("TestConsumer"));
+
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+    sp<DummyProducerListener> listener = new DummyProducerListener();
+    ASSERT_EQ(OK, surface->connect(
+            NATIVE_WINDOW_API_CPU,
+            /*listener*/listener,
+            /*reportBufferRemoval*/true));
+    const int BUFFER_COUNT = 4;
+    ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(window.get(), BUFFER_COUNT));
+
+    sp<GraphicBuffer> detachedBuffer;
+    sp<Fence> outFence;
+    int fences[BUFFER_COUNT];
+    ANativeWindowBuffer* buffers[BUFFER_COUNT];
+    // Allocate buffers because detachNextBuffer requires allocated buffers
+    for (int i = 0; i < BUFFER_COUNT; i++) {
+        ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[i], &fences[i]));
+    }
+    for (int i = 0; i < BUFFER_COUNT; i++) {
+        ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], fences[i]));
+    }
+
+    // Test detached buffer is correctly reported
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    std::vector<sp<GraphicBuffer>> removedBuffers;
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    ASSERT_EQ(1u, removedBuffers.size());
+    ASSERT_EQ(detachedBuffer->handle, removedBuffers.at(0)->handle);
+    // Test the list is flushed one getAndFlushRemovedBuffers returns
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    ASSERT_EQ(0u, removedBuffers.size());
+
+
+    // Test removed buffer list is cleanup after next dequeueBuffer call
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[0], &fences[0]));
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    ASSERT_EQ(0u, removedBuffers.size());
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[0], fences[0]));
+
+    // Test removed buffer list is cleanup after next detachNextBuffer call
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    ASSERT_EQ(1u, removedBuffers.size());
+    ASSERT_EQ(detachedBuffer->handle, removedBuffers.at(0)->handle);
+
+    // Re-allocate buffers since all buffers are detached up to now
+    for (int i = 0; i < BUFFER_COUNT; i++) {
+        ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[i], &fences[i]));
+    }
+    for (int i = 0; i < BUFFER_COUNT; i++) {
+        ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], fences[i]));
+    }
+
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    ASSERT_EQ(NO_ERROR, surface->attachBuffer(detachedBuffer.get()));
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    // Depends on which slot GraphicBufferProducer impl pick, the attach call might
+    // get 0 or 1 buffer removed.
+    ASSERT_LE(removedBuffers.size(), 1u);
+}
 
 class FakeConsumer : public BnConsumerListener {
 public:
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp
index 5d7f660..ec9cbf8 100644
--- a/libs/hwc2on1adapter/Android.bp
+++ b/libs/hwc2on1adapter/Android.bp
@@ -14,7 +14,7 @@
 
 cc_library_shared {
     name: "libhwc2on1adapter",
-    vendor_available: true,
+    vendor: true,
 
     clang: true,
     cppflags: [
diff --git a/libs/hwc2on1adapter/CleanSpec.mk b/libs/hwc2on1adapter/CleanSpec.mk
new file mode 100644
index 0000000..7fc2216
--- /dev/null
+++ b/libs/hwc2on1adapter/CleanSpec.mk
@@ -0,0 +1,52 @@
+# 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwc2on1adapter_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwc2on1adapter.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libhwc2on1adapter.so)
diff --git a/libs/math/include/math/half.h b/libs/math/include/math/half.h
index 615b840..7682973 100644
--- a/libs/math/include/math/half.h
+++ b/libs/math/include/math/half.h
@@ -56,8 +56,8 @@
  */
 class half {
     struct fp16 {
-        uint16_t bits = 0;
-        fp16() noexcept = default;
+        uint16_t bits;
+        explicit constexpr fp16() noexcept : bits(0) { }
         explicit constexpr fp16(uint16_t b) noexcept : bits(b) { }
         void setS(unsigned int s) noexcept { bits = uint16_t((bits & 0x7FFF) | (s<<15)); }
         void setE(unsigned int s) noexcept { bits = uint16_t((bits & 0xE3FF) | (s<<10)); }
@@ -68,11 +68,11 @@
     };
     struct fp32 {
         union {
-            uint32_t bits = 0;
+            uint32_t bits;
             float fp;
         };
-        fp32() noexcept = default;
-        explicit constexpr fp32(float f) : fp(f) { }
+        explicit constexpr fp32() noexcept : bits(0) { }
+        explicit constexpr fp32(float f) noexcept : fp(f) { }
         void setS(unsigned int s) noexcept { bits = uint32_t((bits & 0x7FFFFFFF) | (s<<31)); }
         void setE(unsigned int s) noexcept { bits = uint32_t((bits & 0x807FFFFF) | (s<<23)); }
         void setM(unsigned int s) noexcept { bits = uint32_t((bits & 0xFF800000) | (s<< 0)); }
diff --git a/libs/math/tests/mat_test.cpp b/libs/math/tests/mat_test.cpp
index c365366..3217a1a 100644
--- a/libs/math/tests/mat_test.cpp
+++ b/libs/math/tests/mat_test.cpp
@@ -487,7 +487,7 @@
         for (size_t i = 0; i < v1.size(); ++i) {                \
             EXPECT_FLOAT_EQ(v1[i], v2[i]);                      \
         }                                                       \
-    } else if (std::is_same<TypeParam,float>::value) {          \
+    } else if (std::is_same<TypeParam,double>::value) {         \
         for (size_t i = 0; i < v1.size(); ++i) {                \
             EXPECT_DOUBLE_EQ(v1[i], v2[i]);                     \
         }                                                       \
@@ -506,7 +506,7 @@
     const decltype(T2) t2 = T2;                                 \
     if (std::is_same<TypeParam,float>::value) {                 \
         ASSERT_FLOAT_EQ(t1, t2);                                \
-    } else if (std::is_same<TypeParam,float>::value) {         \
+    } else if (std::is_same<TypeParam,double>::value) {         \
         ASSERT_DOUBLE_EQ(t1, t2);                               \
     } else {                                                    \
         ASSERT_EQ(t1, t2);                                      \
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 80c5ec2..c0602e7 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -179,12 +179,17 @@
     memcpy(fdData, fds.get(), sizeof(int) * fdCount);
     msg.msg_controllen = cmsg->cmsg_len;
 
-    int result = sendmsg(socketFd, &msg, 0);
-    if (result <= 0) {
+    int result;
+    do {
+        result = sendmsg(socketFd, &msg, 0);
+    } while (result == -1 && errno == EINTR);
+    if (result == -1) {
+        result = errno;
         ALOGE("Error writing AHardwareBuffer to socket: error %#x (%s)",
-                result, strerror(errno));
-        return result;
+                result, strerror(result));
+        return -result;
     }
+
     return NO_ERROR;
 }
 
@@ -206,11 +211,15 @@
             .msg_iovlen = 1,
     };
 
-    int result = recvmsg(socketFd, &msg, 0);
-    if (result <= 0) {
+    int result;
+    do {
+        result = recvmsg(socketFd, &msg, 0);
+    } while (result == -1 && errno == EINTR);
+    if (result == -1) {
+        result = errno;
         ALOGE("Error reading AHardwareBuffer from socket: error %#x (%s)",
-                result, strerror(errno));
-        return result;
+                result, strerror(result));
+        return -result;
     }
 
     if (msg.msg_iovlen != 1) {
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index c5d9911..e61fbd6 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -73,7 +73,7 @@
 
 llndk_library {
     name: "libnativewindow",
-    symbol_file: "libnativewindow.map.vndk.txt",
+    symbol_file: "libnativewindow.map.txt",
     unversioned: true,
     export_include_dirs: ["include"],
 }
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index b1d1a72..58045be 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -4,22 +4,40 @@
     AHardwareBuffer_allocate;
     AHardwareBuffer_describe;
     AHardwareBuffer_fromHardwareBuffer;
+    AHardwareBuffer_getNativeHandle; # vndk
     AHardwareBuffer_lock;
     AHardwareBuffer_recvHandleFromUnixSocket;
     AHardwareBuffer_release;
     AHardwareBuffer_sendHandleToUnixSocket;
     AHardwareBuffer_toHardwareBuffer;
     AHardwareBuffer_unlock;
+    ANativeWindowBuffer_getHardwareBuffer; # vndk
+    ANativeWindow_OemStorageGet; # vndk
+    ANativeWindow_OemStorageSet; # vndk
     ANativeWindow_acquire;
+    ANativeWindow_cancelBuffer; # vndk
+    ANativeWindow_dequeueBuffer; # vndk
     ANativeWindow_fromSurface;
     ANativeWindow_fromSurfaceTexture;
     ANativeWindow_getFormat;
     ANativeWindow_getHeight;
     ANativeWindow_getWidth;
     ANativeWindow_lock;
+    ANativeWindow_query; # vndk
+    ANativeWindow_queryf; # vndk
+    ANativeWindow_queueBuffer; # vndk
     ANativeWindow_release;
+    ANativeWindow_setAutoRefresh; # vndk
+    ANativeWindow_setBufferCount; # vndk
+    ANativeWindow_setBufferDataSpace; # vndk
+    ANativeWindow_setBuffersDimensions; # vndk
+    ANativeWindow_setBuffersFormat; # vndk
     ANativeWindow_setBuffersGeometry;
+    ANativeWindow_setBuffersTimestamp; # vndk
     ANativeWindow_setBuffersTransform;
+    ANativeWindow_setSharedBufferMode; # vndk
+    ANativeWindow_setSwapInterval; # vndk
+    ANativeWindow_setUsage; # vndk
     ANativeWindow_unlockAndPost;
   local:
     *;
diff --git a/libs/nativewindow/libnativewindow.map.vndk.txt b/libs/nativewindow/libnativewindow.map.vndk.txt
deleted file mode 100644
index eed4e19..0000000
--- a/libs/nativewindow/libnativewindow.map.vndk.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-LIBNATIVEWINDOW {
-  global:
-    AHardwareBuffer_acquire;
-    AHardwareBuffer_allocate;
-    AHardwareBuffer_describe;
-    AHardwareBuffer_fromHardwareBuffer;
-    AHardwareBuffer_getNativeHandle;
-    AHardwareBuffer_lock;
-    AHardwareBuffer_recvHandleFromUnixSocket;
-    AHardwareBuffer_release;
-    AHardwareBuffer_sendHandleToUnixSocket;
-    AHardwareBuffer_toHardwareBuffer;
-    AHardwareBuffer_unlock;
-    ANativeWindowBuffer_getHardwareBuffer;
-    ANativeWindow_OemStorageGet;
-    ANativeWindow_OemStorageSet;
-    ANativeWindow_acquire;
-    ANativeWindow_cancelBuffer;
-    ANativeWindow_dequeueBuffer;
-    ANativeWindow_fromSurface;
-    ANativeWindow_fromSurfaceTexture;
-    ANativeWindow_getFormat;
-    ANativeWindow_getHeight;
-    ANativeWindow_getWidth;
-    ANativeWindow_lock;
-    ANativeWindow_query;
-    ANativeWindow_queryf;
-    ANativeWindow_queueBuffer;
-    ANativeWindow_release;
-    ANativeWindow_setAutoRefresh;
-    ANativeWindow_setBufferCount;
-    ANativeWindow_setBufferDataSpace;
-    ANativeWindow_setBuffersDimensions;
-    ANativeWindow_setBuffersFormat;
-    ANativeWindow_setBuffersGeometry;
-    ANativeWindow_setBuffersTimestamp;
-    ANativeWindow_setBuffersTransform;
-    ANativeWindow_setSharedBufferMode;
-    ANativeWindow_setSwapInterval;
-    ANativeWindow_setUsage;
-    ANativeWindow_unlockAndPost;
-  local:
-    *;
-};
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index c2e93d8..d9cfed7 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -14,6 +14,7 @@
 
 cc_library_shared {
     name: "libui",
+    vendor_available: true,
 
     clang: true,
     cppflags: [
@@ -60,6 +61,10 @@
         "UiConfig.cpp",
     ],
 
+    include_dirs: [
+        "frameworks/native/include",
+    ],
+
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
@@ -70,10 +75,10 @@
         "libhardware",
         "libhidlbase",
         "libhidltransport",
+        "libhwbinder",
         "libsync",
         "libutils",
         "liblog",
-        "libgraphicsenv",
     ],
 
     static_libs: [
@@ -86,6 +91,8 @@
         "libnativebase_headers",
     ],
 
+    export_include_dirs: ["include"],
+
     export_static_lib_headers: [
         "libarect",
         "libmath",
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index 02d4137..b67f4d9 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -165,7 +165,7 @@
         return INVALID_OPERATION;
     }
 
-    if (size < 1) {
+    if (size < getFlattenedSize()) {
         return NO_MEMORY;
     }
 
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index f8d9401..87dbaf4 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "Gralloc2"
 
+#include <hwbinder/IPCThreadState.h>
 #include <ui/Gralloc2.h>
 
 #include <log/log.h>
@@ -241,6 +242,9 @@
                 *outStride = tmpStride;
             });
 
+    // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
+    hardware::IPCThreadState::self()->flushCommands();
+
     return (ret.isOk()) ? error : kTransactionError;
 }
 
diff --git a/include/ui/ANativeObjectBase.h b/libs/ui/include/ui/ANativeObjectBase.h
similarity index 100%
rename from include/ui/ANativeObjectBase.h
rename to libs/ui/include/ui/ANativeObjectBase.h
diff --git a/include/ui/BufferQueueDefs.h b/libs/ui/include/ui/BufferQueueDefs.h
similarity index 100%
rename from include/ui/BufferQueueDefs.h
rename to libs/ui/include/ui/BufferQueueDefs.h
diff --git a/include/ui/ColorSpace.h b/libs/ui/include/ui/ColorSpace.h
similarity index 100%
rename from include/ui/ColorSpace.h
rename to libs/ui/include/ui/ColorSpace.h
diff --git a/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h
similarity index 100%
rename from include/ui/DebugUtils.h
rename to libs/ui/include/ui/DebugUtils.h
diff --git a/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h
similarity index 100%
rename from include/ui/DisplayInfo.h
rename to libs/ui/include/ui/DisplayInfo.h
diff --git a/include/ui/DisplayStatInfo.h b/libs/ui/include/ui/DisplayStatInfo.h
similarity index 100%
rename from include/ui/DisplayStatInfo.h
rename to libs/ui/include/ui/DisplayStatInfo.h
diff --git a/include/ui/Fence.h b/libs/ui/include/ui/Fence.h
similarity index 100%
rename from include/ui/Fence.h
rename to libs/ui/include/ui/Fence.h
diff --git a/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h
similarity index 100%
rename from include/ui/FenceTime.h
rename to libs/ui/include/ui/FenceTime.h
diff --git a/include/ui/FloatRect.h b/libs/ui/include/ui/FloatRect.h
similarity index 100%
rename from include/ui/FloatRect.h
rename to libs/ui/include/ui/FloatRect.h
diff --git a/include/ui/FrameStats.h b/libs/ui/include/ui/FrameStats.h
similarity index 100%
rename from include/ui/FrameStats.h
rename to libs/ui/include/ui/FrameStats.h
diff --git a/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
similarity index 100%
rename from include/ui/Gralloc2.h
rename to libs/ui/include/ui/Gralloc2.h
diff --git a/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
similarity index 100%
rename from include/ui/GraphicBuffer.h
rename to libs/ui/include/ui/GraphicBuffer.h
diff --git a/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
similarity index 100%
rename from include/ui/GraphicBufferAllocator.h
rename to libs/ui/include/ui/GraphicBufferAllocator.h
diff --git a/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
similarity index 100%
rename from include/ui/GraphicBufferMapper.h
rename to libs/ui/include/ui/GraphicBufferMapper.h
diff --git a/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
similarity index 100%
rename from include/ui/HdrCapabilities.h
rename to libs/ui/include/ui/HdrCapabilities.h
diff --git a/include/ui/PixelFormat.h b/libs/ui/include/ui/PixelFormat.h
similarity index 100%
rename from include/ui/PixelFormat.h
rename to libs/ui/include/ui/PixelFormat.h
diff --git a/include/ui/Point.h b/libs/ui/include/ui/Point.h
similarity index 100%
rename from include/ui/Point.h
rename to libs/ui/include/ui/Point.h
diff --git a/include/ui/Rect.h b/libs/ui/include/ui/Rect.h
similarity index 100%
rename from include/ui/Rect.h
rename to libs/ui/include/ui/Rect.h
diff --git a/include/ui/Region.h b/libs/ui/include/ui/Region.h
similarity index 100%
rename from include/ui/Region.h
rename to libs/ui/include/ui/Region.h
diff --git a/include/ui/UiConfig.h b/libs/ui/include/ui/UiConfig.h
similarity index 100%
rename from include/ui/UiConfig.h
rename to libs/ui/include/ui/UiConfig.h
diff --git a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
index 69cb648..f2e5034 100644
--- a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
+++ b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
@@ -174,8 +174,6 @@
   //
   // There must be at least |MemorySize(record_count)| bytes of space already
   // allocated at |mmap|. The ring does not take ownership.
-  //
-  // Use this function for dynamically sized rings.
   static BroadcastRing Create(void* mmap, size_t mmap_size,
                               uint32_t record_count) {
     BroadcastRing ring(mmap);
@@ -188,12 +186,11 @@
   //
   // There must be at least |MemorySize()| bytes of space already allocated at
   // |mmap|. The ring does not take ownership.
-  //
-  // Use this function for statically sized rings.
   static BroadcastRing Create(void* mmap, size_t mmap_size) {
-    static_assert(Traits::kUseStaticRecordCount,
-                  "Wrong Create() function called for dynamic record count");
-    return Create(mmap, mmap_size, Traits::kStaticRecordCount);
+    return Create(mmap, mmap_size,
+                  Traits::kUseStaticRecordCount
+                      ? Traits::kStaticRecordCount
+                      : BroadcastRing::GetRecordCount(mmap_size));
   }
 
   // Imports an existing ring at |mmap|.
@@ -233,6 +230,30 @@
     return MemorySize(Traits::kStaticRecordCount);
   }
 
+  static uint32_t NextPowerOf2(uint32_t n) {
+    if (n == 0)
+      return 0;
+    n -= 1;
+    n |= n >> 16;
+    n |= n >> 8;
+    n |= n >> 4;
+    n |= n >> 2;
+    n |= n >> 1;
+    return n + 1;
+  }
+
+  // Gets the biggest power of 2 record count that can fit into this mmap.
+  //
+  // The header size has been taken into account.
+  static uint32_t GetRecordCount(size_t mmap_size) {
+    if (mmap_size <= sizeof(Header)) {
+      return 0;
+    }
+    uint32_t count =
+        static_cast<uint32_t>((mmap_size - sizeof(Header)) / sizeof(Record));
+    return IsPowerOfTwo(count) ? count : (NextPowerOf2(count) / 2);
+  }
+
   // Writes a record to the ring.
   //
   // The oldest record is overwritten unless the ring is not already full.
@@ -348,6 +369,9 @@
     return Get(sequence, record);
   }
 
+  // Returns true if this instance has been created or imported.
+  bool is_valid() const { return !!data_.mmap; }
+
   uint32_t record_count() const { return record_count_internal(); }
   uint32_t record_size() const { return record_size_internal(); }
   static constexpr uint32_t mmap_alignment() { return alignof(Mmap); }
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index a09a7a1..b9a53b0 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -9,7 +9,6 @@
 
 #include <pdx/default_transport/client_channel.h>
 #include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/platform_defines.h>
 
 #include "include/private/dvr/bufferhub_rpc.h"
 
@@ -18,15 +17,6 @@
 using android::pdx::rpc::WrapBuffer;
 using android::pdx::Status;
 
-namespace {
-
-// TODO(hendrikw): These flags can not be hard coded.
-constexpr int kUncachedBlobUsageFlags = GRALLOC_USAGE_SW_READ_RARELY |
-                                        GRALLOC_USAGE_SW_WRITE_RARELY |
-                                        GRALLOC_USAGE_PRIVATE_UNCACHED;
-
-}  // anonymous namespace
-
 namespace android {
 namespace dvr {
 
@@ -101,25 +91,14 @@
 int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
   int width = static_cast<int>(size);
   int height = 1;
-  // TODO(hendrikw): These flags can not be hard coded.
-  constexpr int usage = GRALLOC_USAGE_SW_READ_RARELY |
-                        GRALLOC_USAGE_SW_WRITE_RARELY |
-                        GRALLOC_USAGE_PRIVATE_UNCACHED;
-  int ret = Lock(usage, 0, 0, width, height, addr);
+  int ret = Lock(usage(), 0, 0, width, height, addr);
   if (ret == 0)
     Unlock();
   return ret;
 }
 
 int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) {
-  int width = static_cast<int>(size);
-  int height = 1;
-  constexpr int usage =
-      GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_PRIVATE_UNCACHED;
-  int ret = Lock(usage, 0, 0, width, height, addr);
-  if (ret == 0)
-    Unlock();
-  return ret;
+  return GetBlobReadWritePointer(size, addr);
 }
 
 void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
@@ -429,16 +408,5 @@
       InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>());
 }
 
-std::unique_ptr<BufferProducer> BufferProducer::CreateUncachedBlob(
-    size_t size) {
-  return BufferProducer::Create(kUncachedBlobUsageFlags, size);
-}
-
-std::unique_ptr<BufferProducer> BufferProducer::CreatePersistentUncachedBlob(
-    const std::string& name, int user_id, int group_id, size_t size) {
-  return BufferProducer::Create(name, user_id, group_id,
-                                kUncachedBlobUsageFlags, size);
-}
-
 }  // namespace dvr
 }  // namespace android
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 83e9255..be20e72 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -131,15 +131,6 @@
 // The API also assumes that metadata is a serializable type (plain old data).
 class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
  public:
-  // Create a buffer designed to hold arbitrary bytes that can be read and
-  // written from CPU, GPU and DSP. The buffer is mapped uncached so that CPU
-  // reads and writes are predictable.
-  static std::unique_ptr<BufferProducer> CreateUncachedBlob(size_t size);
-
-  // Creates a persistent uncached buffer with the given name and access.
-  static std::unique_ptr<BufferProducer> CreatePersistentUncachedBlob(
-      const std::string& name, int user_id, int group_id, size_t size);
-
   // Imports a bufferhub producer channel, assuming ownership of its handle.
   static std::unique_ptr<BufferProducer> Import(LocalChannelHandle channel);
   static std::unique_ptr<BufferProducer> Import(
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index ffdc9e2..d79d96d 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -129,19 +129,102 @@
 using LocalFence = FenceHandle<pdx::LocalHandle>;
 using BorrowedFence = FenceHandle<pdx::BorrowedHandle>;
 
-struct QueueInfo {
+struct ProducerQueueConfig {
+  // Whether the buffer queue is operating in Async mode.
+  // From GVR's perspective of view, this means a buffer can be acquired
+  // asynchronously by the compositor.
+  // From Android Surface's perspective of view, this is equivalent to
+  // IGraphicBufferProducer's async mode. When in async mode, a producer
+  // will never block even if consumer is running slow.
+  bool is_async;
+
+  // Default buffer width that is set during ProducerQueue's creation.
+  uint32_t default_width;
+
+  // Default buffer height that is set during ProducerQueue's creation.
+  uint32_t default_height;
+
+  // Default buffer format that is set during ProducerQueue's creation.
+  uint32_t default_format;
+
+  // Size of the meta data associated with all the buffers allocated from the
+  // queue.
   size_t meta_size_bytes;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, is_async, default_width,
+                           default_height, default_format, meta_size_bytes);
+};
+
+class ProducerQueueConfigBuilder {
+ public:
+  // Build a ProducerQueueConfig object.
+  ProducerQueueConfig Build() {
+    return {is_async_, default_width_, default_height_, default_format_,
+            meta_size_bytes_};
+  }
+
+  ProducerQueueConfigBuilder& SetIsAsync(bool is_async) {
+    is_async_ = is_async;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultWidth(uint32_t width) {
+    default_width_ = width;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultHeight(uint32_t height) {
+    default_height_ = height;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultFormat(uint32_t format) {
+    default_format_ = format;
+    return *this;
+  }
+
+  template <typename Meta>
+  ProducerQueueConfigBuilder& SetMetadata() {
+    meta_size_bytes_ = sizeof(Meta);
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetMetadataSize(size_t meta_size_bytes) {
+    meta_size_bytes_ = meta_size_bytes;
+    return *this;
+  }
+
+ private:
+  bool is_async_{false};
+  uint32_t default_width_{1};
+  uint32_t default_height_{1};
+  uint32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
+  size_t meta_size_bytes_{0};
+};
+
+// Explicit specializations of ProducerQueueConfigBuilder::Build for void
+// metadata type.
+template <>
+inline ProducerQueueConfigBuilder&
+ProducerQueueConfigBuilder::SetMetadata<void>() {
+  meta_size_bytes_ = 0;
+  return *this;
+}
+
+struct QueueInfo {
+  ProducerQueueConfig producer_config;
   int id;
 
  private:
-  PDX_SERIALIZABLE_MEMBERS(QueueInfo, meta_size_bytes, id);
+  PDX_SERIALIZABLE_MEMBERS(QueueInfo, producer_config, id);
 };
 
 struct UsagePolicy {
-  uint64_t usage_set_mask;
-  uint64_t usage_clear_mask;
-  uint64_t usage_deny_set_mask;
-  uint64_t usage_deny_clear_mask;
+  uint64_t usage_set_mask{0};
+  uint64_t usage_clear_mask{0};
+  uint64_t usage_deny_set_mask{0};
+  uint64_t usage_deny_clear_mask{0};
 
  private:
   PDX_SERIALIZABLE_MEMBERS(UsagePolicy, usage_set_mask, usage_clear_mask,
@@ -219,7 +302,7 @@
 
   // Buffer Queue Methods.
   PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
-                    QueueInfo(size_t meta_size_bytes,
+                    QueueInfo(const ProducerQueueConfig& producer_config,
                               const UsagePolicy& usage_policy));
   PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
                     LocalChannelHandle(Void));
diff --git a/libs/vr/libbufferhub/mocks/client/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/mocks/client/private/dvr/buffer_hub_client.h
deleted file mode 100644
index 33816fa..0000000
--- a/libs/vr/libbufferhub/mocks/client/private/dvr/buffer_hub_client.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef LIB_LIBBUFFERHUB_PRIVATE_DVR_BUFFER_HUB_CLIENT_H_  // NOLINT
-#define LIB_LIBBUFFERHUB_PRIVATE_DVR_BUFFER_HUB_CLIENT_H_
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-// TODO(jwcai) mock not need for now
-class native_handle_t;
-
-namespace android {
-namespace dvr {
-
-// TODO(jwcai) mock not need for now
-class IonBuffer;
-
-class BufferHubBuffer {
- public:
-  MOCK_METHOD1(Poll, int(int timeout_ms));
-  MOCK_METHOD6(Lock, bool(int usage, int x, int y, int width, int height,
-                          void** addr));
-  MOCK_METHOD0(Unlock, int());
-
-  MOCK_METHOD0(native_handle, native_handle_t*());
-  MOCK_METHOD0(buffer, IonBuffer*());
-  MOCK_METHOD0(event_fd, int());
-
-  MOCK_METHOD0(id, int());
-  MOCK_METHOD0(width, int());
-  MOCK_METHOD0(height, int());
-  MOCK_METHOD0(stride, int());
-  MOCK_METHOD0(format, int());
-  MOCK_METHOD0(usage, int());
-};
-
-class BufferProducer : public BufferHubBuffer {
- public:
-  // Note that static method |CreateBuffer| and |Import| are not mocked
-  // here, they are just implementation details and thus not needed.
-  MOCK_METHOD2(Post, int(int ready_fence, uint64_t sequence));
-  MOCK_METHOD1(Gain, int(int* release_fence));
-
-  static BufferProducer* staticObject;
-};
-
-class BufferConsumer : public BufferHubBuffer {
- public:
-  MOCK_METHOD2(Acquire, int(int* ready_fence, uint64_t* sequence));
-  MOCK_METHOD1(Release, int(int release_fence));
-  MOCK_METHOD0(Discard, int());
-  MOCK_METHOD3(DoAcquire,
-               int(int* ready_fence, void* meta, size_t meta_size_bytes));
-
-  static BufferConsumer* staticObject;
-};
-
-}  // namespace dvr
-}  // namespace android
-#endif  // LIB_LIBBUFFERHUB_PRIVATE_DVR_BUFFER_HUB_CLIENT_H_  //NOLINT
diff --git a/libs/vr/libbufferhub/mocks/gralloc/BUILD.gn b/libs/vr/libbufferhub/mocks/gralloc/BUILD.gn
deleted file mode 100644
index 9674c7c..0000000
--- a/libs/vr/libbufferhub/mocks/gralloc/BUILD.gn
+++ /dev/null
@@ -1,23 +0,0 @@
-config("gralloc_config") {
-  include_dirs = [ "." ]
-}
-
-static_library("gralloc") {
-  testonly = true
-
-  sources = [
-    "gralloc.cpp",
-    "gralloc.h",
-  ]
-
-  include_dirs = [
-    "//system/core/include",
-    "//hardware/libhardware/include",
-  ]
-
-  public_deps = [
-    "//dreamos/external/gmock",
-  ]
-
-  public_configs = [ ":gralloc_config" ]
-}
diff --git a/libs/vr/libbufferhub/mocks/gralloc/gralloc.cpp b/libs/vr/libbufferhub/mocks/gralloc/gralloc.cpp
deleted file mode 100644
index 4a923ec..0000000
--- a/libs/vr/libbufferhub/mocks/gralloc/gralloc.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <gralloc_mock.h>
-#include <hardware/gralloc.h>
-
-static alloc_device_t sdevice;
-
-static int local_registerBuffer(struct gralloc_module_t const*,
-                                buffer_handle_t handle) {
-  return GrallocMock::staticObject->registerBuffer(handle);
-}
-
-static int local_unregisterBuffer(struct gralloc_module_t const*,
-                                  buffer_handle_t handle) {
-  return GrallocMock::staticObject->unregisterBuffer(handle);
-}
-
-static int local_unlock(struct gralloc_module_t const*,
-                        buffer_handle_t handle) {
-  return GrallocMock::staticObject->unlock(handle);
-}
-
-static int local_lock(struct gralloc_module_t const*, buffer_handle_t handle,
-                      int usage, int l, int t, int w, int h, void** vaddr) {
-  return GrallocMock::staticObject->lock(handle, usage, l, t, w, h, vaddr);
-}
-
-static int local_alloc(struct alloc_device_t*, int w, int h, int format,
-                       int usage, buffer_handle_t* handle, int* stride) {
-  return GrallocMock::staticObject->alloc(w, h, format, usage, handle, stride);
-}
-
-static int local_free(struct alloc_device_t*, buffer_handle_t handle) {
-  return GrallocMock::staticObject->free(handle);
-}
-
-static int local_open(const struct hw_module_t*, const char*,
-                      struct hw_device_t** device) {
-  sdevice.alloc = local_alloc;
-  sdevice.free = local_free;
-  *device = reinterpret_cast<hw_device_t*>(&sdevice);
-  return 0;
-}
-
-static hw_module_methods_t smethods;
-
-static gralloc_module_t smodule;
-
-int hw_get_module(const char*, const struct hw_module_t** module) {
-  smodule.registerBuffer = local_registerBuffer;
-  smodule.unregisterBuffer = local_unregisterBuffer;
-  smodule.lock = local_lock;
-  smodule.unlock = local_unlock;
-  smethods.open = local_open;
-  smodule.common.methods = &smethods;
-  *module = reinterpret_cast<hw_module_t*>(&smodule);
-  return 0;
-}
-
-int native_handle_close(const native_handle_t* handle) {
-  return GrallocMock::staticObject->native_handle_close(handle);
-}
-
-int native_handle_delete(native_handle_t* handle) {
-  return GrallocMock::staticObject->native_handle_delete(handle);
-}
-
-native_handle_t* native_handle_create(int numFds, int numInts) {
-  return GrallocMock::staticObject->native_handle_create(numFds, numInts);
-}
diff --git a/libs/vr/libbufferhub/mocks/gralloc/gralloc_mock.h b/libs/vr/libbufferhub/mocks/gralloc/gralloc_mock.h
deleted file mode 100644
index f62f579..0000000
--- a/libs/vr/libbufferhub/mocks/gralloc/gralloc_mock.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef LIB_LIBBUFFERHUB_MOCKS_GRALLOC_GRALLOC_MOCK_H_
-#define LIB_LIBBUFFERHUB_MOCKS_GRALLOC_GRALLOC_MOCK_H_
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <hardware/gralloc.h>
-
-// IonBuffer is an abstraction of Ion/Gralloc buffers.
-class GrallocMock {
- public:
-  // Add methods here.
-  MOCK_METHOD1(native_handle_close, int(const native_handle_t*));
-  MOCK_METHOD1(native_handle_delete, int(native_handle_t*));
-  MOCK_METHOD2(native_handle_create, native_handle_t*(int, int));
-  MOCK_METHOD1(registerBuffer, int(buffer_handle_t));
-  MOCK_METHOD1(unregisterBuffer, int(buffer_handle_t));
-  MOCK_METHOD7(lock, int(buffer_handle_t, int, int, int, int, int, void**));
-  MOCK_METHOD1(unlock, int(buffer_handle_t));
-  MOCK_METHOD6(alloc, int(int, int, int, int, buffer_handle_t*, int*));
-  MOCK_METHOD1(free, int(buffer_handle_t));
-  static GrallocMock* staticObject;
-};
-
-#endif  // LIB_LIBBUFFERHUB_MOCKS_GRALLOC_GRALLOC_MOCK_H_
diff --git a/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h
deleted file mode 100644
index 8929c95..0000000
--- a/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// This file has a big hack, it "mocks" the actual IonBuffer by redefining
-// it with mock methods and using the same header guard to prevent the original
-// definition from being included in the same context.
-#ifndef LIB_LIBBUFFERHUB_PRIVATE_DVR_ION_BUFFER_H_  // NOLINT
-#define LIB_LIBBUFFERHUB_PRIVATE_DVR_ION_BUFFER_H_
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <hardware/gralloc.h>
-
-namespace android {
-namespace dvr {
-
-// IonBuffer is an abstraction of Ion/Gralloc buffers.
-class IonBufferMock {
- public:
-  IonBufferMock() {}
-  MOCK_METHOD0(GetGrallocModuleImpl, gralloc_module_t const*());
-  MOCK_METHOD6(Import, int(buffer_handle_t handle, int width, int height,
-                           int layer_count, int stride, int format, int usage));
-  MOCK_METHOD9(Import,
-               int(const int* fd_array, int fd_count, const int* int_array,
-                   int int_count, int width, int height, int layer_count,
-                   int stride, int format, int usage));
-  MOCK_METHOD6(Lock, int(int usage, int x, int y, int width, int height,
-                         void** address));
-  MOCK_METHOD0(Unlock, int());
-  MOCK_CONST_METHOD0(handle, buffer_handle_t());
-  MOCK_CONST_METHOD0(width, int());
-  MOCK_CONST_METHOD0(height, int());
-  MOCK_CONST_METHOD0(layer_count, int());
-  MOCK_CONST_METHOD0(stride, int());
-  MOCK_CONST_METHOD0(format, int());
-  MOCK_CONST_METHOD0(usage, int());
-};
-
-// IonBuffer is an abstraction of Ion/Gralloc buffers.
-class IonBuffer {
- public:
-  IonBuffer() : mock_(new IonBufferMock) {
-    if (initializer) {
-      initializer(mock_.get());
-    }
-  }
-  IonBuffer(IonBuffer&& other) = default;
-  static gralloc_module_t const* GetGrallocModule() {
-    return staticObject->GetGrallocModuleImpl();
-  }
-  int Import(buffer_handle_t handle, int width, int height, int layer_count,
-             int stride, int format, int usage) {
-    return mock_->Import(handle, width, height, layer_count, stride, format,
-                         usage);
-  }
-  int Import(const int* fd_array, int fd_count, const int* int_array,
-             int int_count, int width, int height, int layer_count, int stride,
-             int format, int usage) {
-    return mock_->Import(fd_array, fd_count, int_array, int_count, width,
-                         height, layer_count, stride, format, usage);
-  }
-  int Lock(int usage, int x, int y, int width, int height, void** address) {
-    return mock_->Lock(usage, x, y, width, height, address);
-  }
-  int Unlock() { return mock_->Unlock(); }
-  buffer_handle_t handle() const { return mock_->handle(); }
-  int width() const { return mock_->width(); }
-  int height() const { return mock_->height(); }
-  int layer_count() const { return mock_->layer_count(); }
-  int stride() const { return mock_->stride(); }
-  int format() const { return mock_->format(); }
-  int usage() const { return mock_->usage(); }
-  std::unique_ptr<IonBufferMock> mock_;
-  static IonBufferMock* staticObject;
-  static void (*initializer)(IonBufferMock* target);
-};
-
-}  // namespace dvr
-}  // namespace android
-#endif  // LIB_LIBBUFFERHUB_PRIVATE_DVR_ION_BUFFER_H_ - NOLINT
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 2a3f5fc..0b3b2f0 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -14,8 +14,6 @@
 
 sourceFiles = [
     "buffer_hub_queue_client.cpp",
-    "buffer_hub_queue_core.cpp",
-    "buffer_hub_queue_consumer.cpp",
     "buffer_hub_queue_producer.cpp",
 ]
 
@@ -41,6 +39,7 @@
 ]
 
 headerLibraries = [
+    "libdvr_headers",
     "libnativebase_headers",
 ]
 
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 012a4e7..e59bbb5 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -10,7 +10,6 @@
 #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>
 
 #define RETRY_EINTR(fnc_call)                 \
   ([&]() -> decltype(fnc_call) {              \
@@ -23,34 +22,61 @@
 
 using android::pdx::ErrorStatus;
 using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
 using android::pdx::Status;
 
 namespace android {
 namespace dvr {
 
+namespace {
+
+// Polls an fd for the given events.
+Status<int> PollEvents(int fd, short events) {
+  const int kTimeoutMs = 0;
+  pollfd pfd{fd, events, 0};
+  const int count = RETRY_EINTR(poll(&pfd, 1, kTimeoutMs));
+  if (count < 0) {
+    return ErrorStatus(errno);
+  } else if (count == 0) {
+    return ErrorStatus(ETIMEDOUT);
+  } else {
+    return {pfd.revents};
+  }
+}
+
+// Polls a buffer for the given events, taking care to do the proper
+// translation.
+Status<int> PollEvents(const std::shared_ptr<BufferHubBuffer>& buffer,
+                       short events) {
+  auto poll_status = PollEvents(buffer->event_fd(), events);
+  if (!poll_status)
+    return poll_status;
+
+  return buffer->GetEventMask(poll_status.get());
+}
+
+std::pair<int32_t, int32_t> Unstuff(uint64_t value) {
+  return {static_cast<int32_t>(value >> 32),
+          static_cast<int32_t>(value & ((1ull << 32) - 1))};
+}
+
+uint64_t Stuff(int32_t a, int32_t b) {
+  const uint32_t ua = static_cast<uint32_t>(a);
+  const uint32_t ub = static_cast<uint32_t>(b);
+  return (static_cast<uint64_t>(ua) << 32) | static_cast<uint64_t>(ub);
+}
+
+}  // anonymous namespace
+
 BufferHubQueue::BufferHubQueue(LocalChannelHandle channel_handle)
     : Client{pdx::default_transport::ClientChannel::Create(
-          std::move(channel_handle))},
-      meta_size_(0),
-      buffers_(BufferHubQueue::kMaxQueueCapacity),
-      epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
-      available_buffers_(BufferHubQueue::kMaxQueueCapacity),
-      fences_(BufferHubQueue::kMaxQueueCapacity),
-      capacity_(0),
-      id_(-1) {
+          std::move(channel_handle))} {
   Initialize();
 }
 
 BufferHubQueue::BufferHubQueue(const std::string& endpoint_path)
-    : Client{pdx::default_transport::ClientChannelFactory::Create(
-          endpoint_path)},
-      meta_size_(0),
-      buffers_(BufferHubQueue::kMaxQueueCapacity),
-      epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
-      available_buffers_(BufferHubQueue::kMaxQueueCapacity),
-      fences_(BufferHubQueue::kMaxQueueCapacity),
-      capacity_(0),
-      id_(-1) {
+    : Client{
+          pdx::default_transport::ClientChannelFactory::Create(endpoint_path)} {
   Initialize();
 }
 
@@ -62,9 +88,9 @@
     return;
   }
 
-  epoll_event event = {.events = EPOLLIN | EPOLLET,
-                       .data = {.u64 = static_cast<uint64_t>(
-                                    BufferHubQueue::kEpollQueueEventIndex)}};
+  epoll_event event = {
+      .events = EPOLLIN | EPOLLET,
+      .data = {.u64 = Stuff(-1, BufferHubQueue::kEpollQueueEventIndex)}};
   ret = epoll_fd_.Control(EPOLL_CTL_ADD, event_fd(), &event);
   if (ret < 0) {
     ALOGE("BufferHubQueue::Initialize: Failed to add event fd to epoll set: %s",
@@ -79,15 +105,18 @@
           status.GetErrorMessage().c_str());
     return ErrorStatus(status.error());
   } else {
-    SetupQueue(status.get().meta_size_bytes, status.get().id);
+    SetupQueue(status.get());
     return {};
   }
 }
 
-void BufferHubQueue::SetupQueue(size_t meta_size_bytes, int id) {
-  meta_size_ = meta_size_bytes;
-  id_ = id;
-  meta_buffer_tmp_.reset(meta_size_ > 0 ? new uint8_t[meta_size_] : nullptr);
+void BufferHubQueue::SetupQueue(const QueueInfo& queue_info) {
+  is_async_ = queue_info.producer_config.is_async;
+  default_width_ = queue_info.producer_config.default_width;
+  default_height_ = queue_info.producer_config.default_height;
+  default_format_ = queue_info.producer_config.default_format;
+  meta_size_ = queue_info.producer_config.meta_size_bytes;
+  id_ = queue_info.id;
 }
 
 std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
@@ -152,19 +181,24 @@
     // one for each buffer, in the queue and one extra event for the queue
     // client itself.
     for (int i = 0; i < num_events; i++) {
-      int64_t index = static_cast<int64_t>(events[i].data.u64);
+      int32_t event_fd;
+      int32_t index;
+      std::tie(event_fd, index) = Unstuff(events[i].data.u64);
 
       ALOGD_IF(TRACE,
-               "BufferHubQueue::WaitForBuffers: event %d: index=%" PRId64, i,
-               index);
+               "BufferHubQueue::WaitForBuffers: event %d: event_fd=%d index=%d",
+               i, event_fd, index);
 
       if (is_buffer_event_index(index)) {
-        HandleBufferEvent(static_cast<size_t>(index), events[i].events);
+        HandleBufferEvent(static_cast<size_t>(index), event_fd,
+                          events[i].events);
       } else if (is_queue_event_index(index)) {
         HandleQueueEvent(events[i].events);
       } else {
-        ALOGW("BufferHubQueue::WaitForBuffers: Unknown event index: %" PRId64,
-              index);
+        ALOGW(
+            "BufferHubQueue::WaitForBuffers: Unknown event type event_fd=%d "
+            "index=%d",
+            event_fd, index);
       }
     }
   } while (count() == 0 && capacity() > 0 && !hung_up());
@@ -172,52 +206,72 @@
   return count() != 0;
 }
 
-void BufferHubQueue::HandleBufferEvent(size_t slot, int poll_events) {
-  auto buffer = buffers_[slot];
-  if (!buffer) {
+Status<void> BufferHubQueue::HandleBufferEvent(size_t slot, int event_fd,
+                                               int poll_events) {
+  if (!buffers_[slot]) {
     ALOGW("BufferHubQueue::HandleBufferEvent: Invalid buffer slot: %zu", slot);
-    return;
+    return ErrorStatus(ENOENT);
   }
 
-  auto status = buffer->GetEventMask(poll_events);
+  auto status = buffers_[slot]->GetEventMask(poll_events);
   if (!status) {
     ALOGW("BufferHubQueue::HandleBufferEvent: Failed to get event mask: %s",
           status.GetErrorMessage().c_str());
-    return;
+    return status.error_status();
   }
 
   const int events = status.get();
   if (events & EPOLLIN) {
-    const int ret = OnBufferReady(buffer, &fences_[slot]);
-    if (ret == 0 || ret == -EALREADY || ret == -EBUSY) {
+    auto entry_status = OnBufferReady(buffers_[slot], slot);
+    if (entry_status.ok() || entry_status.error() == EALREADY) {
       // Only enqueue the buffer if it moves to or is already in the state
-      // requested in OnBufferReady(). If the buffer is busy this means that the
-      // buffer moved from released to posted when a new consumer was created
-      // before the ProducerQueue had a chance to regain it. This is a valid
-      // transition that we have to handle because edge triggered poll events
-      // latch the ready state even if it is later de-asserted -- don't enqueue
-      // or print an error log in this case.
-      if (ret != -EBUSY)
-        Enqueue(buffer, slot);
+      // requested in OnBufferReady().
+      return Enqueue(entry_status.take());
+    } else if (entry_status.error() == EBUSY) {
+      // If the buffer is busy this means that the buffer moved from released to
+      // posted when a new consumer was created before the ProducerQueue had a
+      // chance to regain it. This is a valid transition that we have to handle
+      // because edge triggered poll events latch the ready state even if it is
+      // later de-asserted -- don't enqueue or print an error log in this case.
     } else {
       ALOGE(
           "BufferHubQueue::HandleBufferEvent: Failed to set buffer ready, "
           "queue_id=%d buffer_id=%d: %s",
-          id(), buffer->id(), strerror(-ret));
+          id(), buffers_[slot]->id(), entry_status.GetErrorMessage().c_str());
     }
   } else if (events & EPOLLHUP) {
-    // This might be caused by producer replacing an existing buffer slot, or
-    // when BufferHubQueue is shutting down. For the first case, currently the
-    // epoll FD is cleaned up when the replacement consumer client is imported,
-    // we shouldn't detach again if |epollhub_pending_[slot]| is set.
+    // Check to see if the current buffer in the slot hung up. This is a bit of
+    // paranoia to deal with the epoll set getting out of sync with the buffer
+    // slots.
+    auto poll_status = PollEvents(buffers_[slot], POLLIN);
+    if (!poll_status && poll_status.error() != ETIMEDOUT) {
+      ALOGE("BufferHubQueue::HandleBufferEvent: Failed to poll buffer: %s",
+            poll_status.GetErrorMessage().c_str());
+      return poll_status.error_status();
+    }
+
+    const bool hangup_pending = status.ok() && (poll_status.get() & EPOLLHUP);
+
     ALOGW(
-        "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP at slot: %zu, "
-        "buffer event fd: %d, EPOLLHUP pending: %d",
-        slot, buffer->event_fd(), int{epollhup_pending_[slot]});
-    if (epollhup_pending_[slot]) {
-      epollhup_pending_[slot] = false;
+        "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP event: slot=%zu "
+        "event_fd=%d buffer_id=%d hangup_pending=%d poll_status=%x",
+        slot, buffers_[slot]->event_fd(), buffers_[slot]->id(), hangup_pending,
+        poll_status.get());
+
+    if (hangup_pending) {
+      return DetachBuffer(slot);
     } else {
-      DetachBuffer(slot);
+      // Clean up the bookkeeping for the event fd. This is a bit of paranoia to
+      // deal with the epoll set getting out of sync with the buffer slots.
+      // Hitting this path should be very unusual.
+      const int ret = epoll_fd_.Control(EPOLL_CTL_DEL, event_fd, nullptr);
+      if (ret < 0) {
+        ALOGE(
+            "BufferHubQueue::HandleBufferEvent: Failed to remove fd=%d from "
+            "epoll set: %s",
+            event_fd, strerror(-ret));
+        return ErrorStatus(-ret);
+      }
     }
   } else {
     ALOGW(
@@ -225,14 +279,16 @@
         "events=%d",
         slot, events);
   }
+
+  return {};
 }
 
-void BufferHubQueue::HandleQueueEvent(int poll_event) {
+Status<void> BufferHubQueue::HandleQueueEvent(int poll_event) {
   auto status = GetEventMask(poll_event);
   if (!status) {
     ALOGW("BufferHubQueue::HandleQueueEvent: Failed to get event mask: %s",
           status.GetErrorMessage().c_str());
-    return;
+    return status.error_status();
   }
 
   const int events = status.get();
@@ -250,115 +306,98 @@
   } else {
     ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%x", events);
   }
+
+  return {};
 }
 
-int BufferHubQueue::AddBuffer(const std::shared_ptr<BufferHubBuffer>& buf,
-                              size_t slot) {
+Status<void> BufferHubQueue::AddBuffer(
+    const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+  ALOGD_IF(TRACE, "BufferHubQueue::AddBuffer: buffer_id=%d slot=%zu",
+           buffer->id(), slot);
+
   if (is_full()) {
-    // TODO(jwcai) Move the check into Producer's AllocateBuffer and consumer's
-    // import buffer.
     ALOGE("BufferHubQueue::AddBuffer queue is at maximum capacity: %zu",
           capacity_);
-    return -E2BIG;
+    return ErrorStatus(E2BIG);
   }
 
-  if (buffers_[slot] != nullptr) {
-    // Replace the buffer if the slot is preoccupied. This could happen when the
+  if (buffers_[slot]) {
+    // Replace the buffer if the slot is occupied. This could happen when the
     // producer side replaced the slot with a newly allocated buffer. Detach the
     // buffer before setting up with the new one.
-    DetachBuffer(slot);
-    epollhup_pending_[slot] = true;
+    auto detach_status = DetachBuffer(slot);
+    if (!detach_status)
+      return detach_status.error_status();
   }
 
-  epoll_event event = {.events = EPOLLIN | EPOLLET, .data = {.u64 = slot}};
-  const int ret = epoll_fd_.Control(EPOLL_CTL_ADD, buf->event_fd(), &event);
+  epoll_event event = {.events = EPOLLIN | EPOLLET,
+                       .data = {.u64 = Stuff(buffer->event_fd(), slot)}};
+  const int ret = epoll_fd_.Control(EPOLL_CTL_ADD, buffer->event_fd(), &event);
   if (ret < 0) {
     ALOGE("BufferHubQueue::AddBuffer: Failed to add buffer to epoll set: %s",
           strerror(-ret));
-    return ret;
+    return ErrorStatus(-ret);
   }
 
-  buffers_[slot] = buf;
+  buffers_[slot] = buffer;
   capacity_++;
-  return 0;
+  return {};
 }
 
-int BufferHubQueue::DetachBuffer(size_t slot) {
-  auto& buf = buffers_[slot];
-  if (buf == nullptr) {
-    ALOGE("BufferHubQueue::DetachBuffer: Invalid slot: %zu", slot);
-    return -EINVAL;
+Status<void> BufferHubQueue::DetachBuffer(size_t slot) {
+  ALOGD_IF(TRACE, "BufferHubQueue::DetachBuffer: slot=%zu", slot);
+
+  if (buffers_[slot]) {
+    const int ret =
+        epoll_fd_.Control(EPOLL_CTL_DEL, buffers_[slot]->event_fd(), nullptr);
+    if (ret < 0) {
+      ALOGE(
+          "BufferHubQueue::DetachBuffer: Failed to detach buffer from epoll "
+          "set: "
+          "%s",
+          strerror(-ret));
+      return ErrorStatus(-ret);
+    }
+
+    buffers_[slot] = nullptr;
+    capacity_--;
   }
 
-  const int ret = epoll_fd_.Control(EPOLL_CTL_DEL, buf->event_fd(), nullptr);
-  if (ret < 0) {
-    ALOGE(
-        "BufferHubQueue::DetachBuffer: Failed to detach buffer from epoll set: "
-        "%s",
-        strerror(-ret));
-    return ret;
-  }
-
-  buffers_[slot] = nullptr;
-  capacity_--;
-  return 0;
+  return {};
 }
 
-void BufferHubQueue::Enqueue(const std::shared_ptr<BufferHubBuffer>& buf,
-                             size_t slot) {
-  if (count() == capacity_) {
+Status<void> BufferHubQueue::Enqueue(Entry entry) {
+  if (!is_full()) {
+    available_buffers_.Append(std::move(entry));
+    return {};
+  } else {
     ALOGE("BufferHubQueue::Enqueue: Buffer queue is full!");
-    return;
+    return ErrorStatus(E2BIG);
   }
-
-  // Set slot buffer back to vector.
-  // TODO(jwcai) Here have to dynamically allocate BufferInfo::metadata due to
-  // the limitation of the RingBuffer we are using. Would be better to refactor
-  // that.
-  BufferInfo buffer_info(slot, meta_size_);
-  buffer_info.buffer = buf;
-  // Swap metadata loaded during onBufferReady into vector.
-  std::swap(buffer_info.metadata, meta_buffer_tmp_);
-
-  available_buffers_.Append(std::move(buffer_info));
 }
 
 Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(
     int timeout, size_t* slot, void* meta, LocalHandle* fence) {
-  ALOGD_IF(TRACE, "Dequeue: count=%zu, timeout=%d", count(), timeout);
+  ALOGD_IF(TRACE, "BufferHubQueue::Dequeue: count=%zu, timeout=%d", count(),
+           timeout);
 
   if (!WaitForBuffers(timeout))
     return ErrorStatus(ETIMEDOUT);
 
-  std::shared_ptr<BufferHubBuffer> buf;
-  BufferInfo& buffer_info = available_buffers_.Front();
+  auto& entry = available_buffers_.Front();
 
-  *fence = std::move(fences_[buffer_info.slot]);
-
-  // Report current pos as the output slot.
-  std::swap(buffer_info.slot, *slot);
-  // Swap buffer from vector to be returned later.
-  std::swap(buffer_info.buffer, buf);
-  // Swap metadata from vector into tmp so that we can write out to |meta|.
-  std::swap(buffer_info.metadata, meta_buffer_tmp_);
-
-  available_buffers_.PopFront();
-
-  if (!buf) {
-    ALOGE("BufferHubQueue::Dequeue: Buffer to be dequeued is nullptr");
-    return ErrorStatus(ENOBUFS);
-  }
-
-  if (meta) {
-    std::copy(meta_buffer_tmp_.get(), meta_buffer_tmp_.get() + meta_size_,
+  std::shared_ptr<BufferHubBuffer> buffer = std::move(entry.buffer);
+  *slot = entry.slot;
+  *fence = std::move(entry.fence);
+  if (meta && entry.metadata) {
+    std::copy(entry.metadata.get(), entry.metadata.get() + meta_size_,
               reinterpret_cast<uint8_t*>(meta));
   }
 
-  return {std::move(buf)};
-}
+  available_buffers_.PopFront();
 
-ProducerQueue::ProducerQueue(size_t meta_size)
-    : ProducerQueue(meta_size, 0, 0, 0, 0) {}
+  return {std::move(buffer)};
+}
 
 ProducerQueue::ProducerQueue(LocalChannelHandle handle)
     : BASE(std::move(handle)) {
@@ -370,14 +409,11 @@
   }
 }
 
-ProducerQueue::ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
-                             uint64_t usage_clear_mask,
-                             uint64_t usage_deny_set_mask,
-                             uint64_t usage_deny_clear_mask)
+ProducerQueue::ProducerQueue(const ProducerQueueConfig& config,
+                             const UsagePolicy& usage)
     : BASE(BufferHubRPC::kClientPath) {
-  auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
-      meta_size, UsagePolicy{usage_set_mask, usage_clear_mask,
-                             usage_deny_set_mask, usage_deny_clear_mask});
+  auto status =
+      InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(config, usage);
   if (!status) {
     ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
           status.GetErrorMessage().c_str());
@@ -385,31 +421,32 @@
     return;
   }
 
-  SetupQueue(status.get().meta_size_bytes, status.get().id);
+  SetupQueue(status.get());
 }
 
-int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
-                                  uint32_t layer_count, uint32_t format,
-                                  uint64_t usage, size_t* out_slot) {
+Status<void> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+                                           uint32_t layer_count,
+                                           uint32_t format, uint64_t usage,
+                                           size_t* out_slot) {
   if (out_slot == nullptr) {
     ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   }
 
   if (is_full()) {
     ALOGE("ProducerQueue::AllocateBuffer queue is at maximum capacity: %zu",
           capacity());
-    return -E2BIG;
+    return ErrorStatus(E2BIG);
   }
 
-  const size_t kBufferCount = 1U;
+  const size_t kBufferCount = 1u;
   Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
           width, height, layer_count, format, usage, kBufferCount);
   if (!status) {
     ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
           status.GetErrorMessage().c_str());
-    return -status.error();
+    return status.error_status();
   }
 
   auto buffer_handle_slots = status.take();
@@ -429,27 +466,26 @@
                    buffer_slot);
 }
 
-int ProducerQueue::AddBuffer(const std::shared_ptr<BufferProducer>& buf,
-                             size_t slot) {
+Status<void> ProducerQueue::AddBuffer(
+    const std::shared_ptr<BufferProducer>& buffer, size_t slot) {
   ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
-           id(), buf->id(), slot);
+           id(), buffer->id(), slot);
   // For producer buffer, we need to enqueue the newly added buffer
   // immediately. Producer queue starts with all buffers in available state.
-  const int ret = BufferHubQueue::AddBuffer(buf, slot);
-  if (ret < 0)
-    return ret;
+  auto status = BufferHubQueue::AddBuffer(buffer, slot);
+  if (!status)
+    return status;
 
-  Enqueue(buf, slot);
-  return 0;
+  return Enqueue(buffer, slot);
 }
 
-int ProducerQueue::DetachBuffer(size_t slot) {
+Status<void> ProducerQueue::DetachBuffer(size_t slot) {
   auto status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(slot);
   if (!status) {
     ALOGE("ProducerQueue::DetachBuffer: Failed to detach producer buffer: %s",
           status.GetErrorMessage().c_str());
-    return -status.error();
+    return status.error_status();
   }
 
   return BufferHubQueue::DetachBuffer(slot);
@@ -471,12 +507,22 @@
   return {std::static_pointer_cast<BufferProducer>(buffer_status.take())};
 }
 
-int ProducerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                                 LocalHandle* release_fence) {
-  ALOGD_IF(TRACE, "ProducerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
-           id(), buf->id());
-  auto buffer = std::static_pointer_cast<BufferProducer>(buf);
-  return buffer->Gain(release_fence);
+Status<BufferHubQueue::Entry> ProducerQueue::OnBufferReady(
+    const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+  ALOGD_IF(TRACE,
+           "ProducerQueue::OnBufferReady: queue_id=%d buffer_id=%d slot=%zu",
+           id(), buffer->id(), slot);
+
+  // Avoid taking a transient reference, buffer is valid for the duration of
+  // this method call.
+  auto* producer_buffer = static_cast<BufferProducer*>(buffer.get());
+  LocalHandle release_fence;
+
+  const int ret = producer_buffer->Gain(&release_fence);
+  if (ret < 0)
+    return ErrorStatus(-ret);
+  else
+    return {{buffer, nullptr, std::move(release_fence), slot}};
 }
 
 ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import)
@@ -503,12 +549,12 @@
   if (!status) {
     ALOGE("ConsumerQueue::ImportBuffers: Failed to import consumer buffer: %s",
           status.GetErrorMessage().c_str());
-    return ErrorStatus(status.error());
+    return status.error_status();
   }
 
   int ret;
-  int last_error = 0;
-  int imported_buffers = 0;
+  Status<void> last_error;
+  size_t imported_buffers_count = 0;
 
   auto buffer_handle_slots = status.take();
   for (auto& buffer_handle_slot : buffer_handle_slots) {
@@ -530,53 +576,52 @@
             "ConsumerQueue::ImportBuffers: Failed to set ignored state on "
             "imported buffer buffer_id=%d: %s",
             buffer_consumer->id(), strerror(-ret));
-        last_error = ret;
+        last_error = ErrorStatus(-ret);
       }
     }
 
-    ret = AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
-    if (ret < 0) {
+    auto add_status =
+        AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
+    if (!add_status) {
       ALOGE("ConsumerQueue::ImportBuffers: Failed to add buffer: %s",
-            strerror(-ret));
-      last_error = ret;
-      continue;
+            add_status.GetErrorMessage().c_str());
+      last_error = add_status;
     } else {
-      imported_buffers++;
+      imported_buffers_count++;
     }
   }
 
-  if (imported_buffers > 0)
-    return {imported_buffers};
+  if (imported_buffers_count > 0)
+    return {imported_buffers_count};
   else
-    return ErrorStatus(-last_error);
+    return last_error.error_status();
 }
 
-int ConsumerQueue::AddBuffer(const std::shared_ptr<BufferConsumer>& buf,
-                             size_t slot) {
+Status<void> ConsumerQueue::AddBuffer(
+    const std::shared_ptr<BufferConsumer>& buffer, size_t slot) {
   ALOGD_IF(TRACE, "ConsumerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
-           id(), buf->id(), slot);
-  const int ret = BufferHubQueue::AddBuffer(buf, slot);
-  if (ret < 0)
-    return ret;
+           id(), buffer->id(), slot);
+  auto status = BufferHubQueue::AddBuffer(buffer, slot);
+  if (!status)
+    return status;
 
   // Check to see if the buffer is already signaled. This is necessary to catch
   // cases where buffers are already available; epoll edge triggered mode does
   // not fire until and edge transition when adding new buffers to the epoll
-  // set.
-  const int kTimeoutMs = 0;
-  pollfd pfd{buf->event_fd(), POLLIN, 0};
-  const int count = RETRY_EINTR(poll(&pfd, 1, kTimeoutMs));
-  if (count < 0) {
-    const int error = errno;
+  // set. Note that we only poll the fd events because HandleBufferEvent() takes
+  // care of checking the translated buffer events.
+  auto poll_status = PollEvents(buffer->event_fd(), POLLIN);
+  if (!poll_status && poll_status.error() != ETIMEDOUT) {
     ALOGE("ConsumerQueue::AddBuffer: Failed to poll consumer buffer: %s",
-          strerror(errno));
-    return -error;
+          poll_status.GetErrorMessage().c_str());
+    return poll_status.error_status();
   }
 
-  if (count == 1)
-    HandleBufferEvent(slot, pfd.revents);
-
-  return 0;
+  // Update accounting if the buffer is available.
+  if (poll_status)
+    return HandleBufferEvent(slot, buffer->event_fd(), poll_status.get());
+  else
+    return {};
 }
 
 Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
@@ -606,15 +651,30 @@
   return {std::static_pointer_cast<BufferConsumer>(buffer_status.take())};
 }
 
-int ConsumerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                                 LocalHandle* acquire_fence) {
-  ALOGD_IF(TRACE, "ConsumerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
-           id(), buf->id());
-  auto buffer = std::static_pointer_cast<BufferConsumer>(buf);
-  return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
+Status<BufferHubQueue::Entry> ConsumerQueue::OnBufferReady(
+    const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+  ALOGD_IF(TRACE,
+           "ConsumerQueue::OnBufferReady: queue_id=%d buffer_id=%d slot=%zu",
+           id(), buffer->id(), slot);
+
+  // Avoid taking a transient reference, buffer is valid for the duration of
+  // this method call.
+  auto* consumer_buffer = static_cast<BufferConsumer*>(buffer.get());
+  std::unique_ptr<uint8_t[]> metadata(meta_size_ ? new uint8_t[meta_size_]
+                                                 : nullptr);
+  LocalHandle acquire_fence;
+
+  const int ret =
+      consumer_buffer->Acquire(&acquire_fence, metadata.get(), meta_size_);
+  if (ret < 0)
+    return ErrorStatus(-ret);
+  else
+    return {{buffer, std::move(metadata), std::move(acquire_fence), slot}};
 }
 
 Status<void> ConsumerQueue::OnBufferAllocated() {
+  ALOGD_IF(TRACE, "ConsumerQueue::OnBufferAllocated: queue_id=%d", id());
+
   auto status = ImportBuffers();
   if (!status) {
     ALOGE("ConsumerQueue::OnBufferAllocated: Failed to import buffers: %s",
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_consumer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_consumer.cpp
deleted file mode 100644
index 1ea3994..0000000
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_consumer.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "include/private/dvr/buffer_hub_queue_consumer.h"
-
-namespace android {
-namespace dvr {
-
-BufferHubQueueConsumer::BufferHubQueueConsumer(
-    const std::shared_ptr<BufferHubQueueCore>& core)
-    : core_(core) {}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
deleted file mode 100644
index 31cccf0..0000000
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "include/private/dvr/buffer_hub_queue_core.h"
-
-#include <log/log.h>
-
-namespace android {
-namespace dvr {
-
-/* static */
-std::shared_ptr<BufferHubQueueCore> BufferHubQueueCore::Create() {
-  auto core = std::shared_ptr<BufferHubQueueCore>(new BufferHubQueueCore());
-  core->producer_ = ProducerQueue::Create<NativeBufferMetadata>();
-  return core;
-}
-
-/* static */
-std::shared_ptr<BufferHubQueueCore> BufferHubQueueCore::Create(
-    const std::shared_ptr<ProducerQueue>& producer) {
-  if (producer->metadata_size() != sizeof(NativeBufferMetadata)) {
-    ALOGE(
-        "BufferHubQueueCore::Create producer's metadata size is different than "
-        "the size of BufferHubQueueCore::NativeBufferMetadata");
-    return nullptr;
-  }
-
-  auto core = std::shared_ptr<BufferHubQueueCore>(new BufferHubQueueCore());
-  core->producer_ = producer;
-  return core;
-}
-
-BufferHubQueueCore::BufferHubQueueCore()
-    : generation_number_(0),
-      dequeue_timeout_ms_(BufferHubQueue::kNoTimeOut),
-      unique_id_(getUniqueId()) {}
-
-status_t BufferHubQueueCore::AllocateBuffer(uint32_t width, uint32_t height,
-                                            uint32_t layer_count,
-                                            PixelFormat format,
-                                            uint64_t usage) {
-  size_t slot;
-
-  // Allocate new buffer through BufferHub and add it into |producer_| queue for
-  // bookkeeping.
-  if (producer_->AllocateBuffer(width, height, layer_count, format, usage,
-                                &slot) < 0) {
-    ALOGE("Failed to allocate new buffer in BufferHub.");
-    return NO_MEMORY;
-  }
-
-  auto buffer_producer = producer_->GetBuffer(slot);
-
-  LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
-                      "Failed to get buffer producer at slot: %zu", slot);
-
-  buffers_[slot].mBufferProducer = buffer_producer;
-
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueCore::DetachBuffer(size_t slot) {
-  // Detach the buffer producer via BufferHubRPC.
-  int ret = producer_->DetachBuffer(slot);
-  if (ret < 0) {
-    ALOGE("BufferHubQueueCore::DetachBuffer failed through RPC, ret=%s",
-          strerror(-ret));
-    return ret;
-  }
-
-  // Reset in memory objects related the the buffer.
-  buffers_[slot].mBufferProducer = nullptr;
-  buffers_[slot].mGraphicBuffer = nullptr;
-  buffers_[slot].mBufferState.detachProducer();
-  return NO_ERROR;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index e0a3a34..4b3dd7a 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -1,5 +1,6 @@
 #include "include/private/dvr/buffer_hub_queue_producer.h"
 
+#include <dvr/dvr_api.h>
 #include <inttypes.h>
 #include <log/log.h>
 #include <system/window.h>
@@ -7,17 +8,38 @@
 namespace android {
 namespace dvr {
 
-BufferHubQueueProducer::BufferHubQueueProducer(
-    const std::shared_ptr<BufferHubQueueCore>& core)
-    : core_(core) {}
+/* static */
+sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
+  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
+  auto config = ProducerQueueConfigBuilder()
+                    .SetMetadata<DvrNativeBufferMetadata>()
+                    .Build();
+  producer->queue_ = ProducerQueue::Create(config, UsagePolicy{});
+  return producer;
+}
+
+/* static */
+sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
+    const std::shared_ptr<ProducerQueue>& queue) {
+  if (queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) {
+    ALOGE(
+        "BufferHubQueueProducer::Create producer's metadata size is different "
+        "than the size of DvrNativeBufferMetadata");
+    return nullptr;
+  }
+
+  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
+  producer->queue_ = queue;
+  return producer;
+}
 
 status_t BufferHubQueueProducer::requestBuffer(int slot,
                                                sp<GraphicBuffer>* buf) {
   ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
 
-  std::unique_lock<std::mutex> lock(core_->mutex_);
+  std::unique_lock<std::mutex> lock(mutex_);
 
-  if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+  if (connected_api_ == kNoConnectedApi) {
     ALOGE("requestBuffer: BufferHubQueueProducer has no connected producer");
     return NO_INIT;
   }
@@ -26,23 +48,23 @@
     ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot,
           max_buffer_count_);
     return BAD_VALUE;
-  } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
+  } else if (!buffers_[slot].mBufferState.isDequeued()) {
     ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)",
-          slot, core_->buffers_[slot].mBufferState.string());
+          slot, buffers_[slot].mBufferState.string());
     return BAD_VALUE;
-  } else if (core_->buffers_[slot].mGraphicBuffer != nullptr) {
+  } else if (buffers_[slot].mGraphicBuffer != nullptr) {
     ALOGE("requestBuffer: slot %d is not empty.", slot);
     return BAD_VALUE;
-  } else if (core_->buffers_[slot].mBufferProducer == nullptr) {
+  } else if (buffers_[slot].mBufferProducer == nullptr) {
     ALOGE("requestBuffer: slot %d is not dequeued.", slot);
     return BAD_VALUE;
   }
 
-  const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+  const auto& buffer_producer = buffers_[slot].mBufferProducer;
   sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
 
-  core_->buffers_[slot].mGraphicBuffer = graphic_buffer;
-  core_->buffers_[slot].mRequestBufferCalled = true;
+  buffers_[slot].mGraphicBuffer = graphic_buffer;
+  buffers_[slot].mRequestBufferCalled = true;
 
   *buf = graphic_buffer;
   return NO_ERROR;
@@ -53,12 +75,12 @@
   ALOGD_IF(TRACE, "setMaxDequeuedBufferCount: max_dequeued_buffers=%d",
            max_dequeued_buffers);
 
-  std::unique_lock<std::mutex> lock(core_->mutex_);
+  std::unique_lock<std::mutex> lock(mutex_);
 
   if (max_dequeued_buffers <= 0 ||
       max_dequeued_buffers >
           static_cast<int>(BufferHubQueue::kMaxQueueCapacity -
-                           BufferHubQueueCore::kDefaultUndequeuedBuffers)) {
+                           kDefaultUndequeuedBuffers)) {
     ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]",
           max_dequeued_buffers, BufferHubQueue::kMaxQueueCapacity);
     return BAD_VALUE;
@@ -67,7 +89,7 @@
   // The new dequeued_buffers count should not be violated by the number
   // of currently dequeued buffers.
   int dequeued_count = 0;
-  for (const auto& buf : core_->buffers_) {
+  for (const auto& buf : buffers_) {
     if (buf.mBufferState.isDequeued()) {
       dequeued_count++;
     }
@@ -115,22 +137,21 @@
            height, format, usage);
 
   status_t ret;
-  std::unique_lock<std::mutex> lock(core_->mutex_);
+  std::unique_lock<std::mutex> lock(mutex_);
 
-  if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+  if (connected_api_ == kNoConnectedApi) {
     ALOGE("dequeueBuffer: BufferQueue has no connected producer");
     return NO_INIT;
   }
 
   const uint32_t kLayerCount = 1;
-  if (static_cast<int32_t>(core_->producer_->capacity()) <
-      max_dequeued_buffer_count_ +
-          BufferHubQueueCore::kDefaultUndequeuedBuffers) {
-    // Lazy allocation. When the capacity of |core_->producer_| has not reach
+  if (static_cast<int32_t>(queue_->capacity()) <
+      max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) {
+    // Lazy allocation. When the capacity of |queue_| has not reached
     // |max_dequeued_buffer_count_|, allocate new buffer.
     // TODO(jwcai) To save memory, the really reasonable thing to do is to go
     // over existing slots and find first existing one to dequeue.
-    ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
+    ret = AllocateBuffer(width, height, kLayerCount, format, usage);
     if (ret < 0)
       return ret;
   }
@@ -140,8 +161,9 @@
 
   for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
     LocalHandle fence;
-    auto buffer_status =
-        core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot, &fence);
+    auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
+    if (!buffer_status)
+      return NO_MEMORY;
 
     buffer_producer = buffer_status.take();
     if (!buffer_producer)
@@ -164,34 +186,34 @@
         buffer_producer->height(), buffer_producer->format());
     // Mark the slot as reallocating, so that later we can set
     // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
-    core_->buffers_[slot].mIsReallocating = true;
+    buffers_[slot].mIsReallocating = true;
 
-    // Detach the old buffer once the allocation before allocating its
+    // Remove the old buffer once the allocation before allocating its
     // replacement.
-    core_->DetachBuffer(slot);
+    RemoveBuffer(slot);
 
     // Allocate a new producer buffer with new buffer configs. Note that if
     // there are already multiple buffers in the queue, the next one returned
-    // from |core_->producer_->Dequeue| may not be the new buffer we just
-    // reallocated. Retry up to BufferHubQueue::kMaxQueueCapacity times.
-    ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
+    // from |queue_->Dequeue| may not be the new buffer we just reallocated.
+    // Retry up to BufferHubQueue::kMaxQueueCapacity times.
+    ret = AllocateBuffer(width, height, kLayerCount, format, usage);
     if (ret < 0)
       return ret;
   }
 
   // With the BufferHub backed solution. Buffer slot returned from
-  // |core_->producer_->Dequeue| is guaranteed to avaiable for producer's use.
+  // |queue_->Dequeue| is guaranteed to avaiable for producer's use.
   // It's either in free state (if the buffer has never been used before) or
   // in queued state (if the buffer has been dequeued and queued back to
   // BufferHubQueue).
   // TODO(jwcai) Clean this up, make mBufferState compatible with BufferHub's
   // model.
-  LOG_ALWAYS_FATAL_IF((!core_->buffers_[slot].mBufferState.isFree() &&
-                       !core_->buffers_[slot].mBufferState.isQueued()),
+  LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() &&
+                       !buffers_[slot].mBufferState.isQueued()),
                       "dequeueBuffer: slot %zu is not free or queued.", slot);
 
-  core_->buffers_[slot].mBufferState.freeQueued();
-  core_->buffers_[slot].mBufferState.dequeue();
+  buffers_[slot].mBufferState.freeQueued();
+  buffers_[slot].mBufferState.dequeue();
   ALOGD_IF(TRACE, "dequeueBuffer: slot=%zu", slot);
 
   // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
@@ -200,9 +222,9 @@
   *out_slot = slot;
   ret = NO_ERROR;
 
-  if (core_->buffers_[slot].mIsReallocating) {
+  if (buffers_[slot].mIsReallocating) {
     ret |= BUFFER_NEEDS_REALLOCATION;
-    core_->buffers_[slot].mIsReallocating = false;
+    buffers_[slot].mIsReallocating = false;
   }
 
   return ret;
@@ -267,9 +289,9 @@
   }
 
   status_t ret;
-  std::unique_lock<std::mutex> lock(core_->mutex_);
+  std::unique_lock<std::mutex> lock(mutex_);
 
-  if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+  if (connected_api_ == kNoConnectedApi) {
     ALOGE("queueBuffer: BufferQueue has no connected producer");
     return NO_INIT;
   }
@@ -278,22 +300,22 @@
     ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot,
           max_buffer_count_);
     return BAD_VALUE;
-  } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
+  } else if (!buffers_[slot].mBufferState.isDequeued()) {
     ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)",
-          slot, core_->buffers_[slot].mBufferState.string());
+          slot, buffers_[slot].mBufferState.string());
     return BAD_VALUE;
-  } else if ((!core_->buffers_[slot].mRequestBufferCalled ||
-              core_->buffers_[slot].mGraphicBuffer == nullptr)) {
+  } else if ((!buffers_[slot].mRequestBufferCalled ||
+              buffers_[slot].mGraphicBuffer == nullptr)) {
     ALOGE(
         "queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
         "mGraphicBuffer=%p)",
-        slot, core_->buffers_[slot].mRequestBufferCalled,
-        core_->buffers_[slot].mGraphicBuffer.get());
+        slot, buffers_[slot].mRequestBufferCalled,
+        buffers_[slot].mGraphicBuffer.get());
     return BAD_VALUE;
   }
 
   // Post the buffer producer with timestamp in the metadata.
-  const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+  const auto& buffer_producer = buffers_[slot].mBufferProducer;
 
   // Check input crop is not out of boundary of current buffer.
   Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
@@ -306,7 +328,7 @@
 
   LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
 
-  BufferHubQueueCore::NativeBufferMetadata meta_data = {};
+  DvrNativeBufferMetadata meta_data = {};
   meta_data.timestamp = timestamp;
   meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp);
   meta_data.dataspace = static_cast<int32_t>(dataspace);
@@ -318,7 +340,7 @@
   meta_data.transform = static_cast<int32_t>(transform);
 
   buffer_producer->Post(fence_fd, &meta_data, sizeof(meta_data));
-  core_->buffers_[slot].mBufferState.queue();
+  buffers_[slot].mBufferState.queue();
 
   output->width = buffer_producer->width();
   output->height = buffer_producer->height();
@@ -341,9 +363,9 @@
                                               const sp<Fence>& fence) {
   ALOGD_IF(TRACE, __FUNCTION__);
 
-  std::unique_lock<std::mutex> lock(core_->mutex_);
+  std::unique_lock<std::mutex> lock(mutex_);
 
-  if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+  if (connected_api_ == kNoConnectedApi) {
     ALOGE("cancelBuffer: BufferQueue has no connected producer");
     return NO_INIT;
   }
@@ -352,19 +374,19 @@
     ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
           max_buffer_count_);
     return BAD_VALUE;
-  } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
+  } else if (!buffers_[slot].mBufferState.isDequeued()) {
     ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)",
-          slot, core_->buffers_[slot].mBufferState.string());
+          slot, buffers_[slot].mBufferState.string());
     return BAD_VALUE;
   } else if (fence == nullptr) {
     ALOGE("cancelBuffer: fence is NULL");
     return BAD_VALUE;
   }
 
-  auto buffer_producer = core_->buffers_[slot].mBufferProducer;
-  core_->producer_->Enqueue(buffer_producer, slot);
-  core_->buffers_[slot].mBufferState.cancel();
-  core_->buffers_[slot].mFence = fence;
+  auto buffer_producer = buffers_[slot].mBufferProducer;
+  queue_->Enqueue(buffer_producer, slot);
+  buffers_[slot].mBufferState.cancel();
+  buffers_[slot].mFence = fence;
   ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot);
 
   return NO_ERROR;
@@ -373,7 +395,7 @@
 status_t BufferHubQueueProducer::query(int what, int* out_value) {
   ALOGD_IF(TRACE, __FUNCTION__);
 
-  std::unique_lock<std::mutex> lock(core_->mutex_);
+  std::unique_lock<std::mutex> lock(mutex_);
 
   if (out_value == nullptr) {
     ALOGE("query: out_value was NULL");
@@ -386,19 +408,19 @@
       // TODO(b/36187402) This should be the maximum number of buffers that this
       // producer queue's consumer can acquire. Set to be at least one. Need to
       // find a way to set from the consumer side.
-      value = BufferHubQueueCore::kDefaultUndequeuedBuffers;
+      value = kDefaultUndequeuedBuffers;
       break;
     case NATIVE_WINDOW_BUFFER_AGE:
       value = 0;
       break;
     case NATIVE_WINDOW_WIDTH:
-      value = core_->producer_->default_width();
+      value = queue_->default_width();
       break;
     case NATIVE_WINDOW_HEIGHT:
-      value = core_->producer_->default_height();
+      value = queue_->default_height();
       break;
     case NATIVE_WINDOW_FORMAT:
-      value = core_->producer_->default_format();
+      value = queue_->default_format();
       break;
     case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
       // BufferHubQueue is always operating in async mode, thus semantically
@@ -421,6 +443,11 @@
       // there is no way dvr::ConsumerQueue can set it.
       value = 0;
       break;
+    case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
+      // In Daydream's implementation, the consumer end (i.e. VR Compostior)
+      // knows how to handle protected buffers.
+      value = 1;
+      break;
     default:
       return BAD_VALUE;
   }
@@ -442,9 +469,9 @@
     return BAD_VALUE;
   }
 
-  std::unique_lock<std::mutex> lock(core_->mutex_);
+  std::unique_lock<std::mutex> lock(mutex_);
 
-  if (core_->connected_api_ != BufferHubQueueCore::kNoConnectedApi) {
+  if (connected_api_ != kNoConnectedApi) {
     return BAD_VALUE;
   }
 
@@ -453,10 +480,10 @@
     case NATIVE_WINDOW_API_CPU:
     case NATIVE_WINDOW_API_MEDIA:
     case NATIVE_WINDOW_API_CAMERA:
-      core_->connected_api_ = api;
+      connected_api_ = api;
 
-      output->width = core_->producer_->default_width();
-      output->height = core_->producer_->default_height();
+      output->width = queue_->default_width();
+      output->height = queue_->default_height();
 
       // default values, we don't use them yet.
       output->transformHint = 0;
@@ -479,15 +506,15 @@
   // parameter checks here.
   ALOGD_IF(TRACE, __FUNCTION__);
 
-  std::unique_lock<std::mutex> lock(core_->mutex_);
+  std::unique_lock<std::mutex> lock(mutex_);
 
-  if (BufferHubQueueCore::kNoConnectedApi == core_->connected_api_) {
+  if (kNoConnectedApi == connected_api_) {
     return NO_INIT;
-  } else if (api != core_->connected_api_) {
+  } else if (api != connected_api_) {
     return BAD_VALUE;
   }
 
-  core_->connected_api_ = BufferHubQueueCore::kNoConnectedApi;
+  connected_api_ = kNoConnectedApi;
   return NO_ERROR;
 }
 
@@ -521,8 +548,8 @@
     uint32_t generation_number) {
   ALOGD_IF(TRACE, __FUNCTION__);
 
-  std::unique_lock<std::mutex> lock(core_->mutex_);
-  core_->generation_number_ = generation_number;
+  std::unique_lock<std::mutex> lock(mutex_);
+  generation_number_ = generation_number;
   return NO_ERROR;
 }
 
@@ -557,8 +584,8 @@
 status_t BufferHubQueueProducer::setDequeueTimeout(nsecs_t timeout) {
   ALOGD_IF(TRACE, __FUNCTION__);
 
-  std::unique_lock<std::mutex> lock(core_->mutex_);
-  core_->dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
+  std::unique_lock<std::mutex> lock(mutex_);
+  dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
   return NO_ERROR;
 }
 
@@ -577,15 +604,47 @@
 status_t BufferHubQueueProducer::getUniqueId(uint64_t* out_id) const {
   ALOGD_IF(TRACE, __FUNCTION__);
 
-  *out_id = core_->unique_id_;
+  *out_id = unique_id_;
   return NO_ERROR;
 }
 
-IBinder* BufferHubQueueProducer::onAsBinder() {
-  // BufferHubQueueProducer is a non-binder implementation of
-  // IGraphicBufferProducer.
-  ALOGW("BufferHubQueueProducer::onAsBinder is not efficiently supported.");
-  return this;
+status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
+                                                uint32_t layer_count,
+                                                PixelFormat format,
+                                                uint64_t usage) {
+  size_t slot;
+  auto status =
+      queue_->AllocateBuffer(width, height, layer_count, format, usage, &slot);
+  if (!status) {
+    ALOGE(
+        "BufferHubQueueProducer::AllocateBuffer: Failed to allocate buffer: %s",
+        status.GetErrorMessage().c_str());
+    return NO_MEMORY;
+  }
+
+  auto buffer_producer = queue_->GetBuffer(slot);
+
+  LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
+                      "Failed to get buffer producer at slot: %zu", slot);
+
+  buffers_[slot].mBufferProducer = buffer_producer;
+
+  return NO_ERROR;
+}
+
+status_t BufferHubQueueProducer::RemoveBuffer(size_t slot) {
+  auto status = queue_->DetachBuffer(slot);
+  if (!status) {
+    ALOGE("BufferHubQueueProducer::RemoveBuffer: Failed to detach buffer: %s",
+          status.GetErrorMessage().c_str());
+    return INVALID_OPERATION;
+  }
+
+  // Reset in memory objects related the the buffer.
+  buffers_[slot].mBufferProducer = nullptr;
+  buffers_[slot].mGraphicBuffer = nullptr;
+  buffers_[slot].mBufferState.detachProducer();
+  return NO_ERROR;
 }
 
 }  // namespace dvr
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 ed67f79..e62e832 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
@@ -5,6 +5,7 @@
 
 #include <pdx/client.h>
 #include <pdx/status.h>
+#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/epoll_file_descriptor.h>
 #include <private/dvr/ring_buffer.h>
@@ -21,45 +22,42 @@
 // automatically re-requeued when released by the remote side.
 class BufferHubQueue : public pdx::Client {
  public:
-  using LocalHandle = pdx::LocalHandle;
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-  template <typename T>
-  using Status = pdx::Status<T>;
-
   virtual ~BufferHubQueue() {}
-  void Initialize();
 
-  // Create a new consumer queue that is attached to the producer. Returns
+  // Creates a new consumer queue that is attached to the producer. Returns
   // a new consumer queue client or nullptr on failure.
   std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
 
-  // Create a new consumer queue that is attached to the producer. This queue
+  // Creates a new consumer queue that is attached to the producer. This queue
   // sets each of its imported consumer buffers to the ignored state to avoid
   // participation in lifecycle events.
   std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
 
-  // Return the default buffer width of this buffer queue.
-  size_t default_width() const { return default_width_; }
+  // Returns whether the buffer queue is in async mode.
+  bool is_async() const { return is_async_; }
 
-  // Return the default buffer height of this buffer queue.
-  size_t default_height() const { return default_height_; }
+  // Returns the default buffer width of this buffer queue.
+  uint32_t default_width() const { return default_width_; }
 
-  // Return the default buffer format of this buffer queue.
-  int32_t default_format() const { return default_format_; }
+  // Returns the default buffer height of this buffer queue.
+  uint32_t default_height() const { return default_height_; }
 
-  // Create a new consumer in handle form for immediate transport over RPC.
-  Status<LocalChannelHandle> CreateConsumerQueueHandle();
+  // Returns the default buffer format of this buffer queue.
+  uint32_t default_format() const { return default_format_; }
 
-  // Return the number of buffers avaiable for dequeue.
+  // Creates a new consumer in handle form for immediate transport over RPC.
+  pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle();
+
+  // Returns the number of buffers avaiable for dequeue.
   size_t count() const { return available_buffers_.GetSize(); }
 
-  // Return the total number of buffers that the queue is tracking.
+  // Returns the total number of buffers that the queue is tracking.
   size_t capacity() const { return capacity_; }
 
-  // Return the size of metadata structure associated with this BufferBubQueue.
+  // Returns the size of metadata structure associated with this queue.
   size_t metadata_size() const { return meta_size_; }
 
-  // Return whether the buffer queue is alrady full.
+  // Returns whether the buffer queue is full.
   bool is_full() const { return available_buffers_.IsFull(); }
 
   explicit operator bool() const { return epoll_fd_.IsValid(); }
@@ -68,7 +66,7 @@
     return buffers_[slot];
   }
 
-  Status<int> GetEventMask(int events) {
+  pdx::Status<int> GetEventMask(int events) {
     if (auto* client_channel = GetChannel()) {
       return client_channel->GetEventMask(events);
     } else {
@@ -86,81 +84,95 @@
   // occurred.
   bool HandleQueueEvents() { return WaitForBuffers(0); }
 
-  // Enqueue a buffer marks buffer to be available (|Gain|'ed for producer
-  // and |Acquire|'ed for consumer. This is only used for internal bookkeeping.
-  void Enqueue(const std::shared_ptr<BufferHubBuffer>& buf, size_t slot);
-
-  // |BufferHubQueue| will keep track of at most this value of buffers.
+  // The queue tracks at most this many buffers.
   static constexpr size_t kMaxQueueCapacity =
       android::BufferQueueDefs::NUM_BUFFER_SLOTS;
 
-  // Special epoll data field indicating that the epoll event refers to the
-  // queue.
-  static constexpr int64_t kEpollQueueEventIndex = -1;
-
-  // When pass |kNoTimeout| to |Dequeue|, it will block indefinitely without a
-  // timeout.
   static constexpr int kNoTimeOut = -1;
 
   int id() const { return id_; }
   bool hung_up() const { return hung_up_; }
 
  protected:
-  BufferHubQueue(LocalChannelHandle channel);
+  BufferHubQueue(pdx::LocalChannelHandle channel);
   BufferHubQueue(const std::string& endpoint_path);
 
   // Imports the queue parameters by querying BufferHub for the parameters for
   // this channel.
-  Status<void> ImportQueue();
+  pdx::Status<void> ImportQueue();
 
   // Sets up the queue with the given parameters.
-  void SetupQueue(size_t meta_size_bytes_, int id);
+  void SetupQueue(const QueueInfo& queue_info);
 
-  // Called by ProducerQueue::AddBuffer and ConsumerQueue::AddBuffer only. to
-  // register a buffer for epoll and internal bookkeeping.
-  int AddBuffer(const std::shared_ptr<BufferHubBuffer>& buf, size_t slot);
+  // Register a buffer for management by the queue. Used by subclasses to add a
+  // buffer to internal bookkeeping.
+  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer,
+                              size_t slot);
 
-  // Called by ProducerQueue::DetachBuffer and ConsumerQueue::DetachBuffer only.
+  // Called by ProducerQueue::DetachBuffer and ConsumerQueue::DetachBuffer only
   // to deregister a buffer for epoll and internal bookkeeping.
-  virtual int DetachBuffer(size_t slot);
+  virtual pdx::Status<void> DetachBuffer(size_t slot);
 
   // Dequeue a buffer from the free queue, blocking until one is available. The
   // timeout argument specifies the number of milliseconds that |Dequeue()| will
-  // block. Specifying a timeout of -1 causes |Dequeue()| to block indefinitely,
-  // while specifying a timeout equal to zero cause |Dequeue()| to return
+  // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
+  // while specifying a timeout equal to zero cause Dequeue() to return
   // immediately, even if no buffers are available.
-  pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
-                                                        size_t* slot,
-                                                        void* meta,
-                                                        LocalHandle* fence);
+  pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(
+      int timeout, size_t* slot, void* meta, pdx::LocalHandle* fence);
 
-  // Wait for buffers to be released and re-add them to the queue.
+  // Waits for buffers to become available and adds them to the available queue.
   bool WaitForBuffers(int timeout);
-  void HandleBufferEvent(size_t slot, int poll_events);
-  void HandleQueueEvent(int poll_events);
 
-  virtual int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                            LocalHandle* fence) = 0;
+  pdx::Status<void> HandleBufferEvent(size_t slot, int event_fd,
+                                      int poll_events);
+  pdx::Status<void> HandleQueueEvent(int poll_events);
+
+  // Entry in the ring buffer of available buffers that stores related
+  // per-buffer data.
+  struct Entry {
+    Entry() : slot(0) {}
+    Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot)
+        : buffer(buffer), slot(slot) {}
+    Entry(const std::shared_ptr<BufferHubBuffer>& buffer,
+          std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence,
+          size_t slot)
+        : buffer(buffer),
+          metadata(std::move(metadata)),
+          fence(std::move(fence)),
+          slot(slot) {}
+    Entry(Entry&&) = default;
+    Entry& operator=(Entry&&) = default;
+
+    std::shared_ptr<BufferHubBuffer> buffer;
+    std::unique_ptr<uint8_t[]> metadata;
+    pdx::LocalHandle fence;
+    size_t slot;
+  };
+
+  // Enqueues a buffer to the available list (Gained for producer or Acquireed
+  // for consumer).
+  pdx::Status<void> Enqueue(Entry entry);
+
+  virtual pdx::Status<Entry> OnBufferReady(
+      const std::shared_ptr<BufferHubBuffer>& buf, size_t slot) = 0;
 
   // Called when a buffer is allocated remotely.
-  virtual Status<void> OnBufferAllocated() { return {}; }
+  virtual pdx::Status<void> OnBufferAllocated() { return {}; }
 
-  // Data members to handle arbitrary metadata passed through BufferHub. It is
-  // fair to enforce that all buffers in the same queue share the same metadata
-  // type. |meta_size_| is used to store the size of metadata on queue creation;
-  // and |meta_buffer_tmp_| is allocated and resized to |meta_size_| on queue
-  // creation to be later used as temporary space so that we can avoid
-  // additional dynamic memory allocation in each |Enqueue| and |Dequeue| call.
-  size_t meta_size_;
-
-  // Here we intentionally choose |unique_ptr<uint8_t[]>| over vector<uint8_t>
-  // to disallow dynamic resizing for stability reasons.
-  std::unique_ptr<uint8_t[]> meta_buffer_tmp_;
+  // Size of the metadata that buffers in this queue cary.
+  size_t meta_size_{0};
 
  private:
+  void Initialize();
+
+  // Special epoll data field indicating that the epoll event refers to the
+  // queue.
+  static constexpr int64_t kEpollQueueEventIndex = -1;
+
   static constexpr size_t kMaxEvents = 128;
 
-  // The |u64| data field of an epoll event is interpreted as int64_t:
+  // The u64 data field of an epoll event is interpreted as int64_t:
   // When |index| >= 0 and |index| < kMaxQueueCapacity it refers to a specific
   // element of |buffers_| as a direct index;
   static bool is_buffer_event_index(int64_t index) {
@@ -168,102 +180,40 @@
            index < static_cast<int64_t>(BufferHubQueue::kMaxQueueCapacity);
   }
 
-  // When |index| == kEpollQueueEventIndex, it refers to the queue itself.
+  // When |index| == kEpollQueueEventIndex it refers to the queue itself.
   static bool is_queue_event_index(int64_t index) {
     return index == BufferHubQueue::kEpollQueueEventIndex;
   }
 
-  struct BufferInfo {
-    // A logical slot number that is assigned to a buffer at allocation time.
-    // The slot number remains unchanged during the entire life cycle of the
-    // buffer and should not be confused with the enqueue and dequeue order.
-    size_t slot;
+  // Whether the buffer queue is operating in Async mode.
+  // From GVR's perspective of view, this means a buffer can be acquired
+  // asynchronously by the compositor.
+  // From Android Surface's perspective of view, this is equivalent to
+  // IGraphicBufferProducer's async mode. When in async mode, a producer
+  // will never block even if consumer is running slow.
+  bool is_async_{false};
 
-    // A BufferHubBuffer client.
-    std::shared_ptr<BufferHubBuffer> buffer;
-
-    // Metadata associated with the buffer.
-    std::unique_ptr<uint8_t[]> metadata;
-
-    BufferInfo() : BufferInfo(-1, 0) {}
-
-    BufferInfo(size_t slot, size_t metadata_size)
-        : slot(slot),
-          buffer(nullptr),
-          metadata(metadata_size ? new uint8_t[metadata_size] : nullptr) {}
-
-    BufferInfo(BufferInfo&& other)
-        : slot(other.slot),
-          buffer(std::move(other.buffer)),
-          metadata(std::move(other.metadata)) {}
-
-    BufferInfo& operator=(BufferInfo&& other) {
-      slot = other.slot;
-      buffer = std::move(other.buffer);
-      metadata = std::move(other.metadata);
-      return *this;
-    }
-
-   private:
-    BufferInfo(const BufferInfo&) = delete;
-    void operator=(BufferInfo&) = delete;
-  };
-
-  // Default buffer width that can be set to override the buffer width when a
-  // width and height of 0 are specified in AllocateBuffer.
+  // Default buffer width that is set during ProducerQueue's creation.
   size_t default_width_{1};
 
-  // Default buffer height that can be set to override the buffer height when a
-  // width and height of 0 are specified in AllocateBuffer.
+  // Default buffer height that is set during ProducerQueue's creation.
   size_t default_height_{1};
 
-  // Default buffer format that can be set to override the buffer format when it
-  // isn't specified in AllocateBuffer.
-  int32_t default_format_{PIXEL_FORMAT_RGBA_8888};
+  // Default buffer format that is set during ProducerQueue's creation.
+  int32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
 
-  // Buffer queue:
-  // |buffers_| tracks all |BufferHubBuffer|s created by this |BufferHubQueue|.
-  std::vector<std::shared_ptr<BufferHubBuffer>> buffers_;
+  // Tracks the buffers belonging to this queue. Buffers are stored according to
+  // "slot" in this vector. Each slot is a logical id of the buffer within this
+  // queue regardless of its queue position or presence in the ring buffer.
+  std::vector<std::shared_ptr<BufferHubBuffer>> buffers_{kMaxQueueCapacity};
 
-  // |epollhup_pending_| tracks whether a slot of |buffers_| get detached before
-  // its corresponding EPOLLHUP event got handled. This could happen as the
-  // following sequence:
-  // 1. Producer queue's client side allocates a new buffer (at slot 1).
-  // 2. Producer queue's client side replaces an existing buffer (at slot 0).
-  //    This is implemented by first detaching the buffer and then allocating a
-  //    new buffer.
-  // 3. During the same epoll_wait, Consumer queue's client side gets EPOLLIN
-  //    event on the queue which indicates a new buffer is available and the
-  //    EPOLLHUP event for slot 0. Consumer handles these two events in order.
-  // 4. Consumer client calls BufferHubRPC::ConsumerQueueImportBuffers and both
-  //    slot 0 and (the new) slot 1 buffer will be imported. During the import
-  //    of the buffer at slot 1, consumer client detaches the old buffer so that
-  //    the new buffer can be registered. At the same time
-  //    |epollhup_pending_[slot]| is marked to indicate that buffer at this slot
-  //    was detached prior to EPOLLHUP event.
-  // 5. Consumer client continues to handle the EPOLLHUP. Since
-  //    |epollhup_pending_[slot]| is marked as true, it can safely ignore the
-  //    event without detaching the newly allocated buffer at slot 1.
-  //
-  // In normal situations where the previously described sequence doesn't
-  // happen, an EPOLLHUP event should trigger a regular buffer detach.
-  std::vector<bool> epollhup_pending_;
+  // Buffers and related data that are available for dequeue.
+  RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
 
-  // |available_buffers_| uses |dvr::RingBuffer| to implementation queue
-  // sematics. When |Dequeue|, we pop the front element from
-  // |available_buffers_|, and  that buffer's reference count will decrease by
-  // one, while another reference in |buffers_| keeps the last reference to
-  // prevent the buffer from being deleted.
-  RingBuffer<BufferInfo> available_buffers_;
+  // Keeps track with how many buffers have been added into the queue.
+  size_t capacity_{0};
 
-  // Fences (acquire fence for consumer and release fence for consumer) , one
-  // for each buffer slot.
-  std::vector<LocalHandle> fences_;
-
-  // Keep track with how many buffers have been added into the queue.
-  size_t capacity_;
-
-  // Epoll fd used to wait for BufferHub events.
+  // Epoll fd used to manage buffer events.
   EpollFileDescriptor epoll_fd_;
 
   // Flag indicating that the other side hung up. For ProducerQueues this
@@ -273,7 +223,7 @@
   bool hung_up_{false};
 
   // Global id for the queue that is consistent across processes.
-  int id_;
+  int id_{-1};
 
   BufferHubQueue(const BufferHubQueue&) = delete;
   void operator=(BufferHubQueue&) = delete;
@@ -281,14 +231,6 @@
 
 class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
  public:
-  template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create() {
-    return BASE::Create(sizeof(Meta));
-  }
-  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes) {
-    return BASE::Create(meta_size_bytes);
-  }
-
   // Usage bits in |usage_set_mask| will be automatically masked on. Usage bits
   // in |usage_clear_mask| will be automatically masked off. Note that
   // |usage_set_mask| and |usage_clear_mask| may conflict with each other, but
@@ -300,32 +242,20 @@
   // this will be rejected. Note that |usage_deny_set_mask| and
   // |usage_deny_clear_mask| shall not conflict with each other. Such
   // configuration will be treated as invalid input on creation.
-  template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create(uint32_t usage_set_mask,
-                                               uint32_t usage_clear_mask,
-                                               uint32_t usage_deny_set_mask,
-                                               uint32_t usage_deny_clear_mask) {
-    return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask);
-  }
-  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes,
-                                               uint32_t usage_set_mask,
-                                               uint32_t usage_clear_mask,
-                                               uint32_t usage_deny_set_mask,
-                                               uint32_t usage_deny_clear_mask) {
-    return BASE::Create(meta_size_bytes, usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask);
+  static std::unique_ptr<ProducerQueue> Create(
+      const ProducerQueueConfig& config, const UsagePolicy& usage) {
+    return BASE::Create(config, usage);
   }
 
-  // Import a |ProducerQueue| from a channel handle.
-  static std::unique_ptr<ProducerQueue> Import(LocalChannelHandle handle) {
+  // Import a ProducerQueue from a channel handle.
+  static std::unique_ptr<ProducerQueue> Import(pdx::LocalChannelHandle handle) {
     return BASE::Create(std::move(handle));
   }
 
   // Get a buffer producer. Note that the method doesn't check whether the
   // buffer slot has a valid buffer that has been allocated already. When no
-  // buffer has been imported before it returns |nullptr|; otherwise it returns
-  // a shared pointer to a |BufferProducer|.
+  // buffer has been imported before it returns nullptr; otherwise it returns
+  // a shared pointer to a BufferProducer.
   std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
     return std::static_pointer_cast<BufferProducer>(
         BufferHubQueue::GetBuffer(slot));
@@ -333,26 +263,30 @@
 
   // Allocate producer buffer to populate the queue. Once allocated, a producer
   // buffer is automatically enqueue'd into the ProducerQueue and available to
-  // use (i.e. in |Gain|'ed mode).
-  // Returns Zero on success and negative error code when buffer allocation
-  // fails.
-  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
-                     uint32_t format, uint64_t usage, size_t* out_slot);
+  // use (i.e. in GAINED state).
+  pdx::Status<void> AllocateBuffer(uint32_t width, uint32_t height,
+                                   uint32_t layer_count, uint32_t format,
+                                   uint64_t usage, size_t* out_slot);
 
   // Add a producer buffer to populate the queue. Once added, a producer buffer
-  // is available to use (i.e. in |Gain|'ed mode).
-  int AddBuffer(const std::shared_ptr<BufferProducer>& buf, size_t slot);
+  // is available to use (i.e. in GAINED state).
+  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
+                              size_t slot);
 
   // Detach producer buffer from the queue.
-  // Returns Zero on success and negative error code when buffer detach
-  // fails.
-  int DetachBuffer(size_t slot) override;
+  pdx::Status<void> DetachBuffer(size_t slot) override;
 
   // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
   // and caller should call Post() once it's done writing to release the buffer
   // to the consumer side.
   pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
-      int timeout, size_t* slot, LocalHandle* release_fence);
+      int timeout, size_t* slot, pdx::LocalHandle* release_fence);
+
+  // Enqueues a producer buffer in the queue.
+  pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
+                            size_t slot) {
+    return BufferHubQueue::Enqueue({buffer, slot});
+  }
 
  private:
   friend BASE;
@@ -360,29 +294,13 @@
   // Constructors are automatically exposed through ProducerQueue::Create(...)
   // static template methods inherited from ClientBase, which take the same
   // arguments as the constructors.
-  explicit ProducerQueue(size_t meta_size);
-  ProducerQueue(LocalChannelHandle handle);
-  ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
-                uint64_t usage_clear_mask, uint64_t usage_deny_set_mask,
-                uint64_t usage_deny_clear_mask);
+  explicit ProducerQueue(pdx::LocalChannelHandle handle);
+  ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage);
 
-  int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                    LocalHandle* release_fence) override;
+  pdx::Status<Entry> OnBufferReady(
+      const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
 };
 
-// Explicit specializations of ProducerQueue::Create for void metadata type.
-template <>
-inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>() {
-  return ProducerQueue::Create(0);
-}
-template <>
-inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>(
-    uint32_t usage_set_mask, uint32_t usage_clear_mask,
-    uint32_t usage_deny_set_mask, uint32_t usage_deny_clear_mask) {
-  return ProducerQueue::Create(0, usage_set_mask, usage_clear_mask,
-                               usage_deny_set_mask, usage_deny_clear_mask);
-}
-
 class ConsumerQueue : public BufferHubQueue {
  public:
   // Get a buffer consumer. Note that the method doesn't check whether the
@@ -399,7 +317,7 @@
   // used to avoid participation in the buffer lifecycle by a consumer queue
   // that is only used to spawn other consumer queues, such as in an
   // intermediate service.
-  static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle,
+  static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle,
                                                bool ignore_on_import = false) {
     return std::unique_ptr<ConsumerQueue>(
         new ConsumerQueue(std::move(handle), ignore_on_import));
@@ -407,7 +325,7 @@
 
   // Import newly created buffers from the service side.
   // Returns number of buffers successfully imported or an error.
-  Status<size_t> ImportBuffers();
+  pdx::Status<size_t> ImportBuffers();
 
   // Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
   // mode, and caller should call Releasse() once it's done writing to release
@@ -417,33 +335,34 @@
   // when the buffer is orignally created.
   template <typename Meta>
   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
-      int timeout, size_t* slot, Meta* meta, LocalHandle* acquire_fence) {
+      int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
   }
   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
-      int timeout, size_t* slot, LocalHandle* acquire_fence) {
+      int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
   }
 
   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
       int timeout, size_t* slot, void* meta, size_t meta_size,
-      LocalHandle* acquire_fence);
+      pdx::LocalHandle* acquire_fence);
 
  private:
   friend BufferHubQueue;
 
-  ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import = false);
+  ConsumerQueue(pdx::LocalChannelHandle handle, bool ignore_on_import = false);
 
   // Add a consumer buffer to populate the queue. Once added, a consumer buffer
   // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
   // will catch the |Post| and |Acquire| the buffer to make it available for
   // consumer.
-  int AddBuffer(const std::shared_ptr<BufferConsumer>& buf, size_t slot);
+  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+                              size_t slot);
 
-  int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                    LocalHandle* acquire_fence) override;
+  pdx::Status<Entry> OnBufferReady(
+      const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
 
-  Status<void> OnBufferAllocated() override;
+  pdx::Status<void> OnBufferAllocated() override;
 
   // Flag indicating that imported (consumer) buffers should be ignored when
   // imported to avoid participating in the buffer ownership flow.
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_consumer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_consumer.h
deleted file mode 100644
index 8d7bfcc..0000000
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_consumer.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_CONSUMER_H_
-#define ANDROID_DVR_BUFFER_HUB_QUEUE_CONSUMER_H_
-
-#include <private/dvr/buffer_hub_queue_core.h>
-
-#include <gui/IGraphicBufferConsumer.h>
-
-namespace android {
-namespace dvr {
-
-class BufferHubQueueConsumer : public IGraphicBufferConsumer {
- public:
-  BufferHubQueueConsumer(const std::shared_ptr<BufferHubQueueCore>& core);
-
- private:
-  std::shared_ptr<BufferHubQueueCore> core_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_CONSUMER_H_
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
deleted file mode 100644
index 180906b..0000000
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
+++ /dev/null
@@ -1,159 +0,0 @@
-#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_CORE_H_
-#define ANDROID_DVR_BUFFER_HUB_QUEUE_CORE_H_
-
-#include <private/dvr/buffer_hub_queue_client.h>
-
-#include <gui/BufferSlot.h>
-#include <utils/Atomic.h>
-#include <utils/String8.h>
-
-#include <mutex>
-
-namespace android {
-namespace dvr {
-
-class BufferHubQueueCore {
- private:
-  friend class BufferHubQueueProducer;
-
- public:
-  static constexpr int kNoConnectedApi = -1;
-
-  // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer
-  // side logic doesn't limit the number of buffer it can acquire
-  // simultaneously. We need a way for consumer logic to configure and enforce
-  // that.
-  static constexpr int kDefaultUndequeuedBuffers = 1;
-
-  // Create a BufferHubQueueCore instance by creating a new producer queue.
-  static std::shared_ptr<BufferHubQueueCore> Create();
-
-  // Create a BufferHubQueueCore instance by importing an existing prodcuer
-  // queue.
-  static std::shared_ptr<BufferHubQueueCore> Create(
-      const std::shared_ptr<ProducerQueue>& producer);
-
-  // The buffer metadata that an Android Surface (a.k.a. ANativeWindow)
-  // will populate. This must be aligned with the |DvrNativeBufferMetadata|
-  // defined in |dvr_buffer_queue.h|. Please do not remove, modify, or reorder
-  // existing data members. If new fields need to be added, please take extra
-  // care to make sure that new data field is padded properly the size of the
-  // struct stays same.
-  // TODO(b/37578558) Move |dvr_api.h| into a header library so that this
-  // structure won't be copied between |dvr_api.h| and |buffer_hub_qeue_core.h|.
-  struct NativeBufferMetadata {
-    // Timestamp of the frame.
-    int64_t timestamp;
-
-    // Whether the buffer is using auto timestamp.
-    int32_t is_auto_timestamp;
-
-    // Must be one of the HAL_DATASPACE_XXX value defined in system/graphics.h
-    int32_t dataspace;
-
-    // Crop extracted from an ACrop or android::Crop object.
-    int32_t crop_left;
-    int32_t crop_top;
-    int32_t crop_right;
-    int32_t crop_bottom;
-
-    // Must be one of the NATIVE_WINDOW_SCALING_MODE_XXX value defined in
-    // system/window.h.
-    int32_t scaling_mode;
-
-    // Must be one of the ANATIVEWINDOW_TRANSFORM_XXX value defined in
-    // android/native_window.h
-    int32_t transform;
-
-    // Reserved bytes for so that the struct is forward compatible.
-    int32_t reserved[16];
-  };
-
-  class NativeBuffer
-      : public ANativeObjectBase<ANativeWindowBuffer, NativeBuffer, RefBase> {
-   public:
-    explicit NativeBuffer(const std::shared_ptr<BufferHubBuffer>& buffer)
-        : buffer_(buffer) {
-      ANativeWindowBuffer::width = buffer_->width();
-      ANativeWindowBuffer::height = buffer_->height();
-      ANativeWindowBuffer::stride = buffer_->stride();
-      ANativeWindowBuffer::format = buffer_->format();
-      ANativeWindowBuffer::usage = buffer_->usage();
-      ANativeWindowBuffer::handle = buffer_->buffer()->handle();
-    }
-
-    std::shared_ptr<BufferHubBuffer> buffer() { return buffer_; }
-
-   private:
-    std::shared_ptr<BufferHubBuffer> buffer_;
-  };
-
-  // Get the unique buffer producer queue backing this BufferHubQueue.
-  std::shared_ptr<ProducerQueue> GetProducerQueue() { return producer_; }
-
- private:
-  using LocalHandle = pdx::LocalHandle;
-
-  struct BufferHubSlot : public BufferSlot {
-    BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
-    // BufferSlot comes from android framework, using m prefix to comply with
-    // the name convention with the reset of data fields from BufferSlot.
-    std::shared_ptr<BufferProducer> mBufferProducer;
-    bool mIsReallocating;
-  };
-
-  static String8 getUniqueName() {
-    static volatile int32_t counter = 0;
-    return String8::format("unnamed-%d-%d", getpid(),
-                           android_atomic_inc(&counter));
-  }
-
-  static uint64_t getUniqueId() {
-    static std::atomic<uint32_t> counter{0};
-    static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
-    return id | counter++;
-  }
-
-  // Private constructor to force use of |Create|.
-  BufferHubQueueCore();
-
-  // Allocate a new buffer producer through BufferHub.
-  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
-                     PixelFormat format, uint64_t usage);
-
-  // Detach a buffer producer through BufferHub.
-  int DetachBuffer(size_t slot);
-
-  // Mutex for thread safety.
-  std::mutex mutex_;
-
-  // Connect client API, should be one of the NATIVE_WINDOW_API_* flags.
-  int connected_api_{kNoConnectedApi};
-
-  // |buffers_| stores the buffers that have been dequeued from
-  // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets
-  // filled in with the result of |Dequeue|.
-  // TODO(jwcai) The buffer allocated to a slot will also be replaced if the
-  // requested buffer usage or geometry differs from that of the buffer
-  // allocated to a slot.
-  BufferHubSlot buffers_[BufferHubQueue::kMaxQueueCapacity];
-
-  // Concreate implementation backed by BufferHubBuffer.
-  std::shared_ptr<ProducerQueue> producer_;
-
-  // |generation_number_| stores the current generation number of the attached
-  // producer. Any attempt to attach a buffer with a different generation
-  // number will fail.
-  uint32_t generation_number_;
-
-  // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
-  // slot is not yet available. The timeout is stored in milliseconds.
-  int dequeue_timeout_ms_;
-
-  const uint64_t unique_id_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_CORE_H_
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
index bf916ba..7890176 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
@@ -1,16 +1,29 @@
 #ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_PRODUCER_H_
 #define ANDROID_DVR_BUFFER_HUB_QUEUE_PRODUCER_H_
 
-#include <private/dvr/buffer_hub_queue_core.h>
-
 #include <gui/IGraphicBufferProducer.h>
+#include <private/dvr/buffer_hub_queue_client.h>
 
 namespace android {
 namespace dvr {
 
-class BufferHubQueueProducer : public BnInterface<IGraphicBufferProducer> {
+class BufferHubQueueProducer : public BnGraphicBufferProducer {
  public:
-  BufferHubQueueProducer(const std::shared_ptr<BufferHubQueueCore>& core);
+  static constexpr int kNoConnectedApi = -1;
+
+  // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer
+  // side logic doesn't limit the number of buffer it can acquire
+  // simultaneously. We need a way for consumer logic to configure and enforce
+  // that.
+  static constexpr int kDefaultUndequeuedBuffers = 1;
+
+  // Create a BufferHubQueueProducer instance by creating a new producer queue.
+  static sp<BufferHubQueueProducer> Create();
+
+  // Create a BufferHubQueueProducer instance by importing an existing prodcuer
+  // queue.
+  static sp<BufferHubQueueProducer> Create(
+      const std::shared_ptr<ProducerQueue>& producer);
 
   // See |IGraphicBufferProducer::requestBuffer|
   status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
@@ -98,14 +111,34 @@
   // See |IGraphicBufferProducer::getUniqueId|
   status_t getUniqueId(uint64_t* out_id) const override;
 
- protected:
-  IBinder* onAsBinder() override;
-
  private:
   using LocalHandle = pdx::LocalHandle;
 
-  // |core_| holds the actually buffer slots.
-  std::shared_ptr<BufferHubQueueCore> core_;
+  // Private constructor to force use of |Create|.
+  BufferHubQueueProducer() {}
+
+  static uint64_t genUniqueId() {
+    static std::atomic<uint32_t> counter{0};
+    static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
+    return id | counter++;
+  }
+
+  // Allocate new buffer through BufferHub and add it into |queue_| for
+  // bookkeeping.
+  status_t AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+                          PixelFormat format, uint64_t usage);
+
+  // Remove a buffer via BufferHubRPC.
+  status_t RemoveBuffer(size_t slot);
+
+  // Concreate implementation backed by BufferHubBuffer.
+  std::shared_ptr<ProducerQueue> queue_;
+
+  // Mutex for thread safety.
+  std::mutex mutex_;
+
+  // Connect client API, should be one of the NATIVE_WINDOW_API_* flags.
+  int connected_api_{kNoConnectedApi};
 
   // |max_buffer_count_| sets the capacity of the underlying buffer queue.
   int32_t max_buffer_count_{BufferHubQueue::kMaxQueueCapacity};
@@ -113,6 +146,35 @@
   // |max_dequeued_buffer_count_| set the maximum number of buffers that can
   // be dequeued at the same momment.
   int32_t max_dequeued_buffer_count_{1};
+
+  // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
+  // slot is not yet available. The timeout is stored in milliseconds.
+  int dequeue_timeout_ms_{BufferHubQueue::kNoTimeOut};
+
+  // |generation_number_| stores the current generation number of the attached
+  // producer. Any attempt to attach a buffer with a different generation
+  // number will fail.
+  // TOOD(b/38137191) Currently not used as we don't support
+  // IGraphicBufferProducer::detachBuffer.
+  uint32_t generation_number_{0};
+
+  // |buffers_| stores the buffers that have been dequeued from
+  // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets
+  // filled in with the result of |Dequeue|.
+  // TODO(jwcai) The buffer allocated to a slot will also be replaced if the
+  // requested buffer usage or geometry differs from that of the buffer
+  // allocated to a slot.
+  struct BufferHubSlot : public BufferSlot {
+    BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
+    // BufferSlot comes from android framework, using m prefix to comply with
+    // the name convention with the reset of data fields from BufferSlot.
+    std::shared_ptr<BufferProducer> mBufferProducer;
+    bool mIsReallocating;
+  };
+  BufferHubSlot buffers_[BufferHubQueue::kMaxQueueCapacity];
+
+  // A uniqueId used by IGraphicBufferProducer interface.
+  const uint64_t unique_id_{genUniqueId()};
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index fe0b12a..064e3fd 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -6,6 +6,9 @@
 
 #include <vector>
 
+// Enable/disable debug logging.
+#define TRACE 0
+
 namespace android {
 namespace dvr {
 
@@ -13,22 +16,17 @@
 
 namespace {
 
-constexpr int kBufferWidth = 100;
-constexpr int kBufferHeight = 1;
-constexpr int kBufferLayerCount = 1;
-constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
-constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
+constexpr uint32_t kBufferWidth = 100;
+constexpr uint32_t kBufferHeight = 1;
+constexpr uint32_t kBufferLayerCount = 1;
+constexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
+constexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
 
 class BufferHubQueueTest : public ::testing::Test {
  public:
-  template <typename Meta>
-  bool CreateProducerQueue(uint64_t usage_set_mask = 0,
-                           uint64_t usage_clear_mask = 0,
-                           uint64_t usage_deny_set_mask = 0,
-                           uint64_t usage_deny_clear_mask = 0) {
-    producer_queue_ =
-        ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask,
-                                    usage_deny_set_mask, usage_deny_clear_mask);
+  bool CreateProducerQueue(const ProducerQueueConfig& config,
+                           const UsagePolicy& usage) {
+    producer_queue_ = ProducerQueue::Create(config, usage);
     return producer_queue_ != nullptr;
   }
 
@@ -41,26 +39,25 @@
     }
   }
 
-  template <typename Meta>
-  bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
-                    int usage_deny_set_mask = 0,
-                    int usage_deny_clear_mask = 0) {
-    return CreateProducerQueue<Meta>(usage_set_mask, usage_clear_mask,
-                                     usage_deny_set_mask,
-                                     usage_deny_clear_mask) &&
-           CreateConsumerQueue();
+  bool CreateQueues(const ProducerQueueConfig& config,
+                    const UsagePolicy& usage) {
+    return CreateProducerQueue(config, usage) && CreateConsumerQueue();
   }
 
-  void AllocateBuffer() {
+  void AllocateBuffer(size_t* slot_out = nullptr) {
     // Create producer buffer.
     size_t slot;
-    int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                              kBufferLayerCount, kBufferFormat,
-                                              kBufferUsage, &slot);
-    ASSERT_EQ(ret, 0);
+    auto status = producer_queue_->AllocateBuffer(
+        kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+        kBufferUsage, &slot);
+    ASSERT_TRUE(status.ok());
+
+    if (slot_out)
+      *slot_out = slot;
   }
 
  protected:
+  ProducerQueueConfigBuilder config_builder_;
   std::unique_ptr<ProducerQueue> producer_queue_;
   std::unique_ptr<ConsumerQueue> consumer_queue_;
 };
@@ -68,7 +65,8 @@
 TEST_F(BufferHubQueueTest, TestDequeue) {
   const size_t nb_dequeue_times = 16;
 
-  ASSERT_TRUE(CreateQueues<size_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<size_t>().Build(),
+                           UsagePolicy{}));
 
   // Allocate only one buffer.
   AllocateBuffer();
@@ -94,13 +92,14 @@
 }
 
 TEST_F(BufferHubQueueTest, TestProducerConsumer) {
-  const size_t nb_buffer = 16;
+  const size_t kBufferCount = 16;
   size_t slot;
   uint64_t seq;
 
-  ASSERT_TRUE(CreateQueues<uint64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
+                           UsagePolicy{}));
 
-  for (size_t i = 0; i < nb_buffer; i++) {
+  for (size_t i = 0; i < kBufferCount; i++) {
     AllocateBuffer();
 
     // Producer queue has all the available buffers on initialize.
@@ -120,14 +119,23 @@
     ASSERT_EQ(consumer_queue_->capacity(), i + 1);
   }
 
-  for (size_t i = 0; i < nb_buffer; i++) {
+  // Use /dev/zero as a stand-in for a fence. As long as BufferHub does not need
+  // to merge fences, which only happens when multiple consumers release the
+  // same buffer with release fences, the file object should simply pass
+  // through.
+  LocalHandle post_fence("/dev/zero", O_RDONLY);
+  struct stat post_fence_stat;
+  ASSERT_EQ(0, fstat(post_fence.Get(), &post_fence_stat));
+
+  for (size_t i = 0; i < kBufferCount; i++) {
     LocalHandle fence;
-    // First time, there is no buffer available to dequeue.
+
+    // First time there is no buffer available to dequeue.
     auto consumer_status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
     ASSERT_FALSE(consumer_status.ok());
     ASSERT_EQ(ETIMEDOUT, consumer_status.error());
 
-    // Make sure Producer buffer is Post()'ed so that it's ready to Accquire
+    // Make sure Producer buffer is POSTED so that it's ready to Accquire
     // in the consumer's Dequeue() function.
     auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
     ASSERT_TRUE(producer_status.ok());
@@ -135,20 +143,137 @@
     ASSERT_NE(nullptr, producer);
 
     uint64_t seq_in = static_cast<uint64_t>(i);
-    ASSERT_EQ(producer->Post({}, &seq_in, sizeof(seq_in)), 0);
+    ASSERT_EQ(producer->Post(post_fence, &seq_in, sizeof(seq_in)), 0);
 
-    // Second time, the just |Post()|'ed buffer should be dequeued.
+    // Second time the just the POSTED buffer should be dequeued.
     uint64_t seq_out = 0;
     consumer_status = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
     ASSERT_TRUE(consumer_status.ok());
+    EXPECT_TRUE(fence.IsValid());
+
+    struct stat acquire_fence_stat;
+    ASSERT_EQ(0, fstat(fence.Get(), &acquire_fence_stat));
+
+    // The file descriptors should refer to the same file object. Testing the
+    // device id and inode is a proxy for testing that the fds refer to the same
+    // file object.
+    EXPECT_NE(post_fence.Get(), fence.Get());
+    EXPECT_EQ(post_fence_stat.st_dev, acquire_fence_stat.st_dev);
+    EXPECT_EQ(post_fence_stat.st_ino, acquire_fence_stat.st_ino);
+
     auto consumer = consumer_status.take();
     ASSERT_NE(nullptr, consumer);
     ASSERT_EQ(seq_in, seq_out);
   }
 }
 
+TEST_F(BufferHubQueueTest, TestDetach) {
+  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
+
+  // Allocate buffers.
+  const size_t kBufferCount = 4u;
+  for (size_t i = 0; i < kBufferCount; i++) {
+    AllocateBuffer();
+  }
+  ASSERT_EQ(kBufferCount, producer_queue_->count());
+  ASSERT_EQ(kBufferCount, producer_queue_->capacity());
+
+  consumer_queue_ = producer_queue_->CreateConsumerQueue();
+  ASSERT_NE(nullptr, consumer_queue_);
+
+  // Check that buffers are correctly imported on construction.
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_EQ(0u, consumer_queue_->count());
+
+  // Dequeue all the buffers and keep track of them in an array. This prevents
+  // the producer queue ring buffer ref counts from interfering with the tests.
+  struct Entry {
+    std::shared_ptr<BufferProducer> buffer;
+    LocalHandle fence;
+    size_t slot;
+  };
+  std::array<Entry, kBufferCount> buffers;
+
+  for (size_t i = 0; i < kBufferCount; i++) {
+    Entry* entry = &buffers[i];
+    auto producer_status =
+        producer_queue_->Dequeue(0, &entry->slot, &entry->fence);
+    ASSERT_TRUE(producer_status.ok());
+    entry->buffer = producer_status.take();
+    ASSERT_NE(nullptr, entry->buffer);
+    EXPECT_EQ(i, entry->slot);
+  }
+
+  // Detach a buffer and make sure both queues reflect the change.
+  ASSERT_TRUE(producer_queue_->DetachBuffer(buffers[0].slot));
+  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+
+  // As long as the detached buffer is still alive the consumer queue won't know
+  // its gone.
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+  // Release the detached buffer.
+  buffers[0].buffer = nullptr;
+
+  // Now the consumer queue should know it's gone.
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount - 1, consumer_queue_->capacity());
+
+  // Allocate a new buffer. This should take the first empty slot.
+  size_t slot;
+  AllocateBuffer(&slot);
+  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+  EXPECT_EQ(buffers[0].slot, slot);
+  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+  // The consumer queue should pick up the new buffer.
+  EXPECT_EQ(kBufferCount - 1, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+  // Detach and allocate a buffer.
+  ASSERT_TRUE(producer_queue_->DetachBuffer(buffers[1].slot));
+  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+  buffers[1].buffer = nullptr;
+
+  AllocateBuffer(&slot);
+  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+  EXPECT_EQ(buffers[1].slot, slot);
+  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+  // The consumer queue should pick up the new buffer but the count shouldn't
+  // change.
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+  // Detach and allocate a buffer, but don't free the buffer right away.
+  ASSERT_TRUE(producer_queue_->DetachBuffer(buffers[2].slot));
+  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+
+  AllocateBuffer(&slot);
+  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+  EXPECT_EQ(buffers[2].slot, slot);
+  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+  // Release the producer buffer to trigger a POLLHUP event for an already
+  // detached buffer.
+  buffers[2].buffer = nullptr;
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+}
+
 TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
-  ASSERT_TRUE(CreateProducerQueue<void>());
+  // ProducerConfigureBuilder doesn't set Metadata{size}, which means there
+  // is no metadata associated with this BufferQueue's buffer.
+  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate buffers.
   const size_t kBufferCount = 4u;
@@ -226,7 +351,9 @@
 };
 
 TEST_F(BufferHubQueueTest, TestMetadata) {
-  ASSERT_TRUE(CreateQueues<TestMetadata>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<TestMetadata>().Build(),
+                           UsagePolicy{}));
+
   AllocateBuffer();
 
   std::vector<TestMetadata> ms = {
@@ -252,7 +379,9 @@
 }
 
 TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
+
   AllocateBuffer();
 
   int64_t mi = 3;
@@ -271,7 +400,8 @@
 }
 
 TEST_F(BufferHubQueueTest, TestEnqueue) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
   AllocateBuffer();
 
   size_t slot;
@@ -288,7 +418,8 @@
 }
 
 TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
 
   size_t s1;
   AllocateBuffer();
@@ -343,14 +474,15 @@
 
 TEST_F(BufferHubQueueTest, TestUsageSetMask) {
   const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{set_mask, 0, 0, 0}));
 
   // When allocation, leave out |set_mask| from usage bits on purpose.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                            kBufferFormat, kBufferLayerCount,
-                                            kBufferUsage & ~set_mask, &slot);
-  ASSERT_EQ(0, ret);
+  auto status = producer_queue_->AllocateBuffer(
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage & ~set_mask, &slot);
+  ASSERT_TRUE(status.ok());
 
   LocalHandle fence;
   auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
@@ -361,14 +493,15 @@
 
 TEST_F(BufferHubQueueTest, TestUsageClearMask) {
   const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, clear_mask, 0, 0}));
 
   // When allocation, add |clear_mask| into usage bits on purpose.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                            kBufferLayerCount, kBufferFormat,
-                                            kBufferUsage | clear_mask, &slot);
-  ASSERT_EQ(0, ret);
+  auto status = producer_queue_->AllocateBuffer(
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage | clear_mask, &slot);
+  ASSERT_TRUE(status.ok());
 
   LocalHandle fence;
   auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
@@ -379,40 +512,64 @@
 
 TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
   const uint32_t deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, 0, deny_set_mask, 0}));
 
   // Now that |deny_set_mask| is illegal, allocation without those bits should
   // be able to succeed.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
+  auto status = producer_queue_->AllocateBuffer(
       kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
       kBufferUsage & ~deny_set_mask, &slot);
-  ASSERT_EQ(ret, 0);
+  ASSERT_TRUE(status.ok());
 
   // While allocation with those bits should fail.
-  ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                        kBufferLayerCount, kBufferFormat,
-                                        kBufferUsage | deny_set_mask, &slot);
-  ASSERT_EQ(ret, -EINVAL);
+  status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                           kBufferLayerCount, kBufferFormat,
+                                           kBufferUsage | deny_set_mask, &slot);
+  ASSERT_FALSE(status.ok());
+  ASSERT_EQ(EINVAL, status.error());
 }
 
 TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
   const uint32_t deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, 0, 0, deny_clear_mask));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, 0, 0, deny_clear_mask}));
 
   // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
   // mandatory), allocation with those bits should be able to succeed.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
+  auto status = producer_queue_->AllocateBuffer(
       kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
       kBufferUsage | deny_clear_mask, &slot);
-  ASSERT_EQ(ret, 0);
+  ASSERT_TRUE(status.ok());
 
   // While allocation without those bits should fail.
-  ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                        kBufferLayerCount, kBufferFormat,
-                                        kBufferUsage & ~deny_clear_mask, &slot);
-  ASSERT_EQ(ret, -EINVAL);
+  status = producer_queue_->AllocateBuffer(
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage & ~deny_clear_mask, &slot);
+  ASSERT_FALSE(status.ok());
+  ASSERT_EQ(EINVAL, status.error());
+}
+
+TEST_F(BufferHubQueueTest, TestQueueInfo) {
+  static const bool kIsAsync = true;
+  ASSERT_TRUE(CreateQueues(config_builder_.SetIsAsync(kIsAsync)
+                               .SetDefaultWidth(kBufferWidth)
+                               .SetDefaultHeight(kBufferHeight)
+                               .SetDefaultFormat(kBufferFormat)
+                               .Build(),
+                           UsagePolicy{}));
+
+  EXPECT_EQ(producer_queue_->default_width(), kBufferWidth);
+  EXPECT_EQ(producer_queue_->default_height(), kBufferHeight);
+  EXPECT_EQ(producer_queue_->default_format(), kBufferFormat);
+  EXPECT_EQ(producer_queue_->is_async(), kIsAsync);
+
+  EXPECT_EQ(consumer_queue_->default_width(), kBufferWidth);
+  EXPECT_EQ(consumer_queue_->default_height(), kBufferHeight);
+  EXPECT_EQ(consumer_queue_->default_format(), kBufferFormat);
+  EXPECT_EQ(consumer_queue_->is_async(), kIsAsync);
 }
 
 }  // namespace
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
index 64034e8..c7692d0 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -92,8 +92,7 @@
     ALOGD_IF(TRACE, "Begin test: %s.%s", testInfo->test_case_name(),
              testInfo->name());
 
-    auto core = BufferHubQueueCore::Create();
-    mProducer = new BufferHubQueueProducer(core);
+    mProducer = BufferHubQueueProducer::Create();
     ASSERT_TRUE(mProducer != nullptr);
     mSurface = new Surface(mProducer, true);
     ASSERT_TRUE(mSurface != nullptr);
@@ -193,7 +192,7 @@
   EXPECT_EQ(NO_ERROR,
             mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
   EXPECT_LE(0, value);
-  EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, static_cast<size_t>(value));
+  EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value);
 
   EXPECT_EQ(NO_ERROR,
             mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index 41baef8..e3ab7fa 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -13,16 +13,11 @@
 // limitations under the License.
 
 sourceFiles = [
-    "native_buffer_queue.cpp",
     "display_client.cpp",
     "display_manager_client.cpp",
     "display_protocol.cpp",
-    "dummy_native_window.cpp",
-    "frame_history.cpp",
-    "gl_fenced_flush.cpp",
-    "graphics.cpp",
-    "late_latch.cpp",
     "vsync_client.cpp",
+    "shared_buffer_helpers.cpp",
 ]
 
 localIncludeFiles = [
@@ -34,9 +29,6 @@
     "libcutils",
     "liblog",
     "libutils",
-    "libEGL",
-    "libGLESv2",
-    "libvulkan",
     "libui",
     "libgui",
     "libhardware",
@@ -45,16 +37,16 @@
 ]
 
 staticLibraries = [
-    "libbufferhub",
-    "libbufferhubqueue",
     "libdvrcommon",
-    "libdvrgraphics",
-    "libvrsensor",
+    "libbufferhubqueue",
+    "libbufferhub",
+    "libbroadcastring",
     "libpdx_default_transport",
 ]
 
 headerLibraries = [
     "vulkan_headers",
+    "libdvr_headers",
 ]
 
 cc_library {
@@ -74,27 +66,3 @@
 
     name: "libdisplay",
 }
-
-graphicsAppTestFiles = ["tests/graphics_app_tests.cpp"]
-
-cc_test {
-    name: "graphics_app_tests",
-    tags: ["optional"],
-
-    srcs: graphicsAppTestFiles,
-
-    shared_libs: sharedLibraries,
-
-    static_libs: ["libdisplay"] + staticLibraries,
-}
-
-dummyNativeWindowTestFiles = ["tests/dummy_native_window_tests.cpp"]
-
-cc_test {
-    name: "dummy_native_window_tests",
-    tags: [ "optional" ],
-    srcs: dummyNativeWindowTestFiles,
-    shared_libs: sharedLibraries,
-    static_libs: [ "libdisplay" ] + staticLibraries,
-}
-
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 5c9ebd4..6175da7 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -9,7 +9,6 @@
 #include <mutex>
 
 #include <private/dvr/display_protocol.h>
-#include <private/dvr/late_latch.h>
 #include <private/dvr/native_buffer.h>
 
 using android::pdx::ErrorStatus;
@@ -139,13 +138,13 @@
   ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
   for (size_t i = 0; i < capacity; i++) {
     size_t slot;
-    const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
-                                                   format, usage, &slot);
-    if (ret < 0) {
+    auto allocate_status = producer_queue->AllocateBuffer(
+        width, height, layer_count, format, usage, &slot);
+    if (!allocate_status) {
       ALOGE(
           "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
-          producer_queue->id(), strerror(-ret));
-      return ErrorStatus(ENOMEM);
+          producer_queue->id(), allocate_status.GetErrorMessage().c_str());
+      return allocate_status.error_status();
     }
     ALOGD_IF(
         TRACE,
@@ -168,6 +167,19 @@
   return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
 }
 
+Status<std::string> DisplayClient::GetConfigurationData(
+    ConfigFileType config_type) {
+  auto status =
+      InvokeRemoteMethod<DisplayProtocol::GetConfigurationData>(config_type);
+  if (!status && status.error() != ENOENT) {
+    ALOGE(
+        "DisplayClient::GetConfigurationData: Unable to get"
+        "configuration data. Error: %s",
+        status.GetErrorMessage().c_str());
+  }
+  return status;
+}
+
 Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
     const SurfaceAttributes& attributes) {
   int error;
@@ -177,14 +189,14 @@
     return ErrorStatus(error);
 }
 
-Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
-    const std::string& name) {
-  auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
+Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
+    DvrGlobalBufferKey key) {
+  auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
   if (!status) {
     ALOGE(
-        "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
+        "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
         "error=%s",
-        name.c_str(), status.GetErrorMessage().c_str());
+        key, status.GetErrorMessage().c_str());
     return status.error_status();
   }
 
@@ -193,9 +205,9 @@
   const int ret = native_buffer_handle.Import(ion_buffer.get());
   if (ret < 0) {
     ALOGE(
-        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
-        "name=%s; error=%s",
-        name.c_str(), strerror(-ret));
+        "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
+        "key=%d; error=%s",
+        key, strerror(-ret));
     return ErrorStatus(-ret);
   }
 
diff --git a/libs/vr/libdisplay/display_manager_client.cpp b/libs/vr/libdisplay/display_manager_client.cpp
index 82dacf7..098b725 100644
--- a/libs/vr/libdisplay/display_manager_client.cpp
+++ b/libs/vr/libdisplay/display_manager_client.cpp
@@ -32,13 +32,13 @@
   return status;
 }
 
-pdx::Status<std::unique_ptr<IonBuffer>> DisplayManagerClient::SetupNamedBuffer(
-    const std::string& name, size_t size, uint64_t usage) {
-  auto status = InvokeRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
-      name, size, usage);
+pdx::Status<std::unique_ptr<IonBuffer>> DisplayManagerClient::SetupGlobalBuffer(
+    DvrGlobalBufferKey key, size_t size, uint64_t usage) {
+  auto status = InvokeRemoteMethod<DisplayManagerProtocol::SetupGlobalBuffer>(
+      key, size, usage);
   if (!status) {
     ALOGE(
-        "DisplayManagerClient::SetupPoseBuffer: Failed to create the named "
+        "DisplayManagerClient::SetupGlobalBuffer: Failed to create the global "
         "buffer %s",
         status.GetErrorMessage().c_str());
     return status.error_status();
@@ -49,15 +49,27 @@
   const int ret = native_buffer_handle.Import(ion_buffer.get());
   if (ret < 0) {
     ALOGE(
-        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
-        "name=%s; error=%s",
-        name.c_str(), strerror(-ret));
+        "DisplayManagerClient::GetGlobalBuffer: Failed to import global "
+        "buffer: key=%d; error=%s",
+        key, strerror(-ret));
     return ErrorStatus(-ret);
   }
 
   return {std::move(ion_buffer)};
 }
 
+pdx::Status<void> DisplayManagerClient::DeleteGlobalBuffer(
+    DvrGlobalBufferKey key) {
+  auto status =
+      InvokeRemoteMethod<DisplayManagerProtocol::DeleteGlobalBuffer>(key);
+  if (!status) {
+    ALOGE("DisplayManagerClient::DeleteGlobalBuffer Failed: %s",
+          status.GetErrorMessage().c_str());
+  }
+
+  return status;
+}
+
 pdx::Status<std::unique_ptr<ConsumerQueue>>
 DisplayManagerClient::GetSurfaceQueue(int surface_id, int queue_id) {
   auto status = InvokeRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
diff --git a/libs/vr/libdisplay/dummy_native_window.cpp b/libs/vr/libdisplay/dummy_native_window.cpp
deleted file mode 100644
index 4628b8e..0000000
--- a/libs/vr/libdisplay/dummy_native_window.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "include/private/dvr/dummy_native_window.h"
-
-#include <utils/Errors.h>
-
-namespace {
-// Dummy functions required for an ANativeWindow Implementation.
-int F1(struct ANativeWindow*, int) { return 0; }
-int F2(struct ANativeWindow*, struct ANativeWindowBuffer**) { return 0; }
-int F3(struct ANativeWindow*, struct ANativeWindowBuffer*) { return 0; }
-int F4(struct ANativeWindow*, struct ANativeWindowBuffer**, int*) { return 0; }
-int F5(struct ANativeWindow*, struct ANativeWindowBuffer*, int) { return 0; }
-}  // anonymous namespace
-
-namespace android {
-namespace dvr {
-
-DummyNativeWindow::DummyNativeWindow() {
-  ANativeWindow::setSwapInterval = F1;
-  ANativeWindow::dequeueBuffer = F4;
-  ANativeWindow::cancelBuffer = F5;
-  ANativeWindow::queueBuffer = F5;
-  ANativeWindow::query = Query;
-  ANativeWindow::perform = Perform;
-
-  ANativeWindow::dequeueBuffer_DEPRECATED = F2;
-  ANativeWindow::cancelBuffer_DEPRECATED = F3;
-  ANativeWindow::lockBuffer_DEPRECATED = F3;
-  ANativeWindow::queueBuffer_DEPRECATED = F3;
-}
-
-int DummyNativeWindow::Query(const ANativeWindow*, int what, int* value) {
-  switch (what) {
-    // This must be 1 in order for eglCreateWindowSurface to not trigger an
-    // error
-    case NATIVE_WINDOW_IS_VALID:
-      *value = 1;
-      return NO_ERROR;
-    case NATIVE_WINDOW_WIDTH:
-    case NATIVE_WINDOW_HEIGHT:
-    case NATIVE_WINDOW_FORMAT:
-    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
-    case NATIVE_WINDOW_CONCRETE_TYPE:
-    case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
-    case NATIVE_WINDOW_DEFAULT_WIDTH:
-    case NATIVE_WINDOW_DEFAULT_HEIGHT:
-    case NATIVE_WINDOW_TRANSFORM_HINT:
-      *value = 0;
-      return NO_ERROR;
-  }
-
-  *value = 0;
-  return BAD_VALUE;
-}
-
-int DummyNativeWindow::Perform(ANativeWindow*, int operation, ...) {
-  switch (operation) {
-    case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
-    case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
-    case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
-    case NATIVE_WINDOW_SET_USAGE:
-    case NATIVE_WINDOW_CONNECT:
-    case NATIVE_WINDOW_DISCONNECT:
-    case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
-    case NATIVE_WINDOW_API_CONNECT:
-    case NATIVE_WINDOW_API_DISCONNECT:
-    case NATIVE_WINDOW_SET_BUFFER_COUNT:
-    case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
-    case NATIVE_WINDOW_SET_SCALING_MODE:
-      return NO_ERROR;
-    case NATIVE_WINDOW_LOCK:
-    case NATIVE_WINDOW_UNLOCK_AND_POST:
-    case NATIVE_WINDOW_SET_CROP:
-    case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
-      return INVALID_OPERATION;
-  }
-  return NAME_NOT_FOUND;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdisplay/frame_history.cpp b/libs/vr/libdisplay/frame_history.cpp
deleted file mode 100644
index 154afbe..0000000
--- a/libs/vr/libdisplay/frame_history.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <private/dvr/frame_history.h>
-
-#include <errno.h>
-#include <log/log.h>
-#include <sync/sync.h>
-
-#include <pdx/file_handle.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/sync_util.h>
-
-using android::pdx::LocalHandle;
-
-constexpr int kNumFramesToUseForSchedulePrediction = 10;
-constexpr int kDefaultVsyncIntervalPrediction = 1;
-constexpr int kMaxVsyncIntervalPrediction = 4;
-constexpr int kDefaultPendingFrameBufferSize = 10;
-
-namespace android {
-namespace dvr {
-
-FrameHistory::PendingFrame::PendingFrame()
-    : start_ns(0), scheduled_vsync(0), scheduled_finish_ns(0) {}
-
-FrameHistory::PendingFrame::PendingFrame(int64_t start_ns,
-                                         uint32_t scheduled_vsync,
-                                         int64_t scheduled_finish_ns,
-                                         LocalHandle&& fence)
-    : start_ns(start_ns), scheduled_vsync(scheduled_vsync),
-      scheduled_finish_ns(scheduled_finish_ns), fence(std::move(fence)) {}
-
-FrameHistory::FrameHistory() : FrameHistory(kDefaultPendingFrameBufferSize) {}
-
-FrameHistory::FrameHistory(int pending_frame_buffer_size)
-    : pending_frames_(pending_frame_buffer_size),
-      finished_frames_(pending_frame_buffer_size),
-      frame_duration_history_(kNumFramesToUseForSchedulePrediction) {}
-
-void FrameHistory::Reset(int pending_frame_buffer_size) {
-  pending_frames_.Reset(pending_frame_buffer_size);
-  finished_frames_.Reset(pending_frame_buffer_size);
-  frame_duration_history_.Clear();
-}
-
-void FrameHistory::OnFrameStart(uint32_t scheduled_vsync,
-                                int64_t scheduled_finish_ns) {
-  if (!pending_frames_.IsEmpty() && !pending_frames_.Back().fence) {
-    // If we don't have a fence set for the previous frame it's because
-    // OnFrameStart() was called twice in a row with no OnFrameSubmit() call. In
-    // that case throw out the pending frame data for the last frame.
-    pending_frames_.PopBack();
-  }
-
-  if (pending_frames_.IsFull()) {
-    ALOGW("Pending frames buffer is full. Discarding pending frame data.");
-  }
-
-  pending_frames_.Append(PendingFrame(GetSystemClockNs(), scheduled_vsync,
-                                      scheduled_finish_ns, LocalHandle()));
-}
-
-void FrameHistory::OnFrameSubmit(LocalHandle&& fence) {
-  // Add the fence to the previous frame data in pending_frames so we can
-  // track when it finishes.
-  if (!pending_frames_.IsEmpty() && !pending_frames_.Back().fence) {
-    if (fence && pending_frames_.Back().scheduled_vsync != UINT32_MAX)
-      pending_frames_.Back().fence = std::move(fence);
-    else
-      pending_frames_.PopBack();
-  }
-}
-
-void FrameHistory::CheckForFinishedFrames() {
-  if (pending_frames_.IsEmpty())
-    return;
-
-  android::dvr::FenceInfoBuffer fence_info_buffer;
-  while (!pending_frames_.IsEmpty()) {
-    const auto& pending_frame = pending_frames_.Front();
-    if (!pending_frame.fence) {
-      // The frame hasn't been submitted yet, so there's nothing more to do
-      break;
-    }
-
-    int64_t fence_signaled_time = -1;
-    int fence = pending_frame.fence.Get();
-    int sync_result = sync_wait(fence, 0);
-    if (sync_result == 0) {
-      int fence_signaled_result =
-          GetFenceSignaledTimestamp(fence, &fence_info_buffer,
-                                    &fence_signaled_time);
-      if (fence_signaled_result < 0) {
-        ALOGE("Failed getting signaled timestamp from fence");
-      } else {
-        // The frame is finished. Record the duration and move the frame data
-        // from pending_frames_ to finished_frames_.
-        DvrFrameScheduleResult schedule_result = {};
-        schedule_result.vsync_count = pending_frame.scheduled_vsync;
-        schedule_result.scheduled_frame_finish_ns =
-            pending_frame.scheduled_finish_ns;
-        schedule_result.frame_finish_offset_ns =
-            fence_signaled_time - pending_frame.scheduled_finish_ns;
-        finished_frames_.Append(schedule_result);
-        frame_duration_history_.Append(
-            fence_signaled_time - pending_frame.start_ns);
-      }
-      pending_frames_.PopFront();
-    } else {
-      if (errno != ETIME) {
-        ALOGE("sync_wait on frame fence failed. fence=%d errno=%d (%s).",
-              fence, errno, strerror(errno));
-      }
-      break;
-    }
-  }
-}
-
-int FrameHistory::PredictNextFrameVsyncInterval(int64_t vsync_period_ns) const {
-  if (frame_duration_history_.IsEmpty())
-    return kDefaultVsyncIntervalPrediction;
-
-  double total = 0;
-  for (size_t i = 0; i < frame_duration_history_.GetSize(); ++i)
-    total += frame_duration_history_.Get(i);
-  double avg_duration = total / frame_duration_history_.GetSize();
-
-  return std::min(kMaxVsyncIntervalPrediction,
-                  static_cast<int>(avg_duration / vsync_period_ns) + 1);
-}
-
-int FrameHistory::GetPreviousFrameResults(DvrFrameScheduleResult* results,
-                                          int in_result_count) {
-  int out_result_count =
-      std::min(in_result_count, static_cast<int>(finished_frames_.GetSize()));
-  for (int i = 0; i < out_result_count; ++i) {
-    results[i] = finished_frames_.Get(0);
-    finished_frames_.PopFront();
-  }
-  return out_result_count;
-}
-
-uint32_t FrameHistory::GetCurrentFrameVsync() const {
-  return pending_frames_.IsEmpty() ?
-      UINT32_MAX : pending_frames_.Back().scheduled_vsync;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdisplay/gl_fenced_flush.cpp b/libs/vr/libdisplay/gl_fenced_flush.cpp
deleted file mode 100644
index c70d554..0000000
--- a/libs/vr/libdisplay/gl_fenced_flush.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "include/private/dvr/gl_fenced_flush.h"
-
-#include <EGL/eglext.h>
-#include <GLES3/gl31.h>
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Trace.h>
-
-#include <log/log.h>
-
-using android::pdx::LocalHandle;
-
-namespace android {
-namespace dvr {
-
-LocalHandle CreateGLSyncAndFlush(EGLDisplay display) {
-  ATRACE_NAME("CreateGLSyncAndFlush");
-
-  EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID,
-                      EGL_NO_NATIVE_FENCE_FD_ANDROID, EGL_NONE};
-  EGLSyncKHR sync_point =
-      eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
-  glFlush();
-  if (sync_point == EGL_NO_SYNC_KHR) {
-    ALOGE("sync_point == EGL_NO_SYNC_KHR");
-    return LocalHandle();
-  }
-  EGLint fence_fd = eglDupNativeFenceFDANDROID(display, sync_point);
-  eglDestroySyncKHR(display, sync_point);
-
-  if (fence_fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
-    ALOGE("fence_fd == EGL_NO_NATIVE_FENCE_FD_ANDROID");
-    return LocalHandle();
-  }
-  return LocalHandle(fence_fd);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdisplay/graphics.cpp b/libs/vr/libdisplay/graphics.cpp
deleted file mode 100644
index cc140af..0000000
--- a/libs/vr/libdisplay/graphics.cpp
+++ /dev/null
@@ -1,1607 +0,0 @@
-#include <dvr/graphics.h>
-
-#include <inttypes.h>
-#include <sys/timerfd.h>
-#include <array>
-#include <vector>
-
-#include <log/log.h>
-#include <utils/Trace.h>
-
-#ifndef VK_USE_PLATFORM_ANDROID_KHR
-#define VK_USE_PLATFORM_ANDROID_KHR 1
-#endif
-#include <vulkan/vulkan.h>
-
-#include <dvr/dvr_display_types.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/debug.h>
-#include <private/dvr/frame_history.h>
-#include <private/dvr/gl_fenced_flush.h>
-#include <private/dvr/graphics/vr_gl_extensions.h>
-#include <private/dvr/graphics_private.h>
-#include <private/dvr/late_latch.h>
-#include <private/dvr/native_buffer_queue.h>
-#include <private/dvr/platform_defines.h>
-#include <private/dvr/sensor_constants.h>
-#include <private/dvr/vsync_client.h>
-
-#include <system/window.h>
-
-#ifndef EGL_CONTEXT_MAJOR_VERSION
-#define EGL_CONTEXT_MAJOR_VERSION 0x3098
-#define EGL_CONTEXT_MINOR_VERSION 0x30FB
-#endif
-
-using android::pdx::ErrorStatus;
-using android::pdx::LocalHandle;
-using android::pdx::LocalChannelHandle;
-using android::pdx::Status;
-
-using android::dvr::display::DisplayClient;
-using android::dvr::display::Metrics;
-using android::dvr::display::NativeBufferQueue;
-using android::dvr::display::Surface;
-using android::dvr::display::SurfaceAttribute;
-using android::dvr::display::SurfaceAttributes;
-using android::dvr::display::SurfaceAttributeValue;
-using android::dvr::VSyncClient;
-
-namespace {
-
-// TODO(urbanus): revisit once we have per-platform usage config in place.
-constexpr uint64_t kDefaultDisplaySurfaceUsage =
-    GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET |
-    GRALLOC1_PRODUCER_USAGE_PRIVATE_1 | GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET |
-    GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
-constexpr uint32_t kDefaultDisplaySurfaceFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-// TODO(alexst): revisit this count when HW encode is available for casting.
-constexpr size_t kDefaultBufferCount = 4;
-
-// Use with dvrBeginRenderFrame to disable EDS for the current frame.
-constexpr float32x4_t DVR_POSE_NO_EDS = {10.0f, 0.0f, 0.0f, 0.0f};
-
-// Use with dvrBeginRenderFrame to indicate that GPU late-latching is being used
-// for determining the render pose.
-constexpr float32x4_t DVR_POSE_LATE_LATCH = {20.0f, 0.0f, 0.0f, 0.0f};
-
-#ifndef NDEBUG
-
-static const char* GetGlCallbackType(GLenum type) {
-  switch (type) {
-    case GL_DEBUG_TYPE_ERROR_KHR:
-      return "ERROR";
-    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR:
-      return "DEPRECATED_BEHAVIOR";
-    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR:
-      return "UNDEFINED_BEHAVIOR";
-    case GL_DEBUG_TYPE_PORTABILITY_KHR:
-      return "PORTABILITY";
-    case GL_DEBUG_TYPE_PERFORMANCE_KHR:
-      return "PERFORMANCE";
-    case GL_DEBUG_TYPE_OTHER_KHR:
-      return "OTHER";
-    default:
-      return "UNKNOWN";
-  }
-}
-
-static void on_gl_error(GLenum /*source*/, GLenum type, GLuint /*id*/,
-                        GLenum severity, GLsizei /*length*/,
-                        const char* message, const void* /*user_param*/) {
-  char msg[400];
-  snprintf(msg, sizeof(msg), "[" __FILE__ ":%u] GL %s: %s", __LINE__,
-           GetGlCallbackType(type), message);
-  switch (severity) {
-    case GL_DEBUG_SEVERITY_LOW_KHR:
-      ALOGI("%s", msg);
-      break;
-    case GL_DEBUG_SEVERITY_MEDIUM_KHR:
-      ALOGW("%s", msg);
-      break;
-    case GL_DEBUG_SEVERITY_HIGH_KHR:
-      ALOGE("%s", msg);
-      break;
-  }
-  fprintf(stderr, "%s\n", msg);
-}
-
-#endif
-
-int DvrToHalSurfaceFormat(int dvr_surface_format) {
-  switch (dvr_surface_format) {
-    case DVR_SURFACE_FORMAT_RGBA_8888:
-      return HAL_PIXEL_FORMAT_RGBA_8888;
-    case DVR_SURFACE_FORMAT_RGB_565:
-      return HAL_PIXEL_FORMAT_RGB_565;
-    default:
-      return HAL_PIXEL_FORMAT_RGBA_8888;
-  }
-}
-
-int SelectEGLConfig(EGLDisplay dpy, EGLint* attr, unsigned format,
-                    EGLConfig* config) {
-  std::array<EGLint, 4> desired_rgba;
-  switch (format) {
-    case HAL_PIXEL_FORMAT_RGBA_8888:
-    case HAL_PIXEL_FORMAT_BGRA_8888:
-      desired_rgba = {{8, 8, 8, 8}};
-      break;
-    case HAL_PIXEL_FORMAT_RGB_565:
-      desired_rgba = {{5, 6, 5, 0}};
-      break;
-    default:
-      ALOGE("Unsupported framebuffer pixel format %d", format);
-      return -1;
-  }
-
-  EGLint max_configs = 0;
-  if (eglGetConfigs(dpy, NULL, 0, &max_configs) == EGL_FALSE) {
-    ALOGE("No EGL configurations available?!");
-    return -1;
-  }
-
-  std::vector<EGLConfig> configs(max_configs);
-
-  EGLint num_configs;
-  if (eglChooseConfig(dpy, attr, &configs[0], max_configs, &num_configs) ==
-      EGL_FALSE) {
-    ALOGE("eglChooseConfig failed");
-    return -1;
-  }
-
-  std::array<EGLint, 4> config_rgba;
-  for (int i = 0; i < num_configs; i++) {
-    eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE, &config_rgba[0]);
-    eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &config_rgba[1]);
-    eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE, &config_rgba[2]);
-    eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &config_rgba[3]);
-    if (config_rgba == desired_rgba) {
-      *config = configs[i];
-      return 0;
-    }
-  }
-
-  ALOGE("Cannot find a matching EGL config");
-  return -1;
-}
-
-void DestroyEglContext(EGLDisplay egl_display, EGLContext* egl_context) {
-  if (*egl_context != EGL_NO_CONTEXT) {
-    eglDestroyContext(egl_display, *egl_context);
-    *egl_context = EGL_NO_CONTEXT;
-  }
-}
-
-// Perform internal initialization. A GL context must be bound to the current
-// thread.
-// @param internally_created_context True if we created and own the GL context,
-//        false if it was supplied by the application.
-// @return 0 if init was successful, or a negative error code on failure.
-int InitGl(bool internally_created_context) {
-  EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  if (egl_display == EGL_NO_DISPLAY) {
-    ALOGE("eglGetDisplay failed");
-    return -EINVAL;
-  }
-
-  EGLContext egl_context = eglGetCurrentContext();
-  if (egl_context == EGL_NO_CONTEXT) {
-    ALOGE("No GL context bound");
-    return -EINVAL;
-  }
-
-  glGetError();  // Clear the error state
-  GLint major_version, minor_version;
-  glGetIntegerv(GL_MAJOR_VERSION, &major_version);
-  glGetIntegerv(GL_MINOR_VERSION, &minor_version);
-  if (glGetError() != GL_NO_ERROR) {
-    // GL_MAJOR_VERSION and GL_MINOR_VERSION were added in GLES 3. If we get an
-    // error querying them it's almost certainly because it's GLES 1 or 2.
-    ALOGE("Error getting GL version. Must be GLES 3.2 or greater.");
-    return -EINVAL;
-  }
-
-  if (major_version < 3 || (major_version == 3 && minor_version < 2)) {
-    ALOGE("Invalid GL version: %d.%d. Must be GLES 3.2 or greater.",
-          major_version, minor_version);
-    return -EINVAL;
-  }
-
-#ifndef NDEBUG
-  if (internally_created_context) {
-    // Enable verbose GL debug output.
-    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
-    glDebugMessageCallbackKHR(on_gl_error, NULL);
-    GLuint unused_ids = 0;
-    glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0,
-                             &unused_ids, GL_TRUE);
-  }
-#else
-  (void)internally_created_context;
-#endif
-
-  load_gl_extensions();
-  return 0;
-}
-
-int CreateEglContext(EGLDisplay egl_display, DvrSurfaceParameter* parameters,
-                     EGLContext* egl_context) {
-  *egl_context = EGL_NO_CONTEXT;
-
-  EGLint major, minor;
-  if (!eglInitialize(egl_display, &major, &minor)) {
-    ALOGE("Failed to initialize EGL");
-    return -ENXIO;
-  }
-
-  ALOGI("EGL version: %d.%d\n", major, minor);
-
-  int buffer_format = kDefaultDisplaySurfaceFormat;
-
-  for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
-    switch (p->key) {
-      case DVR_SURFACE_PARAMETER_FORMAT_IN:
-        buffer_format = DvrToHalSurfaceFormat(p->value);
-        break;
-    }
-  }
-
-  EGLint config_attrs[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-                           EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE};
-  EGLConfig config = {0};
-
-  int ret = SelectEGLConfig(egl_display, config_attrs, buffer_format, &config);
-  if (ret < 0)
-    return ret;
-
-  ALOGI("EGL SelectEGLConfig ok.\n");
-
-  EGLint context_attrs[] = {EGL_CONTEXT_MAJOR_VERSION,
-                            3,
-                            EGL_CONTEXT_MINOR_VERSION,
-                            2,
-#ifndef NDEBUG
-                            EGL_CONTEXT_FLAGS_KHR,
-                            EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR,
-#endif
-                            EGL_NONE};
-
-  *egl_context =
-      eglCreateContext(egl_display, config, EGL_NO_CONTEXT, context_attrs);
-  if (*egl_context == EGL_NO_CONTEXT) {
-    ALOGE("eglCreateContext failed");
-    return -ENXIO;
-  }
-
-  ALOGI("eglCreateContext ok.\n");
-
-  if (!eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
-                      *egl_context)) {
-    ALOGE("eglMakeCurrent failed");
-    DestroyEglContext(egl_display, egl_context);
-    return -EINVAL;
-  }
-
-  return 0;
-}
-
-// Utility structure to hold info related to creating a surface.
-struct SurfaceResult {
-  std::shared_ptr<Surface> surface;
-  Metrics metrics;
-  uint32_t width;
-  uint32_t height;
-  uint32_t format;
-  uint64_t usage;
-  size_t capacity;
-  int geometry;
-  bool direct_surface;
-};
-
-Status<std::tuple<std::shared_ptr<android::dvr::ProducerQueue>,
-                  std::shared_ptr<android::dvr::BufferProducer>,
-                  volatile DisplaySurfaceMetadata*>>
-CreateMetadataBuffer(const std::shared_ptr<Surface>& surface,
-                     bool direct_surface) {
-  std::shared_ptr<android::dvr::ProducerQueue> queue;
-  std::shared_ptr<android::dvr::BufferProducer> buffer;
-
-  if (!direct_surface) {
-    auto queue_status = surface->CreateQueue(
-        sizeof(DisplaySurfaceMetadata), 1, 1, HAL_PIXEL_FORMAT_BLOB,
-        GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET |
-            GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN |
-            GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER,
-        1);
-    if (!queue_status) {
-      ALOGE("CreateMetadataBuffer: Failed to create queue: %s",
-            queue_status.GetErrorMessage().c_str());
-      return queue_status.error_status();
-    }
-
-    queue = queue_status.take();
-    LocalHandle fence;
-    size_t slot;
-    auto buffer_status = queue->Dequeue(-1, &slot, &fence);
-    if (!buffer_status) {
-      ALOGE("CreateMetadataBuffer: Failed to dequeue buffer: %s",
-            buffer_status.GetErrorMessage().c_str());
-      return buffer_status.error_status();
-    }
-    buffer = buffer_status.take();
-  } else {
-    buffer = android::dvr::BufferProducer::CreateUncachedBlob(
-        sizeof(DisplaySurfaceMetadata));
-    if (!buffer) {
-      ALOGE("CreateMetadataBuffer: Failed to create stand-in buffer!");
-      return ErrorStatus(ENOMEM);
-    }
-  }
-
-  void* address = nullptr;
-  int ret =
-      buffer->GetBlobReadWritePointer(sizeof(DisplaySurfaceMetadata), &address);
-
-  if (ret < 0) {
-    ALOGE("CreateMetadataBuffer: Failed to map buffer: %s", strerror(-ret));
-    return ErrorStatus(-ret);
-  }
-
-  // Post the buffer so that the compositor can retrieve it from the consumer
-  // queue.
-  ret = buffer->Post<void>(LocalHandle{});
-  if (ret < 0) {
-    ALOGE("CreateMetadataBuffer: Failed to post buffer: %s", strerror(-ret));
-    return ErrorStatus(-ret);
-  }
-
-  ALOGD_IF(TRACE, "CreateMetadataBuffer: queue_id=%d buffer_id=%d address=%p",
-           queue ? queue->id() : -1, buffer->id(), address);
-  return {{std::move(queue), std::move(buffer),
-           static_cast<DisplaySurfaceMetadata*>(address)}};
-}
-
-}  // anonymous namespace
-
-Status<SurfaceResult> CreateSurface(struct DvrSurfaceParameter* parameters) {
-  int error;
-  auto client = DisplayClient::Create(&error);
-  if (!client) {
-    ALOGE("CreateApplicationSurface: Failed to create display client!");
-    return ErrorStatus(error);
-  }
-
-  auto metrics_status = client->GetDisplayMetrics();
-  if (!metrics_status) {
-    ALOGE("CreateApplicationSurface: Failed to get display metrics: %s",
-          metrics_status.GetErrorMessage().c_str());
-    return metrics_status.error_status();
-  }
-
-  // Parameters that may be modified by the parameters array. Some of these are
-  // here for future expansion.
-
-  uint32_t request_width = metrics_status.get().display_width;
-  uint32_t request_height = metrics_status.get().display_width;
-  uint32_t request_format = kDefaultDisplaySurfaceFormat;
-  uint64_t request_usage = kDefaultDisplaySurfaceUsage;
-  size_t request_capacity = kDefaultBufferCount;
-  int request_geometry = DVR_SURFACE_GEOMETRY_SINGLE;
-  bool disable_distortion = false;
-  bool disable_stabilization = false;
-  bool disable_cac = false;
-  bool request_visible = false;
-  bool vertical_flip = false;
-  bool direct_surface = false;
-  int request_z_order = 0;
-
-  // Handle parameter inputs.
-  for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
-    switch (p->key) {
-      case DVR_SURFACE_PARAMETER_DISABLE_DISTORTION_IN:
-        disable_distortion = !!p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_DISABLE_STABILIZATION_IN:
-        disable_stabilization = !!p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_DISABLE_CAC_IN:
-        disable_cac = !!p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_VISIBLE_IN:
-        request_visible = !!p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_Z_ORDER_IN:
-        request_z_order = p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_VERTICAL_FLIP_IN:
-        vertical_flip = !!p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_DIRECT_IN:
-        direct_surface = !!p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_WIDTH_IN:
-        request_width = p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_HEIGHT_IN:
-        request_height = p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_FORMAT_IN:
-        request_format = p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_GEOMETRY_IN:
-        request_geometry = p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_ENABLE_LATE_LATCH_IN:
-      case DVR_SURFACE_PARAMETER_CREATE_GL_CONTEXT_IN:
-      case DVR_SURFACE_PARAMETER_DISPLAY_WIDTH_OUT:
-      case DVR_SURFACE_PARAMETER_DISPLAY_HEIGHT_OUT:
-      case DVR_SURFACE_PARAMETER_SURFACE_WIDTH_OUT:
-      case DVR_SURFACE_PARAMETER_SURFACE_HEIGHT_OUT:
-      case DVR_SURFACE_PARAMETER_INTER_LENS_METERS_OUT:
-      case DVR_SURFACE_PARAMETER_LEFT_FOV_LRBT_OUT:
-      case DVR_SURFACE_PARAMETER_RIGHT_FOV_LRBT_OUT:
-      case DVR_SURFACE_PARAMETER_VSYNC_PERIOD_OUT:
-      case DVR_SURFACE_PARAMETER_SURFACE_TEXTURE_TARGET_TYPE_OUT:
-      case DVR_SURFACE_PARAMETER_SURFACE_TEXTURE_TARGET_ID_OUT:
-      case DVR_SURFACE_PARAMETER_GRAPHICS_API_IN:
-      case DVR_SURFACE_PARAMETER_VK_INSTANCE_IN:
-      case DVR_SURFACE_PARAMETER_VK_PHYSICAL_DEVICE_IN:
-      case DVR_SURFACE_PARAMETER_VK_DEVICE_IN:
-      case DVR_SURFACE_PARAMETER_VK_PRESENT_QUEUE_IN:
-      case DVR_SURFACE_PARAMETER_VK_PRESENT_QUEUE_FAMILY_IN:
-      case DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_COUNT_OUT:
-      case DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_FORMAT_OUT:
-        break;
-      default:
-        ALOGE(
-            "CreateSurface: Invalid display surface parameter: key=%d "
-            "value=%" PRId64,
-            p->key, p->value);
-        return ErrorStatus(EINVAL);
-    }
-  }
-
-  // TODO(eieio): Setup a "surface flags" attribute based on the surface
-  // parameters gathered above.
-  SurfaceAttributes surface_attributes;
-
-  surface_attributes[SurfaceAttribute::Direct] = direct_surface;
-  surface_attributes[SurfaceAttribute::Visible] = request_visible;
-  surface_attributes[SurfaceAttribute::ZOrder] = request_z_order;
-
-  auto surface_status = Surface::CreateSurface(surface_attributes);
-  if (!surface_status) {
-    ALOGE("CreateSurface: Failed to create surface: %s",
-          surface_status.GetErrorMessage().c_str());
-    return surface_status.error_status();
-  }
-
-  return {{surface_status.take(), metrics_status.get(), request_width,
-           request_height, request_format, request_usage, request_capacity,
-           request_geometry, direct_surface}};
-}
-
-// TODO(hendrikw): When we remove the calls to this in native_window.cpp, move
-// this back into the anonymous namespace
-Status<SurfaceResult> CreateApplicationSurface(
-    struct DvrSurfaceParameter* parameters) {
-  auto surface_status = CreateSurface(parameters);
-  if (!surface_status)
-    return surface_status;
-
-  // Handle parameter output requests down here so we can return surface info.
-  for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
-    switch (p->key) {
-      case DVR_SURFACE_PARAMETER_DISPLAY_WIDTH_OUT:
-        *static_cast<int32_t*>(p->value_out) =
-            surface_status.get().metrics.display_width;
-        break;
-      case DVR_SURFACE_PARAMETER_DISPLAY_HEIGHT_OUT:
-        *static_cast<int32_t*>(p->value_out) =
-            surface_status.get().metrics.display_height;
-        break;
-      case DVR_SURFACE_PARAMETER_VSYNC_PERIOD_OUT:
-        *static_cast<uint64_t*>(p->value_out) =
-            surface_status.get().metrics.vsync_period_ns;
-        break;
-      case DVR_SURFACE_PARAMETER_SURFACE_WIDTH_OUT:
-        *static_cast<uint32_t*>(p->value_out) = surface_status.get().width;
-        break;
-      case DVR_SURFACE_PARAMETER_SURFACE_HEIGHT_OUT:
-        *static_cast<uint32_t*>(p->value_out) = surface_status.get().height;
-        break;
-
-      default:
-        break;
-    }
-  }
-
-  return surface_status;
-}
-
-extern "C" int dvrGetNativeDisplayDimensions(int* display_width,
-                                             int* display_height) {
-  int error = 0;
-  auto client = DisplayClient::Create(&error);
-  if (!client) {
-    ALOGE("dvrGetNativeDisplayDimensions: Failed to create display client!");
-    return -error;
-  }
-
-  auto metrics_status = client->GetDisplayMetrics();
-  if (!metrics_status) {
-    ALOGE("dvrGetNativeDisplayDimensions: Failed to get display metrics: %s",
-          metrics_status.GetErrorMessage().c_str());
-    return -metrics_status.error();
-  }
-
-  *display_width = static_cast<int>(metrics_status.get().display_width);
-  *display_height = static_cast<int>(metrics_status.get().display_height);
-  return 0;
-}
-
-struct DvrGraphicsContext : public android::ANativeObjectBase<
-                                ANativeWindow, DvrGraphicsContext,
-                                android::LightRefBase<DvrGraphicsContext>> {
- public:
-  DvrGraphicsContext();
-  ~DvrGraphicsContext();
-
-  int graphics_api;  // DVR_SURFACE_GRAPHICS_API_*
-
-  // GL specific members.
-  struct {
-    EGLDisplay egl_display;
-    EGLContext egl_context;
-    bool owns_egl_context;
-    GLuint texture_id[kSurfaceViewMaxCount];
-    int texture_count;
-    GLenum texture_target_type;
-  } gl;
-
-  // VK specific members
-  struct {
-    // These objects are passed in by the application, and are NOT owned
-    // by the context.
-    VkInstance instance;
-    VkPhysicalDevice physical_device;
-    VkDevice device;
-    VkQueue present_queue;
-    uint32_t present_queue_family;
-    const VkAllocationCallbacks* allocation_callbacks;
-    // These objects are owned by the context.
-    ANativeWindow* window;
-    VkSurfaceKHR surface;
-    VkSwapchainKHR swapchain;
-    std::vector<VkImage> swapchain_images;
-    std::vector<VkImageView> swapchain_image_views;
-  } vk;
-
-  // Display surface, metrics, and buffer management members.
-  std::shared_ptr<Surface> display_surface;
-  uint32_t width;
-  uint32_t height;
-  uint32_t format;
-  Metrics display_metrics;
-  std::unique_ptr<NativeBufferQueue> buffer_queue;
-  android::dvr::NativeBufferProducer* current_buffer;
-  bool buffer_already_posted;
-
-  // Synchronization members.
-  std::unique_ptr<android::dvr::VSyncClient> vsync_client;
-  LocalHandle timerfd;
-
-  android::dvr::FrameHistory frame_history;
-
-  // Metadata queue and buffer.
-  // TODO(eieio): Remove the queue once one-off buffers are supported as a
-  // surface primitive element.
-  std::shared_ptr<android::dvr::ProducerQueue> metadata_queue;
-  std::shared_ptr<android::dvr::BufferProducer> metadata_buffer;
-  // Mapped surface metadata (ie: for pose delivery with presented frames).
-  volatile DisplaySurfaceMetadata* surface_metadata;
-
-  // LateLatch support.
-  std::unique_ptr<android::dvr::LateLatch> late_latch;
-
- private:
-  // ANativeWindow function implementations
-  std::mutex lock_;
-  int Post(android::dvr::NativeBufferProducer* buffer, int fence_fd);
-  static int SetSwapInterval(ANativeWindow* window, int interval);
-  static int DequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
-                           int* fence_fd);
-  static int QueueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
-                         int fence_fd);
-  static int CancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
-                          int fence_fd);
-  static int Query(const ANativeWindow* window, int what, int* value);
-  static int Perform(ANativeWindow* window, int operation, ...);
-  static int DequeueBuffer_DEPRECATED(ANativeWindow* window,
-                                      ANativeWindowBuffer** buffer);
-  static int CancelBuffer_DEPRECATED(ANativeWindow* window,
-                                     ANativeWindowBuffer* buffer);
-  static int QueueBuffer_DEPRECATED(ANativeWindow* window,
-                                    ANativeWindowBuffer* buffer);
-  static int LockBuffer_DEPRECATED(ANativeWindow* window,
-                                   ANativeWindowBuffer* buffer);
-
-  DvrGraphicsContext(const DvrGraphicsContext&) = delete;
-  void operator=(const DvrGraphicsContext&) = delete;
-};
-
-DvrGraphicsContext::DvrGraphicsContext()
-    : graphics_api(DVR_GRAPHICS_API_GLES),
-      gl{},
-      vk{},
-      current_buffer(nullptr),
-      buffer_already_posted(false),
-      surface_metadata(nullptr) {
-  gl.egl_display = EGL_NO_DISPLAY;
-  gl.egl_context = EGL_NO_CONTEXT;
-  gl.owns_egl_context = true;
-  gl.texture_target_type = GL_TEXTURE_2D;
-
-  ANativeWindow::setSwapInterval = SetSwapInterval;
-  ANativeWindow::dequeueBuffer = DequeueBuffer;
-  ANativeWindow::cancelBuffer = CancelBuffer;
-  ANativeWindow::queueBuffer = QueueBuffer;
-  ANativeWindow::query = Query;
-  ANativeWindow::perform = Perform;
-
-  ANativeWindow::dequeueBuffer_DEPRECATED = DequeueBuffer_DEPRECATED;
-  ANativeWindow::cancelBuffer_DEPRECATED = CancelBuffer_DEPRECATED;
-  ANativeWindow::lockBuffer_DEPRECATED = LockBuffer_DEPRECATED;
-  ANativeWindow::queueBuffer_DEPRECATED = QueueBuffer_DEPRECATED;
-}
-
-DvrGraphicsContext::~DvrGraphicsContext() {
-  if (graphics_api == DVR_GRAPHICS_API_GLES) {
-    glDeleteTextures(gl.texture_count, gl.texture_id);
-    if (gl.owns_egl_context)
-      DestroyEglContext(gl.egl_display, &gl.egl_context);
-  } else if (graphics_api == DVR_GRAPHICS_API_VULKAN) {
-    if (vk.swapchain != VK_NULL_HANDLE) {
-      for (auto view : vk.swapchain_image_views) {
-        vkDestroyImageView(vk.device, view, vk.allocation_callbacks);
-      }
-      vkDestroySwapchainKHR(vk.device, vk.swapchain, vk.allocation_callbacks);
-      vkDestroySurfaceKHR(vk.instance, vk.surface, vk.allocation_callbacks);
-      delete vk.window;
-    }
-  }
-}
-
-int dvrGraphicsContextCreate(struct DvrSurfaceParameter* parameters,
-                             DvrGraphicsContext** return_graphics_context) {
-  auto context = std::make_unique<DvrGraphicsContext>();
-
-  // See whether we're using GL or Vulkan
-  for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
-    switch (p->key) {
-      case DVR_SURFACE_PARAMETER_GRAPHICS_API_IN:
-        context->graphics_api = p->value;
-        break;
-    }
-  }
-
-  if (context->graphics_api == DVR_GRAPHICS_API_GLES) {
-    context->gl.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    if (context->gl.egl_display == EGL_NO_DISPLAY) {
-      ALOGE("eglGetDisplay failed");
-      return -ENXIO;
-    }
-
-    // See if we should create a GL context
-    for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
-      switch (p->key) {
-        case DVR_SURFACE_PARAMETER_CREATE_GL_CONTEXT_IN:
-          context->gl.owns_egl_context = p->value != 0;
-          break;
-      }
-    }
-
-    if (context->gl.owns_egl_context) {
-      int ret = CreateEglContext(context->gl.egl_display, parameters,
-                                 &context->gl.egl_context);
-      if (ret < 0)
-        return ret;
-    } else {
-      context->gl.egl_context = eglGetCurrentContext();
-    }
-
-    int ret = InitGl(context->gl.owns_egl_context);
-    if (ret < 0)
-      return ret;
-  } else if (context->graphics_api == DVR_GRAPHICS_API_VULKAN) {
-    for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
-      switch (p->key) {
-        case DVR_SURFACE_PARAMETER_VK_INSTANCE_IN:
-          context->vk.instance = reinterpret_cast<VkInstance>(p->value);
-          break;
-        case DVR_SURFACE_PARAMETER_VK_PHYSICAL_DEVICE_IN:
-          context->vk.physical_device =
-              reinterpret_cast<VkPhysicalDevice>(p->value);
-          break;
-        case DVR_SURFACE_PARAMETER_VK_DEVICE_IN:
-          context->vk.device = reinterpret_cast<VkDevice>(p->value);
-          break;
-        case DVR_SURFACE_PARAMETER_VK_PRESENT_QUEUE_IN:
-          context->vk.present_queue = reinterpret_cast<VkQueue>(p->value);
-          break;
-        case DVR_SURFACE_PARAMETER_VK_PRESENT_QUEUE_FAMILY_IN:
-          context->vk.present_queue_family = static_cast<uint32_t>(p->value);
-          break;
-      }
-    }
-  } else {
-    ALOGE("Error: invalid graphics API type");
-    return -EINVAL;
-  }
-
-  auto surface_status = CreateApplicationSurface(parameters);
-  if (!surface_status) {
-    ALOGE("dvrGraphicsContextCreate: Failed to create surface: %s",
-          surface_status.GetErrorMessage().c_str());
-    return -surface_status.error();
-  }
-
-  auto surface_result = surface_status.take();
-
-  context->display_surface = surface_result.surface;
-  context->display_metrics = surface_result.metrics;
-  context->width = surface_result.width;
-  context->height = surface_result.height;
-  context->format = surface_result.format;
-
-  // Create an empty queue. NativeBufferQueue allocates the buffers for this
-  // queue.
-  auto queue_status = context->display_surface->CreateQueue();
-  if (!queue_status) {
-    ALOGE("dvrGraphicsContextCreate: Failed to create queue: %s",
-          queue_status.GetErrorMessage().c_str());
-    return -queue_status.error();
-  }
-
-  context->buffer_queue.reset(new NativeBufferQueue(
-      context->gl.egl_display, queue_status.take(), surface_result.width,
-      surface_result.height, surface_result.format, surface_result.usage,
-      surface_result.capacity));
-
-  // Create the metadata buffer.
-  auto metadata_status = CreateMetadataBuffer(context->display_surface,
-                                              surface_result.direct_surface);
-  if (!metadata_status) {
-    ALOGE("dvrGraphicsContextCreate: Failed to create metadata buffer: %s",
-          metadata_status.GetErrorMessage().c_str());
-    return -metadata_status.error();
-  }
-  std::tie(context->metadata_queue, context->metadata_buffer,
-           context->surface_metadata) = metadata_status.take();
-
-  // The way the call sequence works we need 1 more than the buffer queue
-  // capacity to store data for all pending frames
-  context->frame_history.Reset(context->buffer_queue->capacity() + 1);
-
-  context->vsync_client = VSyncClient::Create();
-  if (!context->vsync_client) {
-    ALOGE("dvrGraphicsContextCreate: failed to create vsync client");
-    return -ECOMM;
-  }
-
-  context->timerfd.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
-  if (!context->timerfd) {
-    ALOGE("dvrGraphicsContextCreate: timerfd_create failed because: %s",
-          strerror(errno));
-    return -EPERM;
-  }
-
-  if (context->graphics_api == DVR_GRAPHICS_API_GLES) {
-    context->gl.texture_count =
-        (surface_result.geometry == DVR_SURFACE_GEOMETRY_SEPARATE_2) ? 2 : 1;
-
-    // Create the GL textures.
-    glGenTextures(context->gl.texture_count, context->gl.texture_id);
-
-    // We must make sure that we have at least one buffer allocated at this time
-    // so that anyone who tries to bind an FBO to context->texture_id
-    // will not get an incomplete buffer.
-    context->current_buffer = context->buffer_queue->Dequeue();
-    LOG_ALWAYS_FATAL_IF(context->gl.texture_count != 1);
-    for (int i = 0; i < context->gl.texture_count; ++i) {
-      glBindTexture(context->gl.texture_target_type, context->gl.texture_id[i]);
-      glEGLImageTargetTexture2DOES(context->gl.texture_target_type,
-                                   context->current_buffer->image_khr(i));
-    }
-    glBindTexture(context->gl.texture_target_type, 0);
-    CHECK_GL();
-
-    bool is_late_latch = false;
-
-    // Pass back the texture target type and id.
-    for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
-      switch (p->key) {
-        case DVR_SURFACE_PARAMETER_ENABLE_LATE_LATCH_IN:
-          is_late_latch = !!p->value;
-          break;
-        case DVR_SURFACE_PARAMETER_SURFACE_TEXTURE_TARGET_TYPE_OUT:
-          *static_cast<GLenum*>(p->value_out) = context->gl.texture_target_type;
-          break;
-        case DVR_SURFACE_PARAMETER_SURFACE_TEXTURE_TARGET_ID_OUT:
-          for (int i = 0; i < context->gl.texture_count; ++i) {
-            *(static_cast<GLuint*>(p->value_out) + i) =
-                context->gl.texture_id[i];
-          }
-          break;
-      }
-    }
-
-    // Initialize late latch.
-    if (is_late_latch) {
-      LocalHandle fd = context->metadata_buffer->GetBlobFd();
-      context->late_latch.reset(
-          new android::dvr::LateLatch(true, std::move(fd)));
-    }
-  } else if (context->graphics_api == DVR_GRAPHICS_API_VULKAN) {
-    VkResult result = VK_SUCCESS;
-    // Create a VkSurfaceKHR from the ANativeWindow.
-    VkAndroidSurfaceCreateInfoKHR android_surface_ci = {};
-    android_surface_ci.sType =
-        VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
-    android_surface_ci.window = context.get();
-    result = vkCreateAndroidSurfaceKHR(
-        context->vk.instance, &android_surface_ci,
-        context->vk.allocation_callbacks, &context->vk.surface);
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    VkBool32 surface_supports_present = VK_FALSE;
-    result = vkGetPhysicalDeviceSurfaceSupportKHR(
-        context->vk.physical_device, context->vk.present_queue_family,
-        context->vk.surface, &surface_supports_present);
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    if (!surface_supports_present) {
-      ALOGE("Error: provided queue family (%u) does not support presentation",
-            context->vk.present_queue_family);
-      return -EPERM;
-    }
-    VkSurfaceCapabilitiesKHR surface_capabilities = {};
-    result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
-        context->vk.physical_device, context->vk.surface,
-        &surface_capabilities);
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    // Determine the swapchain image format.
-    uint32_t device_surface_format_count = 0;
-    result = vkGetPhysicalDeviceSurfaceFormatsKHR(
-        context->vk.physical_device, context->vk.surface,
-        &device_surface_format_count, nullptr);
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    std::vector<VkSurfaceFormatKHR> device_surface_formats(
-        device_surface_format_count);
-    result = vkGetPhysicalDeviceSurfaceFormatsKHR(
-        context->vk.physical_device, context->vk.surface,
-        &device_surface_format_count, device_surface_formats.data());
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    LOG_ALWAYS_FATAL_IF(device_surface_format_count == 0U);
-    LOG_ALWAYS_FATAL_IF(device_surface_formats[0].format ==
-                        VK_FORMAT_UNDEFINED);
-    VkSurfaceFormatKHR present_surface_format = device_surface_formats[0];
-    // Determine the swapchain present mode.
-    // TODO(cort): query device_present_modes to make sure MAILBOX is supported.
-    // But according to libvulkan, it is.
-    uint32_t device_present_mode_count = 0;
-    result = vkGetPhysicalDeviceSurfacePresentModesKHR(
-        context->vk.physical_device, context->vk.surface,
-        &device_present_mode_count, nullptr);
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    std::vector<VkPresentModeKHR> device_present_modes(
-        device_present_mode_count);
-    result = vkGetPhysicalDeviceSurfacePresentModesKHR(
-        context->vk.physical_device, context->vk.surface,
-        &device_present_mode_count, device_present_modes.data());
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    VkPresentModeKHR present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
-    // Extract presentation surface extents, image count, transform, usages,
-    // etc.
-    LOG_ALWAYS_FATAL_IF(
-        static_cast<int>(surface_capabilities.currentExtent.width) == -1 ||
-        static_cast<int>(surface_capabilities.currentExtent.height) == -1);
-    VkExtent2D swapchain_extent = surface_capabilities.currentExtent;
-
-    uint32_t desired_image_count = surface_capabilities.minImageCount;
-    if (surface_capabilities.maxImageCount > 0 &&
-        desired_image_count > surface_capabilities.maxImageCount) {
-      desired_image_count = surface_capabilities.maxImageCount;
-    }
-    VkSurfaceTransformFlagBitsKHR surface_transform =
-        surface_capabilities.currentTransform;
-    VkImageUsageFlags image_usage_flags =
-        surface_capabilities.supportedUsageFlags;
-    LOG_ALWAYS_FATAL_IF(surface_capabilities.supportedCompositeAlpha ==
-                        static_cast<VkFlags>(0));
-    VkCompositeAlphaFlagBitsKHR composite_alpha =
-        VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
-    if (!(surface_capabilities.supportedCompositeAlpha &
-          VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)) {
-      composite_alpha = VkCompositeAlphaFlagBitsKHR(
-          static_cast<int>(surface_capabilities.supportedCompositeAlpha) &
-          -static_cast<int>(surface_capabilities.supportedCompositeAlpha));
-    }
-    // Create VkSwapchainKHR
-    VkSwapchainCreateInfoKHR swapchain_ci = {};
-    swapchain_ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
-    swapchain_ci.pNext = nullptr;
-    swapchain_ci.surface = context->vk.surface;
-    swapchain_ci.minImageCount = desired_image_count;
-    swapchain_ci.imageFormat = present_surface_format.format;
-    swapchain_ci.imageColorSpace = present_surface_format.colorSpace;
-    swapchain_ci.imageExtent.width = swapchain_extent.width;
-    swapchain_ci.imageExtent.height = swapchain_extent.height;
-    swapchain_ci.imageUsage = image_usage_flags;
-    swapchain_ci.preTransform = surface_transform;
-    swapchain_ci.compositeAlpha = composite_alpha;
-    swapchain_ci.imageArrayLayers = 1;
-    swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
-    swapchain_ci.queueFamilyIndexCount = 0;
-    swapchain_ci.pQueueFamilyIndices = nullptr;
-    swapchain_ci.presentMode = present_mode;
-    swapchain_ci.clipped = VK_TRUE;
-    swapchain_ci.oldSwapchain = VK_NULL_HANDLE;
-    result = vkCreateSwapchainKHR(context->vk.device, &swapchain_ci,
-                                  context->vk.allocation_callbacks,
-                                  &context->vk.swapchain);
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    // Create swapchain image views
-    uint32_t image_count = 0;
-    result = vkGetSwapchainImagesKHR(context->vk.device, context->vk.swapchain,
-                                     &image_count, nullptr);
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    LOG_ALWAYS_FATAL_IF(image_count == 0U);
-    context->vk.swapchain_images.resize(image_count);
-    result = vkGetSwapchainImagesKHR(context->vk.device, context->vk.swapchain,
-                                     &image_count,
-                                     context->vk.swapchain_images.data());
-    LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    context->vk.swapchain_image_views.resize(image_count);
-    VkImageViewCreateInfo image_view_ci = {};
-    image_view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
-    image_view_ci.pNext = nullptr;
-    image_view_ci.flags = 0;
-    image_view_ci.format = swapchain_ci.imageFormat;
-    image_view_ci.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
-    image_view_ci.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
-    image_view_ci.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
-    image_view_ci.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
-    image_view_ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-    image_view_ci.subresourceRange.baseMipLevel = 0;
-    image_view_ci.subresourceRange.levelCount = 1;
-    image_view_ci.subresourceRange.baseArrayLayer = 0;
-    image_view_ci.subresourceRange.layerCount = 1;
-    image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
-    image_view_ci.image = VK_NULL_HANDLE;  // filled in below
-    for (uint32_t i = 0; i < image_count; ++i) {
-      image_view_ci.image = context->vk.swapchain_images[i];
-      result = vkCreateImageView(context->vk.device, &image_view_ci,
-                                 context->vk.allocation_callbacks,
-                                 &context->vk.swapchain_image_views[i]);
-      LOG_ALWAYS_FATAL_IF(result != VK_SUCCESS);
-    }
-    // Fill in any requested output parameters.
-    for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
-      switch (p->key) {
-        case DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_COUNT_OUT:
-          *static_cast<uint32_t*>(p->value_out) = image_count;
-          break;
-        case DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_FORMAT_OUT:
-          *static_cast<VkFormat*>(p->value_out) = swapchain_ci.imageFormat;
-          break;
-      }
-    }
-  }
-
-  *return_graphics_context = context.release();
-  return 0;
-}
-
-void dvrGraphicsContextDestroy(DvrGraphicsContext* graphics_context) {
-  delete graphics_context;
-}
-
-// ANativeWindow function implementations. These should only be used
-// by the Vulkan path.
-int DvrGraphicsContext::Post(android::dvr::NativeBufferProducer* buffer,
-                             int fence_fd) {
-  LOG_ALWAYS_FATAL_IF(graphics_api != DVR_GRAPHICS_API_VULKAN);
-  ATRACE_NAME(__PRETTY_FUNCTION__);
-  ALOGI_IF(TRACE, "DvrGraphicsContext::Post: buffer_id=%d, fence_fd=%d",
-           buffer->buffer()->id(), fence_fd);
-  ALOGW_IF(!display_surface->visible(),
-           "DvrGraphicsContext::Post: Posting buffer on invisible surface!!!");
-  // The NativeBufferProducer closes the fence fd, so dup it for tracking in the
-  // frame history.
-  frame_history.OnFrameSubmit(LocalHandle::AsDuplicate(fence_fd));
-  int result = buffer->Post(fence_fd, 0);
-  return result;
-}
-
-int DvrGraphicsContext::SetSwapInterval(ANativeWindow* window, int interval) {
-  ALOGI_IF(TRACE, "SetSwapInterval: window=%p interval=%d", window, interval);
-  DvrGraphicsContext* self = getSelf(window);
-  (void)self;
-  LOG_ALWAYS_FATAL_IF(self->graphics_api != DVR_GRAPHICS_API_VULKAN);
-  return android::NO_ERROR;
-}
-
-int DvrGraphicsContext::DequeueBuffer(ANativeWindow* window,
-                                      ANativeWindowBuffer** buffer,
-                                      int* fence_fd) {
-  ATRACE_NAME(__PRETTY_FUNCTION__);
-
-  DvrGraphicsContext* self = getSelf(window);
-  LOG_ALWAYS_FATAL_IF(self->graphics_api != DVR_GRAPHICS_API_VULKAN);
-  std::lock_guard<std::mutex> autolock(self->lock_);
-
-  if (!self->current_buffer) {
-    self->current_buffer = self->buffer_queue->Dequeue();
-  }
-  ATRACE_ASYNC_BEGIN("BufferDraw", self->current_buffer->buffer()->id());
-  *fence_fd = self->current_buffer->ClaimReleaseFence().Release();
-  *buffer = self->current_buffer;
-
-  ALOGI_IF(TRACE, "DvrGraphicsContext::DequeueBuffer: fence_fd=%d", *fence_fd);
-  return android::NO_ERROR;
-}
-
-int DvrGraphicsContext::QueueBuffer(ANativeWindow* window,
-                                    ANativeWindowBuffer* buffer, int fence_fd) {
-  ATRACE_NAME("NativeWindow::QueueBuffer");
-  ALOGI_IF(TRACE, "NativeWindow::QueueBuffer: fence_fd=%d", fence_fd);
-
-  DvrGraphicsContext* self = getSelf(window);
-  LOG_ALWAYS_FATAL_IF(self->graphics_api != DVR_GRAPHICS_API_VULKAN);
-  std::lock_guard<std::mutex> autolock(self->lock_);
-
-  android::dvr::NativeBufferProducer* native_buffer =
-      static_cast<android::dvr::NativeBufferProducer*>(buffer);
-  ATRACE_ASYNC_END("BufferDraw", native_buffer->buffer()->id());
-  bool do_post = true;
-  if (self->buffer_already_posted) {
-    // Check that the buffer is the one we expect, but handle it if this happens
-    // in production by allowing this buffer to post on top of the previous one.
-    LOG_FATAL_IF(native_buffer != self->current_buffer);
-    if (native_buffer == self->current_buffer) {
-      do_post = false;
-      if (fence_fd >= 0)
-        close(fence_fd);
-    }
-  }
-  if (do_post) {
-    ATRACE_ASYNC_BEGIN("BufferPost", native_buffer->buffer()->id());
-    self->Post(native_buffer, fence_fd);
-  }
-  self->buffer_already_posted = false;
-  self->current_buffer = nullptr;
-
-  return android::NO_ERROR;
-}
-
-int DvrGraphicsContext::CancelBuffer(ANativeWindow* window,
-                                     ANativeWindowBuffer* buffer,
-                                     int fence_fd) {
-  ATRACE_NAME("DvrGraphicsContext::CancelBuffer");
-  ALOGI_IF(TRACE, "DvrGraphicsContext::CancelBuffer: fence_fd: %d", fence_fd);
-
-  DvrGraphicsContext* self = getSelf(window);
-  LOG_ALWAYS_FATAL_IF(self->graphics_api != DVR_GRAPHICS_API_VULKAN);
-  std::lock_guard<std::mutex> autolock(self->lock_);
-
-  android::dvr::NativeBufferProducer* native_buffer =
-      static_cast<android::dvr::NativeBufferProducer*>(buffer);
-  ATRACE_ASYNC_END("BufferDraw", native_buffer->buffer()->id());
-  ATRACE_INT("CancelBuffer", native_buffer->buffer()->id());
-  bool do_enqueue = true;
-  if (self->buffer_already_posted) {
-    // Check that the buffer is the one we expect, but handle it if this happens
-    // in production by returning this buffer to the buffer queue.
-    LOG_FATAL_IF(native_buffer != self->current_buffer);
-    if (native_buffer == self->current_buffer) {
-      do_enqueue = false;
-    }
-  }
-  if (do_enqueue) {
-    self->buffer_queue->Enqueue(native_buffer);
-  }
-  if (fence_fd >= 0)
-    close(fence_fd);
-  self->buffer_already_posted = false;
-  self->current_buffer = nullptr;
-
-  return android::NO_ERROR;
-}
-
-int DvrGraphicsContext::Query(const ANativeWindow* window, int what,
-                              int* value) {
-  DvrGraphicsContext* self = getSelf(const_cast<ANativeWindow*>(window));
-  LOG_ALWAYS_FATAL_IF(self->graphics_api != DVR_GRAPHICS_API_VULKAN);
-  std::lock_guard<std::mutex> autolock(self->lock_);
-
-  switch (what) {
-    case NATIVE_WINDOW_WIDTH:
-      *value = self->width;
-      return android::NO_ERROR;
-    case NATIVE_WINDOW_HEIGHT:
-      *value = self->height;
-      return android::NO_ERROR;
-    case NATIVE_WINDOW_FORMAT:
-      *value = self->format;
-      return android::NO_ERROR;
-    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
-      *value = 1;
-      return android::NO_ERROR;
-    case NATIVE_WINDOW_CONCRETE_TYPE:
-      *value = NATIVE_WINDOW_SURFACE;
-      return android::NO_ERROR;
-    case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
-      *value = 1;
-      return android::NO_ERROR;
-    case NATIVE_WINDOW_DEFAULT_WIDTH:
-      *value = self->width;
-      return android::NO_ERROR;
-    case NATIVE_WINDOW_DEFAULT_HEIGHT:
-      *value = self->height;
-      return android::NO_ERROR;
-    case NATIVE_WINDOW_TRANSFORM_HINT:
-      *value = 0;
-      return android::NO_ERROR;
-  }
-
-  *value = 0;
-  return android::BAD_VALUE;
-}
-
-int DvrGraphicsContext::Perform(ANativeWindow* window, int operation, ...) {
-  DvrGraphicsContext* self = getSelf(window);
-  LOG_ALWAYS_FATAL_IF(self->graphics_api != DVR_GRAPHICS_API_VULKAN);
-  std::lock_guard<std::mutex> autolock(self->lock_);
-
-  va_list args;
-  va_start(args, operation);
-
-  // TODO(eieio): The following operations are not used at this time. They are
-  // included here to help document which operations may be useful and what
-  // parameters they take.
-  switch (operation) {
-    case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: {
-      int w = va_arg(args, int);
-      int h = va_arg(args, int);
-      ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: w=%d h=%d", w, h);
-      return android::NO_ERROR;
-    }
-
-    case NATIVE_WINDOW_SET_BUFFERS_FORMAT: {
-      int format = va_arg(args, int);
-      ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_FORMAT: format=%d", format);
-      return android::NO_ERROR;
-    }
-
-    case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: {
-      int transform = va_arg(args, int);
-      ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: transform=%d",
-               transform);
-      return android::NO_ERROR;
-    }
-
-    case NATIVE_WINDOW_SET_USAGE: {
-      int usage = va_arg(args, int);
-      ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_USAGE: usage=%d", usage);
-      return android::NO_ERROR;
-    }
-
-    case NATIVE_WINDOW_CONNECT:
-    case NATIVE_WINDOW_DISCONNECT:
-    case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
-    case NATIVE_WINDOW_API_CONNECT:
-    case NATIVE_WINDOW_API_DISCONNECT:
-      // TODO(eieio): we should implement these
-      return android::NO_ERROR;
-
-    case NATIVE_WINDOW_SET_BUFFER_COUNT: {
-      int buffer_count = va_arg(args, int);
-      ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFER_COUNT: bufferCount=%d",
-               buffer_count);
-      return android::NO_ERROR;
-    }
-    case NATIVE_WINDOW_SET_BUFFERS_DATASPACE: {
-      android_dataspace_t data_space =
-          static_cast<android_dataspace_t>(va_arg(args, int));
-      ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_DATASPACE: dataSpace=%d",
-               data_space);
-      return android::NO_ERROR;
-    }
-    case NATIVE_WINDOW_SET_SCALING_MODE: {
-      int mode = va_arg(args, int);
-      ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_SCALING_MODE: mode=%d", mode);
-      return android::NO_ERROR;
-    }
-
-    case NATIVE_WINDOW_LOCK:
-    case NATIVE_WINDOW_UNLOCK_AND_POST:
-    case NATIVE_WINDOW_SET_CROP:
-    case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
-      return android::INVALID_OPERATION;
-  }
-
-  return android::NAME_NOT_FOUND;
-}
-
-int DvrGraphicsContext::DequeueBuffer_DEPRECATED(ANativeWindow* window,
-                                                 ANativeWindowBuffer** buffer) {
-  int fence_fd = -1;
-  int ret = DequeueBuffer(window, buffer, &fence_fd);
-
-  // wait for fence
-  if (ret == android::NO_ERROR && fence_fd != -1)
-    close(fence_fd);
-
-  return ret;
-}
-
-int DvrGraphicsContext::CancelBuffer_DEPRECATED(ANativeWindow* window,
-                                                ANativeWindowBuffer* buffer) {
-  return CancelBuffer(window, buffer, -1);
-}
-
-int DvrGraphicsContext::QueueBuffer_DEPRECATED(ANativeWindow* window,
-                                               ANativeWindowBuffer* buffer) {
-  return QueueBuffer(window, buffer, -1);
-}
-
-int DvrGraphicsContext::LockBuffer_DEPRECATED(ANativeWindow* /*window*/,
-                                              ANativeWindowBuffer* /*buffer*/) {
-  return android::NO_ERROR;
-}
-// End ANativeWindow implementation
-
-int dvrSetEdsPose(DvrGraphicsContext* graphics_context,
-                  float32x4_t render_pose_orientation,
-                  float32x4_t render_pose_translation) {
-  ATRACE_NAME("dvrSetEdsPose");
-  if (!graphics_context->current_buffer) {
-    ALOGE("dvrBeginRenderFrame must be called before dvrSetEdsPose");
-    return -EPERM;
-  }
-
-  // When late-latching is enabled, the pose buffer is written by the GPU, so
-  // we don't touch it here.
-  float32x4_t is_late_latch = DVR_POSE_LATE_LATCH;
-  if (render_pose_orientation[0] != is_late_latch[0]) {
-    volatile DisplaySurfaceMetadata* data = graphics_context->surface_metadata;
-    uint32_t buffer_index = 0;
-    ALOGE_IF(TRACE, "write pose index %d %f %f", buffer_index,
-             render_pose_orientation[0], render_pose_orientation[1]);
-    data->orientation[buffer_index] = render_pose_orientation;
-    data->translation[buffer_index] = render_pose_translation;
-  }
-
-  return 0;
-}
-
-int dvrBeginRenderFrameEds(DvrGraphicsContext* graphics_context,
-                           float32x4_t render_pose_orientation,
-                           float32x4_t render_pose_translation) {
-  ATRACE_NAME("dvrBeginRenderFrameEds");
-  LOG_ALWAYS_FATAL_IF(graphics_context->graphics_api != DVR_GRAPHICS_API_GLES);
-  CHECK_GL();
-  // Grab a buffer from the queue and set its pose.
-  if (!graphics_context->current_buffer) {
-    graphics_context->current_buffer =
-        graphics_context->buffer_queue->Dequeue();
-  }
-
-  int ret = dvrSetEdsPose(graphics_context, render_pose_orientation,
-                          render_pose_translation);
-  if (ret < 0)
-    return ret;
-
-  ATRACE_ASYNC_BEGIN("BufferDraw",
-                     graphics_context->current_buffer->buffer()->id());
-
-  {
-    ATRACE_NAME("glEGLImageTargetTexture2DOES");
-    // Bind the texture to the latest buffer in the queue.
-    for (int i = 0; i < graphics_context->gl.texture_count; ++i) {
-      glBindTexture(graphics_context->gl.texture_target_type,
-                    graphics_context->gl.texture_id[i]);
-      glEGLImageTargetTexture2DOES(
-          graphics_context->gl.texture_target_type,
-          graphics_context->current_buffer->image_khr(i));
-    }
-    glBindTexture(graphics_context->gl.texture_target_type, 0);
-  }
-  CHECK_GL();
-  return 0;
-}
-
-int dvrBeginRenderFrameEdsVk(DvrGraphicsContext* graphics_context,
-                             float32x4_t render_pose_orientation,
-                             float32x4_t render_pose_translation,
-                             VkSemaphore acquire_semaphore,
-                             VkFence acquire_fence,
-                             uint32_t* swapchain_image_index,
-                             VkImageView* swapchain_image_view) {
-  ATRACE_NAME("dvrBeginRenderFrameEds");
-  LOG_ALWAYS_FATAL_IF(graphics_context->graphics_api !=
-                      DVR_GRAPHICS_API_VULKAN);
-
-  // Acquire a swapchain image. This calls Dequeue() internally.
-  VkResult result = vkAcquireNextImageKHR(
-      graphics_context->vk.device, graphics_context->vk.swapchain, UINT64_MAX,
-      acquire_semaphore, acquire_fence, swapchain_image_index);
-  if (result != VK_SUCCESS)
-    return -EINVAL;
-
-  // Set the pose pose.
-  int ret = dvrSetEdsPose(graphics_context, render_pose_orientation,
-                          render_pose_translation);
-  if (ret < 0)
-    return ret;
-  *swapchain_image_view =
-      graphics_context->vk.swapchain_image_views[*swapchain_image_index];
-  return 0;
-}
-
-int dvrBeginRenderFrame(DvrGraphicsContext* graphics_context) {
-  return dvrBeginRenderFrameEds(graphics_context, DVR_POSE_NO_EDS,
-                                DVR_POSE_NO_EDS);
-}
-int dvrBeginRenderFrameVk(DvrGraphicsContext* graphics_context,
-                          VkSemaphore acquire_semaphore, VkFence acquire_fence,
-                          uint32_t* swapchain_image_index,
-                          VkImageView* swapchain_image_view) {
-  return dvrBeginRenderFrameEdsVk(
-      graphics_context, DVR_POSE_NO_EDS, DVR_POSE_NO_EDS, acquire_semaphore,
-      acquire_fence, swapchain_image_index, swapchain_image_view);
-}
-
-int dvrBeginRenderFrameLateLatch(DvrGraphicsContext* graphics_context,
-                                 uint32_t /*flags*/,
-                                 uint32_t target_vsync_count, int num_views,
-                                 const float** projection_matrices,
-                                 const float** eye_from_head_matrices,
-                                 const float** pose_offset_matrices,
-                                 uint32_t* out_late_latch_buffer_id) {
-  if (!graphics_context->late_latch) {
-    return -EPERM;
-  }
-  if (num_views > DVR_GRAPHICS_SURFACE_MAX_VIEWS) {
-    ALOGE("dvrBeginRenderFrameLateLatch called with too many views.");
-    return -EINVAL;
-  }
-  dvrBeginRenderFrameEds(graphics_context, DVR_POSE_LATE_LATCH,
-                         DVR_POSE_LATE_LATCH);
-  auto& ll = graphics_context->late_latch;
-  // TODO(jbates) Need to change this shader so that it dumps the single
-  // captured pose for both eyes into the display surface metadata buffer at
-  // the right index.
-  android::dvr::LateLatchInput input;
-  memset(&input, 0, sizeof(input));
-  for (int i = 0; i < num_views; ++i) {
-    memcpy(input.proj_mat + i, *(projection_matrices + i), 16 * sizeof(float));
-    memcpy(input.eye_from_head_mat + i, *(eye_from_head_matrices + i),
-           16 * sizeof(float));
-    memcpy(input.pose_offset + i, *(pose_offset_matrices + i),
-           16 * sizeof(float));
-  }
-  input.pose_index =
-      target_vsync_count & android::dvr::kPoseAsyncBufferIndexMask;
-  input.render_pose_index =
-      graphics_context->current_buffer->surface_buffer_index();
-  ll->AddLateLatch(input);
-  *out_late_latch_buffer_id = ll->output_buffer_id();
-  return 0;
-}
-
-extern "C" int dvrGraphicsWaitNextFrame(
-    DvrGraphicsContext* graphics_context, int64_t start_delay_ns,
-    DvrFrameSchedule* out_next_frame_schedule) {
-  start_delay_ns = std::max(start_delay_ns, static_cast<int64_t>(0));
-
-  // We only do one-shot timers:
-  int64_t wake_time_ns = 0;
-
-  uint32_t current_frame_vsync;
-  int64_t current_frame_scheduled_finish_ns;
-  int64_t vsync_period_ns;
-
-  int fetch_schedule_result = graphics_context->vsync_client->GetSchedInfo(
-      &vsync_period_ns, &current_frame_scheduled_finish_ns,
-      &current_frame_vsync);
-  if (fetch_schedule_result == 0) {
-    wake_time_ns = current_frame_scheduled_finish_ns + start_delay_ns;
-    // If the last wakeup time is still in the future, use it instead to avoid
-    // major schedule jumps when applications call WaitNextFrame with
-    // aggressive offsets.
-    int64_t now = android::dvr::GetSystemClockNs();
-    if (android::dvr::TimestampGT(wake_time_ns - vsync_period_ns, now)) {
-      wake_time_ns -= vsync_period_ns;
-      --current_frame_vsync;
-    }
-    // If the next wakeup time is in the past, add a vsync period to keep the
-    // application on schedule.
-    if (android::dvr::TimestampLT(wake_time_ns, now)) {
-      wake_time_ns += vsync_period_ns;
-      ++current_frame_vsync;
-    }
-  } else {
-    ALOGE("Error getting frame schedule because: %s",
-          strerror(-fetch_schedule_result));
-    // Sleep for a vsync period to avoid cascading failure.
-    wake_time_ns = android::dvr::GetSystemClockNs() +
-                   graphics_context->display_metrics.vsync_period_ns;
-  }
-
-  // Adjust nsec to [0..999,999,999].
-  struct itimerspec wake_time;
-  wake_time.it_interval.tv_sec = 0;
-  wake_time.it_interval.tv_nsec = 0;
-  wake_time.it_value = android::dvr::NsToTimespec(wake_time_ns);
-  bool sleep_result =
-      timerfd_settime(graphics_context->timerfd.Get(), TFD_TIMER_ABSTIME,
-                      &wake_time, nullptr) == 0;
-  if (sleep_result) {
-    ATRACE_NAME("sleep");
-    uint64_t expirations = 0;
-    sleep_result = read(graphics_context->timerfd.Get(), &expirations,
-                        sizeof(uint64_t)) == sizeof(uint64_t);
-    if (!sleep_result) {
-      ALOGE("Error: timerfd read failed");
-    }
-  } else {
-    ALOGE("Error: timerfd_settime failed because: %s", strerror(errno));
-  }
-
-  auto& frame_history = graphics_context->frame_history;
-  frame_history.CheckForFinishedFrames();
-  if (fetch_schedule_result == 0) {
-    uint32_t next_frame_vsync =
-        current_frame_vsync +
-        frame_history.PredictNextFrameVsyncInterval(vsync_period_ns);
-    int64_t next_frame_scheduled_finish =
-        (wake_time_ns - start_delay_ns) + vsync_period_ns;
-    frame_history.OnFrameStart(next_frame_vsync, next_frame_scheduled_finish);
-    if (out_next_frame_schedule) {
-      out_next_frame_schedule->vsync_count = next_frame_vsync;
-      out_next_frame_schedule->scheduled_frame_finish_ns =
-          next_frame_scheduled_finish;
-    }
-  } else {
-    frame_history.OnFrameStart(UINT32_MAX, -1);
-  }
-
-  return (fetch_schedule_result == 0 && sleep_result) ? 0 : -1;
-}
-
-extern "C" void dvrGraphicsPostEarly(DvrGraphicsContext* graphics_context) {
-  ATRACE_NAME("dvrGraphicsPostEarly");
-  ALOGI_IF(TRACE, "dvrGraphicsPostEarly");
-
-  LOG_ALWAYS_FATAL_IF(graphics_context->graphics_api != DVR_GRAPHICS_API_GLES);
-
-  // Note that this function can be called before or after
-  // dvrBeginRenderFrame.
-  if (!graphics_context->buffer_already_posted) {
-    graphics_context->buffer_already_posted = true;
-
-    if (!graphics_context->current_buffer) {
-      graphics_context->current_buffer =
-          graphics_context->buffer_queue->Dequeue();
-    }
-
-    auto buffer = graphics_context->current_buffer->buffer().get();
-    ATRACE_ASYNC_BEGIN("BufferPost", buffer->id());
-    int result = buffer->Post<void>(LocalHandle());
-    if (result < 0)
-      ALOGE("Buffer post failed: %d (%s)", result, strerror(-result));
-  }
-}
-
-int dvrPresent(DvrGraphicsContext* graphics_context) {
-  LOG_ALWAYS_FATAL_IF(graphics_context->graphics_api != DVR_GRAPHICS_API_GLES);
-
-  std::array<char, 128> buf;
-  snprintf(buf.data(), buf.size(), "dvrPresent|vsync=%d|",
-           graphics_context->frame_history.GetCurrentFrameVsync());
-  ATRACE_NAME(buf.data());
-
-  if (!graphics_context->current_buffer) {
-    ALOGE("Error: dvrPresent called without dvrBeginRenderFrame");
-    return -EPERM;
-  }
-
-  LocalHandle fence_fd =
-      android::dvr::CreateGLSyncAndFlush(graphics_context->gl.egl_display);
-
-  ALOGI_IF(TRACE, "PostBuffer: buffer_id=%d, fence_fd=%d",
-           graphics_context->current_buffer->buffer()->id(), fence_fd.Get());
-  ALOGW_IF(!graphics_context->display_surface->visible(),
-           "PostBuffer: Posting buffer on invisible surface!!!");
-
-  auto buffer = graphics_context->current_buffer->buffer().get();
-  ATRACE_ASYNC_END("BufferDraw", buffer->id());
-  if (!graphics_context->buffer_already_posted) {
-    ATRACE_ASYNC_BEGIN("BufferPost", buffer->id());
-    int result = buffer->Post<void>(fence_fd);
-    if (result < 0)
-      ALOGE("Buffer post failed: %d (%s)", result, strerror(-result));
-  }
-
-  graphics_context->frame_history.OnFrameSubmit(std::move(fence_fd));
-  graphics_context->buffer_already_posted = false;
-  graphics_context->current_buffer = nullptr;
-  return 0;
-}
-
-int dvrPresentVk(DvrGraphicsContext* graphics_context,
-                 VkSemaphore submit_semaphore, uint32_t swapchain_image_index) {
-  LOG_ALWAYS_FATAL_IF(graphics_context->graphics_api !=
-                      DVR_GRAPHICS_API_VULKAN);
-
-  std::array<char, 128> buf;
-  snprintf(buf.data(), buf.size(), "dvrPresent|vsync=%d|",
-           graphics_context->frame_history.GetCurrentFrameVsync());
-  ATRACE_NAME(buf.data());
-
-  if (!graphics_context->current_buffer) {
-    ALOGE("Error: dvrPresentVk called without dvrBeginRenderFrameVk");
-    return -EPERM;
-  }
-
-  // Present the specified image. Internally, this gets a fence from the
-  // Vulkan driver and passes it to DvrGraphicsContext::Post(),
-  // which in turn passes it to buffer->Post() and adds it to frame_history.
-  VkPresentInfoKHR present_info = {};
-  present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
-  present_info.swapchainCount = 1;
-  present_info.pSwapchains = &graphics_context->vk.swapchain;
-  present_info.pImageIndices = &swapchain_image_index;
-  present_info.waitSemaphoreCount =
-      (submit_semaphore != VK_NULL_HANDLE) ? 1 : 0;
-  present_info.pWaitSemaphores = &submit_semaphore;
-  VkResult result =
-      vkQueuePresentKHR(graphics_context->vk.present_queue, &present_info);
-  if (result != VK_SUCCESS) {
-    return -EINVAL;
-  }
-
-  return 0;
-}
-
-extern "C" int dvrGetFrameScheduleResults(DvrGraphicsContext* context,
-                                          DvrFrameScheduleResult* results,
-                                          int in_result_count) {
-  if (!context || !results)
-    return -EINVAL;
-
-  return context->frame_history.GetPreviousFrameResults(results,
-                                                        in_result_count);
-}
-
-extern "C" void dvrGraphicsSurfaceSetVisible(
-    DvrGraphicsContext* graphics_context, int visible) {
-  graphics_context->display_surface->SetVisible(visible);
-}
-
-extern "C" int dvrGraphicsSurfaceGetVisible(
-    DvrGraphicsContext* graphics_context) {
-  return !!graphics_context->display_surface->visible();
-}
-
-extern "C" void dvrGraphicsSurfaceSetZOrder(
-    DvrGraphicsContext* graphics_context, int z_order) {
-  graphics_context->display_surface->SetZOrder(z_order);
-}
-
-extern "C" int dvrGraphicsSurfaceGetZOrder(
-    DvrGraphicsContext* graphics_context) {
-  return graphics_context->display_surface->z_order();
-}
diff --git a/libs/vr/libdisplay/include/dvr/graphics.h b/libs/vr/libdisplay/include/dvr/graphics.h
deleted file mode 100644
index c83a698..0000000
--- a/libs/vr/libdisplay/include/dvr/graphics.h
+++ /dev/null
@@ -1,450 +0,0 @@
-#ifndef DVR_GRAPHICS_H_
-#define DVR_GRAPHICS_H_
-
-#include <EGL/egl.h>
-#include <sys/cdefs.h>
-
-#ifdef __ARM_NEON
-#include <arm_neon.h>
-#else
-#ifndef __FLOAT32X4T_86
-#define __FLOAT32X4T_86
-typedef float float32x4_t __attribute__((__vector_size__(16)));
-typedef struct float32x4x4_t { float32x4_t val[4]; };
-#endif
-#endif
-
-#ifndef VK_USE_PLATFORM_ANDROID_KHR
-#define VK_USE_PLATFORM_ANDROID_KHR 1
-#endif
-#include <vulkan/vulkan.h>
-
-__BEGIN_DECLS
-
-// Display surface parameters used to specify display surface options.
-enum {
-  DVR_SURFACE_PARAMETER_NONE = 0,
-  // WIDTH
-  DVR_SURFACE_PARAMETER_WIDTH_IN,
-  // HEIGHT
-  DVR_SURFACE_PARAMETER_HEIGHT_IN,
-  // DISABLE_DISTORTION
-  DVR_SURFACE_PARAMETER_DISABLE_DISTORTION_IN,
-  // DISABLE_STABILIZATION
-  DVR_SURFACE_PARAMETER_DISABLE_STABILIZATION_IN,
-  // Disable chromatic aberration correction
-  DVR_SURFACE_PARAMETER_DISABLE_CAC_IN,
-  // ENABLE_LATE_LATCH: Enable late latching of pose data for application
-  // GPU shaders.
-  DVR_SURFACE_PARAMETER_ENABLE_LATE_LATCH_IN,
-  // VISIBLE
-  DVR_SURFACE_PARAMETER_VISIBLE_IN,
-  // Z_ORDER
-  DVR_SURFACE_PARAMETER_Z_ORDER_IN,
-  // EXCLUDE_FROM_BLUR
-  DVR_SURFACE_PARAMETER_EXCLUDE_FROM_BLUR_IN,
-  // BLUR_BEHIND
-  DVR_SURFACE_PARAMETER_BLUR_BEHIND_IN,
-  // DISPLAY_WIDTH
-  DVR_SURFACE_PARAMETER_DISPLAY_WIDTH_OUT,
-  // DISPLAY_HEIGHT
-  DVR_SURFACE_PARAMETER_DISPLAY_HEIGHT_OUT,
-  // SURFACE_WIDTH: Returns width of allocated surface buffer.
-  DVR_SURFACE_PARAMETER_SURFACE_WIDTH_OUT,
-  // SURFACE_HEIGHT: Returns height of allocated surface buffer.
-  DVR_SURFACE_PARAMETER_SURFACE_HEIGHT_OUT,
-  // INTER_LENS_METERS: Returns float value in meters, the distance between
-  // lenses.
-  DVR_SURFACE_PARAMETER_INTER_LENS_METERS_OUT,
-  // LEFT_FOV_LRBT: Return storage must have room for array of 4 floats (in
-  // radians). The layout is left, right, bottom, top as indicated by LRBT.
-  DVR_SURFACE_PARAMETER_LEFT_FOV_LRBT_OUT,
-  // RIGHT_FOV_LRBT: Return storage must have room for array of 4 floats (in
-  // radians). The layout is left, right, bottom, top as indicated by LRBT.
-  DVR_SURFACE_PARAMETER_RIGHT_FOV_LRBT_OUT,
-  // VSYNC_PERIOD: Returns the period of the display refresh (in
-  // nanoseconds per refresh), as a 64-bit unsigned integer.
-  DVR_SURFACE_PARAMETER_VSYNC_PERIOD_OUT,
-  // SURFACE_TEXTURE_TARGET_TYPE: Returns the type of texture used as the render
-  // target.
-  DVR_SURFACE_PARAMETER_SURFACE_TEXTURE_TARGET_TYPE_OUT,
-  // SURFACE_TEXTURE_TARGET_ID: Returns the texture ID used as the render
-  // target.
-  DVR_SURFACE_PARAMETER_SURFACE_TEXTURE_TARGET_ID_OUT,
-  // Whether the surface needs to be flipped vertically before display. Default
-  // is 0.
-  DVR_SURFACE_PARAMETER_VERTICAL_FLIP_IN,
-  // A bool indicating whether or not to create a GL context for the surface.
-  // 0: don't create a context
-  // Non-zero: create a context.
-  // Default is 1.
-  // If this value is 0, there must be a GLES 3.2 or greater context bound on
-  // the current thread at the time dvrGraphicsContextCreate is called.
-  DVR_SURFACE_PARAMETER_CREATE_GL_CONTEXT_IN,
-  // Specify one of DVR_SURFACE_GEOMETRY_*.
-  DVR_SURFACE_PARAMETER_GEOMETRY_IN,
-  // FORMAT: One of DVR_SURFACE_FORMAT_RGBA_8888 or DVR_SURFACE_FORMAT_RGB_565.
-  // Default is DVR_SURFACE_FORMAT_RGBA_8888.
-  DVR_SURFACE_PARAMETER_FORMAT_IN,
-  // GRAPHICS_API: One of DVR_SURFACE_GRAPHICS_API_GLES or
-  // DVR_SURFACE_GRAPHICS_API_VULKAN. Default is GLES.
-  DVR_SURFACE_PARAMETER_GRAPHICS_API_IN,
-  // VK_INSTANCE: In Vulkan mode, the application creates a VkInstance and
-  // passes it in.
-  DVR_SURFACE_PARAMETER_VK_INSTANCE_IN,
-  // VK_PHYSICAL_DEVICE: In Vulkan mode, the application passes in the
-  // PhysicalDevice handle corresponding to the logical device passed to
-  // VK_DEVICE.
-  DVR_SURFACE_PARAMETER_VK_PHYSICAL_DEVICE_IN,
-  // VK_DEVICE: In Vulkan mode, the application creates a VkDevice and
-  // passes it in.
-  DVR_SURFACE_PARAMETER_VK_DEVICE_IN,
-  // VK_PRESENT_QUEUE: In Vulkan mode, the application selects a
-  // presentation-compatible VkQueue and passes it in.
-  DVR_SURFACE_PARAMETER_VK_PRESENT_QUEUE_IN,
-  // VK_PRESENT_QUEUE_FAMILY: In Vulkan mode, the application passes in the
-  // index of the queue family containing the VkQueue passed to
-  // VK_PRESENT_QUEUE.
-  DVR_SURFACE_PARAMETER_VK_PRESENT_QUEUE_FAMILY_IN,
-  // VK_SWAPCHAIN_IMAGE_COUNT: In Vulkan mode, the number of swapchain images
-  // will be returned here.
-  DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_COUNT_OUT,
-  // VK_SWAPCHAIN_IMAGE_FORMAT: In Vulkan mode, the VkFormat of the swapchain
-  // images will be returned here.
-  DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_FORMAT_OUT,
-  // DIRECT: Whether the surface goes directly to the display or to the
-  // compositor. Default is 0 (compositor). Only processes with either uid=root
-  // (test tools) or uid validated by IsTrustedUid() may set this to 1.
-  DVR_SURFACE_PARAMETER_DIRECT_IN,
-};
-
-enum {
-  // Default surface type. One wide buffer with the left eye view in the left
-  // half and the right eye view in the right half.
-  DVR_SURFACE_GEOMETRY_SINGLE,
-  // Separate buffers, one per eye. The width parameters still refer to the
-  // total width (2 * eye view width).
-  DVR_SURFACE_GEOMETRY_SEPARATE_2,
-};
-
-// Surface format. Gvr only supports RGBA_8888 and RGB_565 for now, so those are
-// the only formats we provide here.
-enum {
-  DVR_SURFACE_FORMAT_RGBA_8888,
-  DVR_SURFACE_FORMAT_RGB_565,
-};
-
-enum {
-  // Graphics contexts are created for OpenGL ES client applications by default.
-  DVR_GRAPHICS_API_GLES,
-  // Create the graphics context for Vulkan client applications.
-  DVR_GRAPHICS_API_VULKAN,
-};
-
-#define DVR_SURFACE_PARAMETER_IN(name, value) \
-  { DVR_SURFACE_PARAMETER_##name##_IN, (value), NULL }
-#define DVR_SURFACE_PARAMETER_OUT(name, value) \
-  { DVR_SURFACE_PARAMETER_##name##_OUT, 0, (value) }
-#define DVR_SURFACE_PARAMETER_LIST_END \
-  { DVR_SURFACE_PARAMETER_NONE, 0, NULL }
-
-struct DvrSurfaceParameter {
-  int32_t key;
-  int64_t value;
-  void* value_out;
-};
-
-// This is a convenience struct to hold the relevant information of the HMD
-// lenses.
-struct DvrLensInfo {
-  float inter_lens_meters;
-  float left_fov[4];
-  float right_fov[4];
-};
-
-int dvrGetNativeDisplayDimensions(int* native_width, int* native_height);
-
-typedef struct DvrReadBuffer DvrReadBuffer;
-
-// Opaque struct that represents a graphics context, the texture swap chain,
-// and surfaces.
-typedef struct DvrGraphicsContext DvrGraphicsContext;
-
-// Create the graphics context. with the given parameters. The list of
-// parameters is terminated with an entry where key ==
-// DVR_SURFACE_PARAMETER_NONE. For example, the parameters array could be built
-// as follows:
-//   int display_width = 0, display_height = 0;
-//   int surface_width = 0, surface_height = 0;
-//   float inter_lens_meters = 0.0f;
-//   float left_fov[4] = {0.0f};
-//   float right_fov[4] = {0.0f};
-//   int disable_warp = 0;
-//   DvrSurfaceParameter surface_params[] = {
-//       DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, disable_warp),
-//       DVR_SURFACE_PARAMETER_OUT(DISPLAY_WIDTH, &display_width),
-//       DVR_SURFACE_PARAMETER_OUT(DISPLAY_HEIGHT, &display_height),
-//       DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &surface_width),
-//       DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &surface_height),
-//       DVR_SURFACE_PARAMETER_OUT(INTER_LENS_METERS, &inter_lens_meters),
-//       DVR_SURFACE_PARAMETER_OUT(LEFT_FOV_LRBT, left_fov),
-//       DVR_SURFACE_PARAMETER_OUT(RIGHT_FOV_LRBT, right_fov),
-//       DVR_SURFACE_PARAMETER_LIST_END,
-//   };
-int dvrGraphicsContextCreate(struct DvrSurfaceParameter* parameters,
-                             DvrGraphicsContext** return_graphics_context);
-
-// Destroy the graphics context.
-void dvrGraphicsContextDestroy(DvrGraphicsContext* graphics_context);
-
-// For every frame a schedule is decided by the system compositor. A sample
-// schedule for two frames is shown below.
-//
-// |                        |                        |
-// |-----------------|------|-----------------|------|
-// |                        |                        |
-// V0                A1     V1                A2     V2
-//
-// V0, V1, and V2 are display vsync events. Vsync events are uniquely identified
-// throughout the DVR system by a vsync count maintained by the system
-// compositor.
-//
-// A1 and A2 indicate when the application should finish rendering its frame,
-// including all GPU work. Under normal circumstances the scheduled finish
-// finish time will be set a few milliseconds before the vsync time, to give the
-// compositor time to perform distortion and EDS on the app's buffer. For apps
-// that don't use system distortion the scheduled frame finish time will be
-// closer to the vsync time. Other factors can also effect the scheduled frame
-// finish time, e.g. whether or not the System UI is being displayed.
-typedef struct DvrFrameSchedule {
-  // vsync_count is used as a frame identifier.
-  uint32_t vsync_count;
-
-  // The time when the app should finish rendering its frame, including all GPU
-  // work.
-  int64_t scheduled_frame_finish_ns;
-} DvrFrameSchedule;
-
-// Sleep until it's time to render the next frame. This should be the first
-// function called as part of an app's render loop, which normally looks like
-// this:
-//
-// while (1) {
-//   DvrFrameSchedule schedule;
-//   dvrGraphicsWaitNextFrame(..., &schedule); // Sleep until it's time to
-//                                             // render the next frame
-//   pose = dvrPoseGet(schedule.vsync_count);
-//   dvrBeginRenderFrame(...);
-//   <render a frame using the pose>
-//   dvrPresent(...); // Post the buffer
-// }
-//
-// |start_delay_ns| adjusts how long this function blocks the app from starting
-// its next frame. If |start_delay_ns| is 0, the function waits until the
-// scheduled frame finish time for the current frame, which gives the app one
-// full vsync period to render the next frame. If the app needs less than a full
-// vysnc period to render the frame, pass in a non-zero |start_delay_ns| to
-// delay the start of frame rendering further. For example, if the vsync period
-// is 11.1ms and the app takes 6ms to render a frame, consider setting this to
-// 5ms (note that the value is in nanoseconds, so 5,000,000ns) so that the app
-// finishes the frame closer to the scheduled frame finish time. Delaying the
-// start of rendering allows the app to use a more up-to-date pose for
-// rendering.
-// |start_delay_ns| must be a positive value or 0. If you're unsure what to set
-// for |start_delay_ns|, use 0.
-//
-// |out_next_frame_schedule| is an output parameter that will contain the
-// schedule for the next frame. It can be null. This function returns a negative
-// error code on failure.
-int dvrGraphicsWaitNextFrame(DvrGraphicsContext* graphics_context,
-                             int64_t start_delay_ns,
-                             DvrFrameSchedule* out_next_frame_schedule);
-
-// Prepares the graphics context's texture for rendering.  This function should
-// be called once for each frame, ideally immediately before the first GL call
-// on the framebuffer which wraps the surface texture.
-//
-// For GL contexts, GL states are modified as follows by this function:
-// glBindTexture(GL_TEXTURE_2D, 0);
-//
-// @param[in] graphics_context The DvrGraphicsContext.
-// @param[in] render_pose_orientation Head pose orientation that rendering for
-//            this frame will be based off of. This must be an unmodified value
-//            from DvrPoseAsync, returned by dvrPoseGet.
-// @param[in] render_pose_translation Head pose translation that rendering for
-//            this frame will be based off of. This must be an unmodified value
-//            from DvrPoseAsync, returned by dvrPoseGet.
-// @return 0 on success or a negative error code on failure.
-// Check GL errors with glGetError for other error conditions.
-int dvrBeginRenderFrameEds(DvrGraphicsContext* graphics_context,
-                           float32x4_t render_pose_orientation,
-                           float32x4_t render_pose_translation);
-int dvrBeginRenderFrameEdsVk(DvrGraphicsContext* graphics_context,
-                             float32x4_t render_pose_orientation,
-                             float32x4_t render_pose_translation,
-                             VkSemaphore acquire_semaphore,
-                             VkFence acquire_fence,
-                             uint32_t* swapchain_image_index,
-                             VkImageView* swapchain_image_view);
-// Same as dvrBeginRenderFrameEds, but with no EDS (asynchronous reprojection).
-//
-// For GL contexts, GL states are modified as follows by this function:
-// glBindTexture(GL_TEXTURE_2D, 0);
-//
-// @param[in] graphics_context The DvrGraphicsContext.
-// @return 0 on success or a negative error code on failure.
-// Check GL errors with glGetError for other error conditions.
-int dvrBeginRenderFrame(DvrGraphicsContext* graphics_context);
-int dvrBeginRenderFrameVk(DvrGraphicsContext* graphics_context,
-                          VkSemaphore acquire_semaphore, VkFence acquire_fence,
-                          uint32_t* swapchain_image_index,
-                          VkImageView* swapchain_image_view);
-
-// Maximum number of views per surface buffer (for multiview, multi-eye, etc).
-#define DVR_GRAPHICS_SURFACE_MAX_VIEWS 4
-
-// Output data format of late latch shader. The application can bind all or part
-// of this data with the buffer ID returned by dvrBeginRenderFrameLateLatch.
-// This struct is compatible with std140 layout for use from shaders.
-struct __attribute__((__packed__)) DvrGraphicsLateLatchData {
-  // Column-major order.
-  float view_proj_matrix[DVR_GRAPHICS_SURFACE_MAX_VIEWS][16];
-  // Column-major order.
-  float view_matrix[DVR_GRAPHICS_SURFACE_MAX_VIEWS][16];
-  // Quaternion for pose orientation from start space.
-  float pose_orientation[4];
-  // Pose translation from start space.
-  float pose_translation[4];
-};
-
-// Begin render frame with late latching of pose data. This kicks off a compute
-// shader that will read the latest head pose and then compute and output
-// matrices that can be used by application shaders.
-//
-// Matrices are computed with the following pseudo code.
-//   Pose pose = getLateLatchPose();
-//   out.pose_orientation = pose.orientation;
-//   out.pose_translation = pose.translation;
-//   mat4 head_from_center = ComputeInverseMatrix(pose);
-//   for each view:
-//     out.viewMatrix[view] =
-//         eye_from_head_matrices[view] * head_from_center *
-//         pose_offset_matrices[view];
-//     out.viewProjMatrix[view] =
-//         projection_matrices[view] * out.viewMatrix[view];
-//
-// For GL contexts, GL states are modified as follows by this function:
-// glBindTexture(GL_TEXTURE_2D, 0);
-// glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
-// glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
-// glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
-// glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0);
-// glUseProgram(0);
-//
-// @param[in] graphics_context The DvrGraphicsContext.
-// @param[in] flags Specify 0.
-// @param[in] target_vsync_count The target vsync count that this frame will
-//            display at. This is used for pose prediction.
-// @param[in] num_views Number of matrices in each of the following matrix array
-//            parameters. Typically 2 for left and right eye views. Maximum is
-//            DVR_GRAPHICS_SURFACE_MAX_VIEWS.
-// @param[in] projection_matrices Array of pointers to |num_views| matrices with
-//            column-major layout. These are the application projection
-//            matrices.
-// @param[in] eye_from_head_matrices Array of pointers to |num_views| matrices
-//            with column-major layout. See pseudo code for how these are used.
-// @param[in] pose_offset_matrices Array of pointers to |num_views| matrices
-//            with column-major layout. See pseudo code for how these are used.
-// @param[out] out_late_latch_buffer_id The GL buffer ID of the output buffer of
-//             of type DvrGraphicsLateLatchData.
-// @return 0 on success or a negative error code on failure.
-// Check GL errors with glGetError for other error conditions.
-int dvrBeginRenderFrameLateLatch(DvrGraphicsContext* graphics_context,
-                                 uint32_t flags, uint32_t target_vsync_count,
-                                 int num_views,
-                                 const float** projection_matrices,
-                                 const float** eye_from_head_matrices,
-                                 const float** pose_offset_matrices,
-                                 uint32_t* out_late_latch_buffer_id);
-
-// Present a frame for display.
-// This call is normally non-blocking, unless the internal buffer queue is full.
-// @return 0 on success or a negative error code on failure.
-int dvrPresent(DvrGraphicsContext* graphics_context);
-int dvrPresentVk(DvrGraphicsContext* graphics_context,
-                 VkSemaphore submit_semaphore, uint32_t swapchain_image_index);
-
-// Post the next buffer early. This allows the application to race with either
-// the async EDS process or the scanline for applications that are not using
-// system distortion. When this is called, the next buffer in the queue is
-// posted for display. It is up to the application to kick its GPU rendering
-// work in time. If the rendering is incomplete there will be significant,
-// undesirable tearing artifacts.
-// It is not recommended to use this feature with system distortion.
-void dvrGraphicsPostEarly(DvrGraphicsContext* graphics_context);
-
-// Used to retrieve frame measurement timings from dvrGetFrameScheduleResults().
-typedef struct DvrFrameScheduleResult {
-  // vsync_count is used as a frame identifier.
-  uint32_t vsync_count;
-
-  // The app's scheduled frame finish time.
-  int64_t scheduled_frame_finish_ns;
-
-  // The difference (in nanoseconds) between the scheduled finish time and the
-  // actual finish time.
-  //
-  // A value of +2ms for frame_finish_offset_ns indicates the app's frame was
-  // late and may have been skipped by the compositor for that vsync. A value of
-  // -1ms indicates the app's frame finished just ahead of schedule, as
-  // desired. A value of -6ms indicates the app's frame finished well ahead of
-  // schedule for that vsync. In that case the app may have unnecessary visual
-  // latency. Consider using the start_delay_ns parameter in
-  // dvrGraphicsWaitNextFrame() to align the app's frame finish time closer to
-  // the scheduled finish time.
-  int64_t frame_finish_offset_ns;
-} DvrFrameScheduleResult;
-
-// Retrieve the latest frame schedule results for the app. To collect all the
-// results this should be called each frame. The results for each frame are
-// returned only once.
-// The number of results written to |results| is returned on success, or a
-// negative error code on failure.
-// |graphics_context| is the context to retrieve frame schedule results for.
-// |results| is an array that will contain the frame schedule results.
-// |result_count| is the size of the |results| array. It's recommended to pass
-// in an array with 2 elements to ensure results for all frames are collected.
-int dvrGetFrameScheduleResults(DvrGraphicsContext* graphics_context,
-                               DvrFrameScheduleResult* results,
-                               int result_count);
-
-// Make the surface visible or hidden based on |visible|.
-// 0: hidden, Non-zero: visible.
-void dvrGraphicsSurfaceSetVisible(DvrGraphicsContext* graphics_context,
-                                  int visible);
-
-// Returns surface visilibity last requested by the client.
-int dvrGraphicsSurfaceGetVisible(DvrGraphicsContext* graphics_context);
-
-// Returns surface z order last requested by the client.
-int dvrGraphicsSurfaceGetZOrder(DvrGraphicsContext* graphics_context);
-
-// Sets the compositor z-order of the surface. Higher values display on
-// top of lower values.
-void dvrGraphicsSurfaceSetZOrder(DvrGraphicsContext* graphics_context,
-                                 int z_order);
-
-typedef struct DvrVideoMeshSurface DvrVideoMeshSurface;
-
-DvrVideoMeshSurface* dvrGraphicsVideoMeshSurfaceCreate(
-    DvrGraphicsContext* graphics_context);
-void dvrGraphicsVideoMeshSurfaceDestroy(DvrVideoMeshSurface* surface);
-
-// Present a VideoMeshSurface with the current video mesh transfromation matrix.
-void dvrGraphicsVideoMeshSurfacePresent(DvrGraphicsContext* graphics_context,
-                                        DvrVideoMeshSurface* surface,
-                                        const int eye, const float* transform);
-
-__END_DECLS
-
-#endif  // DVR_GRAPHICS_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 7a7f670..ce0bc80 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -1,6 +1,7 @@
 #ifndef ANDROID_DVR_DISPLAY_CLIENT_H_
 #define ANDROID_DVR_DISPLAY_CLIENT_H_
 
+#include <dvr/dvr_api.h>
 #include <hardware/hwcomposer.h>
 #include <pdx/client.h>
 #include <pdx/file_handle.h>
@@ -67,8 +68,9 @@
 class DisplayClient : public pdx::ClientBase<DisplayClient> {
  public:
   pdx::Status<Metrics> GetDisplayMetrics();
-  pdx::Status<std::unique_ptr<IonBuffer>> GetNamedBuffer(
-      const std::string& name);
+  pdx::Status<std::string> GetConfigurationData(ConfigFileType config_type);
+  pdx::Status<std::unique_ptr<IonBuffer>> GetGlobalBuffer(
+      DvrGlobalBufferKey key);
   pdx::Status<std::unique_ptr<Surface>> CreateSurface(
       const SurfaceAttributes& attributes);
 
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
index fea8415..7281b76 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
@@ -21,8 +21,9 @@
   ~DisplayManagerClient() override;
 
   pdx::Status<std::vector<SurfaceState>> GetSurfaceState();
-  pdx::Status<std::unique_ptr<IonBuffer>> SetupNamedBuffer(
-      const std::string& name, size_t size, uint64_t usage);
+  pdx::Status<std::unique_ptr<IonBuffer>> SetupGlobalBuffer(
+      DvrGlobalBufferKey key, size_t size, uint64_t usage);
+  pdx::Status<void> DeleteGlobalBuffer(DvrGlobalBufferKey key);
   pdx::Status<std::unique_ptr<ConsumerQueue>> GetSurfaceQueue(int surface_id,
                                                               int queue_id);
 
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
index f34d61f..d1787e6 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_protocol.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -8,6 +8,8 @@
 
 #include <dvr/dvr_display_types.h>
 
+#include <dvr/dvr_api.h>
+#include <pdx/rpc/buffer_wrapper.h>
 #include <pdx/rpc/remote_method.h>
 #include <pdx/rpc/serializable.h>
 #include <pdx/rpc/variant.h>
@@ -184,6 +186,12 @@
   PDX_SERIALIZABLE_MEMBERS(SurfaceInfo, surface_id, visible, z_order);
 };
 
+enum class ConfigFileType : uint32_t {
+  kLensMetrics,
+  kDeviceMetrics,
+  kDeviceConfiguration
+};
+
 struct DisplayProtocol {
   // Service path.
   static constexpr char kClientPath[] = "system/vr/display/client";
@@ -191,7 +199,8 @@
   // Op codes.
   enum {
     kOpGetMetrics = 0,
-    kOpGetNamedBuffer,
+    kOpGetConfigurationData,
+    kOpGetGlobalBuffer,
     kOpIsVrAppRunning,
     kOpCreateSurface,
     kOpGetSurfaceInfo,
@@ -205,8 +214,10 @@
 
   // Methods.
   PDX_REMOTE_METHOD(GetMetrics, kOpGetMetrics, Metrics(Void));
-  PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
-                    LocalNativeBufferHandle(std::string name));
+  PDX_REMOTE_METHOD(GetConfigurationData, kOpGetConfigurationData,
+                    std::string(ConfigFileType config_type));
+  PDX_REMOTE_METHOD(GetGlobalBuffer, kOpGetGlobalBuffer,
+                    LocalNativeBufferHandle(DvrGlobalBufferKey key));
   PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, bool(Void));
   PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
                     SurfaceInfo(const SurfaceAttributes& attributes));
@@ -225,7 +236,8 @@
   enum {
     kOpGetSurfaceState = 0,
     kOpGetSurfaceQueue,
-    kOpSetupNamedBuffer,
+    kOpSetupGlobalBuffer,
+    kOpDeleteGlobalBuffer,
   };
 
   // Aliases.
@@ -237,9 +249,11 @@
                     std::vector<SurfaceState>(Void));
   PDX_REMOTE_METHOD(GetSurfaceQueue, kOpGetSurfaceQueue,
                     LocalChannelHandle(int surface_id, int queue_id));
-  PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
-                    LocalNativeBufferHandle(const std::string& name,
-                                            size_t size, uint64_t usage));
+  PDX_REMOTE_METHOD(SetupGlobalBuffer, kOpSetupGlobalBuffer,
+                    LocalNativeBufferHandle(DvrGlobalBufferKey key, size_t size,
+                                            uint64_t usage));
+  PDX_REMOTE_METHOD(DeleteGlobalBuffer, kOpDeleteGlobalBuffer,
+                    void(DvrGlobalBufferKey key));
 };
 
 struct VSyncSchedInfo {
diff --git a/libs/vr/libdisplay/include/private/dvr/dummy_native_window.h b/libs/vr/libdisplay/include/private/dvr/dummy_native_window.h
deleted file mode 100644
index b9c1067..0000000
--- a/libs/vr/libdisplay/include/private/dvr/dummy_native_window.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef ANDROID_DVR_DUMMY_NATIVE_WINDOW_H_
-#define ANDROID_DVR_DUMMY_NATIVE_WINDOW_H_
-
-#include <android/native_window.h>
-#include <ui/ANativeObjectBase.h>
-#include <system/window.h>
-
-namespace android {
-namespace dvr {
-
-// DummyNativeWindow is an implementation of ANativeWindow that is
-// essentially empty and is used as a surface placeholder during context
-// creation for contexts that we don't intend to call eglSwapBuffers on.
-class DummyNativeWindow
-    : public ANativeObjectBase<ANativeWindow, DummyNativeWindow,
-                               LightRefBase<DummyNativeWindow> > {
- public:
-  DummyNativeWindow();
-
- private:
-  static int Query(const ANativeWindow* window, int what, int* value);
-  static int Perform(ANativeWindow* window, int operation, ...);
-
-  DummyNativeWindow(const DummyNativeWindow&) = delete;
-  void operator=(DummyNativeWindow&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_DUMMY_NATIVE_WINDOW_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/frame_history.h b/libs/vr/libdisplay/include/private/dvr/frame_history.h
deleted file mode 100644
index 53e0717..0000000
--- a/libs/vr/libdisplay/include/private/dvr/frame_history.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef ANDROID_DVR_FRAME_HISTORY_H_
-#define ANDROID_DVR_FRAME_HISTORY_H_
-
-#include <dvr/graphics.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/ring_buffer.h>
-
-namespace android {
-namespace dvr {
-
-// FrameHistory tracks frame times from the start of rendering commands to when
-// the buffer is ready.
-class FrameHistory {
- public:
-  FrameHistory();
-  explicit FrameHistory(int pending_frame_buffer_size);
-
-  void Reset(int pending_frame_buffer_size);
-
-  // Call when starting rendering commands (i.e. dvrBeginRenderFrame).
-  void OnFrameStart(uint32_t scheduled_vsync, int64_t scheduled_finish_ns);
-
-  // Call when rendering commands are finished (i.e. dvrPresent).
-  void OnFrameSubmit(android::pdx::LocalHandle&& fence);
-
-  // Call once per frame to see if any pending frames have finished.
-  void CheckForFinishedFrames();
-
-  // Uses the recently completed frame render times to predict how long the next
-  // frame will take, in vsync intervals. For example if the predicted frame
-  // time is 10ms and the vsync interval is 11ms, this will return 1. If the
-  // predicted frame time is 12ms and the vsync interval is 11ms, this will
-  // return 2.
-  int PredictNextFrameVsyncInterval(int64_t vsync_period_ns) const;
-
-  // Returns results for recently completed frames. Each frame's result is
-  // returned only once.
-  int GetPreviousFrameResults(DvrFrameScheduleResult* results,
-                              int result_count);
-
-  // Gets the vsync count for the most recently started frame. If there are no
-  // started frames this will return UINT32_MAX.
-  uint32_t GetCurrentFrameVsync() const;
-
- private:
-  struct PendingFrame {
-    int64_t start_ns;
-    uint32_t scheduled_vsync;
-    int64_t scheduled_finish_ns;
-    android::pdx::LocalHandle fence;
-
-    PendingFrame();
-    PendingFrame(int64_t start_ns, uint32_t scheduled_vsync,
-                 int64_t scheduled_finish_ns,
-                 android::pdx::LocalHandle&& fence);
-
-    PendingFrame(PendingFrame&&) = default;
-    PendingFrame& operator=(PendingFrame&&) = default;
-    PendingFrame(const PendingFrame&) = delete;
-    PendingFrame& operator=(const PendingFrame&) = delete;
-  };
-
-  RingBuffer<PendingFrame> pending_frames_;
-  RingBuffer<DvrFrameScheduleResult> finished_frames_;
-  RingBuffer<int64_t> frame_duration_history_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_FRAME_HISTORY_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/gl_fenced_flush.h b/libs/vr/libdisplay/include/private/dvr/gl_fenced_flush.h
deleted file mode 100644
index 1d75335..0000000
--- a/libs/vr/libdisplay/include/private/dvr/gl_fenced_flush.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ANDROID_DVR_GL_FENCED_FLUSH_H_
-#define ANDROID_DVR_GL_FENCED_FLUSH_H_
-
-#include <EGL/egl.h>
-#include <pdx/file_handle.h>
-
-namespace android {
-namespace dvr {
-
-// Creates a EGL_SYNC_NATIVE_FENCE_ANDROID and flushes. Returns the fence as a
-// file descriptor.
-pdx::LocalHandle CreateGLSyncAndFlush(EGLDisplay display);
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_GL_FENCED_FLUSH_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/graphics_private.h b/libs/vr/libdisplay/include/private/dvr/graphics_private.h
deleted file mode 100644
index a08b0df..0000000
--- a/libs/vr/libdisplay/include/private/dvr/graphics_private.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef ANDROID_DVR_GRAPHICS_PRIVATE_H_
-#define ANDROID_DVR_GRAPHICS_PRIVATE_H_
-
-#ifdef __ARM_NEON
-#include <arm_neon.h>
-#else
-#ifndef __FLOAT32X4T_86
-#define __FLOAT32X4T_86
-typedef float float32x4_t __attribute__ ((__vector_size__ (16)));
-typedef struct float32x4x4_t { float32x4_t val[4]; };
-#endif
-#endif
-
-#include <sys/cdefs.h>
-
-#include <dvr/graphics.h>
-
-__BEGIN_DECLS
-
-#define kSurfaceBufferMaxCount 4
-#define kSurfaceViewMaxCount 4
-
-struct __attribute__((packed, aligned(16))) DisplaySurfaceMetadata {
-  // Array of orientations and translations corresponding with surface buffers.
-  // The index is associated with each allocated buffer by DisplaySurface and
-  // communicated to clients.
-  // The maximum number of buffers is hard coded here as 4 so that we can bind
-  // this data structure in GPU shaders.
-  float32x4_t orientation[kSurfaceBufferMaxCount];
-  float32x4_t translation[kSurfaceBufferMaxCount];
-};
-
-// Sets the pose used by the system for EDS. If dvrBeginRenderFrameEds() or
-// dvrBeginRenderFrameLateLatch() are called instead of dvrBeginRenderFrame()
-// it's not necessary to call this function. If this function is used, the call
-// must be made after dvrBeginRenderFrame() and before dvrPresent().
-//
-// @param[in] graphics_context The DvrGraphicsContext.
-// @param[in] render_pose_orientation Head pose orientation that rendering for
-//            this frame will be based off of. This must be an unmodified value
-//            from DvrPoseAsync, returned by dvrPoseGet.
-// @param[in] render_pose_translation Head pose translation that rendering for
-//            this frame will be based off of. This must be an unmodified value
-//            from DvrPoseAsync, returned by dvrPoseGet.
-// @return 0 on success or a negative error code on failure.
-int dvrSetEdsPose(DvrGraphicsContext* graphics_context,
-                  float32x4_t render_pose_orientation,
-                  float32x4_t render_pose_translation);
-
-__END_DECLS
-
-#endif  // ANDROID_DVR_GRAPHICS_PRIVATE_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/late_latch.h b/libs/vr/libdisplay/include/private/dvr/late_latch.h
deleted file mode 100644
index c91d15c..0000000
--- a/libs/vr/libdisplay/include/private/dvr/late_latch.h
+++ /dev/null
@@ -1,190 +0,0 @@
-#ifndef ANDROID_DVR_LATE_LATCH_H_
-#define ANDROID_DVR_LATE_LATCH_H_
-
-#include <atomic>
-#include <thread>
-#include <vector>
-
-#include <dvr/dvr_display_types.h>
-#include <dvr/pose_client.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/graphics/shader_program.h>
-#include <private/dvr/graphics/vr_gl_extensions.h>
-#include <private/dvr/graphics_private.h>
-#include <private/dvr/types.h>
-
-struct DvrPose;
-
-namespace android {
-namespace dvr {
-
-// Input data for late latch compute shader.
-struct LateLatchInput {
-  // For app late latch:
-  mat4 eye_from_head_mat[kSurfaceViewMaxCount];
-  mat4 proj_mat[kSurfaceViewMaxCount];
-  mat4 pose_offset[kSurfaceViewMaxCount];
-  // For EDS late latch only:
-  mat4 eds_mat1[kSurfaceViewMaxCount];
-  mat4 eds_mat2[kSurfaceViewMaxCount];
-  // For both app and EDS late latch:
-  uint32_t pose_index;
-  uint32_t render_pose_index;
-};
-
-// Output data for late latch shader. The application can use all or part of
-// this data by calling LateLatch::BindUniformBuffer.
-// This struct matches the layout of DvrGraphicsLateLatchData.
-struct LateLatchOutput {
-  mat4 view_proj_matrix[kSurfaceViewMaxCount];
-  mat4 view_matrix[kSurfaceViewMaxCount];
-  vec4 pose_quaternion;
-  vec4 pose_translation;
-};
-
-// LateLatch provides a facility for GL workloads to acquire a late-adjusted
-// model-view projection matrix, adjusted based on the position/quaternion pose
-// read from a buffer that is being written to asynchronously. The adjusted
-// MVP matrix is written to a GL buffer object via GL transform feedback.
-class LateLatch {
- public:
-  enum BufferType {
-    kViewProjMatrix,
-    kViewMatrix,
-    kPoseQuaternion,
-    kPoseTranslation,
-    // Max transform feedback count is 4, so no more buffers can go here.
-    kNumBuffers,
-  };
-
-  static size_t GetBufferSize(BufferType type) {
-    switch (type) {
-      default:
-      case kViewProjMatrix:
-      case kViewMatrix:
-        return 4 * 4 * sizeof(float);
-      case kPoseQuaternion:
-      case kPoseTranslation:
-        return 4 * sizeof(float);
-    }
-  }
-
-  static size_t GetBufferOffset(BufferType type, int view) {
-    switch (type) {
-      default:
-      case kViewProjMatrix:
-        return offsetof(LateLatchOutput, view_proj_matrix) +
-               GetBufferSize(type) * view;
-      case kViewMatrix:
-        return offsetof(LateLatchOutput, view_matrix) +
-               GetBufferSize(type) * view;
-      case kPoseQuaternion:
-        return offsetof(LateLatchOutput, pose_quaternion);
-      case kPoseTranslation:
-        return offsetof(LateLatchOutput, pose_translation);
-    }
-  }
-
-  explicit LateLatch(bool is_app_late_latch);
-  LateLatch(bool is_app_late_latch, pdx::LocalHandle&& surface_metadata_fd);
-  ~LateLatch();
-
-  // Bind the late-latch output data as a GL_UNIFORM_BUFFER. For example,
-  // to bind just the view_matrix from the output:
-  // BindUniformBuffer(BINDING, offsetof(LateLatchOutput, view_matrix),
-  //                   sizeof(mat4));
-  // buffer_index is the index of one of the output buffers if more than 1 were
-  // requested in the constructor.
-  void BindUniformBuffer(GLuint ubo_binding, size_t offset, size_t size) const {
-    glBindBufferRange(GL_UNIFORM_BUFFER, ubo_binding, output_buffer_id_, offset,
-                      size);
-  }
-
-  void BindUniformBuffer(GLuint ubo_binding, BufferType type, int view) const {
-    glBindBufferRange(GL_UNIFORM_BUFFER, ubo_binding, output_buffer_id_,
-                      GetBufferOffset(type, view), GetBufferSize(type));
-  }
-
-  GLuint output_buffer_id() const { return output_buffer_id_; }
-
-  void UnbindUniformBuffer(GLuint ubo_binding) const {
-    glBindBufferBase(GL_UNIFORM_BUFFER, ubo_binding, 0);
-  }
-
-  void CaptureOutputData(LateLatchOutput* data) const;
-
-  // Add the late latch GL commands for this frame. This should be done just
-  // before the first application draw calls that are dependent on the head
-  // latest head pose.
-  //
-  // For efficiency, the application projection and eye_from_head matrices are
-  // passed through the late latch shader and output in various combinations to
-  // allow for both simple application vertex shaders that can take the view-
-  // projection matrix as-is and shaders that need to access the view matrix
-  // separately.
-  //
-  // GL state must be reset to default for this call.
-  void AddLateLatch(const LateLatchInput& data) const;
-
-  // After calling AddEdsLateLatch one or more times, this method must be called
-  // to add the necessary GL memory barrier to ensure late latch outputs are
-  // written before the EDS and warp shaders read them.
-  void PostEdsLateLatchBarrier() const {
-    // The transform feedback buffer is going to be read as a uniform by EDS,
-    // so we need a uniform memory barrier.
-    glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
-  }
-
-  // Typically not for use by application code. This method adds the EDS late
-  // latch that will adjust the application framebuffer with the latest head
-  // pose.
-  // buffer_index is the index of one of the output buffers if more than 1 were
-  // requested in the constructor.
-  void AddEdsLateLatch(const LateLatchInput& data,
-                       GLuint render_pose_buffer_object) const;
-
-  // For debugging purposes, capture the output during the next call to
-  // AddLateLatch. Set to NULL to reset.
-  void SetLateLatchDataCapture(LateLatchOutput* app_late_latch) {
-    app_late_latch_output_ = app_late_latch;
-  }
-
-  // For debugging purposes, capture the output during the next call to
-  // AddEdsLateLatch. Set to NULL to reset.
-  void SetEdsLateLatchDataCapture(LateLatchOutput* eds_late_latch) {
-    eds_late_latch_output_ = eds_late_latch;
-  }
-
- private:
-  LateLatch(const LateLatch&) = delete;
-  LateLatch& operator=(const LateLatch&) = delete;
-
-  void LoadLateLatchShader();
-
-  // Late latch shader.
-  ShaderProgram late_latch_program_;
-
-  // Async pose ring buffer object.
-  GLuint pose_buffer_object_;
-
-  GLuint metadata_buffer_id_;
-
-  // Pose matrix buffers
-  GLuint input_buffer_id_;
-  GLuint output_buffer_id_;
-
-  bool is_app_late_latch_;
-  // During development, these can be used to capture the pose output data.
-  LateLatchOutput* app_late_latch_output_;
-  LateLatchOutput* eds_late_latch_output_;
-
-  DvrPose* pose_client_;
-
-  pdx::LocalHandle surface_metadata_fd_;
-  pdx::LocalHandle pose_buffer_fd_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_LATE_LATCH_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
deleted file mode 100644
index a260f17..0000000
--- a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef ANDROID_DVR_NATIVE_BUFFER_QUEUE_H_
-#define ANDROID_DVR_NATIVE_BUFFER_QUEUE_H_
-
-#include <semaphore.h>
-
-#include <mutex>
-#include <vector>
-
-#include <private/dvr/native_buffer.h>
-#include <private/dvr/ring_buffer.h>
-
-#include "display_client.h"
-
-namespace android {
-namespace dvr {
-namespace display {
-
-// A wrapper over dvr::ProducerQueue that caches EGLImage.
-class NativeBufferQueue {
- public:
-  NativeBufferQueue(EGLDisplay display,
-                    const std::shared_ptr<ProducerQueue>& producer_queue,
-                    uint32_t width, uint32_t height, uint32_t format,
-                    uint64_t usage, size_t capacity);
-
-  uint32_t width() const { return width_; }
-  uint32_t height() const { return height_; }
-  uint32_t format() const { return format_; }
-  uint64_t usage() const { return usage_; }
-  size_t capacity() const { return producer_queue_->capacity(); }
-
-  // Dequeue a buffer from the free queue, blocking until one is available.
-  NativeBufferProducer* Dequeue();
-
-  // An noop here to keep Vulkan path in GraphicsContext happy.
-  // TODO(jwcai, cort) Move Vulkan path into GVR/Google3.
-  void Enqueue(NativeBufferProducer* /*buffer*/) {}
-
- private:
-  EGLDisplay display_;
-  uint32_t width_;
-  uint32_t height_;
-  uint32_t format_;
-  uint64_t usage_;
-  std::shared_ptr<ProducerQueue> producer_queue_;
-  std::vector<sp<NativeBufferProducer>> buffers_;
-
-  NativeBufferQueue(const NativeBufferQueue&) = delete;
-  void operator=(const NativeBufferQueue&) = delete;
-};
-
-}  // namespace display
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_NATIVE_BUFFER_QUEUE_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
new file mode 100644
index 0000000..ed06515
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
@@ -0,0 +1,141 @@
+#ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+#define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+
+#include <assert.h>
+#include <tuple>
+
+#include <libbroadcastring/broadcast_ring.h>
+#include <private/dvr/display_client.h>
+
+namespace android {
+namespace dvr {
+
+// The buffer usage type for mapped shared buffers.
+enum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY };
+
+// Holds the memory for the mapped shared buffer. Unlocks and releases the
+// underlying IonBuffer in destructor.
+class CPUMappedBuffer {
+ public:
+  // This constructor will create a display client and get the buffer from it.
+  CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode);
+
+  // If you already have the IonBuffer, use this. It will take ownership.
+  CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode);
+
+  // Use this if you do not want to take ownership.
+  CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode);
+
+  ~CPUMappedBuffer();
+
+  // Getters.
+  size_t Size() const { return size_; }
+  void* Address() const { return address_; }
+  bool IsMapped() const { return Address() != nullptr; }
+
+  // Attempt mapping this buffer to the CPU addressable space.
+  // This will create a display client and see if the buffer exists.
+  // If the buffer has not been setup yet, you will need to try again later.
+  void TryMapping();
+
+ protected:
+  // The memory area if we managed to map it.
+  size_t size_ = 0;
+  void* address_ = nullptr;
+
+  // If we are polling the display client, the buffer key here.
+  DvrGlobalBufferKey buffer_key_;
+
+  // If we just own the IonBuffer outright, it's here.
+  std::unique_ptr<IonBuffer> owned_buffer_ = nullptr;
+
+  // The last time we connected to the display service.
+  int64_t last_display_service_connection_ns_ = 0;
+
+  // If we do not own the IonBuffer, it's here
+  IonBuffer* buffer_ = nullptr;
+
+  // The usage mode.
+  CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN;
+};
+
+// Represents a broadcast ring inside a mapped shared memory buffer.
+// If has the same set of constructors as CPUMappedBuffer.
+// The template argument is the concrete BroadcastRing class that this buffer
+// holds.
+template <class RingType>
+class CPUMappedBroadcastRing : public CPUMappedBuffer {
+ public:
+  CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode)
+      : CPUMappedBuffer(key, mode) {}
+
+  CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode)
+      : CPUMappedBuffer(std::move(buffer), mode) {}
+
+  CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode)
+      : CPUMappedBuffer(buffer, mode) {}
+
+  // Helper function for publishing records in the ring.
+  void Publish(const typename RingType::Record& record) {
+    assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) ||
+           (usage_mode_ == CPUUsageMode::WRITE_RARELY));
+
+    auto ring = Ring();
+    if (ring) {
+      ring->Put(record);
+    }
+  }
+
+  // Helper function for getting records from the ring.
+  // Returns true if we were able to retrieve the latest.
+  bool GetNewest(typename RingType::Record* record) {
+    assert((usage_mode_ == CPUUsageMode::READ_OFTEN) ||
+           (usage_mode_ == CPUUsageMode::READ_RARELY));
+
+    auto ring = Ring();
+    if (ring) {
+      return ring->GetNewest(&sequence_, record);
+    }
+
+    return false;
+  }
+
+  // Try obtaining the ring. If the named buffer has not been created yet, it
+  // will return nullptr.
+  RingType* Ring() {
+    if (IsMapped() == false) {
+      TryMapping();
+
+      if (IsMapped()) {
+        switch (usage_mode_) {
+          case CPUUsageMode::READ_OFTEN:
+          case CPUUsageMode::READ_RARELY: {
+            RingType ring;
+            bool import_ok;
+            std::tie(ring, import_ok) = RingType::Import(address_, size_);
+            if (import_ok) {
+              ring_ = std::make_unique<RingType>(ring);
+            }
+          } break;
+          case CPUUsageMode::WRITE_OFTEN:
+          case CPUUsageMode::WRITE_RARELY:
+            ring_ =
+                std::make_unique<RingType>(RingType::Create(address_, size_));
+            break;
+        }
+      }
+    }
+
+    return ring_.get();
+  }
+
+ protected:
+  std::unique_ptr<RingType> ring_ = nullptr;
+
+  uint32_t sequence_ = 0;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
diff --git a/libs/vr/libdisplay/late_latch.cpp b/libs/vr/libdisplay/late_latch.cpp
deleted file mode 100644
index e67f009..0000000
--- a/libs/vr/libdisplay/late_latch.cpp
+++ /dev/null
@@ -1,460 +0,0 @@
-#include "include/private/dvr/late_latch.h"
-
-#include <unistd.h>
-
-#include <fstream>
-#include <iostream>
-#include <string>
-
-#include <log/log.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/debug.h>
-#include <private/dvr/graphics/gpu_profiler.h>
-#include <private/dvr/pose_client_internal.h>
-#include <private/dvr/sensor_constants.h>
-#include <private/dvr/types.h>
-
-#define PRINT_MATRIX 0
-
-#if PRINT_MATRIX
-#ifndef LOG_TAG
-#define LOG_TAG "latelatch"
-#endif
-
-#define PE(str, ...)                                                  \
-  fprintf(stderr, "[%s:%d] " str, __FILE__, __LINE__, ##__VA_ARGS__); \
-  ALOGI("[%s:%d] " str, __FILE__, __LINE__, ##__VA_ARGS__)
-
-#define PV4(v) PE(#v "=%f,%f,%f,%f\n", v[0], v[1], v[2], v[3]);
-#define PM4(m)                                                               \
-  PE(#m ":\n %f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f\n",       \
-     m(0, 0), m(0, 1), m(0, 2), m(0, 3), m(1, 0), m(1, 1), m(1, 2), m(1, 3), \
-     m(2, 0), m(2, 1), m(2, 2), m(2, 3), m(3, 0), m(3, 1), m(3, 2), m(3, 3))
-#endif  // PRINT_MATRIX
-
-#define STRINGIFY2(s) #s
-#define STRINGIFY(s) STRINGIFY2(s)
-
-// Compute shader bindings.
-// GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS must be at least 8 for GLES 3.1.
-#define POSE_BINDING 0
-#define RENDER_POSE_BINDING 1
-#define INPUT_BINDING 2
-#define OUTPUT_BINDING 3
-
-using android::pdx::LocalHandle;
-
-namespace {
-
-static const std::string kShaderLateLatch = R"(  // NOLINT
-  struct Pose {
-    vec4 quat;
-    vec3 pos;
-  };
-
-  // Must match DvrPoseAsync C struct.
-  struct DvrPoseAsync {
-    vec4 orientation;
-    vec4 translation;
-    vec4 right_orientation;
-    vec4 right_translation;
-    vec4 angular_velocity;
-    vec4 velocity;
-    vec4 reserved[2];
-  };
-
-  // Must match LateLatchInputData C struct.
-  layout(binding = INPUT_BINDING, std140)
-  buffer InputData {
-    mat4 uEyeFromHeadMat[kSurfaceViewMaxCount];
-    mat4 uProjMat[kSurfaceViewMaxCount];
-    mat4 uPoseOffset[kSurfaceViewMaxCount];
-    mat4 uEdsMat1[kSurfaceViewMaxCount];
-    mat4 uEdsMat2[kSurfaceViewMaxCount];
-    uint uPoseIndex;
-    uint uRenderPoseIndex;
-  } bIn;
-
-  // std140 is to layout the structure in a consistent, standard way so we
-  // can access it from C++.
-  // This structure exactly matches the pose ring buffer in pose_client.h.
-  layout(binding = POSE_BINDING, std140)
-  buffer PoseBuffer {
-    DvrPoseAsync data[kPoseAsyncBufferTotalCount];
-  } bPose;
-
-  // Must stay in sync with DisplaySurfaceMetadata C struct.
-  // GPU thread 0 will exclusively read in a pose and capture it
-  // into this array.
-  layout(binding = RENDER_POSE_BINDING, std140)
-  buffer DisplaySurfaceMetadata {
-    vec4 orientation[kSurfaceBufferMaxCount];
-    vec4 translation[kSurfaceBufferMaxCount];
-  } bSurfaceData;
-
-  // Must stay in sync with DisplaySurfaceMetadata C struct.
-  // Each thread writes to a vertic
-  layout(binding = OUTPUT_BINDING, std140)
-  buffer Output {
-    mat4 viewProjMatrix[kSurfaceViewMaxCount];
-    mat4 viewMatrix[kSurfaceViewMaxCount];
-    vec4 quaternion;
-    vec4 translation;
-  } bOut;
-
-  // Thread 0 will also store the single quat/pos pair in shared variables
-  // for the other threads to use (left and right eye in this array).
-  shared Pose sharedPose[2];
-
-  // Rotate v1 by the given quaternion. This is based on mathfu's
-  // Quaternion::Rotate function. It is the typical implementation of this
-  // operation. Eigen has a similar method (Quaternion::_transformVector) that
-  // supposedly requires fewer operations, but I am skeptical of optimizing
-  // shader code without proper profiling first.
-  vec3 rotate(vec4 quat, vec3 v1) {
-    float ss = 2.0 * quat.w;
-    vec3 v = quat.xyz;
-    return ss * cross(v, v1) + (ss * quat.w - 1.0) * v1 +
-           2.0 * dot(v, v1) * v;
-  }
-
-  // See Eigen Quaternion::conjugate;
-  // Note that this isn't a true multiplicative inverse unless you can guarantee
-  // quat is also normalized, but that typically isn't an issue for our
-  // purposes.
-  vec4 quatInvert(vec4 quat) {
-    return vec4(-quat.xyz, quat.w);
-  }
-
-  // This is based on mathfu's Quaternion::operator*(Quaternion)
-  // Eigen's version is mathematically equivalent, just notationally different.
-  vec4 quatMul(vec4 q1, vec4 q2) {
-    return vec4(q1.w * q2.xyz + q2.w * q1.xyz + cross(q1.xyz, q2.xyz),
-                q1.w * q2.w - dot(q1.xyz, q2.xyz));
-  }
-
-  // Equivalent to pose.h GetObjectFromReferenceMatrix.
-  mat4 getInverseMatrix(Pose pose) {
-    // Invert quaternion and store fields the way Eigen does so we can
-    // keep in sync with Eigen methods easier.
-    vec4 quatInv = quatInvert(pose.quat);
-    vec3 v = quatInv.xyz;
-    float s = quatInv.w;
-    // Convert quaternion to matrix. See Eigen Quaternion::toRotationMatrix()
-    float x2 = v.x * v.x, y2 = v.y * v.y, z2 = v.z * v.z;
-    float sx = s * v.x, sy = s * v.y, sz = s * v.z;
-    float xz = v.x * v.z, yz = v.y * v.z, xy = v.x * v.y;
-    // Inverse translation.
-    vec3 point = -pose.pos;
-
-    return
-      mat4(1.0 - 2.0 * (y2 + z2), 2.0 * (xy + sz), 2.0 * (xz - sy), 0.0,
-           2.0 * (xy - sz), 1.0 - 2.0 * (x2 + z2), 2.0 * (sx + yz), 0.0,
-           2.0 * (sy + xz), 2.0 * (yz - sx), 1.0 - 2.0 * (x2 + y2), 0.0,
-           0.0, 0.0, 0.0, 1.0)*
-      mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
-           point.x, point.y, point.z, 1.0);
-  }
-
-  void appLateLatch() {
-    uint poseIndex = (gl_LocalInvocationIndex & uint(1));
-    mat4 head_from_center = getInverseMatrix(sharedPose[poseIndex]);
-    bOut.viewMatrix[gl_LocalInvocationIndex] =
-        bIn.uEyeFromHeadMat[gl_LocalInvocationIndex] *
-        head_from_center * bIn.uPoseOffset[gl_LocalInvocationIndex];
-    bOut.viewProjMatrix[gl_LocalInvocationIndex] =
-        bIn.uProjMat[gl_LocalInvocationIndex] *
-        bOut.viewMatrix[gl_LocalInvocationIndex];
-  }
-
-  // Extract the app frame's pose.
-  Pose getPoseFromApp() {
-    Pose p;
-    p.quat = bSurfaceData.orientation[bIn.uRenderPoseIndex];
-    p.pos =  bSurfaceData.translation[bIn.uRenderPoseIndex].xyz;
-    return p;
-  }
-
-  // See Posef::GetPoseOffset.
-  Pose getPoseOffset(Pose p1, Pose p2) {
-    Pose p;
-    p.quat = quatMul(quatInvert(p2.quat), p1.quat);
-    // TODO(jbates) Consider enabling positional EDS when it is better
-    //              tested.
-    // p.pos = p2.pos - p1.pos;
-    p.pos = vec3(0.0);
-    return p;
-  }
-
-  void edsLateLatch() {
-    Pose pose1 = getPoseFromApp();
-    Pose correction;
-    // Ignore the texture pose if the quat is not unit-length.
-    float tex_quat_length = length(pose1.quat);
-    uint poseIndex = (gl_LocalInvocationIndex & uint(1));
-    if (abs(tex_quat_length - 1.0) < 0.001)
-      correction = getPoseOffset(pose1, sharedPose[poseIndex]);
-    else
-      correction = Pose(vec4(0, 0, 0, 1), vec3(0, 0, 0));
-    mat4 eye_old_from_eye_new_matrix = getInverseMatrix(correction);
-    bOut.viewProjMatrix[gl_LocalInvocationIndex] =
-        bIn.uEdsMat1[gl_LocalInvocationIndex] *
-        eye_old_from_eye_new_matrix * bIn.uEdsMat2[gl_LocalInvocationIndex];
-    // Currently unused, except for debugging:
-    bOut.viewMatrix[gl_LocalInvocationIndex] = eye_old_from_eye_new_matrix;
-  }
-
-  // One thread per surface view.
-  layout (local_size_x = kSurfaceViewMaxCount, local_size_y = 1,
-          local_size_z = 1) in;
-
-  void main() {
-    // First, thread 0 late latches pose and stores it into various places.
-    if (gl_LocalInvocationIndex == uint(0)) {
-      sharedPose[0].quat = bPose.data[bIn.uPoseIndex].orientation;
-      sharedPose[0].pos =  bPose.data[bIn.uPoseIndex].translation.xyz;
-      sharedPose[1].quat = bPose.data[bIn.uPoseIndex].right_orientation;
-      sharedPose[1].pos =  bPose.data[bIn.uPoseIndex].right_translation.xyz;
-      if (IS_APP_LATE_LATCH) {
-        bSurfaceData.orientation[bIn.uRenderPoseIndex] = sharedPose[0].quat;
-        bSurfaceData.translation[bIn.uRenderPoseIndex] = vec4(sharedPose[0].pos, 0.0);
-        // TODO(jbates) implement app late-latch support for separate eye poses.
-        // App late latch currently uses the same pose for both eye views.
-        sharedPose[1] = sharedPose[0];
-      }
-      bOut.quaternion = sharedPose[0].quat;
-      bOut.translation = vec4(sharedPose[0].pos, 0.0);
-    }
-
-    // Memory barrier to make sure all threads can see prior writes.
-    memoryBarrierShared();
-
-    // Execution barrier to block all threads here until all threads have
-    // reached this point -- ensures the late latching is done.
-    barrier();
-
-    if (IS_APP_LATE_LATCH)
-      appLateLatch();
-    else
-      edsLateLatch();
-  }
-)";
-
-}  // anonymous namespace
-
-namespace android {
-namespace dvr {
-
-LateLatch::LateLatch(bool is_app_late_latch)
-    : LateLatch(is_app_late_latch, LocalHandle()) {}
-
-LateLatch::LateLatch(bool is_app_late_latch,
-                     LocalHandle&& surface_metadata_fd)
-    : is_app_late_latch_(is_app_late_latch),
-      app_late_latch_output_(NULL),
-      eds_late_latch_output_(NULL),
-      surface_metadata_fd_(std::move(surface_metadata_fd)) {
-  CHECK_GL();
-  glGenBuffers(1, &input_buffer_id_);
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, input_buffer_id_);
-  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LateLatchInput), nullptr,
-               GL_DYNAMIC_DRAW);
-  glGenBuffers(1, &output_buffer_id_);
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, output_buffer_id_);
-  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LateLatchOutput), nullptr,
-               GL_DYNAMIC_COPY);
-  CHECK_GL();
-
-  pose_client_ = dvrPoseCreate();
-  if (!pose_client_) {
-    ALOGE("LateLatch Error: failed to create pose client");
-  } else {
-    int ret = privateDvrPoseGetRingBufferFd(pose_client_, &pose_buffer_fd_);
-    if (ret < 0) {
-      ALOGE("LateLatch Error: failed to get pose ring buffer");
-    }
-  }
-
-  glGenBuffers(1, &pose_buffer_object_);
-  glGenBuffers(1, &metadata_buffer_id_);
-  if (!glBindSharedBufferQCOM) {
-    ALOGE("Error: Missing gralloc buffer extension, no pose data");
-  } else {
-    if (pose_buffer_fd_) {
-      glBindBuffer(GL_SHADER_STORAGE_BUFFER, pose_buffer_object_);
-      glBindSharedBufferQCOM(GL_SHADER_STORAGE_BUFFER,
-                             kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync),
-                             pose_buffer_fd_.Get());
-    }
-    CHECK_GL();
-  }
-
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, metadata_buffer_id_);
-  if (surface_metadata_fd_ && glBindSharedBufferQCOM) {
-    glBindSharedBufferQCOM(GL_SHADER_STORAGE_BUFFER,
-                           sizeof(DisplaySurfaceMetadata),
-                           surface_metadata_fd_.Get());
-  } else {
-    // Fall back on internal metadata buffer when none provided, for example
-    // when distortion is done in the application process.
-    glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(DisplaySurfaceMetadata),
-                 nullptr, GL_DYNAMIC_COPY);
-  }
-  CHECK_GL();
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
-
-  CHECK_GL();
-  LoadLateLatchShader();
-}
-
-LateLatch::~LateLatch() {
-  glDeleteBuffers(1, &metadata_buffer_id_);
-  glDeleteBuffers(1, &input_buffer_id_);
-  glDeleteBuffers(1, &output_buffer_id_);
-  glDeleteBuffers(1, &pose_buffer_object_);
-  dvrPoseDestroy(pose_client_);
-}
-
-void LateLatch::LoadLateLatchShader() {
-  std::string str;
-  str += "\n#define POSE_BINDING " STRINGIFY(POSE_BINDING);
-  str += "\n#define RENDER_POSE_BINDING " STRINGIFY(RENDER_POSE_BINDING);
-  str += "\n#define INPUT_BINDING " STRINGIFY(INPUT_BINDING);
-  str += "\n#define OUTPUT_BINDING " STRINGIFY(OUTPUT_BINDING);
-  str += "\n#define kPoseAsyncBufferTotalCount " STRINGIFY(
-      kPoseAsyncBufferTotalCount);
-  str += "\n#define kSurfaceBufferMaxCount " STRINGIFY(kSurfaceBufferMaxCount);
-  str += "\n#define kSurfaceBufferMaxCount " STRINGIFY(kSurfaceBufferMaxCount);
-  str += "\n#define kSurfaceViewMaxCount " STRINGIFY(kSurfaceViewMaxCount);
-  str += "\n#define IS_APP_LATE_LATCH ";
-  str += is_app_late_latch_ ? "true" : "false";
-  str += "\n";
-  str += kShaderLateLatch;
-  late_latch_program_.Link(str);
-  CHECK_GL();
-}
-
-void LateLatch::CaptureOutputData(LateLatchOutput* data) const {
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, output_buffer_id_);
-  LateLatchOutput* out_data = static_cast<LateLatchOutput*>(glMapBufferRange(
-      GL_SHADER_STORAGE_BUFFER, 0, sizeof(LateLatchOutput), GL_MAP_READ_BIT));
-  *data = *out_data;
-  glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
-  CHECK_GL();
-}
-
-void LateLatch::AddLateLatch(const LateLatchInput& data) const {
-  LOG_ALWAYS_FATAL_IF(!is_app_late_latch_);
-  CHECK_GL();
-  late_latch_program_.Use();
-
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, RENDER_POSE_BINDING,
-                   metadata_buffer_id_);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, POSE_BINDING, pose_buffer_object_);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BINDING, output_buffer_id_);
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, input_buffer_id_);
-  LateLatchInput* adata = (LateLatchInput*)glMapBufferRange(
-      GL_SHADER_STORAGE_BUFFER, 0, sizeof(LateLatchInput),
-      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
-  if (adata)
-    *adata = data;
-  else
-    ALOGE("Error: LateLatchInput gl mapping is null");
-  glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BINDING, input_buffer_id_);
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
-  CHECK_GL();
-
-  // The output buffer is going to be written but it may be read by
-  // earlier shaders, so we need a shader storage memory barrier.
-  glMemoryBarrier(GL_SHADER_STORAGE_BUFFER);
-
-  glDispatchCompute(1, 1, 1);
-  CHECK_GL();
-
-  // The transform feedback buffer is going to be read as a uniform by the app,
-  // so we need a uniform memory barrier.
-  glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
-
-  if (app_late_latch_output_) {
-    // Capture the output data:
-    CaptureOutputData(app_late_latch_output_);
-  }
-#if PRINT_MATRIX
-  // Print the composed matrix to stderr:
-  LateLatchOutput out_data;
-  CaptureOutputData(&out_data);
-  CHECK_GL();
-  PE("LL APP slot:%d\n", data.render_pose_index);
-  PM4(data.proj_mat[0]);
-  PM4(out_data.view_proj_matrix[0]);
-  PM4(out_data.view_proj_matrix[1]);
-  PM4(out_data.view_proj_matrix[2]);
-  PM4(out_data.view_proj_matrix[3]);
-  PM4(out_data.view_matrix[0]);
-  PM4(out_data.view_matrix[1]);
-  PM4(out_data.view_matrix[2]);
-  PM4(out_data.view_matrix[3]);
-  PV4(out_data.pose_quaternion);
-  PV4(out_data.pose_translation);
-#endif
-
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, RENDER_POSE_BINDING, 0);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, POSE_BINDING, 0);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BINDING, 0);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BINDING, 0);
-  glUseProgram(0);
-}
-
-void LateLatch::AddEdsLateLatch(const LateLatchInput& data,
-                                GLuint render_pose_buffer_object) const {
-  LOG_ALWAYS_FATAL_IF(is_app_late_latch_);
-  late_latch_program_.Use();
-
-  // Fall back on internal buffer when none is provided.
-  if (!render_pose_buffer_object)
-    render_pose_buffer_object = metadata_buffer_id_;
-
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, RENDER_POSE_BINDING,
-                   render_pose_buffer_object);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, POSE_BINDING, pose_buffer_object_);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BINDING, output_buffer_id_);
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, input_buffer_id_);
-  LateLatchInput* adata = (LateLatchInput*)glMapBufferRange(
-      GL_SHADER_STORAGE_BUFFER, 0, sizeof(LateLatchInput),
-      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
-  *adata = data;
-  glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
-  glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BINDING, input_buffer_id_);
-  CHECK_GL();
-
-  glDispatchCompute(1, 1, 1);
-  CHECK_GL();
-
-  if (eds_late_latch_output_) {
-    // Capture the output data:
-    CaptureOutputData(eds_late_latch_output_);
-  }
-#if PRINT_MATRIX
-  // Print the composed matrix to stderr:
-  LateLatchOutput out_data;
-  CaptureOutputData(&out_data);
-  CHECK_GL();
-  PE("LL EDS\n");
-  PM4(out_data.view_proj_matrix[0]);
-  PM4(out_data.view_matrix[0]);
-  PV4(out_data.pose_quaternion);
-  PV4(out_data.pose_translation);
-#endif
-
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, RENDER_POSE_BINDING, 0);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, POSE_BINDING, 0);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BINDING, 0);
-  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BINDING, 0);
-  glUseProgram(0);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdisplay/native_buffer_queue.cpp b/libs/vr/libdisplay/native_buffer_queue.cpp
deleted file mode 100644
index 1bb05d8..0000000
--- a/libs/vr/libdisplay/native_buffer_queue.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "include/private/dvr/native_buffer_queue.h"
-
-#include <log/log.h>
-#include <sys/epoll.h>
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Trace.h>
-
-#include <array>
-
-#include <dvr/dvr_display_types.h>
-
-namespace android {
-namespace dvr {
-namespace display {
-
-NativeBufferQueue::NativeBufferQueue(
-    EGLDisplay display, const std::shared_ptr<ProducerQueue>& producer_queue,
-    uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
-    size_t capacity)
-    : display_(display),
-      width_(width),
-      height_(height),
-      format_(format),
-      usage_(usage),
-      producer_queue_(producer_queue),
-      buffers_(capacity) {
-  for (size_t i = 0; i < capacity; i++) {
-    size_t slot;
-    // TODO(jwcai) Should change to use BufferViewPort's spec to config.
-    const int ret = producer_queue_->AllocateBuffer(width_, height_, 1, format_,
-                                                    usage_, &slot);
-    if (ret < 0) {
-      ALOGE(
-          "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer: %s",
-          strerror(-ret));
-      return;
-    }
-
-    ALOGD_IF(TRACE, "NativeBufferQueue::NativeBufferQueue: slot=%zu", slot);
-  }
-}
-
-NativeBufferProducer* NativeBufferQueue::Dequeue() {
-  ATRACE_NAME("NativeBufferQueue::Dequeue");
-  size_t slot;
-  pdx::LocalHandle fence;
-  auto buffer_status = producer_queue_->Dequeue(-1, &slot, &fence);
-  if (!buffer_status) {
-    ALOGE("NativeBufferQueue::Dequeue: Failed to dequeue buffer: %s",
-          buffer_status.GetErrorMessage().c_str());
-    return nullptr;
-  }
-
-  if (buffers_[slot] == nullptr)
-    buffers_[slot] =
-        new NativeBufferProducer(buffer_status.take(), display_, slot);
-
-  ALOGD_IF(TRACE, "NativeBufferQueue::Dequeue: slot=%zu buffer=%p", slot,
-           buffers_[slot].get());
-  return buffers_[slot].get();
-}
-
-}  // namespace display
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdisplay/shared_buffer_helpers.cpp b/libs/vr/libdisplay/shared_buffer_helpers.cpp
new file mode 100644
index 0000000..6ebf487
--- /dev/null
+++ b/libs/vr/libdisplay/shared_buffer_helpers.cpp
@@ -0,0 +1,98 @@
+#include <private/dvr/clock_ns.h>
+#include <private/dvr/shared_buffer_helpers.h>
+
+namespace android {
+namespace dvr {
+namespace {
+
+// We will not poll the display service for buffers more frequently than this.
+constexpr size_t kDisplayServiceTriesPerSecond = 2;
+}  // namespace
+
+CPUMappedBuffer::CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode)
+    : buffer_key_(key), usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer,
+                                 CPUUsageMode mode)
+    : owned_buffer_(std::move(buffer)),
+      buffer_(owned_buffer_.get()),
+      usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode)
+    : buffer_(buffer), usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::~CPUMappedBuffer() {
+  if (IsMapped()) {
+    buffer_->Unlock();
+  }
+}
+
+void CPUMappedBuffer::TryMapping() {
+  // Do we have an IonBuffer for this shared memory object?
+  if (buffer_ == nullptr) {
+    // Has it been too long since we last connected to the display service?
+    const auto current_time_ns = GetSystemClockNs();
+    if ((current_time_ns - last_display_service_connection_ns_) <
+        (1e9 / kDisplayServiceTriesPerSecond)) {
+      // Early exit.
+      return;
+    }
+    last_display_service_connection_ns_ = current_time_ns;
+
+    // Create a display client and get the buffer.
+    auto display_client = display::DisplayClient::Create();
+    if (display_client) {
+      auto get_result = display_client->GetGlobalBuffer(buffer_key_);
+      if (get_result.ok()) {
+        owned_buffer_ = get_result.take();
+        buffer_ = owned_buffer_.get();
+      } else {
+        // The buffer has not been created yet. This is OK, we will keep
+        // retrying.
+      }
+    } else {
+      ALOGE("Unable to create display client for shared buffer access");
+    }
+  }
+
+  if (buffer_) {
+    auto usage = buffer_->usage() & ~GRALLOC_USAGE_SW_READ_MASK &
+                 ~GRALLOC_USAGE_SW_WRITE_MASK;
+
+    // Figure out the usage bits.
+    switch (usage_mode_) {
+      case CPUUsageMode::READ_OFTEN:
+        usage |= GRALLOC_USAGE_SW_READ_OFTEN;
+        break;
+      case CPUUsageMode::READ_RARELY:
+        usage |= GRALLOC_USAGE_SW_READ_RARELY;
+        break;
+      case CPUUsageMode::WRITE_OFTEN:
+        usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+        break;
+      case CPUUsageMode::WRITE_RARELY:
+        usage |= GRALLOC_USAGE_SW_WRITE_RARELY;
+        break;
+    }
+
+    int width = static_cast<int>(buffer_->width());
+    int height = 1;
+    const auto ret = buffer_->Lock(usage, 0, 0, width, height, &address_);
+
+    if (ret < 0 || !address_) {
+      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, address_);
+      buffer_->Unlock();
+    } else {
+      size_ = width;
+    }
+  }
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libdisplay/tests/dummy_native_window_tests.cpp b/libs/vr/libdisplay/tests/dummy_native_window_tests.cpp
deleted file mode 100644
index 5f3ff53..0000000
--- a/libs/vr/libdisplay/tests/dummy_native_window_tests.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#include <private/dvr/dummy_native_window.h>
-#include <gtest/gtest.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-
-class DummyNativeWindowTests : public ::testing::Test {
- public:
-  EGLDisplay display_;
-  bool initialized_;
-
-  DummyNativeWindowTests()
-      : display_(nullptr)
-      , initialized_(false)
-  {
-  }
-
-  virtual void SetUp() {
-    display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
-    ASSERT_NE(nullptr, display_);
-    initialized_ = eglInitialize(display_, nullptr, nullptr);
-
-    ASSERT_TRUE(initialized_);
-  }
-
-  virtual void TearDown() {
-    if (display_ && initialized_) {
-      eglTerminate(display_);
-    }
-  }
-};
-
-// Test that eglCreateWindowSurface works with DummyNativeWindow
-TEST_F(DummyNativeWindowTests, TryCreateEglWindow) {
-  EGLint attribs[] = {
-      EGL_NONE,
-  };
-
-  EGLint num_configs;
-  EGLConfig config;
-  ASSERT_TRUE(eglChooseConfig(display_, attribs, &config, 1, &num_configs));
-
-  std::unique_ptr<android::dvr::DummyNativeWindow> dummy_window(
-      new android::dvr::DummyNativeWindow());
-
-  EGLint context_attribs[] = {
-    EGL_NONE,
-  };
-
-  EGLSurface surface = eglCreateWindowSurface(display_, config,
-                                              dummy_window.get(),
-                                              context_attribs);
-
-  EXPECT_NE(nullptr, surface);
-
-  bool destroyed = eglDestroySurface(display_, surface);
-
-  EXPECT_TRUE(destroyed);
-}
-
diff --git a/libs/vr/libdisplay/tests/graphics_app_tests.cpp b/libs/vr/libdisplay/tests/graphics_app_tests.cpp
deleted file mode 100644
index c592ba9..0000000
--- a/libs/vr/libdisplay/tests/graphics_app_tests.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-#include <dvr/graphics.h>
-#include <gtest/gtest.h>
-
-TEST(GraphicsAppTests, GetNativeDisplayDimensions) {
-  int width, height;
-  dvrGetNativeDisplayDimensions(&width, &height);
-  EXPECT_GT(width, 0);
-  EXPECT_GT(height, 0);
-}
-
-// TODO(jpoichet) How to check it worked?
-TEST(GraphicsAppTests, GraphicsSurfaceSetVisible) {
-  DvrSurfaceParameter surface_params[] = {DVR_SURFACE_PARAMETER_LIST_END};
-  DvrGraphicsContext* context = nullptr;
-  int result = dvrGraphicsContextCreate(surface_params, &context);
-  ASSERT_GE(result, 0);
-  ASSERT_NE(context, nullptr);
-  dvrGraphicsSurfaceSetVisible(context, 0);
-  dvrGraphicsSurfaceSetVisible(context, 1);
-  dvrGraphicsSurfaceSetVisible(context, 2);
-}
-
-// TODO(jpoichet) How to check it worked?
-TEST(GraphicsAppTests, GraphicsSurfaceSetZOrder) {
-  DvrSurfaceParameter surface_params[] = {DVR_SURFACE_PARAMETER_LIST_END};
-  DvrGraphicsContext* context = nullptr;
-  int result = dvrGraphicsContextCreate(surface_params, &context);
-  ASSERT_GE(result, 0);
-  ASSERT_NE(context, nullptr);
-  dvrGraphicsSurfaceSetZOrder(context, -1);
-  dvrGraphicsSurfaceSetZOrder(context, 0);
-  dvrGraphicsSurfaceSetZOrder(context, 1);
-  dvrGraphicsSurfaceSetZOrder(context, 2);
-}
-
-TEST(GraphicsAppTests, GraphicsContext) {
-  DvrGraphicsContext* context = 0;
-  int display_width = 0, display_height = 0;
-  int surface_width = 0, surface_height = 0;
-  float inter_lens_meters = 0.0f;
-  float left_fov[4] = {0.0f};
-  float right_fov[4] = {0.0f};
-  uint64_t vsync_period = 0;
-  int disable_warp = 0;
-  DvrSurfaceParameter surface_params[] = {
-      DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, disable_warp),
-      DVR_SURFACE_PARAMETER_OUT(DISPLAY_WIDTH, &display_width),
-      DVR_SURFACE_PARAMETER_OUT(DISPLAY_HEIGHT, &display_height),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &surface_width),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &surface_height),
-      DVR_SURFACE_PARAMETER_OUT(INTER_LENS_METERS, &inter_lens_meters),
-      DVR_SURFACE_PARAMETER_OUT(LEFT_FOV_LRBT, left_fov),
-      DVR_SURFACE_PARAMETER_OUT(RIGHT_FOV_LRBT, right_fov),
-      DVR_SURFACE_PARAMETER_OUT(VSYNC_PERIOD, &vsync_period),
-      DVR_SURFACE_PARAMETER_LIST_END,
-  };
-  dvrGraphicsContextCreate(surface_params, &context);
-  EXPECT_NE(nullptr, context);
-
-  dvrGraphicsSurfaceSetVisible(context, 1);
-
-  DvrFrameSchedule schedule;
-  int wait_result = dvrGraphicsWaitNextFrame(context, 0, &schedule);
-  EXPECT_EQ(wait_result, 0);
-  EXPECT_GE(schedule.vsync_count, 0u);
-
-  dvrBeginRenderFrame(context);
-
-  // Check range of vsync period from 60fps to 100fps.
-  // TODO(jbates) Once we have stable hardware, clamp this range down further.
-  EXPECT_LE(vsync_period, 1000000000ul / 60ul);
-  EXPECT_GE(vsync_period, 1000000000ul / 100ul);
-
-  dvrPresent(context);
-  dvrGraphicsContextDestroy(context);
-}
-
-TEST(GraphicsAppTests, CustomSurfaceSize) {
-  DvrGraphicsContext* context = 0;
-  int display_width = 0, display_height = 0;
-  int surface_width = 0, surface_height = 0;
-  float inter_lens_meters = 0.0f;
-  float left_fov[4] = {0.0f};
-  float right_fov[4] = {0.0f};
-  int disable_warp = 0;
-  int req_width = 256, req_height = 128;
-  DvrSurfaceParameter surface_params[] = {
-      DVR_SURFACE_PARAMETER_IN(WIDTH, req_width),
-      DVR_SURFACE_PARAMETER_IN(HEIGHT, req_height),
-      DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, disable_warp),
-      DVR_SURFACE_PARAMETER_OUT(DISPLAY_WIDTH, &display_width),
-      DVR_SURFACE_PARAMETER_OUT(DISPLAY_HEIGHT, &display_height),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &surface_width),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &surface_height),
-      DVR_SURFACE_PARAMETER_OUT(INTER_LENS_METERS, &inter_lens_meters),
-      DVR_SURFACE_PARAMETER_OUT(LEFT_FOV_LRBT, left_fov),
-      DVR_SURFACE_PARAMETER_OUT(RIGHT_FOV_LRBT, right_fov),
-      DVR_SURFACE_PARAMETER_LIST_END,
-  };
-  dvrGraphicsContextCreate(surface_params, &context);
-  EXPECT_NE(nullptr, context);
-
-  EXPECT_EQ(req_width, surface_width);
-  EXPECT_EQ(req_height, surface_height);
-  dvrGraphicsContextDestroy(context);
-}
-
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index fa78b1c..4650871 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -27,6 +27,7 @@
     "dvr_api.cpp",
     "dvr_buffer.cpp",
     "dvr_buffer_queue.cpp",
+    "dvr_configuration_data.cpp",
     "dvr_display_manager.cpp",
     "dvr_hardware_composer_client.cpp",
     "dvr_surface.cpp",
@@ -34,10 +35,11 @@
 ]
 
 static_libs = [
+    "libbroadcastring",
     "libbufferhub",
     "libbufferhubqueue",
-    "libdisplay",
     "libvrsensor",
+    "libdisplay",
     "libvirtualtouchpadclient",
     "libvr_hwc-impl",
     "libvr_hwc-binder",
diff --git a/libs/vr/libdvr/build_sdk.py b/libs/vr/libdvr/build_sdk.py
new file mode 100755
index 0000000..b3c2e44
--- /dev/null
+++ b/libs/vr/libdvr/build_sdk.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+import sys
+import os
+import argparse
+
+# Run this script to generate dvr_api.h in the current directory.
+
+def make_argument_parser():
+  parser = argparse.ArgumentParser(
+      description='Process DVR API headers into exportable SDK files.')
+  return parser
+
+parser = make_argument_parser()
+
+in_file = open("include/dvr/dvr_api.h", "r")
+out_file = open("./dvr_api.h", "w")
+
+h_filename = ""
+for line in in_file:
+  if line.startswith("// dvr_") and line.endswith(".h\n"):
+    h_filename = "include/dvr/" + line[3:].strip()
+  if line.startswith("typedef ") and "(*Dvr" in line:
+    start = line.find("(*Dvr") + 5
+    end = line.find("Ptr)")
+    if end != -1:
+      name = "dvr" + line[start:end]
+      # Find the comments for this function and insert into output.
+      with open(h_filename, 'r') as h_file:
+        h_lines = h_file.readlines()
+        i = 1
+        while i < len(h_lines):
+          if name in h_lines[i]:
+            end_i = i
+            while h_lines[i - 1].startswith("//"): i -= 1
+            while i < end_i:
+              out_file.write(h_lines[i])
+              i += 1
+            break
+          i += 1
+  if line.startswith('#include "dvr_api_entries.h"'):
+    with open("include/dvr/dvr_api_entries.h") as f:
+      out_file.write(f.read())
+  else:
+    out_file.write(line)
+
+in_file.close()
+out_file.close()
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 2c95583..5f35dcf 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -6,6 +6,7 @@
 // Headers from libdvr
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_configuration_data.h>
 #include <dvr/dvr_display_manager.h>
 #include <dvr/dvr_surface.h>
 #include <dvr/dvr_vsync.h>
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 95c0e26..f668510 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -75,16 +75,8 @@
 
   // Lazy creation of |native_window|.
   if (write_queue->native_window == nullptr) {
-    std::shared_ptr<dvr::BufferHubQueueCore> core =
-        dvr::BufferHubQueueCore::Create(write_queue->producer_queue);
-    if (core == nullptr) {
-      ALOGE(
-          "dvrWriteBufferQueueGetExternalSurface: Failed to create native "
-          "window.");
-      return -ENOMEM;
-    }
-
-    sp<IGraphicBufferProducer> gbp = new dvr::BufferHubQueueProducer(core);
+    sp<IGraphicBufferProducer> gbp =
+        dvr::BufferHubQueueProducer::Create(write_queue->producer_queue);
     sp<Surface> surface = new Surface(gbp, true);
     write_queue->native_window = static_cast<ANativeWindow*>(surface.get());
     ANativeWindow_acquire(write_queue->native_window);
diff --git a/libs/vr/libdvr/dvr_configuration_data.cpp b/libs/vr/libdvr/dvr_configuration_data.cpp
new file mode 100644
index 0000000..df0d54e
--- /dev/null
+++ b/libs/vr/libdvr/dvr_configuration_data.cpp
@@ -0,0 +1,40 @@
+#include "include/dvr/dvr_configuration_data.h"
+
+#include <private/dvr/display_client.h>
+
+using android::dvr::display::ConfigFileType;
+using android::dvr::display::DisplayClient;
+
+extern "C" {
+
+int dvrConfigurationDataGet(int config_type, uint8_t** data,
+                            size_t* data_size) {
+  if (!data || !data_size) {
+    return -EINVAL;
+  }
+
+  auto client = DisplayClient::Create();
+  if (!client) {
+    ALOGE("dvrGetGlobalBuffer: Failed to create display client!");
+    return -ECOMM;
+  }
+
+  ConfigFileType config_file_type = static_cast<ConfigFileType>(config_type);
+  auto config_data_status =
+      client->GetConfigurationData(config_file_type);
+
+  if (!config_data_status) {
+    return -config_data_status.error();
+  }
+
+  *data_size = config_data_status.get().size();
+  *data = new uint8_t[*data_size];
+  std::copy_n(config_data_status.get().begin(), *data_size, *data);
+  return 0;
+}
+
+void dvrConfigurationDataDestroy(uint8_t* data) {
+  delete[] data;
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
index 87636ec..97cd4ee 100644
--- a/libs/vr/libdvr/dvr_display_manager.cpp
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -5,6 +5,7 @@
 #include <private/android/AHardwareBufferHelpers.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_client.h>
 #include <private/dvr/display_manager_client.h>
 
 #include "dvr_internal.h"
@@ -111,19 +112,20 @@
 
 void dvrDisplayManagerDestroy(DvrDisplayManager* client) { delete client; }
 
-int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
-                                      const char* name, size_t size,
-                                      uint64_t usage, DvrBuffer** buffer_out) {
-  if (!client || !name || !buffer_out)
+int dvrDisplayManagerSetupGlobalBuffer(DvrDisplayManager* client,
+                                       DvrGlobalBufferKey key, size_t size,
+                                       uint64_t usage, DvrBuffer** buffer_out) {
+  if (!client || !buffer_out)
     return -EINVAL;
 
   uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
 
   auto buffer_status =
-      client->client->SetupNamedBuffer(name, size, gralloc_usage);
+      client->client->SetupGlobalBuffer(key, size, gralloc_usage);
   if (!buffer_status) {
-    ALOGE("dvrDisplayManagerSetupPoseBuffer: Failed to setup named buffer: %s",
-          buffer_status.GetErrorMessage().c_str());
+    ALOGE(
+        "dvrDisplayManagerSetupGlobalBuffer: Failed to setup global buffer: %s",
+        buffer_status.GetErrorMessage().c_str());
     return -buffer_status.error();
   }
 
@@ -131,6 +133,23 @@
   return 0;
 }
 
+int dvrDisplayManagerDeleteGlobalBuffer(DvrDisplayManager* client,
+                                        DvrGlobalBufferKey key) {
+  if (!client)
+    return -EINVAL;
+
+  auto buffer_status = client->client->DeleteGlobalBuffer(key);
+  if (!buffer_status) {
+    ALOGE(
+        "dvrDisplayManagerDeleteGlobalBuffer: Failed to delete named buffer: "
+        "%s",
+        buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
+  }
+
+  return 0;
+}
+
 int dvrDisplayManagerGetEventFd(DvrDisplayManager* client) {
   if (!client)
     return -EINVAL;
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index 67e2ae8..1fe9874 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -156,22 +156,22 @@
   return 0;
 }
 
-int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
+int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer) {
   auto client = DisplayClient::Create();
   if (!client) {
-    ALOGE("dvrGetNamedBuffer: Failed to create display client!");
+    ALOGE("dvrGetGlobalBuffer: Failed to create display client!");
     return -ECOMM;
   }
 
-  if (out_buffer == nullptr || name == nullptr) {
-    ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
+  if (out_buffer == nullptr) {
+    ALOGE("dvrGetGlobalBuffer: Invalid inputs: key=%d, out_buffer=%p.", key,
           out_buffer);
     return -EINVAL;
   }
 
-  auto status = client->GetNamedBuffer(name);
+  auto status = client->GetGlobalBuffer(key);
   if (!status) {
-    ALOGE("dvrGetNamedBuffer: Failed to find named buffer name=%s: %s", name,
+    ALOGE("dvrGetGlobalBuffer: Failed to find named buffer key=%d: %s", key,
           status.GetErrorMessage().c_str());
     return -status.error();
   }
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 8a203e0..0eb393e 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -18,7 +18,7 @@
 typedef uint64_t DvrSurfaceUpdateFlags;
 typedef struct DvrDisplayManager DvrDisplayManager;
 typedef struct DvrSurfaceState DvrSurfaceState;
-typedef struct DvrPose DvrPose;
+typedef struct DvrPoseClient DvrPoseClient;
 typedef struct DvrVSyncClient DvrVSyncClient;
 typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
 
@@ -33,19 +33,31 @@
 typedef struct DvrSurface DvrSurface;
 typedef uint64_t DvrSurfaceAttributeType;
 typedef int32_t DvrSurfaceAttributeKey;
+typedef int32_t DvrGlobalBufferKey;
 
 typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue;
 typedef struct DvrSurfaceAttribute DvrSurfaceAttribute;
 
 struct native_handle;
 
+// Device metrics data type enums.
+enum {
+  // Request the device lens metrics protobuf. This matches cardboard protos.
+  DVR_CONFIGURATION_DATA_LENS_METRICS = 0,
+  // Request the device metrics protobuf.
+  DVR_CONFIGURATION_DATA_DEVICE_METRICS = 1,
+  // Request the per device configuration data file.
+  DVR_CONFIGURATION_DATA_DEVICE_CONFIG = 2,
+};
+
 // dvr_display_manager.h
 typedef int (*DvrDisplayManagerCreatePtr)(DvrDisplayManager** client_out);
 typedef void (*DvrDisplayManagerDestroyPtr)(DvrDisplayManager* client);
-typedef int (*DvrDisplayManagerSetupNamedBufferPtr)(DvrDisplayManager* client,
-                                                    const char* name,
-                                                    size_t size, uint64_t usage,
-                                                    DvrBuffer** buffer_out);
+typedef int (*DvrDisplayManagerSetupGlobalBufferPtr)(DvrDisplayManager* client,
+                                                     DvrGlobalBufferKey key,
+                                                     size_t size,
+                                                     uint64_t usage,
+                                                     DvrBuffer** buffer_out);
 typedef int (*DvrDisplayManagerGetEventFdPtr)(DvrDisplayManager* client);
 typedef int (*DvrDisplayManagerTranslateEpollEventMaskPtr)(
     DvrDisplayManager* client, int in_events, int* out_events);
@@ -54,6 +66,9 @@
 typedef int (*DvrDisplayManagerGetReadBufferQueuePtr)(
     DvrDisplayManager* client, int surface_id, int queue_id,
     DvrReadBufferQueue** queue_out);
+typedef int (*DvrConfigurationDataGetPtr)(int config_type, uint8_t** data,
+                                          size_t* data_size);
+typedef void (*DvrConfigurationDataDestroyPtr)(uint8_t* data);
 typedef int (*DvrSurfaceStateCreatePtr)(DvrSurfaceState** surface_state);
 typedef void (*DvrSurfaceStateDestroyPtr)(DvrSurfaceState* surface_state);
 typedef int (*DvrSurfaceStateGetSurfaceCountPtr)(DvrSurfaceState* surface_state,
@@ -151,7 +166,8 @@
                                             size_t meta_size_bytes);
 
 // dvr_surface.h
-typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
+typedef int (*DvrGetGlobalBufferPtr)(DvrGlobalBufferKey key,
+                                     DvrBuffer** out_buffer);
 typedef int (*DvrSurfaceCreatePtr)(const DvrSurfaceAttribute* attributes,
                                    size_t attribute_count,
                                    DvrSurface** surface_out);
@@ -174,14 +190,15 @@
                                              uint32_t* next_vsync_count);
 
 // pose_client.h
-typedef DvrPose* (*DvrPoseCreatePtr)(void);
-typedef void (*DvrPoseDestroyPtr)(DvrPose* client);
-typedef int (*DvrPoseGetPtr)(DvrPose* client, uint32_t vsync_count,
-                             DvrPoseAsync* out_pose);
-typedef uint32_t (*DvrPoseGetVsyncCountPtr)(DvrPose* client);
-typedef int (*DvrPoseGetControllerPtr)(DvrPose* client, int32_t controller_id,
-                                       uint32_t vsync_count,
-                                       DvrPoseAsync* out_pose);
+typedef DvrPoseClient* (*DvrPoseClientCreatePtr)(void);
+typedef void (*DvrPoseClientDestroyPtr)(DvrPoseClient* client);
+typedef int (*DvrPoseClientGetPtr)(DvrPoseClient* client, uint32_t vsync_count,
+                                   DvrPoseAsync* out_pose);
+typedef uint32_t (*DvrPoseClientGetVsyncCountPtr)(DvrPoseClient* client);
+typedef int (*DvrPoseClientGetControllerPtr)(DvrPoseClient* client,
+                                             int32_t controller_id,
+                                             uint32_t vsync_count,
+                                             DvrPoseAsync* out_pose);
 
 // virtual_touchpad_client.h
 typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)(void);
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 09568fd..441df4f 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -11,11 +11,13 @@
 // Display manager client
 DVR_V1_API_ENTRY(DisplayManagerCreate);
 DVR_V1_API_ENTRY(DisplayManagerDestroy);
-DVR_V1_API_ENTRY(DisplayManagerSetupNamedBuffer);
+DVR_V1_API_ENTRY(DisplayManagerSetupGlobalBuffer);
 DVR_V1_API_ENTRY(DisplayManagerGetEventFd);
 DVR_V1_API_ENTRY(DisplayManagerTranslateEpollEventMask);
 DVR_V1_API_ENTRY(DisplayManagerGetSurfaceState);
 DVR_V1_API_ENTRY(DisplayManagerGetReadBufferQueue);
+DVR_V1_API_ENTRY(ConfigurationDataGet);
+DVR_V1_API_ENTRY(ConfigurationDataDestroy);
 DVR_V1_API_ENTRY(SurfaceStateCreate);
 DVR_V1_API_ENTRY(SurfaceStateDestroy);
 DVR_V1_API_ENTRY(SurfaceStateGetSurfaceCount);
@@ -84,14 +86,14 @@
 DVR_V1_API_ENTRY(SurfaceGetId);
 DVR_V1_API_ENTRY(SurfaceSetAttributes);
 DVR_V1_API_ENTRY(SurfaceCreateWriteBufferQueue);
-DVR_V1_API_ENTRY(GetNamedBuffer);
+DVR_V1_API_ENTRY(GetGlobalBuffer);
 
 // Pose client
-DVR_V1_API_ENTRY(PoseCreate);
-DVR_V1_API_ENTRY(PoseDestroy);
-DVR_V1_API_ENTRY(PoseGet);
-DVR_V1_API_ENTRY(PoseGetVsyncCount);
-DVR_V1_API_ENTRY(PoseGetController);
+DVR_V1_API_ENTRY(PoseClientCreate);
+DVR_V1_API_ENTRY(PoseClientDestroy);
+DVR_V1_API_ENTRY(PoseClientGet);
+DVR_V1_API_ENTRY(PoseClientGetVsyncCount);
+DVR_V1_API_ENTRY(PoseClientGetController);
 
 // Virtual touchpad client
 DVR_V1_API_ENTRY(VirtualTouchpadCreate);
diff --git a/libs/vr/libdvr/include/dvr/dvr_configuration_data.h b/libs/vr/libdvr/include/dvr/dvr_configuration_data.h
new file mode 100644
index 0000000..22a509f
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_configuration_data.h
@@ -0,0 +1,24 @@
+#ifndef DVR_CONFIGURATION_DATA_H_
+#define DVR_CONFIGURATION_DATA_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include <dvr/dvr_display_types.h>
+#include <dvr/dvr_surface.h>
+
+__BEGIN_DECLS
+
+// Loads device configuration data of DVR_CONFIGURATION_DATA_*.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrConfigurationDataGet(int config_type,
+                            uint8_t** data, size_t* data_size);
+
+// Destroy the configuration data returned from dvrGetConfigurationData.
+void dvrConfigurationDataDestroy(uint8_t* data);
+
+__END_DECLS
+
+#endif  // DVR_CONFIGURATION_DATA_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
index d5aef8b..0f80e20 100644
--- a/libs/vr/libdvr/include/dvr/dvr_display_manager.h
+++ b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
@@ -28,9 +28,17 @@
 // Sets up a named buffer for shared memory data transfer between display
 // clients and the display manager.
 // @return 0 on success. Otherwise returns a negative error value.
-int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
-                                      const char* name, size_t size,
-                                      uint64_t usage, DvrBuffer** buffer_out);
+int dvrDisplayManagerSetupGlobalBuffer(DvrDisplayManager* client,
+                                       DvrGlobalBufferKey key, size_t size,
+                                       uint64_t usage, DvrBuffer** buffer_out);
+
+// Deletes a named buffer. WARNING: This is dangerous because any existing
+// clients of this buffer will not be notified and will remain attached to
+// the old buffer. This is useful for tests, but probably not for production
+// code.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerDeleteGlobalBuffer(DvrDisplayManager* client,
+                                        DvrGlobalBufferKey key);
 
 // Returns an fd used to signal when surface updates occur. Note that depending
 // on the underlying transport, only a subset of the real event bits may be
diff --git a/libs/vr/libdvr/include/dvr/dvr_pose.h b/libs/vr/libdvr/include/dvr/dvr_pose.h
new file mode 100644
index 0000000..a7e83c9
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_pose.h
@@ -0,0 +1,79 @@
+#ifndef ANDROID_DVR_PUBLIC_POSE_H_
+#define ANDROID_DVR_PUBLIC_POSE_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+#ifdef __ARM_NEON
+#include <arm_neon.h>
+#else
+#ifndef __FLOAT32X4T_86
+#define __FLOAT32X4T_86
+typedef float float32x4_t __attribute__((__vector_size__(16)));
+#endif
+#endif
+
+// Represents an estimated pose, accessed asynchronously through a shared ring
+// buffer. No assumptions should be made about the data in padding space.
+// The size of this struct is 128 bytes.
+typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync {
+  // Left eye head-from-start orientation quaternion x,y,z,w.
+  float32x4_t orientation;
+  // Left eye head-from-start position x,y,z,pad in meters.
+  float32x4_t position;
+  // Right eye head-from-start orientation quaternion x,y,z,w.
+  float32x4_t right_orientation;
+  // Right eye head-from-start position x,y,z,pad in meters.
+  float32x4_t right_position;
+  // Start-space angular velocity x,y,z,pad in radians per second.
+  float32x4_t angular_velocity;
+  // Start-space positional velocity x,y,z,pad in meters per second.
+  float32x4_t velocity;
+  // Timestamp of when this pose is predicted for, typically halfway through
+  // scanout.
+  int64_t timestamp_ns;
+  // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose.
+  //
+  // If DVR_POSE_FLAG_VALID is not set, the pose is indeterminate.
+  uint64_t flags;
+  // Reserved padding to 128 bytes.
+  uint8_t pad[16];
+} DvrPoseAsync;
+
+enum {
+  DVR_POSE_FLAG_VALID = (1UL << 0),       // This pose is valid.
+  DVR_POSE_FLAG_HEAD = (1UL << 1),        // This pose is the head.
+  DVR_POSE_FLAG_CONTROLLER = (1UL << 2),  // This pose is a controller.
+};
+
+// Represents a sensor pose sample.
+typedef struct __attribute__((packed, aligned(16))) DvrPose {
+  // Head-from-start orientation quaternion x,y,z,w.
+  float32x4_t orientation;
+
+  // The angular velocity where the x,y,z is the rotation axis and the
+  // magnitude is the radians / second in the same coordinate frame as
+  // orientation.
+  float32x4_t angular_velocity;
+
+  // Head-from-start position x,y,z,pad in meters.
+  float32x4_t position;
+
+  // In meters / second in the same coordinate frame as position.
+  float32x4_t velocity;
+
+  // In meters / second ^ 2 in the same coordinate frame as position.
+  float32x4_t acceleration;
+
+  // Timestamp for the measurement in nanoseconds.
+  int64_t timestamp_ns;
+
+  // Padding to 96 bytes so the size is a multiple of 16.
+  uint8_t padding[8];
+} DvrPose;
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_PUBLIC_POSE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
new file mode 100644
index 0000000..ce17f0c
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
@@ -0,0 +1,102 @@
+#ifndef ANDROID_DVR_SHARED_BUFFERS_H_
+#define ANDROID_DVR_SHARED_BUFFERS_H_
+
+#include <dvr/dvr_pose.h>
+#include <dvr/dvr_vrflinger_config.h>
+#include <dvr/dvr_vsync.h>
+#include <libbroadcastring/broadcast_ring.h>
+
+// This header is shared by VrCore and Android and must be kept in sync.
+namespace android {
+namespace dvr {
+
+// Increment when the layout for the buffers change.
+constexpr uint32_t kSharedBufferLayoutVersion = 1;
+
+// Note: These buffers will be mapped from various system processes as well
+// as VrCore and the application processes in a r/w manner.
+//
+// Therefore it is possible for the application to mess with the contents of
+// these buffers.
+//
+// While using them, assume garbage memory: Your logic must not crash or lead
+// to execution of unsafe code as a function of the contents of these buffers.
+
+// Sanity check for basic type sizes.
+static_assert(sizeof(DvrPoseAsync) == 128, "Unexpected size for DvrPoseAsync");
+static_assert(sizeof(DvrPose) == 96, "Unexpected size for DvrPose");
+static_assert(sizeof(DvrVsync) == 32, "Unexpected size for DvrVsync");
+
+// A helper class that provides compile time sized traits for the BroadcastRing.
+template <class DvrType, size_t StaticCount>
+class DvrRingBufferTraits {
+ public:
+  using Record = DvrType;
+  static constexpr bool kUseStaticRecordSize = false;
+  static constexpr uint32_t kStaticRecordCount = StaticCount;
+  static constexpr int kMaxReservedRecords = 1;
+  static constexpr int kMinAvailableRecords = 1;
+};
+
+// Traits classes.
+using DvrPoseTraits = DvrRingBufferTraits<DvrPose, 0>;
+using DvrVsyncTraits = DvrRingBufferTraits<DvrVsync, 2>;
+using DvrVrFlingerConfigTraits = DvrRingBufferTraits<DvrVrFlingerConfig, 2>;
+
+// The broadcast ring classes that will expose the data.
+using DvrPoseRing = BroadcastRing<DvrPose, DvrPoseTraits>;
+using DvrVsyncRing = BroadcastRing<DvrVsync, DvrVsyncTraits>;
+using DvrVrFlingerConfigRing =
+    BroadcastRing<DvrVrFlingerConfig, DvrVrFlingerConfigTraits>;
+
+// This is a shared memory buffer for passing pose data estimated at vsyncs.
+//
+// This will be primarily used for late latching and EDS where we bind this
+// buffer in a shader and extract the right vsync-predicted pose.
+struct __attribute__((packed, aligned(16))) DvrVsyncPoseBuffer {
+  enum : int {
+    // The number vsync predicted poses to keep in the ring buffer.
+    // Must be a power of 2.
+    kSize = 8,
+    kIndexMask = kSize - 1,
+
+    // The number of vsyncs (from the current vsync) we predict in vsync buffer.
+    // The other poses are left alone.
+    kMinFutureCount = 4
+  };
+
+  // The vsync predicted poses.
+  // The pose for the vsync n is:
+  // vsync_poses[n % kSize]
+  //
+  // This buffer is unsynchronized: It is possible to get torn reads as the
+  // sensor service updates the predictions as new sensor measurements come
+  // in. In particular, it is possible to get the position and an updated
+  // orientation while reading.
+  DvrPoseAsync vsync_poses[kSize];
+
+  // The latest sensor pose for GPU usage.
+  DvrPose current_pose;
+
+  // Current vsync_count (where sensord is writing poses from).
+  uint32_t vsync_count;
+
+  // For 16 byte alignment.
+  uint8_t padding[12];
+};
+
+static_assert(sizeof(DvrVsyncPoseBuffer) == 1136,
+              "Unexpected size for DvrVsyncPoseBuffer");
+
+// The keys for the dvr global buffers.
+enum DvrGlobalBuffers : int32_t {
+  kVsyncPoseBuffer = 1,
+  kVsyncBuffer = 2,
+  kSensorPoseBuffer = 3,
+  kVrFlingerConfigBufferKey = 4
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SHARED_BUFFERS_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 361488e..e3ab41b 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -6,16 +6,13 @@
 #include <stdint.h>
 #include <sys/cdefs.h>
 
+#include <dvr/dvr_api.h>
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_buffer_queue.h>
 #include <dvr/dvr_display_types.h>
 
 __BEGIN_DECLS
 
-typedef struct DvrBuffer DvrBuffer;
-typedef struct DvrSurface DvrSurface;
-typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
-
 // Attribute types. The values are one-hot encoded to support singluar types or
 // masks of supported types.
 enum {
@@ -82,9 +79,9 @@
                                      size_t capacity,
                                      DvrWriteBufferQueue** queue_out);
 
-// Get a named buffer from the display service.
+// Get a global buffer from the display service.
 // @return 0 on success. Otherwise returns a negative error value.
-int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
+int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer);
 
 __END_DECLS
 
diff --git a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h b/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
new file mode 100644
index 0000000..cfe9d62
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
@@ -0,0 +1,30 @@
+#ifndef ANDROID_DVR_VRFLINGER_CONFIG_H
+#define ANDROID_DVR_VRFLINGER_CONFIG_H
+
+// This header is shared by VrCore and Android and must be kept in sync.
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// This is a shared memory buffer for passing config data from VrCore to
+// libvrflinger in SurfaceFlinger.
+struct DvrVrFlingerConfig {
+  // Offset before vsync to submit frames to hardware composer.
+  int frame_post_offset_ns{4000000};
+
+  // If the number of pending fences goes over this count at the point when we
+  // are about to submit a new frame to HWC, we will drop the frame. This
+  // should be a signal that the display driver has begun queuing frames. Note
+  // that with smart displays (with RAM), the fence is signaled earlier than
+  // the next vsync, at the point when the DMA to the display completes.
+  // Currently we use a smart display and the EDS timing coincides with zero
+  // pending fences, so this is 0.
+  size_t allowed_pending_fence_count{0};
+
+  // New fields should always be added to the end for backwards compat.
+};
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_VRFLINGER_CONFIG_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h
index 1eea3d9..87fdf31 100644
--- a/libs/vr/libdvr/include/dvr/dvr_vsync.h
+++ b/libs/vr/libdvr/include/dvr/dvr_vsync.h
@@ -8,6 +8,27 @@
 
 typedef struct DvrVSyncClient DvrVSyncClient;
 
+// Represents a vsync sample. The size of this struct is 32 bytes.
+typedef struct __attribute__((packed, aligned(16))) DvrVsync {
+  // The timestamp for the last vsync in nanoseconds.
+  uint64_t vsync_timestamp_ns;
+
+  // The index of the last vsync.
+  uint32_t vsync_count;
+
+  // Scan out for the left eye = vsync_timestamp_ns + vsync_left_eye_offset_ns.
+  int32_t vsync_left_eye_offset_ns;
+
+  // Scan out for the right eye = vsync_timestamp_ns + vsync_right_eye_offset_ns
+  int32_t vsync_right_eye_offset_ns;
+
+  // The period of a vsync in nanoseconds.
+  uint32_t vsync_period_ns;
+
+  // Padding to 32 bytes so the size is a multiple of 16.
+  uint8_t padding[8];
+} DvrVsync;
+
 // Creates a new client to the system vsync service.
 int dvrVSyncClientCreate(DvrVSyncClient** client_out);
 
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index ef746e2..ab2ee75 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -32,6 +32,7 @@
     "libdvrcommon",
     "libdisplay",
     "libpdx_default_transport",
+    "libbroadcastring",
 ]
 
 cc_test {
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index 474e968..2426a49 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -25,8 +25,9 @@
 class DvrBufferQueueTest : public ::testing::Test {
  protected:
   void SetUp() override {
+    auto config = ProducerQueueConfigBuilder().SetMetadata<TestMeta>().Build();
     write_queue_ = CreateDvrWriteBufferQueueFromProducerQueue(
-        ProducerQueue::Create<TestMeta>(0, 0, 0, 0));
+        ProducerQueue::Create(config, UsagePolicy{}));
     ASSERT_NE(nullptr, write_queue_);
   }
 
@@ -40,10 +41,11 @@
   void AllocateBuffers(size_t buffer_count) {
     size_t out_slot;
     for (size_t i = 0; i < buffer_count; i++) {
-      int ret = GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
-                    ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
-                                     kBufferFormat, kBufferUsage, &out_slot);
-      ASSERT_EQ(0, ret);
+      auto status =
+          GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
+              ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
+                               kBufferFormat, kBufferUsage, &out_slot);
+      ASSERT_TRUE(status.ok());
     }
   }
 
@@ -196,11 +198,13 @@
   ASSERT_EQ(nullptr, window);
 
   // A write queue with DvrNativeBufferMetadata should work fine.
+  auto config = ProducerQueueConfigBuilder()
+                    .SetMetadata<DvrNativeBufferMetadata>()
+                    .Build();
   std::unique_ptr<DvrWriteBufferQueue, decltype(&dvrWriteBufferQueueDestroy)>
-      write_queue(
-          CreateDvrWriteBufferQueueFromProducerQueue(
-              ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0)),
-          dvrWriteBufferQueueDestroy);
+      write_queue(CreateDvrWriteBufferQueueFromProducerQueue(
+                      ProducerQueue::Create(config, UsagePolicy{})),
+                  dvrWriteBufferQueueDestroy);
   ASSERT_NE(nullptr, write_queue.get());
 
   ret = dvrWriteBufferQueueGetExternalSurface(write_queue.get(), &window);
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
index a2414d6..2249154 100644
--- a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -1,3 +1,4 @@
+#include <android-base/properties.h>
 #include <base/logging.h>
 #include <gtest/gtest.h>
 #include <poll.h>
@@ -9,6 +10,7 @@
 #include <thread>
 #include <vector>
 
+#include <dvr/dvr_configuration_data.h>
 #include <dvr/dvr_deleter.h>
 #include <dvr/dvr_display_manager.h>
 #include <dvr/dvr_surface.h>
@@ -200,6 +202,23 @@
     return {std::move(queue_ids)};
   }
 
+  Status<std::vector<uint8_t>> GetConfigData(int config_type) {
+    uint8_t* data = nullptr;
+    size_t data_size = 0;
+    int error = dvrConfigurationDataGet(config_type, &data, &data_size);
+    if (error < 0) {
+      return ErrorStatus(-error);
+    }
+
+    if (!data || data_size == 0) {
+      return ErrorStatus(EINVAL);
+    }
+    std::vector<uint8_t> data_result(data, data + data_size);
+    dvrConfigurationDataDestroy(data);
+    std::string s(data, data + data_size);
+    return {std::move(data_result)};
+  }
+
  private:
   UniqueDvrDisplayManager display_manager_;
   UniqueDvrSurfaceState surface_state_;
@@ -573,6 +592,24 @@
   dvrWriteBufferDestroy(buffer);
 }
 
+TEST_F(DvrDisplayManagerTest, ConfigurationData) {
+  // TODO(hendrikw): Move this out of the display manager tests.
+  auto data1 = manager_->GetConfigData(-1);
+  ASSERT_STATUS_ERROR(data1);
+
+  const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics";
+
+  // This should be run on devices with and without built in metrics.
+  bool has_metric = !base::GetProperty(kDvrLensMetricsProperty, "").empty();
+  auto data2 = manager_->GetConfigData(DVR_CONFIGURATION_DATA_LENS_METRICS);
+  if (has_metric) {
+    ASSERT_STATUS_OK(data2);
+    ASSERT_NE(0u, data2.get().size());
+  } else {
+    ASSERT_STATUS_ERROR(data2);
+  }
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index e65f6d5..419083f 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,7 +1,9 @@
 #include <android/hardware_buffer.h>
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_display_manager.h>
+#include <dvr/dvr_shared_buffers.h>
 #include <dvr/dvr_surface.h>
+#include <dvr/dvr_vrflinger_config.h>
 #include <system/graphics.h>
 
 #include <base/logging.h>
@@ -12,7 +14,7 @@
 
 namespace {
 
-class DvrNamedBufferTest : public ::testing::Test {
+class DvrGlobalBufferTest : public ::testing::Test {
  protected:
   void SetUp() override {
     const int ret = dvrDisplayManagerCreate(&client_);
@@ -28,17 +30,17 @@
   DvrDisplayManager* client_ = nullptr;
 };
 
-TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
-  const char* buffer_name = "same_name";
+TEST_F(DvrGlobalBufferTest, TestGlobalBuffersSameName) {
+  const DvrGlobalBufferKey buffer_key = 101;
   DvrBuffer* buffer1 = nullptr;
   int ret1 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer1);
+      dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key, 10, 0, &buffer1);
   ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, buffer1);
 
   DvrBuffer* buffer2 = nullptr;
   int ret2 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer2);
+      dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key, 10, 0, &buffer2);
   ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, buffer2);
 
@@ -71,7 +73,7 @@
   dvrBufferDestroy(buffer2);
 
   DvrBuffer* buffer3 = nullptr;
-  int e3 = dvrGetNamedBuffer(buffer_name, &buffer3);
+  int e3 = dvrGetGlobalBuffer(buffer_key, &buffer3);
   ASSERT_NE(nullptr, buffer3);
   ASSERT_EQ(0, e3);
 
@@ -95,38 +97,38 @@
   AHardwareBuffer_release(hardware_buffer3);
 }
 
-TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
-  const char* buffer_name1 = "test1";
-  const char* buffer_name2 = "test2";
+TEST_F(DvrGlobalBufferTest, TestMultipleGlobalBuffers) {
+  const DvrGlobalBufferKey buffer_key1 = 102;
+  const DvrGlobalBufferKey buffer_key2 = 103;
   DvrBuffer* setup_buffer1 = nullptr;
-  int ret1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0,
-                                               &setup_buffer1);
+  int ret1 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key1, 10, 0,
+                                                &setup_buffer1);
   ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, setup_buffer1);
   dvrBufferDestroy(setup_buffer1);
 
   DvrBuffer* setup_buffer2 = nullptr;
-  int ret2 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0,
-                                               &setup_buffer2);
+  int ret2 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key2, 10, 0,
+                                                &setup_buffer2);
   ASSERT_EQ(0, ret2);
   ASSERT_NE(nullptr, setup_buffer2);
   dvrBufferDestroy(setup_buffer2);
 
   DvrBuffer* buffer1 = nullptr;
-  int e1 = dvrGetNamedBuffer(buffer_name1, &buffer1);
+  int e1 = dvrGetGlobalBuffer(buffer_key1, &buffer1);
   ASSERT_NE(nullptr, buffer1);
   ASSERT_EQ(0, e1);
   dvrBufferDestroy(buffer1);
 
   DvrBuffer* buffer2 = nullptr;
-  int e2 = dvrGetNamedBuffer(buffer_name2, &buffer2);
+  int e2 = dvrGetGlobalBuffer(buffer_key2, &buffer2);
   ASSERT_NE(nullptr, buffer2);
   ASSERT_EQ(0, e2);
   dvrBufferDestroy(buffer2);
 }
 
-TEST_F(DvrNamedBufferTest, TestNamedBufferUsage) {
-  const char* buffer_name = "buffer_usage";
+TEST_F(DvrGlobalBufferTest, TestGlobalBufferUsage) {
+  const DvrGlobalBufferKey buffer_key = 100;
 
   // Set usage to AHARDWAREBUFFER_USAGE_VIDEO_ENCODE. We use this because
   // internally AHARDWAREBUFFER_USAGE_VIDEO_ENCODE is converted to
@@ -136,8 +138,8 @@
   const uint64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
 
   DvrBuffer* setup_buffer = nullptr;
-  int e1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage,
-                                             &setup_buffer);
+  int e1 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key, 10, usage,
+                                              &setup_buffer);
   ASSERT_NE(nullptr, setup_buffer);
   ASSERT_EQ(0, e1);
 
@@ -154,6 +156,154 @@
   AHardwareBuffer_release(hardware_buffer);
 }
 
+TEST_F(DvrGlobalBufferTest, TestGlobalBufferCarriesData) {
+  const DvrGlobalBufferKey buffer_name = 110;
+
+  uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
+                   AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+  constexpr size_t size = 1024 * sizeof(uint64_t);
+  constexpr uint64_t value = 0x123456787654321;
+
+  {
+    // Allocate some data and set it to something.
+    DvrBuffer* setup_buffer = nullptr;
+    int e1 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_name, size,
+                                                usage, &setup_buffer);
+    ASSERT_NE(nullptr, setup_buffer);
+    ASSERT_EQ(0, e1);
+
+    AHardwareBuffer* hardware_buffer = nullptr;
+    int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
+    ASSERT_EQ(0, e2);
+    ASSERT_NE(nullptr, hardware_buffer);
+
+    void* buffer;
+    int e3 = AHardwareBuffer_lock(hardware_buffer, usage, -1, nullptr, &buffer);
+    ASSERT_EQ(0, e3);
+    ASSERT_NE(nullptr, buffer);
+    // Verify that the buffer pointer is at least 16 byte aligned.
+    ASSERT_EQ(0, reinterpret_cast<uintptr_t>(buffer) & (16 - 1));
+
+    uint64_t* data = static_cast<uint64_t*>(buffer);
+    constexpr size_t num_values = size / sizeof(uint64_t);
+    for (size_t i = 0; i < num_values; ++i) {
+      data[i] = value;
+    }
+
+    int32_t fence = -1;
+    int e4 = AHardwareBuffer_unlock(hardware_buffer, &fence);
+    ASSERT_EQ(0, e4);
+
+    dvrBufferDestroy(setup_buffer);
+    AHardwareBuffer_release(hardware_buffer);
+  }
+
+  {
+    // Get the buffer and check that all the data is still present.
+    DvrBuffer* setup_buffer = nullptr;
+    int e1 = dvrGetGlobalBuffer(buffer_name, &setup_buffer);
+    ASSERT_NE(nullptr, setup_buffer);
+    ASSERT_EQ(0, e1);
+
+    AHardwareBuffer* hardware_buffer = nullptr;
+    int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
+    ASSERT_EQ(0, e2);
+    ASSERT_NE(nullptr, hardware_buffer);
+
+    void* buffer;
+    int e3 = AHardwareBuffer_lock(hardware_buffer, usage, -1, nullptr, &buffer);
+    ASSERT_EQ(0, e3);
+    ASSERT_NE(nullptr, buffer);
+    // Verify that the buffer pointer is at least 16 byte aligned.
+    ASSERT_EQ(0, reinterpret_cast<uintptr_t>(buffer) & (16 - 1));
+
+    uint64_t* data = static_cast<uint64_t*>(buffer);
+    constexpr size_t num_values = size / sizeof(uint64_t);
+    bool is_equal = true;
+    for (size_t i = 0; i < num_values; ++i) {
+      is_equal &= (data[i] == value);
+    }
+    ASSERT_TRUE(is_equal);
+
+    int32_t fence = -1;
+    int e4 = AHardwareBuffer_unlock(hardware_buffer, &fence);
+    ASSERT_EQ(0, e4);
+
+    dvrBufferDestroy(setup_buffer);
+    AHardwareBuffer_release(hardware_buffer);
+  }
+}
+
+TEST_F(DvrGlobalBufferTest, TestGlobalBufferZeroed) {
+  const DvrGlobalBufferKey buffer_name = 120;
+
+  // Allocate 1MB and check that it is all zeros.
+  uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
+                   AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+  constexpr size_t size = 1024 * 1024;
+  DvrBuffer* setup_buffer = nullptr;
+  int e1 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_name, size, usage,
+                                              &setup_buffer);
+  ASSERT_NE(nullptr, setup_buffer);
+  ASSERT_EQ(0, e1);
+
+  AHardwareBuffer* hardware_buffer = nullptr;
+  int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
+  ASSERT_EQ(0, e2);
+  ASSERT_NE(nullptr, hardware_buffer);
+
+  void* buffer;
+  int e3 = AHardwareBuffer_lock(hardware_buffer, usage, -1, nullptr, &buffer);
+  ASSERT_EQ(0, e3);
+  ASSERT_NE(nullptr, buffer);
+  // Verify that the buffer pointer is at least 16 byte aligned.
+  ASSERT_EQ(0, reinterpret_cast<uintptr_t>(buffer) & (16 - 1));
+
+  uint64_t* data = static_cast<uint64_t*>(buffer);
+  constexpr size_t num_values = size / sizeof(uint64_t);
+  uint64_t zero = 0;
+  for (size_t i = 0; i < num_values; ++i) {
+    zero |= data[i];
+  }
+  ASSERT_EQ(0, zero);
+
+  int32_t fence = -1;
+  int e4 = AHardwareBuffer_unlock(hardware_buffer, &fence);
+  ASSERT_EQ(0, e4);
+
+  dvrBufferDestroy(setup_buffer);
+  AHardwareBuffer_release(hardware_buffer);
+}
+
+TEST_F(DvrGlobalBufferTest, TestVrflingerConfigBuffer) {
+  const DvrGlobalBufferKey buffer_name =
+      DvrGlobalBuffers::kVrFlingerConfigBufferKey;
+
+  // First delete any existing buffer so we can test the failure case.
+  dvrDisplayManagerDeleteGlobalBuffer(client_, buffer_name);
+
+  const uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
+                         AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
+
+  size_t correct_size = DvrVrFlingerConfigRing::MemorySize();
+  size_t wrong_size = DvrVrFlingerConfigRing::MemorySize(0);
+
+  // Setup an invalid config buffer (too small) and assert that it fails.
+  DvrBuffer* setup_buffer = nullptr;
+  int e1 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_name, wrong_size,
+                                              usage, &setup_buffer);
+  ASSERT_EQ(nullptr, setup_buffer);
+  ASSERT_GT(0, e1);
+
+  // Setup a correct config buffer.
+  int e2 = dvrDisplayManagerSetupGlobalBuffer(
+      client_, buffer_name, correct_size, usage, &setup_buffer);
+  ASSERT_NE(nullptr, setup_buffer);
+  ASSERT_EQ(0, e2);
+
+  dvrBufferDestroy(setup_buffer);
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index eb78348..62aeb79 100644
--- a/libs/vr/libdvrcommon/Android.bp
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -12,11 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-sourceFiles = [
-    "frame_time_history.cpp",
-    "sync_util.cpp",
-]
-
 localIncludeFiles = [
     "include",
 ]
@@ -33,14 +28,13 @@
     "libhardware",
 ]
 
-staticLibraries = ["libpdx_default_transport"]
+staticLibraries = ["libpdx_default_transport", "libbroadcastring"]
 
 headerLibraries = [
     "libeigen",
 ]
 
 cc_library {
-    srcs: sourceFiles,
     local_include_dirs: localIncludeFiles,
 
     cflags: [
@@ -49,8 +43,6 @@
     ],
     export_include_dirs: localIncludeFiles,
 
-    shared_libs: sharedLibraries,
-    static_libs: staticLibraries,
     header_libs: headerLibraries,
     export_header_lib_headers: headerLibraries,
 
diff --git a/libs/vr/libdvrcommon/frame_time_history.cpp b/libs/vr/libdvrcommon/frame_time_history.cpp
deleted file mode 100644
index d4718a9..0000000
--- a/libs/vr/libdvrcommon/frame_time_history.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <private/dvr/frame_time_history.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace dvr {
-
-void FrameTimeHistory::AddSample(int64_t frame_time) {
-  if (size_ == frame_times_.size()) {
-    int64_t expired_frame_time = frame_times_[start_];
-    frame_times_[start_] = frame_time;
-    start_ = (start_ + 1) % frame_times_.size();
-    total_frame_time_ -= expired_frame_time;
-  } else {
-    frame_times_[(start_ + size_) % frame_times_.size()] = frame_time;
-    size_++;
-  }
-  total_frame_time_ += frame_time;
-}
-
-int FrameTimeHistory::GetSampleCount() const { return size_; }
-
-int64_t FrameTimeHistory::GetAverage() const {
-  LOG_ALWAYS_FATAL_IF(size_ == 0);
-  return total_frame_time_ / size_;
-}
-
-void FrameTimeHistory::ResetWithSeed(int64_t frame_time_seed) {
-  start_ = 0;
-  size_ = frame_times_.size();
-  for (size_t i = 0; i < size_; ++i)
-    frame_times_[i] = frame_time_seed;
-  total_frame_time_ = frame_time_seed * size_;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvrcommon/include/private/dvr/frame_time_history.h b/libs/vr/libdvrcommon/include/private/dvr/frame_time_history.h
deleted file mode 100644
index 008c636..0000000
--- a/libs/vr/libdvrcommon/include/private/dvr/frame_time_history.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef ANDROID_DVR_FRAME_TIME_HISTORY_H_
-#define ANDROID_DVR_FRAME_TIME_HISTORY_H_
-
-#include <stdint.h>
-
-#include <array>
-
-namespace android {
-namespace dvr {
-
-// Maintains frame time history and provides averaging utility methods.
-class FrameTimeHistory {
- public:
-  void AddSample(int64_t frame_time);
-  int GetSampleCount() const;
-  int64_t GetAverage() const;
-  float GetAverageFps() const {
-    return 1000000000.0f / static_cast<float>(GetAverage());
-  }
-  void ResetWithSeed(int64_t frame_time_seed);
-
- private:
-  static constexpr int kFrameTimeHistoryNumSamples = 30;
-  std::array<int64_t, kFrameTimeHistoryNumSamples> frame_times_;
-  int start_ = 0;
-  size_t size_ = 0;
-  int64_t total_frame_time_ = 0;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_FRAME_TIME_HISTORY_H_
diff --git a/libs/vr/libdvrcommon/include/private/dvr/platform_defines.h b/libs/vr/libdvrcommon/include/private/dvr/platform_defines.h
deleted file mode 100644
index 2176903..0000000
--- a/libs/vr/libdvrcommon/include/private/dvr/platform_defines.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ANDROID_DVR_PLATFORM_DEFINES_H_
-#define ANDROID_DVR_PLATFORM_DEFINES_H_
-
-#include <hardware/gralloc1.h>
-// Platform-specific macros and defines.
-
-// QCOM's GRALLOC_USAGE_PRIVATE_ALLOC_UBWC usage bits.
-#define GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION GRALLOC_USAGE_PRIVATE_1 | GRALLOC1_PRODUCER_USAGE_PRIVATE_0
-
-// QCOM bit to use the ADSP heap. This carveout heap is accessible to Linux,
-// Hexagon DSPs, and the GPU.
-#define GRALLOC_USAGE_PRIVATE_ADSP_HEAP 0x01000000
-
-// Force a gralloc buffer to get the uncached ION option set.
-#define GRALLOC_USAGE_PRIVATE_UNCACHED 0x02000000
-
-#endif  // ANDROID_DVR_PLATFORM_DEFINES_H_
diff --git a/libs/vr/libdvrcommon/include/private/dvr/sync_util.h b/libs/vr/libdvrcommon/include/private/dvr/sync_util.h
deleted file mode 100644
index c6911bc..0000000
--- a/libs/vr/libdvrcommon/include/private/dvr/sync_util.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef ANDROID_DVR_SYNC_UTIL_H_
-#define ANDROID_DVR_SYNC_UTIL_H_
-
-#include <cstdint>
-#include <type_traits>
-
-namespace android {
-namespace dvr {
-
-constexpr size_t kFenceInfoBufferSize = 4096;
-
-// This buffer is eventually mapped to a sync_fence_info_data struct (from
-// sync.h), whose largest member is a uint32_t. We align to 8 bytes to be extra
-// cautious.
-using FenceInfoBuffer = std::aligned_storage<kFenceInfoBufferSize, 8>::type;
-
-// Get fence info. Internally this works just like sync_fence_info(), except the
-// caller supplies a memory buffer instead of allocating memory.
-// On success, returns 0. On error, -1 is returned, and errno is set.
-int GetSyncFenceInfo(int fence_fd, FenceInfoBuffer* buffer);
-
-// Returns the timestamp when the fence was first signaled. buffer is used as
-// described in GetSyncFenceInfo().
-// On success, returns 0. On error, -1 is returned, and errno is set.
-int GetFenceSignaledTimestamp(int fence_fd, FenceInfoBuffer* buffer,
-                              int64_t* timestamp);
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SYNC_UTIL_H_
diff --git a/libs/vr/libdvrcommon/sync_util.cpp b/libs/vr/libdvrcommon/sync_util.cpp
deleted file mode 100644
index 3637936..0000000
--- a/libs/vr/libdvrcommon/sync_util.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "include/private/dvr/sync_util.h"
-
-#include <errno.h>
-#include <sys/ioctl.h>
-
-// TODO: http://b/33239638 Move GetSyncFenceInfo() into upstream libsync instead
-//   of duplicating functionality and structure definitions from it.
-struct sync_fence_info_data {
- uint32_t len;
- char name[32];
- int32_t status;
- uint8_t pt_info[0];
-};
-
-struct sync_pt_info {
- uint32_t len;
- char obj_name[32];
- char driver_name[32];
- int32_t status;
- uint64_t timestamp_ns;
- uint8_t driver_data[0];
-};
-
-#define SYNC_IOC_MAGIC '>'
-#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
-#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
-#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_fence_info_data)
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-// This is copied from sync_pt_info() in libsync/sync.c. It's been cleaned up to
-// remove lint warnings.
-sync_pt_info* GetSyncPtInfo(sync_fence_info_data* info, sync_pt_info* itr) {
-  if (itr == nullptr)
-    itr = reinterpret_cast<sync_pt_info*>(info->pt_info);
-  else
-    itr = reinterpret_cast<sync_pt_info*>(reinterpret_cast<uint8_t*>(itr) +
-                                          itr->len);
-
-  if (reinterpret_cast<uint8_t*>(itr) - reinterpret_cast<uint8_t*>(info) >=
-      static_cast<int>(info->len))
-    return nullptr;
-
-  return itr;
-}
-
-}  // namespace
-
-int GetSyncFenceInfo(int fence_fd, FenceInfoBuffer* buffer) {
-  // If the implementation of sync_fence_info() in libsync/sync.c changes, this
-  // function should be changed to match.
-  if (buffer == nullptr) {
-    errno = EINVAL;
-    return -1;
-  }
-
-  sync_fence_info_data* fence_info =
-      reinterpret_cast<sync_fence_info_data*>(buffer);
-  fence_info->len = kFenceInfoBufferSize;
-  return ioctl(fence_fd, SYNC_IOC_FENCE_INFO, fence_info);
-}
-
-int GetFenceSignaledTimestamp(int fence_fd, FenceInfoBuffer* buffer,
-                              int64_t* timestamp) {
-  int result = GetSyncFenceInfo(fence_fd, buffer);
-  if (result < 0)
-    return result;
-
-  sync_fence_info_data* fence_info =
-      reinterpret_cast<sync_fence_info_data*>(buffer);
-  struct sync_pt_info* pt_info = nullptr;
-  while ((pt_info = GetSyncPtInfo(fence_info, pt_info)) != nullptr) {
-    if (pt_info->status == 1) {
-      *timestamp = pt_info->timestamp_ns;
-      return 0;
-    }
-  }
-
-  errno = EAGAIN;
-  return -1;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvrgraphics/Android.bp b/libs/vr/libdvrgraphics/Android.bp
deleted file mode 100644
index 73a8bf8..0000000
--- a/libs/vr/libdvrgraphics/Android.bp
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-sourceFiles = [
-    "blur.cpp",
-    "debug_text.cpp",
-    "egl_image.cpp",
-    "gpu_profiler.cpp",
-    "shader_program.cpp",
-    "timer_query.cpp",
-    "vr_gl_extensions.cpp",
-]
-
-localIncludeFiles = [
-    "include",
-]
-
-staticLibraries = [
-    "libbufferhub",
-    "libdvrcommon",
-    "libpdx_default_transport",
-]
-
-sharedLibraries = [
-    "libcutils",
-    "libbase",
-    "libEGL",
-    "libGLESv2",
-    "libpng",
-    "liblog",
-]
-
-cc_library_static {
-    srcs: sourceFiles,
-    cflags: [
-        "-DGL_GLEXT_PROTOTYPES",
-        "-DEGL_EGLEXT_PROTOTYPES",
-    ],
-    export_include_dirs: localIncludeFiles,
-    shared_libs: sharedLibraries,
-    static_libs: staticLibraries,
-    // Rather than add this header-file-only library to all users of libdvrgraphics,
-    // include it here.
-    whole_static_libs: ["libarect"],
-    name: "libdvrgraphics",
-}
diff --git a/libs/vr/libdvrgraphics/assets/controller_proto2.png b/libs/vr/libdvrgraphics/assets/controller_proto2.png
deleted file mode 100644
index ffcb646..0000000
--- a/libs/vr/libdvrgraphics/assets/controller_proto2.png
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libdvrgraphics/assets/controller_proto2_body.obj b/libs/vr/libdvrgraphics/assets/controller_proto2_body.obj
deleted file mode 100644
index 4e54900..0000000
--- a/libs/vr/libdvrgraphics/assets/controller_proto2_body.obj
+++ /dev/null
@@ -1,5018 +0,0 @@
-# This file uses centimeters as units for non-parametric coordinates.
-
-v 0.001777 0.012900 0.101619
-v -0.005750 0.012900 0.096150
-v -0.004652 0.012900 0.092770
-v 0.005750 0.012900 0.096150
-v 0.004652 0.012900 0.099530
-v -0.001777 0.012900 0.090681
-v 0.004652 0.012900 0.092770
-v 0.001777 0.012900 0.090681
-v -0.001777 0.012900 0.101619
-v -0.004652 0.012900 0.099530
-v -0.001777 0.012900 0.073181
-v -0.004652 0.012900 0.075270
-v 0.001777 0.012900 0.073181
-v 0.004652 0.012900 0.075270
-v 0.005750 0.012900 0.078650
-v 0.004652 0.012900 0.082030
-v -0.005750 0.012900 0.078650
-v -0.004652 0.012900 0.082030
-v -0.001777 0.012900 0.084119
-v 0.001777 0.012900 0.084119
-v -0.016000 0.012900 0.050841
-v 0.016000 0.012900 0.050835
-v 0.013856 0.012900 0.058900
-v 0.008000 0.012900 0.064756
-v -0.000000 0.012900 0.066900
-v -0.008000 0.012900 0.064756
-v -0.013856 0.012900 0.058900
-v 0.008000 0.012900 0.037044
-v -0.008000 0.012900 0.037044
-v -0.013856 0.012900 0.042900
-v 0.000000 0.012900 0.034900
-v 0.013856 0.012900 0.042900
-v -0.020000 0.006760 0.075600
-v -0.020000 0.006760 -0.012398
-v -0.018877 -0.001982 0.044797
-v -0.018480 -0.003505 0.048732
-v -0.018777 -0.001945 0.075600
-v -0.017726 -0.003833 0.163093
-v -0.013161 -0.013053 0.058159
-v -0.016670 -0.008191 0.054819
-v -0.016119 -0.008731 0.075600
-v -0.009698 -0.015662 0.059338
-v -0.012025 -0.013632 0.075600
-v -0.006504 -0.016678 0.075600
-v -0.000000 -0.017750 0.075600
-v -0.000000 -0.015479 0.162587
-v 0.006873 -0.016611 0.058552
-v 0.005238 -0.017469 0.059981
-v -0.000000 -0.018152 0.060190
-v -0.006874 -0.016610 0.058551
-v -0.005577 -0.017375 0.059951
-v -0.000001 -0.017790 0.058889
-v -0.017783 -0.005639 0.052082
-v -0.016159 -0.008440 0.053561
-v -0.018202 -0.002766 0.042130
-v -0.019040 -0.001282 0.040457
-v -0.019004 -0.001521 0.036065
-v -0.019278 -0.000710 -0.012015
-v -0.018775 -0.002635 0.031956
-v -0.018323 -0.004451 0.028346
-v -0.017636 -0.005173 0.029543
-v -0.015438 -0.011195 0.021684
-v -0.017576 -0.006793 0.025305
-v -0.017651 -0.007495 -0.011666
-v -0.016133 -0.009192 0.024525
-v -0.009254 -0.016963 0.019047
-v -0.012694 -0.014052 0.021271
-v -0.014657 -0.012757 -0.011402
-v -0.012775 -0.014437 0.019994
-v -0.004877 -0.018641 0.018555
-v 0.000000 -0.019243 0.018406
-v -0.004053 -0.017659 -0.013120
-v 0.000000 -0.020012 -0.011045
-v -0.007741 -0.016386 -0.013187
-v -0.007793 -0.018450 -0.011122
-v -0.011145 -0.016607 -0.011212
-v -0.013377 -0.011450 -0.013446
-v -0.017416 0.000890 -0.014092
-v -0.010471 -0.009590 0.164744
-v -0.020000 0.006760 0.163598
-v -0.017045 0.000607 0.165278
-v -0.019121 0.000433 0.163292
-v -0.012455 -0.011131 0.162773
-v -0.015399 -0.007954 0.162910
-v -0.011105 -0.009754 0.164735
-v -0.008928 -0.013453 0.162674
-v -0.004759 -0.014945 0.162610
-v 0.000000 -0.013582 0.164534
-v -0.016850 0.012900 -0.012204
-v -0.016850 0.011003 -0.014204
-v -0.017833 0.012745 0.163406
-v -0.016850 0.011003 0.165404
-v 0.016850 0.011003 0.165404
-v 0.016850 0.012900 0.163404
-v -0.016850 0.012900 0.163404
-v -0.018496 0.012405 0.163413
-v -0.019171 0.011802 0.163424
-v -0.017585 0.010679 0.165421
-v -0.019183 0.011788 -0.012224
-v -0.019646 0.010959 0.163436
-v -0.017717 0.010496 0.165430
-v -0.019850 0.009900 -0.012263
-v -0.017851 0.009891 0.165462
-v -0.019850 0.009900 0.163463
-v -0.017851 0.009891 -0.014262
-v -0.019650 0.010946 -0.012236
-v -0.018511 0.012395 -0.012213
-v -0.017342 0.010872 -0.014211
-v -0.017849 0.012739 -0.012207
-v 0.019850 0.009900 -0.012263
-v 0.019850 0.009900 0.163463
-v 0.019652 0.010946 0.163437
-v 0.019180 0.011789 0.163424
-v 0.019649 0.010953 -0.012236
-v 0.017351 0.010866 0.165411
-v 0.018506 0.012398 0.163413
-v 0.017845 0.012741 0.163406
-v 0.018501 0.012401 -0.012213
-v 0.016850 0.012900 -0.012204
-v 0.016850 0.011003 -0.014204
-v 0.017836 0.012745 -0.012207
-v 0.017359 0.010861 -0.014211
-v 0.019174 0.011796 -0.012224
-v 0.020000 0.006760 -0.012398
-v 0.020000 0.006760 0.075600
-v 0.020000 0.006760 0.163598
-v 0.017851 0.009891 0.165462
-v 0.004914 -0.018632 0.018558
-v 0.012694 -0.014513 0.019962
-v 0.009842 -0.017439 -0.011172
-v 0.009194 -0.016995 0.019036
-v 0.012696 -0.014051 0.021272
-v 0.016134 -0.009190 0.024527
-v 0.018283 -0.005474 -0.011769
-v 0.015491 -0.011112 0.021736
-v 0.017878 -0.005923 0.026303
-v 0.016851 -0.008573 0.023600
-v 0.018521 -0.003703 0.029628
-v 0.019042 -0.001309 0.037868
-v 0.018891 -0.002096 0.033543
-v 0.018999 -0.001456 0.042247
-v 0.018278 -0.004181 0.049954
-v 0.018757 -0.002471 0.046344
-v 0.017676 -0.004685 0.048340
-v 0.018202 -0.002767 0.042132
-v 0.017483 -0.006410 0.053015
-v 0.016158 -0.008441 0.053562
-v 0.016251 -0.008973 0.055490
-v 0.013246 -0.012968 0.058115
-v 0.012687 -0.013111 0.057055
-v 0.009848 -0.015576 0.059304
-v 0.006504 -0.016678 0.075600
-v 0.012025 -0.013632 0.075600
-v 0.012453 -0.011132 0.162773
-v 0.015398 -0.007956 0.162909
-v 0.018777 -0.001945 0.075600
-v 0.016119 -0.008731 0.075600
-v 0.017726 -0.003834 0.163093
-v 0.016090 -0.005051 -0.013781
-v 0.019494 0.000840 -0.012095
-v 0.014597 -0.009662 -0.013539
-v 0.015987 -0.010626 -0.011508
-v 0.012048 -0.013130 -0.013358
-v 0.012738 -0.015322 -0.011275
-v 0.004233 -0.017617 -0.013122
-v 0.004123 -0.019588 -0.011066
-v 0.008927 -0.013454 0.162674
-v 0.004758 -0.014945 0.162610
-v 0.007966 -0.011801 0.164627
-v 0.011095 -0.009763 0.164734
-v -0.016170 0.000544 0.165275
-v 0.019122 0.000435 0.163292
-v -0.000000 -0.018116 -0.013096
-v 0.008618 -0.015654 -0.013225
-v -0.018000 0.006760 -0.014400
-v -0.016263 -0.005366 -0.013764
-v -0.010678 -0.014560 -0.013283
-v 0.018001 0.006760 -0.014400
-v 0.017116 0.010978 -0.014205
-v -0.017101 0.010981 -0.014205
-v -0.017576 0.010688 -0.014220
-v -0.017712 0.010505 -0.014230
-v 0.017851 0.009891 -0.014262
-v 0.017713 0.010505 -0.014230
-v -0.000000 -0.016565 0.057943
-v 0.005098 -0.015909 0.057716
-v -0.012314 -0.011868 0.055681
-v 0.012233 -0.011949 0.055734
-v -0.009091 -0.014324 0.057057
-v 0.009220 -0.014251 0.057022
-v -0.014780 -0.008209 0.052349
-v 0.014512 -0.008747 0.052978
-v 0.015923 -0.005957 0.049562
-v 0.016463 -0.004315 0.046176
-v -0.016130 -0.005374 0.048538
-v 0.016787 -0.003149 0.038024
-v -0.016587 -0.003874 0.044839
-v 0.016736 -0.003311 0.042260
-v 0.016623 -0.003908 0.033843
-v -0.016780 -0.003141 0.040668
-v 0.016216 -0.005454 0.030112
-v 0.018185 -0.002935 0.035641
-v 0.015501 -0.007542 0.027010
-v 0.014368 -0.009927 0.024580
-v -0.015201 -0.008261 0.026184
-v 0.017637 -0.005172 0.029546
-v 0.011788 -0.013271 0.022276
-v 0.008677 -0.015490 0.021243
-v 0.006874 -0.017616 0.019963
-v 0.004690 -0.016976 0.020729
-v -0.008734 -0.015460 0.021254
-v -0.000000 -0.017541 0.020568
-v 0.000001 -0.018813 0.019687
-v -0.006872 -0.017617 0.019962
-v -0.004662 -0.016983 0.020727
-v -0.011831 -0.013230 0.022299
-v -0.014150 -0.010300 0.024269
-v -0.016017 -0.006100 0.029007
-v -0.018185 -0.002936 0.035639
-v -0.016751 -0.003331 0.036408
-v -0.016508 -0.004384 0.032442
-v -0.017676 -0.004684 0.048338
-v -0.012688 -0.013110 0.057054
-v -0.005290 -0.015857 0.057697
-v -0.017359 0.010861 0.165411
-v -0.017114 0.010978 0.165405
-v 0.017105 0.010980 0.165405
-v 0.017998 0.006760 0.165600
-v 0.013678 -0.007019 0.164878
-v 0.017042 0.000595 0.165277
-v -0.017998 0.006760 0.165600
-v 0.004260 -0.013110 0.164559
-v -0.004262 -0.013110 0.164559
-v -0.007973 -0.011798 0.164627
-v -0.013690 -0.007003 0.164879
-v 0.014199 0.012900 0.042702
-v 0.000000 0.012900 0.034505
-v -0.014199 0.012900 0.042702
-v -0.008198 0.012900 0.036701
-v 0.008198 0.012900 0.036701
-v -0.014199 0.012900 0.059098
-v -0.008198 0.012900 0.065099
-v -0.000000 0.012900 0.067295
-v 0.008198 0.012900 0.065099
-v 0.014199 0.012900 0.059098
-v -0.001880 0.012900 0.072863
-v -0.004923 0.012900 0.075074
-v 0.001880 0.012900 0.072863
-v 0.004923 0.012900 0.075074
-v 0.006085 0.012900 0.078650
-v 0.004923 0.012900 0.082227
-v -0.006085 0.012900 0.078650
-v -0.004923 0.012900 0.082227
-v -0.001880 0.012900 0.084437
-v 0.001880 0.012900 0.084437
-v -0.005003 0.012900 0.099785
-v -0.001911 0.012900 0.102031
-v 0.001911 0.012900 0.090269
-v 0.005003 0.012900 0.092515
-v -0.001911 0.012900 0.090269
-v 0.005003 0.012900 0.099785
-v 0.006184 0.012900 0.096150
-v -0.005003 0.012900 0.092515
-v -0.006184 0.012900 0.096150
-v 0.001911 0.012900 0.102031
-v 0.017551 0.010715 -0.014201
-v 0.017144 0.009891 -0.014262
-v 0.017010 0.010505 -0.014230
-v 0.017287 0.006760 -0.014400
-v -0.017159 0.009891 -0.014262
-v -0.017025 0.010505 -0.014230
-v -0.017302 0.006760 -0.014400
-v -0.003838 -0.017246 -0.013142
-v -0.007274 -0.016060 -0.013204
-v -0.012667 -0.011115 -0.013463
-v -0.016493 0.001142 -0.014106
-v 0.015107 -0.004951 -0.013786
-v 0.013539 -0.009795 -0.013532
-v 0.011678 -0.012609 -0.013385
-v 0.003882 -0.017207 -0.013144
-v -0.000062 -0.017671 -0.013120
-v 0.008313 -0.015223 -0.013248
-v -0.015318 -0.005229 -0.013772
-v -0.010464 -0.013804 -0.013322
-v -0.003962 -0.019557 -0.011198
-v 0.016850 0.012900 0.075600
-v 0.019850 0.009900 0.075600
-v 0.019177 0.011793 0.075600
-v 0.018504 0.012399 0.075600
-v 0.019650 0.010950 0.075600
-v -0.016850 0.012900 0.075600
-v -0.019177 0.011795 0.075600
-v -0.017841 0.012742 0.075600
-v -0.019850 0.009900 0.075600
-v -0.019648 0.010952 0.075600
-v -0.018504 0.012400 0.075600
-v 0.017708 0.010514 0.165429
-v 0.017545 0.010700 0.165401
-v 0.017078 0.010513 0.165429
-v 0.017357 0.006760 0.165600
-v 0.017216 0.009891 0.165462
-v -0.017229 0.009891 0.165462
-v -0.017370 0.006760 0.165600
-v -0.017099 0.010496 0.165430
-v -0.000000 -0.013199 0.164554
-v 0.007511 -0.011520 0.164642
-v 0.010461 -0.009598 0.164743
-v 0.012897 -0.007011 0.164878
-v 0.016165 0.000533 0.165274
-v 0.004017 -0.012754 0.164578
-v -0.004019 -0.012754 0.164578
-v -0.007518 -0.011517 0.164642
-v -0.012909 -0.006996 0.164879
-v 0.000000 0.012900 0.163404
-v 0.000000 0.011003 0.165404
-v -0.000006 0.009891 0.165462
-v -0.000006 0.006760 0.165600
-v -0.000010 0.010505 0.165429
-v -0.000003 0.000539 0.165274
-v -0.000006 -0.007003 0.164879
-v -0.000005 -0.009594 0.164743
-v -0.000003 -0.011518 0.164642
-v -0.016850 0.012900 0.031793
-v -0.020000 0.006760 0.031793
-v 0.020000 0.006760 0.031793
-v 0.016850 0.012900 0.031793
-v -0.019181 0.011791 0.031793
-v -0.017846 0.012740 0.031793
-v 0.018502 0.012400 0.031793
-v 0.019650 0.010952 0.031793
-v 0.017838 0.012744 0.031793
-v 0.019850 0.009900 0.031793
-v 0.019175 0.011795 0.031793
-v -0.019850 0.009900 0.031793
-v -0.019650 0.010948 0.031793
-v -0.018509 0.012397 0.031793
-v -0.019180 0.011791 0.037044
-v -0.020000 0.006760 0.037044
-v -0.017846 0.012741 0.037044
-v -0.016850 0.012900 0.037044
-v -0.019850 0.009900 0.037044
-v -0.019649 0.010948 0.037044
-v -0.018508 0.012397 0.037044
-v -0.014664 -0.003820 0.165046
-v 0.014655 -0.003835 0.165045
-v 0.015513 -0.003806 0.165046
-v -0.015521 -0.003790 0.165047
-v -0.000004 -0.003827 0.165045
-v 0.000251 -0.015641 -0.013226
-v -0.019850 0.009900 0.043222
-v -0.019649 0.010949 0.043222
-v -0.018507 0.012398 0.043222
-v -0.019180 0.011792 0.043222
-v -0.020000 0.006760 0.043222
-v -0.017845 0.012741 0.043222
-v -0.019850 0.009900 0.050841
-v -0.019649 0.010950 0.050841
-v -0.018506 0.012398 0.050841
-v -0.019179 0.011793 0.050841
-v -0.020000 0.006760 0.050841
-v -0.017844 0.012741 0.050841
-v -0.016850 0.012900 0.050841
-v -0.019850 0.009900 0.059353
-v -0.019649 0.010951 0.059352
-v -0.018505 0.012399 0.059353
-v -0.019178 0.011794 0.059352
-v -0.020000 0.006760 0.059352
-v -0.017843 0.012741 0.059352
-v 0.020000 0.006760 0.025653
-v -0.016850 0.012900 0.025680
-v -0.020000 0.006760 0.025653
-v 0.016850 0.012900 0.025680
-v -0.019181 0.011790 0.025677
-v -0.017847 0.012740 0.025679
-v 0.018502 0.012401 0.025678
-v 0.019650 0.010952 0.025675
-v 0.017837 0.012744 0.025679
-v 0.000251 -0.013207 -0.013354
-v 0.000000 0.012900 -0.012204
-v 0.000000 0.012900 0.025680
-v 0.000251 -0.010455 -0.013498
-v -0.000007 0.010505 -0.014230
-v -0.000008 0.009891 -0.014262
-v 0.019850 0.009900 0.025671
-v 0.019175 0.011795 0.025677
-v -0.019850 0.009900 0.025671
-v -0.019650 0.010948 0.025675
-v -0.018509 0.012396 0.025678
-v 0.017448 -0.005338 0.075600
-v 0.019388 0.002407 0.075600
-v 0.017236 0.000838 -0.014090
-v 0.016380 0.000959 -0.014096
-v 0.020000 0.006760 0.037056
-v 0.019850 0.009900 0.037056
-v 0.019175 0.011795 0.037056
-v 0.018502 0.012400 0.037056
-v 0.019650 0.010952 0.037056
-v 0.020000 0.006760 0.043243
-v 0.019850 0.009900 0.043243
-v 0.019176 0.011794 0.043243
-v 0.018502 0.012400 0.043243
-v 0.019650 0.010951 0.043243
-v 0.016395 0.012900 0.050834
-v 0.020000 0.006760 0.050835
-v 0.019850 0.009900 0.050835
-v 0.019176 0.011794 0.050835
-v 0.018503 0.012400 0.050835
-v 0.019650 0.010951 0.050836
-v 0.017838 0.012744 0.043243
-v 0.016850 0.012900 0.037044
-v 0.017838 0.012744 0.037044
-v 0.000251 0.006760 -0.014400
-v 0.000251 -0.005090 -0.013779
-v 0.016850 0.012900 0.050835
-v 0.017838 0.012744 0.050835
-v 0.016850 0.012900 0.043243
-v 0.017838 0.012744 0.075600
-v 0.000251 0.001050 -0.014101
-v -0.017448 -0.005338 0.075600
-v -0.019388 0.002407 0.075600
-v 0.020000 0.006760 0.059351
-v 0.019850 0.009900 0.059351
-v 0.019176 0.011793 0.059351
-v 0.018503 0.012400 0.059351
-v 0.019650 0.010951 0.059351
-v 0.017838 0.012744 0.059351
-v 0.016850 0.012900 0.059351
-v -0.016850 0.012900 0.043222
-v 0.000000 0.011003 -0.014204
-v 0.018424 -0.002660 0.026136
-v -0.016395 0.012900 0.050840
-v -0.016850 0.012900 0.059352
-v -0.009165 0.012900 0.107061
-v 0.018510 -0.002803 0.055317
-v 0.009165 0.012900 0.107061
-v 0.000000 0.012900 0.107061
-v -0.016000 0.009159 0.050841
-v 0.016000 0.009159 0.050835
-v 0.013856 0.009159 0.058900
-v 0.008000 0.009159 0.064756
-v -0.000000 0.009159 0.066900
-v -0.008000 0.009159 0.064756
-v -0.013856 0.009159 0.058900
-v 0.008000 0.009159 0.037044
-v -0.008000 0.009159 0.037044
-v -0.013856 0.009159 0.042900
-v 0.000000 0.009159 0.034900
-v 0.013856 0.009159 0.042900
-v 0.001777 0.009159 0.101619
-v -0.005750 0.009159 0.096150
-v -0.004652 0.009159 0.092770
-v 0.005750 0.009159 0.096150
-v 0.004652 0.009159 0.099530
-v -0.001777 0.009159 0.090681
-v 0.004652 0.009159 0.092770
-v 0.001777 0.009159 0.090681
-v -0.001777 0.009159 0.101619
-v -0.004652 0.009159 0.099530
-v -0.001777 0.009159 0.073181
-v -0.004652 0.009159 0.075270
-v 0.001777 0.009159 0.073181
-v 0.004652 0.009159 0.075270
-v 0.005750 0.009159 0.078650
-v 0.004652 0.009159 0.082030
-v -0.005750 0.009159 0.078650
-v -0.004652 0.009159 0.082030
-v -0.001777 0.009159 0.084119
-v 0.001777 0.009159 0.084119
-v 0.019986 0.007045 -0.012386
-v -0.017987 0.007044 -0.014388
-v 0.017344 0.007044 0.165587
-v 0.017987 0.007044 -0.014388
-v -0.019986 0.007045 -0.012386
-v 0.017985 0.007044 0.165587
-v 0.019986 0.007044 0.163586
-v -0.017985 0.007044 0.165587
-v -0.019986 0.007044 0.163586
-v 0.017274 0.007044 -0.014388
-v -0.017289 0.007044 -0.014388
-v 0.019986 0.007045 0.075600
-v -0.019986 0.007045 0.075600
-v -0.017357 0.007044 0.165587
-v -0.000006 0.007044 0.165587
-v -0.019986 0.007045 0.031793
-v 0.019986 0.007045 0.031793
-v -0.019986 0.007045 0.037044
-v 0.000227 0.007044 -0.014388
-v -0.019986 0.007045 0.043222
-v -0.019986 0.007045 0.050841
-v -0.019986 0.007045 0.059352
-v 0.019986 0.007045 0.025654
-v -0.019986 0.007045 0.025654
-v 0.019986 0.007045 0.037056
-v 0.019986 0.007045 0.043243
-v 0.019986 0.007045 0.050835
-v 0.019986 0.007045 0.059351
-v -0.019559 0.006736 0.075337
-v -0.019559 0.006736 -0.011771
-v -0.019559 0.006736 0.163028
-v 0.019559 0.006736 -0.011771
-v 0.019559 0.006736 0.075337
-v 0.019559 0.006736 0.163028
-v -0.017603 0.006736 -0.013672
-v 0.017604 0.006736 -0.013672
-v 0.017935 0.006736 0.165023
-v -0.017935 0.006736 0.165023
-v 0.016906 0.006736 -0.013672
-v -0.016920 0.006736 -0.013672
-v 0.017297 0.006736 0.165023
-v -0.017309 0.006736 0.165023
-v -0.000006 0.006736 0.165023
-v -0.019559 0.006736 0.031683
-v 0.019559 0.006736 0.031683
-v -0.019559 0.006736 0.036915
-v -0.019559 0.006736 0.043072
-v -0.019559 0.006736 0.050664
-v -0.019559 0.006736 0.059146
-v 0.019559 0.006736 0.025563
-v -0.019559 0.006736 0.025563
-v 0.019559 0.006736 0.036927
-v 0.019559 0.006736 0.043092
-v 0.019559 0.006736 0.050658
-v 0.000245 0.006736 -0.013672
-v 0.019559 0.006736 0.059144
-v 0.019545 0.007020 -0.011759
-v -0.017590 0.007019 -0.013660
-v 0.017284 0.007019 0.165011
-v 0.017590 0.007019 -0.013660
-v -0.019545 0.007020 -0.011759
-v 0.017922 0.007019 0.165011
-v 0.019545 0.007020 0.163016
-v -0.017922 0.007019 0.165011
-v -0.019545 0.007020 0.163016
-v 0.016893 0.007019 -0.013660
-v -0.016908 0.007019 -0.013660
-v 0.019545 0.007020 0.075337
-v -0.019545 0.007020 0.075337
-v -0.017297 0.007019 0.165011
-v -0.000006 0.007019 0.165011
-v -0.019545 0.007020 0.031683
-v 0.019545 0.007020 0.031683
-v -0.019545 0.007020 0.036915
-v 0.000222 0.007019 -0.013660
-v -0.019545 0.007020 0.043072
-v -0.019545 0.007020 0.050664
-v -0.019545 0.007020 0.059146
-v 0.019545 0.007020 0.025565
-v -0.019545 0.007020 0.025565
-v 0.019545 0.007020 0.036927
-v 0.019545 0.007020 0.043092
-v 0.019545 0.007020 0.050658
-v 0.019545 0.007020 0.059144
-v -0.017984 0.007113 -0.014384
-v 0.017341 0.007113 0.165584
-v -0.019983 0.007114 -0.012383
-v -0.019983 0.007114 0.163583
-v 0.019983 0.007114 0.075600
-v -0.000006 0.007113 0.165584
-v -0.019983 0.007114 0.031793
-v -0.019983 0.007114 0.037044
-v -0.019983 0.007114 0.043222
-v -0.019983 0.007114 0.050841
-v -0.019983 0.007114 0.059352
-v -0.019983 0.007114 0.025655
-v 0.019983 0.007114 -0.012383
-v 0.017984 0.007113 -0.014384
-v 0.017981 0.007113 0.165584
-v 0.019983 0.007114 0.163583
-v -0.017981 0.007113 0.165584
-v 0.017271 0.007113 -0.014384
-v -0.017286 0.007113 -0.014384
-v -0.019983 0.007114 0.075600
-v -0.017354 0.007113 0.165584
-v 0.019983 0.007114 0.031793
-v 0.000221 0.007113 -0.014384
-v 0.019983 0.007114 0.025655
-v 0.019983 0.007114 0.037056
-v 0.019983 0.007114 0.043243
-v 0.019983 0.007114 0.050835
-v 0.019983 0.007114 0.059351
-v -0.017987 0.006687 0.165596
-v -0.019990 0.006685 0.163594
-v 0.017987 0.006687 0.165596
-v -0.019991 0.006672 -0.012393
-v 0.017992 0.006690 -0.014396
-v -0.017994 0.006691 -0.014396
-v 0.019990 0.006685 0.163594
-v -0.019993 0.006709 0.075600
-v 0.019994 0.006690 -0.012394
-v -0.017293 0.006694 -0.014397
-v 0.017343 0.006687 0.165596
-v -0.017356 0.006687 0.165596
-v -0.000006 0.006687 0.165596
-v -0.019987 0.006657 0.050770
-v 0.000251 0.006693 -0.014396
-v -0.019989 0.006665 0.043189
-v -0.019988 0.006662 0.037032
-v -0.019986 0.006649 0.031795
-v -0.019980 0.006628 0.025684
-v 0.019993 0.006709 0.075600
-v 0.017276 0.006692 -0.014396
-v 0.019981 0.006649 0.025658
-v 0.019985 0.006651 0.050782
-v 0.019989 0.006665 0.037065
-v 0.019987 0.006656 0.031814
-v 0.019988 0.006663 0.043231
-v -0.019982 0.006639 0.059227
-v 0.019982 0.006647 0.059303
-vt 0.554694 0.657391
-vt 0.433825 0.577068
-vt 0.537413 0.732767
-vt 0.171840 0.756473
-vt 0.004212 0.517422
-vt 0.508978 0.054638
-vt 0.392232 0.366129
-vt 0.535955 0.277647
-vt 0.676569 0.426611
-vt 0.570944 0.608854
-vt 0.657163 0.340708
-vt 0.197012 0.750978
-vt 0.634797 0.224341
-vt 0.536619 0.527298
-vt 0.536314 0.531147
-vt 0.536640 0.005947
-vt 0.644694 0.154642
-vt 0.655354 0.714621
-vt 0.454133 0.386270
-vt 0.251537 0.915962
-vt 0.562843 0.123107
-vt 0.676441 0.480812
-vt 0.655355 0.642524
-vt 0.637665 0.486200
-vt 0.432241 0.529792
-vt 0.433661 0.200774
-vt 0.633750 0.219086
-vt 0.454217 0.366000
-vt 0.347872 0.351543
-vt 0.532084 0.715142
-vt 0.083498 0.916082
-vt 0.432769 0.139167
-vt 0.029777 0.173023
-vt 0.971059 0.270165
-vt 0.196511 0.924853
-vt 0.069097 0.789362
-vt 0.432118 0.226219
-vt 0.960817 0.525768
-vt 0.062888 0.898170
-vt 0.751919 0.532438
-vt 0.645243 0.032928
-vt 0.536503 0.029725
-vt 0.107693 0.763735
-vt 0.746048 0.263094
-vt 0.039255 0.237927
-vt 0.745523 0.377500
-vt 0.794566 0.698936
-vt 0.748277 0.502909
-vt 0.981678 0.688262
-vt 0.655395 0.610961
-vt 0.014520 0.474610
-vt 0.967778 0.039348
-vt 0.955233 0.260973
-vt 0.015769 0.092595
-vt 0.634942 0.252270
-vt 0.709424 0.528492
-vt 0.674041 0.251333
-vt 0.637096 0.502534
-vt 0.535204 0.530002
-vt 0.273950 0.423995
-vt 0.635823 0.535625
-vt 0.359047 0.385937
-vt 0.553218 0.164920
-vt 0.192800 0.757975
-vt 0.634735 0.222563
-vt 0.535521 0.522712
-vt 0.329998 0.345864
-vt 0.029987 0.504457
-vt 0.004768 0.505706
-vt 0.299688 0.366041
-vt 0.595338 0.596712
-vt 0.023828 0.663170
-vt 0.537897 0.678838
-vt 0.961468 0.192683
-vt 0.971275 0.266931
-vt 0.304474 0.848948
-vt 0.031633 0.458764
-vt 0.747975 0.497125
-vt 0.283964 0.890144
-vt 0.960814 0.228346
-vt 0.361245 0.386645
-vt 0.349320 0.402955
-vt 0.330282 0.408849
-vt 0.039492 0.241423
-vt 0.536760 0.713602
-vt 0.442348 0.349999
-vt 0.102746 0.756393
-vt 0.016753 0.149163
-vt 0.214218 0.745926
-vt 0.750133 0.062884
-vt 0.609524 0.161420
-vt 0.014526 0.472387
-vt 0.977669 0.236466
-vt 0.030308 0.150596
-vt 0.297338 0.894235
-vt 0.019649 0.278496
-vt 0.546671 0.126797
-vt 0.015396 0.168157
-vt 0.212882 0.760696
-vt 0.787316 0.081761
-vt 0.012582 0.624053
-vt 0.774112 0.718076
-vt 0.727050 0.629840
-vt 0.099210 0.924604
-vt 0.284711 0.787354
-vt 0.984125 0.711960
-vt 0.983477 0.045252
-vt 0.709486 0.537653
-vt 0.706809 0.620714
-vt 0.775145 0.106442
-vt 0.316737 0.380021
-vt 0.539605 0.004563
-vt 0.696671 0.159777
-vt 0.434073 0.229407
-vt 0.392184 0.386776
-vt 0.748928 0.228219
-vt 0.330347 0.406689
-vt 0.774356 0.710607
-vt 0.539622 0.459478
-vt 0.070462 0.768085
-vt 0.433350 0.596419
-vt 0.017375 0.271882
-vt 0.988091 0.736164
-vt 0.038080 0.286727
-vt 0.956653 0.498984
-vt 0.643348 0.004427
-vt 0.567158 0.121473
-vt 0.004703 0.376145
-vt 0.536588 0.737505
-vt 0.490932 0.375868
-vt 0.675853 0.533596
-vt 0.636743 0.530371
-vt 0.590770 0.475309
-vt 0.538671 0.024090
-vt 0.538521 0.033513
-vt 0.043277 0.857867
-vt 0.749450 0.032688
-vt 0.645173 0.029445
-vt 0.754393 0.023111
-vt 0.589149 0.533687
-vt 0.013383 0.242884
-vt 0.779461 0.710223
-vt 0.531271 0.710635
-vt 0.587157 0.229693
-vt 0.438687 0.371517
-vt 0.674437 0.267925
-vt 0.655378 0.678955
-vt 0.732820 0.609916
-vt 0.709914 0.619362
-vt 0.756039 0.657320
-vt 0.736972 0.091197
-vt 0.261922 0.777755
-vt 0.428189 0.680875
-vt 0.774985 0.650207
-vt 0.566885 0.642223
-vt 0.265301 0.924613
-vt 0.534033 0.735766
-vt 0.403920 0.403362
-vt 0.534025 0.222534
-vt 0.344296 0.372255
-vt 0.423430 0.342895
-vt 0.751600 0.028401
-vt 0.674169 0.257466
-vt 0.655361 0.630077
-vt 0.040907 0.832261
-vt 0.588054 0.224282
-vt 0.954687 0.488290
-vt 0.536350 0.710608
-vt 0.635114 0.258340
-vt 0.434245 0.524422
-vt 0.455933 0.365409
-vt 0.098472 0.751315
-vt 0.034060 0.471008
-vt 0.971354 0.487374
-vt 0.550671 0.093325
-vt 0.277201 0.909329
-vt 0.025321 0.643014
-vt 0.709536 0.503914
-vt 0.984312 0.378254
-vt 0.979750 0.666962
-vt 0.978251 0.601641
-vt 0.709493 0.536905
-vt 0.751446 0.535548
-vt 0.751236 0.536631
-vt 0.746915 0.245359
-vt 0.970965 0.268624
-vt 0.708384 0.222919
-vt 0.549232 0.313231
-vt 0.055990 0.784833
-vt 0.691240 0.378056
-vt 0.009608 0.248066
-vt 0.587869 0.259631
-vt 0.329955 0.343701
-vt 0.432345 0.236884
-vt 0.012306 0.642800
-vt 0.013446 0.468400
-vt 0.962921 0.644716
-vt 0.761952 0.657429
-vt 0.956562 0.255253
-vt 0.682882 0.614869
-vt 0.655394 0.612791
-vt 0.038668 0.275454
-vt 0.154653 0.930696
-vt 0.603935 0.620730
-vt 0.971265 0.271920
-vt 0.980807 0.074201
-vt 0.008589 0.510309
-vt 0.423159 0.409961
-vt 0.979928 0.526074
-vt 0.746895 0.027032
-vt 0.639296 0.291549
-vt 0.707748 0.267567
-vt 0.655352 0.710416
-vt 0.302023 0.385460
-vt 0.978558 0.100001
-vt 0.707715 0.257157
-vt 0.709559 0.481150
-vt 0.678586 0.427749
-vt 0.538563 0.295323
-vt 0.589068 0.302785
-vt 0.321827 0.363518
-vt 0.749767 0.224348
-vt 0.004374 0.516796
-vt 0.537692 0.481776
-vt 0.707680 0.218088
-vt 0.540126 0.738139
-vt 0.095330 0.906145
-vt 0.051304 0.864865
-vt 0.748400 0.008421
-vt 0.749619 0.003632
-vt 0.748082 0.003099
-vt 0.538111 0.005071
-vt 0.541146 0.004472
-vt 0.677240 0.327978
-vt 0.531948 0.713658
-vt 0.655397 0.737485
-vt 0.673187 0.226015
-vt 0.521964 0.411128
-vt 0.979908 0.525604
-vt 0.423475 0.344711
-vt 0.749228 0.023240
-vt 0.274018 0.328282
-vt 0.802967 0.001424
-vt 0.290863 0.785753
-vt 0.311067 0.849306
-vt 0.772869 0.678776
-vt 0.774077 0.718536
-vt 0.526667 0.101677
-vt 0.249993 0.755988
-vt 0.971146 0.485923
-vt 0.779256 0.718195
-vt 0.531589 0.718580
-vt 0.954594 0.266047
-vt 0.433746 0.277285
-vt 0.409325 0.371161
-vt 0.009620 0.247452
-vt 0.330149 0.391516
-vt 0.339081 0.364414
-vt 0.956471 0.519081
-vt 0.025901 0.623647
-vt 0.116296 0.915735
-vt 0.309020 0.825194
-vt 0.008185 0.682350
-vt 0.036461 0.262598
-vt 0.955339 0.493327
-vt 0.676143 0.497530
-vt 0.009030 0.235849
-vt 0.709533 0.487456
-vt 0.535066 0.255380
-vt 0.348072 0.401160
-vt 0.531348 0.710226
-vt 0.636835 0.509223
-vt 0.034995 0.511718
-vt 0.301854 0.366717
-vt 0.536597 0.028305
-vt 0.029675 0.195353
-vt 0.643361 0.009756
-vt 0.536889 0.498065
-vt 0.655354 0.713178
-vt 0.405161 0.350797
-vt 0.590859 0.472850
-vt 0.433423 0.363566
-vt 0.299959 0.386171
-vt 0.972895 0.491371
-vt 0.008259 0.560156
-vt 0.250249 0.930884
-vt 0.297009 0.848558
-vt 0.978844 0.242936
-vt 0.956744 0.521765
-vt 0.432278 0.615510
-vt 0.028368 0.091511
-vt 0.428819 0.074182
-vt 0.300447 0.816374
-vt 0.590645 0.478125
-vt 0.675014 0.537098
-vt 0.588282 0.276082
-vt 0.779220 0.718583
-vt 0.016948 0.111647
-vt 0.525790 0.653731
-vt 0.278146 0.791181
-vt 0.746247 0.257677
-vt 0.533658 0.024110
-vt 0.011107 0.662066
-vt 0.434475 0.469057
-vt 0.033360 0.231697
-vt 0.584750 0.152850
-vt 0.544124 0.678517
-vt 0.503025 0.726987
-vt 0.134691 0.743314
-vt 0.971919 0.480712
-vt 0.361166 0.366144
-vt 0.718219 0.130605
-vt 0.536565 0.504705
-vt 0.633687 0.219826
-vt 0.588135 0.269890
-vt 0.641617 0.463663
-vt 0.640483 0.461614
-vt 0.629973 0.443284
-vt 0.423192 0.408130
-vt 0.645562 0.061918
-vt 0.540987 0.029754
-vt 0.047483 0.832403
-vt 0.645257 0.034371
-vt 0.056776 0.856726
-vt 0.749529 0.032224
-vt 0.754691 0.032153
-vt 0.538302 0.738043
-vt 0.744670 0.062316
-vt 0.533634 0.024500
-vt 0.012978 0.193447
-vt 0.174444 0.741716
-vt 0.544872 0.094017
-vt 0.644305 0.152511
-vt 0.676009 0.503630
-vt 0.248607 0.770773
-vt 0.684540 0.613164
-vt 0.538354 0.735708
-vt 0.803117 0.754596
-vt 0.216163 0.923612
-vt 0.509042 0.698525
-vt 0.534821 0.009833
-vt 0.589833 0.530107
-vt 0.655353 0.732167
-vt 0.977857 0.519571
-vt 0.579456 0.137911
-vt 0.231654 0.764947
-vt 0.034543 0.248596
-vt 0.533591 0.223650
-vt 0.432271 0.234785
-vt 0.434126 0.231462
-vt 0.688923 0.378114
-vt 0.708399 0.221031
-vt 0.034526 0.247939
-vt 0.292615 0.871304
-vt 0.971832 0.273596
-vt 0.799650 0.030402
-vt 0.425214 0.041700
-vt 0.670522 0.152200
-vt 0.695412 0.140669
-vt 0.707712 0.251038
-vt 0.707717 0.244226
-vt 0.676339 0.487134
-vt 0.432252 0.527666
-vt 0.650571 0.588307
-vt 0.311618 0.402432
-vt 0.422919 0.392337
-vt 0.979884 0.228177
-vt 0.535566 0.521602
-vt 0.588120 0.226046
-vt 0.674953 0.536432
-vt 0.628248 0.312708
-vt 0.745517 0.158086
-vt 0.637511 0.490851
-vt 0.954561 0.483546
-vt 0.977404 0.126169
-vt 0.766630 0.678460
-vt 0.020850 0.685237
-vt 0.954700 0.274866
-vt 0.116373 0.930626
-vt 0.778725 0.715144
-vt 0.434018 0.475875
-vt 0.969029 0.717057
-vt 0.504650 0.422273
-vt 0.414114 0.388961
-vt 0.536884 0.715094
-vt 0.658207 0.416637
-vt 0.749371 0.218152
-vt 0.961663 0.611119
-vt 0.707784 0.273832
-vt 0.591159 0.451477
-vt 0.589762 0.500619
-vt 0.033419 0.483409
-vt 0.302237 0.803799
-vt 0.349132 0.349732
-vt 0.502727 0.423468
-vt 0.404913 0.402032
-vt 0.393972 0.366687
-vt 0.359063 0.366870
-vt 0.580721 0.134282
-vt 0.432424 0.518965
-vt 0.029970 0.505122
-vt 0.666956 0.165275
-vt 0.130987 0.758053
-vt 0.033282 0.230988
-vt 0.165394 0.748950
-vt 0.959856 0.239506
-vt 0.673878 0.244528
-vt 0.978602 0.155059
-vt 0.194514 0.939639
-vt 0.432109 0.224126
-vt 0.248619 0.924770
-vt 0.214068 0.938346
-vt 0.743041 0.091680
-vt 0.707623 0.226473
-vt 0.672964 0.217825
-vt 0.408922 0.380917
-vt 0.013225 0.240276
-vt 0.637100 0.165993
-vt 0.019745 0.376348
-vt 0.537181 0.492060
-vt 0.501237 0.328565
-vt 0.971142 0.484002
-vt 0.025254 0.580845
-vt 0.046237 0.804550
-vt 0.799776 0.726015
-vt 0.019320 0.282406
-vt 0.747751 0.491741
-vt 0.747616 0.487298
-vt 0.751529 0.622943
-vt 0.965817 0.694833
-vt 0.775565 0.736773
-vt 0.977723 0.517740
-vt 0.535534 0.266906
-vt 0.536475 0.710112
-vt 0.708447 0.598419
-vt 0.511184 0.375053
-vt 0.588948 0.525537
-vt 0.134639 0.935257
-vt 0.232458 0.750383
-vt 0.977806 0.234635
-vt 0.587127 0.228828
-vt 0.774231 0.710110
-vt 0.033491 0.465502
-vt 0.564276 0.141784
-vt 0.012884 0.072516
-vt 0.961373 0.155913
-vt 0.433206 0.265388
-vt 0.587707 0.253630
-vt 0.667836 0.379009
-vt 0.673044 0.218479
-vt 0.393842 0.386229
-vt 0.673938 0.221318
-vt 0.978894 0.511274
-vt 0.134723 0.920201
-vt 0.533909 0.231992
-vt 0.587527 0.246988
-vt 0.424401 0.360512
-vt 0.779539 0.710633
-vt 0.773947 0.713601
-vt 0.431307 0.106060
-vt 0.019614 0.280387
-vt 0.548780 0.657506
-vt 0.288979 0.807196
-vt 0.031882 0.490231
-vt 0.962067 0.124384
-vt 0.234728 0.920862
-vt 0.627895 0.614871
-vt 0.443320 0.348593
-vt 0.537398 0.293340
-vt 0.432080 0.389619
-vt 0.424600 0.713567
-vt 0.534800 0.248802
-vt 0.723508 0.150293
-vt 0.535050 0.228106
-vt 0.707636 0.225824
-vt 0.772427 0.738055
-vt 0.312856 0.400772
-vt 0.675128 0.528262
-vt 0.029839 0.111471
-vt 0.028708 0.522273
-vt 0.433635 0.553350
-vt 0.014258 0.476311
-vt 0.954473 0.270805
-vt 0.283724 0.911294
-vt 0.273718 0.376163
-vt 0.668375 0.150233
-vt 0.715959 0.128100
-vt 0.680454 0.591088
-vt 0.055062 0.799398
-vt 0.050889 0.880505
-vt 0.754359 0.022717
-vt 0.754641 0.032550
-vt 0.533543 0.033869
-vt 0.538652 0.024553
-vt 0.541071 0.028294
-vt 0.330471 0.361139
-vt 0.747009 0.028476
-vt 0.432501 0.516834
-vt 0.116076 0.745878
-vt 0.588015 0.265250
-vt 0.586855 0.221581
-vt 0.778862 0.713659
-vt 0.956688 0.232390
-vt 0.488712 0.375927
-vt 0.503327 0.028036
-vt 0.321776 0.388098
-vt 0.636669 0.532149
-vt 0.773290 0.732766
-vt 0.748710 0.509329
-vt 0.709556 0.510690
-vt 0.034108 0.477084
-vt 0.634733 0.245542
-vt 0.025427 0.069662
-vt 0.978682 0.641721
-vt 0.731380 0.629037
-vt 0.749174 0.642084
-vt 0.709440 0.529141
-vt 0.674539 0.274234
-vt 0.621388 0.590325
-vt 0.019365 0.276651
-vt 0.776699 0.735852
-vt 0.637867 0.479935
-vt 0.520882 0.339321
-vt 0.750975 0.527204
-vt 0.645827 0.091805
-vt 0.646015 0.117769
-vt 0.971376 0.482292
-vt 0.434189 0.283992
-vt 0.590404 0.484365
-vt 0.959832 0.514154
-vt 0.675237 0.329210
-vt 0.979708 0.191026
-vt 0.437733 0.381368
-vt 0.675843 0.510408
-vt 0.503178 0.329675
-vt 0.025798 0.603493
-vt 0.794708 0.056991
-vt 0.012105 0.604851
-vt 0.017221 0.130184
-vt 0.747482 0.481345
-vt 0.955680 0.473929
-vt 0.745821 0.273495
-vt 0.536629 0.718536
-vt 0.232684 0.935844
-vt 0.185956 0.932429
-vt 0.134021 0.750309
-vt 0.014205 0.470309
-vt 0.770665 0.738140
-vt 0.589917 0.528339
-vt 0.710195 0.532052
-vt 0.434300 0.522334
-vt 0.532968 0.732810
-vt 0.217665 0.930945
-vt 0.579339 0.629079
-vt 0.037980 0.269265
-vt 0.588604 0.532806
-vt 0.030407 0.130646
-vt 0.967376 0.378295
-vt 0.635602 0.534880
-vt 0.433742 0.481481
-vt 0.432791 0.251722
-vt 0.551499 0.623682
-vt 0.675115 0.528897
-vt 0.415208 0.363401
-vt 0.655354 0.708970
-vt 0.673197 0.226652
-vt 0.534984 0.226345
-vt 0.533870 0.230887
-vt 0.774148 0.737529
-vt 0.537461 0.486426
-vt 0.655372 0.620846
-vt 0.710214 0.533946
-vt 0.075712 0.892473
-vt 0.455878 0.386811
-vt 0.635263 0.264024
-vt 0.709525 0.492136
-vt 0.535309 0.261328
-vt 0.540765 0.457546
-vt 0.638200 0.293545
-vt 0.004754 0.505085
-vt 0.536594 0.718076
-vt 0.066970 0.894065
-vt 0.539219 0.009858
-vt 0.064045 0.876558
-vt 0.535776 0.006830
-vt 0.540046 0.006873
-vt 0.752926 0.008342
-vt 0.751905 0.005321
-vt 0.747505 0.005422
-vt 0.643330 0.006812
-vt 0.750869 0.004295
-vt 0.978763 0.243402
-vt 0.748979 0.227388
-vt 0.551316 0.438743
-vt 0.655353 0.717380
-vt 0.516716 0.079815
-vt 0.637316 0.496500
-vt 0.515915 0.675884
-vt 0.750919 0.526369
-vt 0.746520 0.251844
-vt 0.154248 0.923133
-vt 0.194581 0.743421
-vt 0.962073 0.571203
-vt 0.038629 0.281388
-vt 0.295445 0.826673
-vt 0.534980 0.736642
-vt 0.434221 0.177364
-vt 0.537481 0.063633
-vt 0.979562 0.563043
-vt 0.959789 0.240026
-vt 0.074590 0.772179
-vt 0.018629 0.284195
-vt 0.962374 0.092665
-vt 0.433210 0.494645
-vt 0.258438 0.767007
-vt 0.727350 0.114562
-vt 0.697277 0.142739
-vt 0.597429 0.146563
-vt 0.433479 0.271736
-vt 0.635940 0.526832
-vt 0.344015 0.381758
-vt 0.590218 0.488996
-vt 0.589506 0.507278
-vt 0.442222 0.402540
-vt 0.538004 0.475527
-vt 0.588362 0.278896
-vt 0.316426 0.370673
-vt 0.746434 0.003017
-vt 0.275577 0.770394
-vt 0.646095 0.131027
-vt 0.676255 0.491827
-vt 0.773822 0.715094
-vt 0.296673 0.882054
-vt 0.777827 0.732811
-vt 0.786819 0.673874
-vt 0.433003 0.501783
-vt 0.763117 0.122406
-vt 0.123327 0.925350
-vt 0.743824 0.642148
-vt 0.600829 0.619378
-vt 0.655353 0.718823
-vt 0.588988 0.524669
-vt 0.009192 0.236470
-vt 0.154071 0.741716
-vt 0.772291 0.735789
-vt 0.587238 0.220708
-vt 0.978813 0.510808
-vt 0.561531 0.642164
-vt 0.093101 0.914476
-vt 0.271514 0.904463
-vt 0.175243 0.924813
-vt 0.988091 0.019862
-vt 0.745931 0.267570
-vt 0.600260 0.144983
-vt 0.619960 0.152558
-vt 0.621256 0.150570
-vt 0.749384 0.219039
-vt 0.311290 0.349875
-vt 0.536696 0.525523
-vt 0.589997 0.494618
-vt 0.635522 0.274981
-vt 0.533504 0.033479
-vt 0.538597 0.033956
-vt 0.543337 0.062375
-vt 0.749193 0.022772
-vt 0.733832 0.113928
-vt 0.751479 0.026980
-vt 0.644841 0.023120
-vt 0.645011 0.024559
-vt 0.645013 0.028037
-vt 0.535718 0.271520
-vt 0.956413 0.235079
-vt 0.433777 0.158150
-vt 0.054858 0.832802
-vt 0.150736 0.756501
-vt 0.655325 0.735104
-vt 0.745790 0.137738
-vt 0.633948 0.227137
-vt 0.008436 0.512945
-vt 0.633970 0.227876
-vt 0.312513 0.351535
-vt 0.955625 0.280389
-vt 0.751786 0.530237
-vt 0.960831 0.526445
-vt 0.588393 0.281351
-vt 0.034756 0.515254
-vt 0.979851 0.228650
-vt 0.174079 0.939853
-vt 0.583671 0.629880
-vt 0.954771 0.479510
-vt 0.010724 0.585680
-vt 0.430716 0.648801
-vt 0.971613 0.739967
-vt 0.306608 0.873583
-vt 0.012346 0.481019
-vt 0.626238 0.613166
-vt 0.709525 0.497824
-vt 0.404167 0.349459
-vt 0.960824 0.227823
-vt 0.673972 0.223152
-vt 0.655367 0.657822
-vt 0.432992 0.258751
-vt 0.971547 0.015732
-vt 0.228014 0.756387
-vt 0.083275 0.774579
-vt 0.060100 0.807273
-vt 0.025131 0.558293
-vt 0.963614 0.073193
-vt 0.154068 0.937899
-vt 0.972835 0.262921
-vt 0.674278 0.263197
-vt 0.707728 0.262864
-vt 0.749885 0.222152
-vt 0.635912 0.527572
-vt 0.707545 0.217380
-vt 0.646161 0.142743
-vt 0.338718 0.389165
-vt 0.675893 0.531763
-vt 0.959900 0.514674
-vt 0.531552 0.718192
-vt 0.635378 0.268715
-vt 0.443290 0.404005
-vt 0.036256 0.293301
-vt 0.028786 0.521557
-vt 0.963982 0.673742
-vt 0.433455 0.487915
-vn -0.521090 0.772906 0.362053
-vn -0.285351 0.888921 0.358321
-vn -0.567682 0.823248 0.000000
-vn -0.311600 0.950213 0.000000
-vn 0.372764 -0.088140 -0.923731
-vn 0.321855 0.605804 -0.727606
-vn 0.913199 -0.133217 -0.385123
-vn 0.747977 0.586436 -0.310843
-vn -0.992997 0.118139 0.000000
-vn -0.992990 0.118199 0.000000
-vn -0.939966 0.341268 0.000000
-vn -0.939891 0.341476 0.000000
-vn -0.782058 0.623205 0.000000
-vn -0.569305 0.822126 0.000000
-vn -0.782234 0.622985 0.000000
-vn -0.569521 0.821977 0.000000
-vn -0.870160 0.331315 0.364764
-vn -0.720412 0.591619 0.361930
-vn -0.939332 0.343010 0.000000
-vn -0.780839 0.624732 0.000000
-vn -0.984672 -0.174417 0.000336
-vn -0.952300 -0.305104 0.005982
-vn -0.902001 -0.203565 0.380730
-vn -0.857846 -0.346612 0.379420
-vn -0.250746 -0.957540 -0.142281
-vn -0.297408 -0.954362 0.027223
-vn -0.513463 -0.830318 -0.216629
-vn -0.581935 -0.812903 0.023255
-vn -0.778583 -0.505372 0.372032
-vn -0.857846 -0.346612 0.379420
-vn -0.886617 -0.462368 0.011231
-vn -0.952300 -0.305104 0.005982
-vn -0.660766 -0.650298 0.374834
-vn -0.778583 -0.505372 0.372032
-vn -0.788745 -0.614540 0.014893
-vn -0.886617 -0.462368 0.011231
-vn 0.000000 -0.925801 0.378011
-vn -0.000855 -0.999608 0.027986
-vn 0.238233 -0.894792 0.377614
-vn 0.296405 -0.954678 0.027101
-vn 0.296405 -0.954678 0.027101
-vn -0.000855 -0.999608 0.027986
-vn 0.231212 -0.957992 -0.169686
-vn 0.004517 -0.992742 -0.120182
-vn -0.238259 -0.894775 0.377637
-vn -0.471889 -0.796857 0.377279
-vn -0.297408 -0.954362 0.027223
-vn -0.581935 -0.812903 0.023255
-vn 0.581567 -0.813174 0.022981
-vn 0.296405 -0.954678 0.027101
-vn 0.511229 -0.844469 -0.159738
-vn 0.231212 -0.957992 -0.169686
-vn 0.238233 -0.894792 0.377614
-vn 0.296405 -0.954678 0.027101
-vn 0.471859 -0.796889 0.377249
-vn 0.581567 -0.813174 0.022981
-vn 0.007019 -0.844861 -0.534939
-vn 0.004517 -0.992742 -0.120182
-vn -0.250746 -0.957540 -0.142281
-vn 0.241984 -0.835699 -0.493002
-vn 0.231212 -0.957992 -0.169686
-vn 0.004517 -0.992742 -0.120182
-vn 0.007019 -0.844861 -0.534939
-vn 0.241984 -0.835699 -0.493002
-vn 0.004517 -0.992742 -0.120182
-vn -0.243419 -0.829015 -0.503470
-vn -0.250746 -0.957540 -0.142281
-vn -0.513463 -0.830318 -0.216629
-vn -0.243419 -0.829015 -0.503470
-vn 0.007019 -0.844861 -0.534939
-vn -0.250746 -0.957540 -0.142281
-vn -0.243419 -0.829015 -0.503470
-vn -0.513463 -0.830318 -0.216629
-vn -0.710895 -0.695605 -0.103736
-vn -0.460262 -0.773604 -0.435541
-vn -0.710895 -0.695605 -0.103736
-vn -0.849339 -0.521933 -0.078800
-vn -0.243419 -0.829015 -0.503470
-vn -0.710895 -0.695605 -0.103736
-vn -0.460262 -0.773604 -0.435541
-vn -0.604308 -0.711613 -0.358355
-vn -0.849339 -0.521933 -0.078800
-vn -0.913458 -0.399399 -0.077945
-vn -0.460262 -0.773604 -0.435541
-vn -0.849339 -0.521933 -0.078800
-vn -0.604308 -0.711613 -0.358355
-vn -0.639161 -0.723760 -0.260084
-vn -0.913458 -0.399399 -0.077945
-vn -0.939019 -0.338459 -0.060733
-vn -0.604308 -0.711613 -0.358355
-vn -0.913458 -0.399399 -0.077945
-vn -0.639161 -0.723760 -0.260084
-vn -0.639161 -0.723760 -0.260084
-vn -0.939019 -0.338459 -0.060733
-vn -0.949451 -0.312272 -0.032076
-vn -0.648624 -0.756632 -0.082432
-vn -0.949451 -0.312272 -0.032076
-vn -0.954279 -0.298907 0.002472
-vn -0.639161 -0.723760 -0.260084
-vn -0.949451 -0.312272 -0.032076
-vn -0.648624 -0.756632 -0.082432
-vn 0.028932 0.428152 -0.903243
-vn 0.000000 0.418594 -0.908174
-vn 0.068943 0.929284 -0.362875
-vn 0.000000 0.928819 -0.370533
-vn -0.648624 -0.756632 -0.082432
-vn -0.954279 -0.298907 0.002472
-vn -0.951202 -0.308125 0.016572
-vn -0.647672 -0.752810 0.117467
-vn -0.951202 -0.308125 0.016572
-vn -0.949874 -0.309738 0.042452
-vn -0.859060 -0.359823 -0.364066
-vn -0.899920 -0.425957 0.093297
-vn -0.909937 -0.184063 -0.371666
-vn -0.939317 -0.333574 0.080082
-vn -0.648624 -0.756632 -0.082432
-vn -0.951202 -0.308125 0.016572
-vn -0.647672 -0.752810 0.117467
-vn -0.638581 -0.710667 0.295241
-vn -0.949874 -0.309738 0.042452
-vn -0.939317 -0.333574 0.080082
-vn -0.647672 -0.752810 0.117467
-vn -0.949874 -0.309738 0.042452
-vn -0.638581 -0.710667 0.295241
-vn -0.758811 -0.548713 -0.350885
-vn -0.782121 -0.606665 0.142282
-vn -0.859060 -0.359823 -0.364066
-vn -0.899920 -0.425957 0.093297
-vn -0.638581 -0.710667 0.295241
-vn -0.939317 -0.333574 0.080082
-vn -0.899920 -0.425957 0.093297
-vn -0.609223 -0.680913 0.406454
-vn -0.899920 -0.425957 0.093297
-vn -0.782121 -0.606665 0.142282
-vn -0.638581 -0.710667 0.295241
-vn -0.899920 -0.425957 0.093297
-vn -0.609223 -0.680913 0.406454
-vn -0.467923 -0.734358 0.491698
-vn -0.782121 -0.606665 0.142282
-vn -0.633088 -0.762062 0.135871
-vn -0.609223 -0.680913 0.406454
-vn -0.782121 -0.606665 0.142282
-vn -0.467923 -0.734358 0.491698
-vn -0.584690 -0.736127 -0.340962
-vn -0.633088 -0.762062 0.135871
-vn -0.758811 -0.548713 -0.350885
-vn -0.782121 -0.606665 0.142282
-vn -0.467923 -0.734358 0.491698
-vn -0.633088 -0.762062 0.135871
-vn -0.429001 -0.879885 0.204353
-vn -0.429001 -0.879885 0.204353
-vn -0.382251 -0.857281 -0.344896
-vn -0.200814 -0.956675 0.210824
-vn -0.191601 -0.913507 -0.358878
-vn -0.237198 -0.806417 0.541691
-vn -0.429001 -0.879885 0.204353
-vn -0.200814 -0.956675 0.210824
-vn -0.467923 -0.734358 0.491698
-vn -0.429001 -0.879885 0.204353
-vn -0.237198 -0.806417 0.541691
-vn 0.000702 -0.938897 -0.344197
-vn -0.001221 -0.985450 0.169959
-vn -0.191601 -0.913507 -0.358878
-vn -0.200814 -0.956675 0.210824
-vn -0.001221 -0.985450 0.169959
-vn 0.000275 -0.811299 0.584631
-vn -0.200814 -0.956675 0.210824
-vn 0.000702 -0.938897 -0.344197
-vn -0.191601 -0.913507 -0.358878
-vn 0.002747 -0.441857 -0.897081
-vn -0.087345 -0.430315 -0.898443
-vn 0.212324 -0.913234 -0.347739
-vn 0.439571 -0.822101 -0.361838
-vn 0.209422 -0.955035 0.209880
-vn 0.453122 -0.859397 0.236892
-vn 0.000275 -0.811299 0.584631
-vn -0.001221 -0.985450 0.169959
-vn 0.209422 -0.955035 0.209880
-vn -0.277025 -0.360404 -0.890711
-vn -0.171580 -0.405969 -0.897636
-vn -0.584690 -0.736127 -0.340962
-vn -0.382251 -0.857281 -0.344896
-vn 0.106113 -0.434098 -0.894594
-vn 0.212324 -0.913234 -0.347739
-vn 0.002747 -0.441857 -0.897081
-vn 0.000702 -0.938897 -0.344197
-vn -0.342519 -0.277268 -0.897666
-vn -0.277025 -0.360404 -0.890711
-vn -0.758811 -0.548713 -0.350885
-vn -0.584690 -0.736127 -0.340962
-vn -0.386469 -0.166759 -0.907102
-vn -0.342519 -0.277268 -0.897666
-vn -0.859060 -0.359823 -0.364066
-vn -0.758811 -0.548713 -0.350885
-vn -0.991137 -0.132636 -0.007416
-vn -0.734553 0.678551 -0.000092
-vn -0.991018 -0.133704 -0.002472
-vn -0.734685 0.678408 0.000000
-vn 0.319082 -0.282245 0.904723
-vn 0.000000 -0.052339 0.998629
-vn 0.253949 -0.348223 0.902358
-vn 0.000000 -0.052402 0.998626
-vn 0.311907 -0.598482 -0.737925
-vn 0.739459 -0.596169 -0.312703
-vn 0.233778 -0.773910 -0.588566
-vn 0.590148 -0.771523 -0.237652
-vn -0.087286 -0.425991 0.900507
-vn 0.000000 -0.434743 0.900555
-vn 0.000000 -0.052096 0.998642
-vn 0.000000 -0.052157 0.998639
-vn 0.377487 -0.139135 0.915503
-vn 0.000000 -0.052309 0.998631
-vn 0.352987 -0.211408 0.911431
-vn 0.000000 -0.052309 0.998631
-vn -0.254165 -0.348043 0.902367
-vn -0.174140 -0.397386 0.900977
-vn 0.000031 -0.052432 0.998624
-vn -0.000031 -0.052432 0.998624
-vn -0.319323 -0.281907 0.904744
-vn -0.353195 -0.211129 0.911415
-vn -0.778583 -0.505372 0.372032
-vn -0.857846 -0.346612 0.379420
-vn 0.253949 -0.348223 0.902358
-vn 0.660743 -0.650336 0.374808
-vn 0.319082 -0.282245 0.904723
-vn 0.778579 -0.505401 0.372000
-vn -0.353195 -0.211129 0.911415
-vn -0.377613 -0.138923 0.915483
-vn -0.857846 -0.346612 0.379420
-vn -0.902001 -0.203565 0.380730
-vn 0.000000 -0.434743 0.900555
-vn -0.087286 -0.425991 0.900507
-vn 0.000000 -0.925801 0.378011
-vn -0.238259 -0.894775 0.377637
-vn -0.174140 -0.397386 0.900977
-vn -0.254165 -0.348043 0.902367
-vn -0.471889 -0.796857 0.377279
-vn -0.660766 -0.650298 0.374834
-vn 0.238233 -0.894792 0.377614
-vn 0.087254 -0.426017 0.900498
-vn 0.000000 -0.925801 0.378011
-vn 0.000000 -0.434743 0.900555
-vn -0.254165 -0.348043 0.902367
-vn -0.319323 -0.281907 0.904744
-vn -0.660766 -0.650298 0.374834
-vn -0.778583 -0.505372 0.372032
-vn -0.919299 0.124793 0.373250
-vn -0.395796 0.091006 0.913818
-vn -0.870160 0.331315 0.364764
-vn -0.392471 0.192390 0.899418
-vn 0.396049 0.205456 0.894948
-vn 0.396174 0.091223 0.913633
-vn 0.867846 0.335834 0.366140
-vn 0.919256 0.124211 0.373550
-vn -0.312362 0.298720 0.901774
-vn -0.720412 0.591619 0.361930
-vn -0.392471 0.192390 0.899418
-vn -0.870160 0.331315 0.364764
-vn -0.992942 0.118598 0.000000
-vn -0.919299 0.124793 0.373250
-vn -0.939332 0.343010 0.000000
-vn -0.870160 0.331315 0.364764
-vn -0.285351 0.888921 0.358321
-vn -0.122289 0.433856 0.892645
-vn -0.069248 0.929275 0.362841
-vn -0.029177 0.427853 0.903377
-vn -0.782587 0.622541 0.000000
-vn -0.569973 0.821663 0.000000
-vn -0.722183 0.589362 -0.362083
-vn -0.523403 0.771371 -0.361988
-vn -0.313581 0.949562 0.000000
-vn -0.079471 0.996837 0.000000
-vn -0.287517 0.888248 -0.358259
-vn -0.070103 0.929281 -0.362660
-vn -0.122289 0.433856 0.892645
-vn -0.285351 0.888921 0.358321
-vn -0.224988 0.373677 0.899859
-vn -0.521090 0.772906 0.362053
-vn -0.569973 0.821663 0.000000
-vn -0.313581 0.949562 0.000000
-vn -0.523403 0.771371 -0.361988
-vn -0.287517 0.888248 -0.358259
-vn -0.939966 0.341268 0.000000
-vn -0.782587 0.622541 0.000000
-vn -0.870643 0.329573 -0.365189
-vn -0.722183 0.589362 -0.362083
-vn -0.285351 0.888921 0.358321
-vn -0.069248 0.929275 0.362841
-vn -0.311600 0.950213 0.000000
-vn -0.078738 0.996895 0.000000
-vn -0.224988 0.373677 0.899859
-vn -0.521090 0.772906 0.362053
-vn -0.312362 0.298720 0.901774
-vn -0.720412 0.591619 0.361930
-vn -0.312152 0.299273 -0.901663
-vn -0.393298 0.193094 -0.898906
-vn -0.722183 0.589362 -0.362083
-vn -0.870643 0.329573 -0.365189
-vn -0.720412 0.591619 0.361930
-vn -0.521090 0.772906 0.362053
-vn -0.780839 0.624732 0.000000
-vn -0.567682 0.823248 0.000000
-vn -0.224897 0.374747 -0.899436
-vn -0.312152 0.299273 -0.901663
-vn -0.523403 0.771371 -0.361988
-vn -0.722183 0.589362 -0.362083
-vn -0.121224 0.433042 -0.893185
-vn -0.224897 0.374747 -0.899436
-vn -0.287517 0.888248 -0.358259
-vn -0.523403 0.771371 -0.361988
-vn -0.029329 0.427604 -0.903490
-vn -0.121224 0.433042 -0.893185
-vn -0.070103 0.929281 -0.362660
-vn -0.287517 0.888248 -0.358259
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.992997 0.118139 0.000000
-vn -0.992990 0.118199 0.000000
-vn 0.000000 0.052309 -0.998631
-vn 0.000000 0.048190 -0.998838
-vn -0.393298 0.193094 -0.898906
-vn -0.396046 0.091008 -0.913710
-vn -0.734964 0.678106 0.000061
-vn -0.670866 0.741578 0.000000
-vn -0.730909 0.682475 0.000000
-vn -0.670866 0.741578 0.000000
-vn 0.029085 0.427176 0.903701
-vn 0.121893 0.433583 0.892832
-vn 0.069399 0.929325 0.362684
-vn 0.286943 0.888480 0.358145
-vn 0.720131 0.591401 0.362843
-vn 0.527037 0.768230 0.363393
-vn 0.320333 0.310109 0.895108
-vn 0.235030 0.375908 0.896356
-vn 0.121893 0.433583 0.892832
-vn 0.235030 0.375908 0.896356
-vn 0.286943 0.888480 0.358145
-vn 0.527037 0.768230 0.363393
-vn 0.939143 0.343526 0.000000
-vn 0.993040 0.117774 0.000000
-vn 0.868458 0.334950 -0.365499
-vn 0.919351 0.124242 -0.373307
-vn 0.310045 -0.595674 0.740976
-vn 0.000000 -0.675817 0.737069
-vn 0.263930 -0.785352 0.559967
-vn 0.000000 -0.675849 0.737040
-vn 0.568602 0.822613 0.000000
-vn 0.780351 0.625342 0.000000
-vn 0.524598 0.770401 -0.362326
-vn 0.719155 0.592775 -0.362538
-vn 0.780351 0.625342 0.000000
-vn 0.939143 0.343526 0.000000
-vn 0.719155 0.592775 -0.362538
-vn 0.868458 0.334950 -0.365499
-vn 0.867846 0.335834 0.366140
-vn 0.720131 0.591401 0.362843
-vn 0.396049 0.205456 0.894948
-vn 0.320333 0.310109 0.895108
-vn 0.311536 0.950234 0.000000
-vn 0.568602 0.822613 0.000000
-vn 0.286295 0.888581 -0.358411
-vn 0.524598 0.770401 -0.362326
-vn 0.078190 0.996939 0.000000
-vn 0.311536 0.950234 0.000000
-vn 0.068943 0.929284 -0.362875
-vn 0.286295 0.888581 -0.358411
-vn 0.325795 0.316060 -0.891046
-vn 0.719155 0.592775 -0.362538
-vn 0.392297 0.200055 -0.897820
-vn 0.868458 0.334950 -0.365499
-vn -0.381763 0.058475 0.922409
-vn 0.000000 0.044008 0.999031
-vn -0.395796 0.091006 0.913818
-vn 0.000000 0.048434 0.998826
-vn 0.939246 0.343245 0.000000
-vn 0.993048 0.117711 0.000000
-vn 0.939213 0.343335 0.000000
-vn 0.993044 0.117741 0.000000
-vn -0.353195 -0.211129 0.911415
-vn -0.319323 -0.281907 0.904744
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052279 0.998633
-vn 0.239788 -0.804483 0.543423
-vn 0.209422 -0.955035 0.209880
-vn 0.453122 -0.859397 0.236892
-vn 0.239788 -0.804483 0.543423
-vn 0.000275 -0.811299 0.584631
-vn 0.209422 -0.955035 0.209880
-vn 0.640223 -0.679501 -0.358321
-vn 0.802405 -0.482688 -0.350938
-vn 0.640007 -0.753384 0.151006
-vn 0.797224 -0.586336 0.143685
-vn 0.239788 -0.804483 0.543423
-vn 0.453122 -0.859397 0.236892
-vn 0.640007 -0.753384 0.151006
-vn 0.466575 -0.738743 0.486381
-vn 0.640007 -0.753384 0.151006
-vn 0.797224 -0.586336 0.143685
-vn 0.466575 -0.738743 0.486381
-vn 0.239788 -0.804483 0.543423
-vn 0.640007 -0.753384 0.151006
-vn 0.596342 -0.683993 0.420155
-vn 0.797224 -0.586336 0.143685
-vn 0.897571 -0.428521 0.103613
-vn 0.596342 -0.683993 0.420155
-vn 0.466575 -0.738743 0.486381
-vn 0.797224 -0.586336 0.143685
-vn 0.366104 -0.154792 -0.917610
-vn 0.877705 -0.298509 -0.374869
-vn 0.374497 -0.244701 -0.894356
-vn 0.802405 -0.482688 -0.350938
-vn 0.596342 -0.683993 0.420155
-vn 0.897571 -0.428521 0.103613
-vn 0.934625 -0.355612 0.004151
-vn 0.897571 -0.428521 0.103613
-vn 0.797224 -0.586336 0.143685
-vn 0.877705 -0.298509 -0.374869
-vn 0.802405 -0.482688 -0.350938
-vn 0.638345 -0.713270 0.289416
-vn 0.934625 -0.355612 0.004151
-vn 0.949811 -0.310561 0.037569
-vn 0.638345 -0.713270 0.289416
-vn 0.596342 -0.683993 0.420155
-vn 0.934625 -0.355612 0.004151
-vn 0.638345 -0.713270 0.289416
-vn 0.949811 -0.310561 0.037569
-vn 0.950440 -0.308980 0.034579
-vn 0.985937 -0.163336 -0.035341
-vn 0.897571 -0.428521 0.103613
-vn 0.904830 -0.170541 -0.390126
-vn 0.877705 -0.298509 -0.374869
-vn 0.650787 -0.750218 0.116827
-vn 0.950440 -0.308980 0.034579
-vn 0.957065 -0.289866 0.002228
-vn 0.650787 -0.750218 0.116827
-vn 0.638345 -0.713270 0.289416
-vn 0.950440 -0.308980 0.034579
-vn 0.650787 -0.750218 0.116827
-vn 0.957065 -0.289866 0.002228
-vn 0.949985 -0.312053 -0.012299
-vn 0.649294 -0.756172 -0.081364
-vn 0.949985 -0.312053 -0.012299
-vn 0.946362 -0.321059 -0.036318
-vn 0.649294 -0.756172 -0.081364
-vn 0.650787 -0.750218 0.116827
-vn 0.949985 -0.312053 -0.012299
-vn 0.912059 -0.149299 0.381914
-vn 0.989641 -0.143562 -0.000641
-vn 0.750260 0.586248 0.305652
-vn 0.738513 0.674239 0.000000
-vn 0.637546 -0.726174 -0.257307
-vn 0.946362 -0.321059 -0.036318
-vn 0.922100 -0.382311 -0.059756
-vn 0.637546 -0.726174 -0.257307
-vn 0.649294 -0.756172 -0.081364
-vn 0.946362 -0.321059 -0.036318
-vn 0.946362 -0.321059 -0.036318
-vn 0.981702 -0.190316 0.006439
-vn 0.922100 -0.382311 -0.059756
-vn 0.637546 -0.726174 -0.257307
-vn 0.922100 -0.382311 -0.059756
-vn 0.898822 -0.432030 -0.073948
-vn 0.898822 -0.432030 -0.073948
-vn 0.951306 -0.308211 0.004853
-vn 0.834906 -0.542718 -0.091587
-vn 0.884960 -0.465507 0.012208
-vn 0.602210 -0.707044 -0.370720
-vn 0.898822 -0.432030 -0.073948
-vn 0.834906 -0.542718 -0.091587
-vn 0.602210 -0.707044 -0.370720
-vn 0.637546 -0.726174 -0.257307
-vn 0.898822 -0.432030 -0.073948
-vn 0.834906 -0.542718 -0.091587
-vn 0.884960 -0.465507 0.012208
-vn 0.726236 -0.680854 -0.094976
-vn 0.789045 -0.614139 0.015504
-vn 0.602210 -0.707044 -0.370720
-vn 0.834906 -0.542718 -0.091587
-vn 0.726236 -0.680854 -0.094976
-vn 0.789045 -0.614139 0.015504
-vn 0.581567 -0.813174 0.022981
-vn 0.726236 -0.680854 -0.094976
-vn 0.511229 -0.844469 -0.159738
-vn 0.461423 -0.761703 -0.454861
-vn 0.726236 -0.680854 -0.094976
-vn 0.511229 -0.844469 -0.159738
-vn 0.461423 -0.761703 -0.454861
-vn 0.602210 -0.707044 -0.370720
-vn 0.726236 -0.680854 -0.094976
-vn -0.513463 -0.830318 -0.216629
-vn -0.581935 -0.812903 0.023255
-vn -0.710895 -0.695605 -0.103736
-vn -0.788745 -0.614540 0.014893
-vn 0.241984 -0.835699 -0.493002
-vn 0.511229 -0.844469 -0.159738
-vn 0.231212 -0.957992 -0.169686
-vn 0.241984 -0.835699 -0.493002
-vn 0.461423 -0.761703 -0.454861
-vn 0.511229 -0.844469 -0.159738
-vn 0.471859 -0.796889 0.377249
-vn 0.581567 -0.813174 0.022981
-vn 0.660743 -0.650336 0.374808
-vn 0.789045 -0.614139 0.015504
-vn -0.471889 -0.796857 0.377279
-vn -0.660766 -0.650298 0.374834
-vn -0.581935 -0.812903 0.023255
-vn -0.788745 -0.614540 0.014893
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 0.699991 -0.714152
-vn 0.000000 0.699991 -0.714152
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn -0.171580 -0.405969 -0.897636
-vn -0.087345 -0.430315 -0.898443
-vn -0.382251 -0.857281 -0.344896
-vn -0.191601 -0.913507 -0.358878
-vn 0.087254 -0.426017 0.900498
-vn 0.238233 -0.894792 0.377614
-vn 0.173990 -0.397360 0.901018
-vn 0.471859 -0.796889 0.377249
-vn 0.173990 -0.397360 0.901018
-vn 0.471859 -0.796889 0.377249
-vn 0.253949 -0.348223 0.902358
-vn 0.660743 -0.650336 0.374808
-vn 0.319082 -0.282245 0.904723
-vn 0.778579 -0.505401 0.372000
-vn 0.352987 -0.211408 0.911431
-vn 0.857781 -0.346641 0.379541
-vn 0.901970 -0.203534 0.380821
-vn 0.377487 -0.139135 0.915503
-vn 0.857781 -0.346641 0.379541
-vn 0.352987 -0.211408 0.911431
-vn 0.375234 -0.102697 0.921223
-vn 0.912059 -0.149299 0.381914
-vn 0.329149 0.602020 0.727484
-vn 0.750260 0.586248 0.305652
-vn 0.122871 0.434167 -0.892414
-vn 0.286295 0.888581 -0.358411
-vn 0.228679 0.372332 -0.899486
-vn 0.524598 0.770401 -0.362326
-vn 0.028932 0.428152 -0.903243
-vn 0.068943 0.929284 -0.362875
-vn 0.122871 0.434167 -0.892414
-vn 0.286295 0.888581 -0.358411
-vn -0.048831 -0.536314 -0.842605
-vn 0.048037 -0.537777 -0.841717
-vn -0.000397 -0.487642 -0.873044
-vn 0.241984 -0.835699 -0.493002
-vn 0.048037 -0.537777 -0.841717
-vn 0.120276 -0.592529 -0.796519
-vn 0.007019 -0.844861 -0.534939
-vn 0.048037 -0.537777 -0.841717
-vn 0.241984 -0.835699 -0.493002
-vn -0.127296 -0.607792 0.783827
-vn -0.114081 -0.538145 0.835096
-vn 0.133795 -0.607355 0.783083
-vn 0.113316 -0.537375 0.835696
-vn 0.461423 -0.761703 -0.454861
-vn 0.120276 -0.592529 -0.796519
-vn 0.138436 -0.667855 -0.731304
-vn 0.241984 -0.835699 -0.493002
-vn 0.120276 -0.592529 -0.796519
-vn 0.461423 -0.761703 -0.454861
-vn -0.171456 -0.865459 -0.470726
-vn 0.147194 -0.854141 -0.498775
-vn -0.176492 -0.781012 -0.599058
-vn 0.183848 -0.767314 -0.614352
-vn 0.602210 -0.707044 -0.370720
-vn 0.138436 -0.667855 -0.731304
-vn 0.183848 -0.767314 -0.614352
-vn 0.461423 -0.761703 -0.454861
-vn 0.138436 -0.667855 -0.731304
-vn 0.602210 -0.707044 -0.370720
-vn -0.154304 -0.850013 0.503654
-vn 0.165595 -0.881167 0.442857
-vn -0.123083 -0.939557 0.319503
-vn 0.105839 -0.942204 0.317883
-vn 0.602210 -0.707044 -0.370720
-vn 0.183848 -0.767314 -0.614352
-vn 0.147194 -0.854141 -0.498775
-vn -0.123083 -0.939557 0.319503
-vn 0.105839 -0.942204 0.317883
-vn -0.165385 -0.979921 0.111366
-vn 0.128944 -0.988856 0.074406
-vn 0.637546 -0.726174 -0.257307
-vn 0.147194 -0.854141 -0.498775
-vn 0.095371 -0.953529 -0.285809
-vn 0.602210 -0.707044 -0.370720
-vn 0.147194 -0.854141 -0.498775
-vn 0.637546 -0.726174 -0.257307
-vn -0.121832 -0.784555 0.607972
-vn 0.125158 -0.786652 0.604577
-vn -0.154304 -0.850013 0.503654
-vn 0.165595 -0.881167 0.442857
-vn 0.637546 -0.726174 -0.257307
-vn 0.095371 -0.953529 -0.285809
-vn 0.166633 -0.977095 -0.132361
-vn -0.127296 -0.607792 0.783827
-vn 0.133795 -0.607355 0.783083
-vn -0.157268 -0.676224 0.719714
-vn 0.172404 -0.693613 0.699412
-vn 0.649294 -0.756172 -0.081364
-vn 0.166633 -0.977095 -0.132361
-vn 0.128944 -0.988856 0.074406
-vn 0.637546 -0.726174 -0.257307
-vn 0.166633 -0.977095 -0.132361
-vn 0.649294 -0.756172 -0.081364
-vn -0.140114 -0.669504 -0.729474
-vn 0.138436 -0.667855 -0.731304
-vn -0.119057 -0.591407 -0.797536
-vn 0.120276 -0.592529 -0.796519
-vn 0.650787 -0.750218 0.116827
-vn 0.128944 -0.988856 0.074406
-vn 0.105839 -0.942204 0.317883
-vn 0.649294 -0.756172 -0.081364
-vn 0.128944 -0.988856 0.074406
-vn 0.650787 -0.750218 0.116827
-vn -0.165385 -0.979921 0.111366
-vn 0.128944 -0.988856 0.074406
-vn -0.145208 -0.987646 -0.058901
-vn 0.166633 -0.977095 -0.132361
-vn 0.650787 -0.750218 0.116827
-vn 0.105839 -0.942204 0.317883
-vn 0.165595 -0.881167 0.442857
-vn -0.123999 -0.951033 -0.283125
-vn 0.095371 -0.953529 -0.285809
-vn -0.171456 -0.865459 -0.470726
-vn 0.147194 -0.854141 -0.498775
-vn 0.638345 -0.713270 0.289416
-vn 0.165595 -0.881167 0.442857
-vn 0.125158 -0.786652 0.604577
-vn 0.650787 -0.750218 0.116827
-vn 0.165595 -0.881167 0.442857
-vn 0.638345 -0.713270 0.289416
-vn 0.596342 -0.683993 0.420155
-vn 0.125158 -0.786652 0.604577
-vn 0.172404 -0.693613 0.699412
-vn 0.638345 -0.713270 0.289416
-vn 0.125158 -0.786652 0.604577
-vn 0.596342 -0.683993 0.420155
-vn -0.145208 -0.987646 -0.058901
-vn 0.166633 -0.977095 -0.132361
-vn -0.123999 -0.951033 -0.283125
-vn 0.095371 -0.953529 -0.285809
-vn 0.596342 -0.683993 0.420155
-vn 0.172404 -0.693613 0.699412
-vn 0.133795 -0.607355 0.783083
-vn -0.114081 -0.538145 0.835096
-vn -0.046175 -0.491786 0.869491
-vn 0.113316 -0.537375 0.835696
-vn 0.046267 -0.491606 0.869588
-vn 0.466575 -0.738743 0.486381
-vn 0.133795 -0.607355 0.783083
-vn 0.113316 -0.537375 0.835696
-vn 0.596342 -0.683993 0.420155
-vn 0.133795 -0.607355 0.783083
-vn 0.466575 -0.738743 0.486381
-vn 0.239788 -0.804483 0.543423
-vn 0.113316 -0.537375 0.835696
-vn 0.046267 -0.491606 0.869588
-vn 0.466575 -0.738743 0.486381
-vn 0.113316 -0.537375 0.835696
-vn 0.239788 -0.804483 0.543423
-vn -0.046175 -0.491786 0.869491
-vn 0.000031 -0.438709 0.898629
-vn 0.046267 -0.491606 0.869588
-vn 0.239788 -0.804483 0.543423
-vn 0.046267 -0.491606 0.869588
-vn 0.000275 -0.811299 0.584631
-vn -0.237198 -0.806417 0.541691
-vn -0.046175 -0.491786 0.869491
-vn -0.114081 -0.538145 0.835096
-vn 0.000275 -0.811299 0.584631
-vn -0.237198 -0.806417 0.541691
-vn -0.200814 -0.956675 0.210824
-vn -0.237198 -0.806417 0.541691
-vn 0.000275 -0.811299 0.584631
-vn -0.046175 -0.491786 0.869491
-vn -0.467923 -0.734358 0.491698
-vn -0.114081 -0.538145 0.835096
-vn -0.127296 -0.607792 0.783827
-vn -0.467923 -0.734358 0.491698
-vn -0.237198 -0.806417 0.541691
-vn -0.114081 -0.538145 0.835096
-vn -0.467923 -0.734358 0.491698
-vn -0.127296 -0.607792 0.783827
-vn -0.157268 -0.676224 0.719714
-vn -0.609223 -0.680913 0.406454
-vn -0.157268 -0.676224 0.719714
-vn -0.121832 -0.784555 0.607972
-vn -0.609223 -0.680913 0.406454
-vn -0.467923 -0.734358 0.491698
-vn -0.157268 -0.676224 0.719714
-vn -0.609223 -0.680913 0.406454
-vn -0.121832 -0.784555 0.607972
-vn -0.154304 -0.850013 0.503654
-vn -0.638581 -0.710667 0.295241
-vn -0.154304 -0.850013 0.503654
-vn -0.123083 -0.939557 0.319503
-vn -0.638581 -0.710667 0.295241
-vn -0.609223 -0.680913 0.406454
-vn -0.154304 -0.850013 0.503654
-vn -0.647672 -0.752810 0.117467
-vn -0.123083 -0.939557 0.319503
-vn -0.165385 -0.979921 0.111366
-vn -0.647672 -0.752810 0.117467
-vn -0.638581 -0.710667 0.295241
-vn -0.123083 -0.939557 0.319503
-vn -0.647672 -0.752810 0.117467
-vn -0.165385 -0.979921 0.111366
-vn -0.145208 -0.987646 -0.058901
-vn -0.648624 -0.756632 -0.082432
-vn -0.145208 -0.987646 -0.058901
-vn -0.123999 -0.951033 -0.283125
-vn -0.648624 -0.756632 -0.082432
-vn -0.647672 -0.752810 0.117467
-vn -0.145208 -0.987646 -0.058901
-vn -0.639161 -0.723760 -0.260084
-vn -0.123999 -0.951033 -0.283125
-vn -0.171456 -0.865459 -0.470726
-vn -0.639161 -0.723760 -0.260084
-vn -0.648624 -0.756632 -0.082432
-vn -0.123999 -0.951033 -0.283125
-vn -0.639161 -0.723760 -0.260084
-vn -0.171456 -0.865459 -0.470726
-vn -0.176492 -0.781012 -0.599058
-vn -0.604308 -0.711613 -0.358355
-vn -0.639161 -0.723760 -0.260084
-vn -0.176492 -0.781012 -0.599058
-vn -0.460262 -0.773604 -0.435541
-vn -0.140114 -0.669504 -0.729474
-vn -0.119057 -0.591407 -0.797536
-vn -0.460262 -0.773604 -0.435541
-vn -0.604308 -0.711613 -0.358355
-vn -0.140114 -0.669504 -0.729474
-vn -0.243419 -0.829015 -0.503470
-vn -0.119057 -0.591407 -0.797536
-vn -0.048831 -0.536314 -0.842605
-vn -0.243419 -0.829015 -0.503470
-vn -0.460262 -0.773604 -0.435541
-vn -0.119057 -0.591407 -0.797536
-vn -0.243419 -0.829015 -0.503470
-vn -0.048831 -0.536314 -0.842605
-vn 0.007019 -0.844861 -0.534939
-vn -0.745103 0.591285 -0.308552
-vn -0.734685 0.678408 0.000000
-vn -0.500057 0.836990 -0.222241
-vn -0.670866 0.741578 0.000000
-vn 0.253949 -0.348223 0.902358
-vn 0.000000 -0.052402 0.998626
-vn 0.173990 -0.397360 0.901018
-vn 0.000031 -0.052339 0.998629
-vn 0.381762 0.058535 0.922405
-vn 0.396174 0.091223 0.913633
-vn 0.000000 0.044038 0.999030
-vn 0.000000 0.048464 0.998825
-vn 0.000000 0.052126 0.998641
-vn -0.392471 0.192390 0.899418
-vn 0.000000 0.048434 0.998826
-vn -0.395796 0.091006 0.913818
-vn -0.381975 0.058596 -0.922313
-vn -0.396046 0.091008 -0.913710
-vn 0.000000 0.043978 -0.999033
-vn 0.000000 0.048190 -0.998838
-vn -0.316758 0.606690 -0.729103
-vn -0.214888 0.828363 -0.517338
-vn 0.000000 0.699991 -0.714152
-vn 0.000000 0.732851 -0.680389
-vn -0.393298 0.193094 -0.898906
-vn -0.396046 0.091008 -0.913710
-vn -0.870643 0.329573 -0.365189
-vn -0.919325 0.124518 -0.373278
-vn 0.173990 -0.397360 0.901018
-vn 0.000031 -0.052339 0.998629
-vn 0.087254 -0.426017 0.900498
-vn 0.000000 -0.052126 0.998641
-vn -0.912094 -0.149238 0.381855
-vn -0.902001 -0.203565 0.380730
-vn -0.375319 -0.102543 0.921206
-vn -0.377613 -0.138923 0.915483
-vn 0.000000 0.044008 0.999031
-vn 0.000000 0.044069 0.999029
-vn 0.000000 0.048434 0.998826
-vn 0.000000 0.048434 0.998826
-vn 0.000000 0.048160 -0.998840
-vn 0.395989 0.090856 -0.913750
-vn 0.000000 0.043978 -0.999033
-vn 0.382011 0.058628 -0.922296
-vn -0.319323 -0.281907 0.904744
-vn -0.254165 -0.348043 0.902367
-vn 0.000000 -0.052279 0.998633
-vn 0.000031 -0.052432 0.998624
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078433 0.996919 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.719155 0.592775 -0.362538
-vn 0.325795 0.316060 -0.891046
-vn 0.524598 0.770401 -0.362326
-vn 0.228679 0.372332 -0.899486
-vn 0.919351 0.124242 -0.373307
-vn 0.395989 0.090856 -0.913750
-vn 0.868458 0.334950 -0.365499
-vn 0.392297 0.200055 -0.897820
-vn 0.998866 0.047610 0.000000
-vn 0.993055 0.117650 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993066 0.117560 0.000000
-vn 0.395989 0.090856 -0.913750
-vn 0.000000 0.048160 -0.998840
-vn 0.392297 0.200055 -0.897820
-vn 0.002930 0.055209 -0.998470
-vn -0.316758 0.606690 -0.729103
-vn -0.745103 0.591285 -0.308552
-vn -0.214888 0.828363 -0.517338
-vn -0.500057 0.836990 -0.222241
-vn 0.000000 0.052279 -0.998633
-vn 0.000000 0.048190 -0.998838
-vn 0.000000 0.052309 -0.998631
-vn 0.000000 0.048190 -0.998838
-vn 0.392297 0.200055 -0.897820
-vn 0.002930 0.055209 -0.998470
-vn 0.325795 0.316060 -0.891046
-vn 0.228679 0.372332 -0.899486
-vn 0.228679 0.372332 -0.899486
-vn 0.002930 0.055209 -0.998470
-vn 0.122871 0.434167 -0.892414
-vn 0.028932 0.428152 -0.903243
-vn -0.393298 0.193094 -0.898906
-vn -0.312152 0.299273 -0.901663
-vn 0.000000 0.052309 -0.998631
-vn -0.224897 0.374747 -0.899436
-vn -0.029329 0.427604 -0.903490
-vn 0.000000 0.052309 -0.998631
-vn -0.121224 0.433042 -0.893185
-vn -0.224897 0.374747 -0.899436
-vn 0.000000 0.418594 -0.908174
-vn 0.028932 0.428152 -0.903243
-vn 0.000000 0.052279 -0.998633
-vn 0.002930 0.055209 -0.998470
-vn 0.184245 -0.380941 -0.906056
-vn 0.106113 -0.434098 -0.894594
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn -0.171580 -0.405969 -0.897636
-vn -0.277025 -0.360404 -0.890711
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.366104 -0.154792 -0.917610
-vn 0.374497 -0.244701 -0.894356
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn -0.386469 -0.166759 -0.907102
-vn 0.000000 -0.052309 -0.998631
-vn -0.342519 -0.277268 -0.897666
-vn 0.000000 -0.052309 -0.998631
-vn 0.106113 -0.434098 -0.894594
-vn 0.002747 -0.441857 -0.897081
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052339 -0.998629
-vn -0.277025 -0.360404 -0.890711
-vn -0.342519 -0.277268 -0.897666
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn -0.386469 -0.166759 -0.907102
-vn -0.385668 -0.101262 -0.917064
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn -0.171580 -0.405969 -0.897636
-vn 0.000000 -0.052309 -0.998631
-vn -0.087345 -0.430315 -0.898443
-vn 0.000000 -0.052339 -0.998629
-vn 0.184245 -0.380941 -0.906056
-vn 0.000000 -0.052309 -0.998631
-vn 0.304368 -0.320665 -0.896958
-vn 0.000000 -0.052339 -0.998629
-vn -0.087345 -0.430315 -0.898443
-vn 0.000000 -0.052339 -0.998629
-vn 0.002747 -0.441857 -0.897081
-vn 0.000000 -0.052339 -0.998629
-vn 0.374497 -0.244701 -0.894356
-vn 0.304368 -0.320665 -0.896958
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 0.699991 -0.714152
-vn 0.372764 -0.088140 -0.923731
-vn 0.321855 0.605804 -0.727606
-vn -0.316758 0.606690 -0.729103
-vn 0.000000 0.699991 -0.714152
-vn -0.379990 -0.085209 -0.921058
-vn 0.000000 -0.052309 -0.998631
-vn 0.209422 -0.955035 0.209880
-vn -0.001221 -0.985450 0.169959
-vn 0.212324 -0.913234 -0.347739
-vn 0.000702 -0.938897 -0.344197
-vn 0.184245 -0.380941 -0.906056
-vn 0.439571 -0.822101 -0.361838
-vn 0.106113 -0.434098 -0.894594
-vn 0.212324 -0.913234 -0.347739
-vn 0.720131 0.591401 0.362843
-vn 0.867846 0.335834 0.366140
-vn 0.781137 0.624360 0.000000
-vn 0.939468 0.342637 0.000000
-vn 0.527037 0.768230 0.363393
-vn 0.720131 0.591401 0.362843
-vn 0.569396 0.822064 0.000000
-vn 0.781137 0.624360 0.000000
-vn 0.867846 0.335834 0.366140
-vn 0.919256 0.124211 0.373550
-vn 0.939468 0.342637 0.000000
-vn 0.993066 0.117560 0.000000
-vn 0.993066 0.117560 0.000000
-vn 0.919256 0.124211 0.373550
-vn 0.998866 0.047610 0.000000
-vn 0.922245 0.060458 0.381850
-vn -0.992964 0.118414 0.000000
-vn -0.992942 0.118598 0.000000
-vn -0.939600 0.342275 0.000000
-vn -0.939332 0.343010 0.000000
-vn 0.780580 0.625056 0.000000
-vn 0.939246 0.343245 0.000000
-vn 0.780499 0.625156 0.000000
-vn 0.939213 0.343335 0.000000
-vn 0.000000 0.928845 0.370470
-vn 0.000000 0.418172 0.908368
-vn 0.069399 0.929325 0.362684
-vn 0.029085 0.427176 0.903701
-vn 0.396174 0.091223 0.913633
-vn 0.396049 0.205456 0.894948
-vn 0.000000 0.048464 0.998825
-vn 0.003998 0.056093 0.998418
-vn 0.000000 0.052005 0.998647
-vn 0.000000 0.052126 0.998641
-vn 0.000000 0.048434 0.998826
-vn 0.000000 0.048434 0.998826
-vn -0.392471 0.192390 0.899418
-vn 0.000000 0.052126 0.998641
-vn -0.312362 0.298720 0.901774
-vn -0.224988 0.373677 0.899859
-vn -0.029177 0.427853 0.903377
-vn -0.122289 0.433856 0.892645
-vn 0.000000 0.052126 0.998641
-vn -0.224988 0.373677 0.899859
-vn 0.396049 0.205456 0.894948
-vn 0.320333 0.310109 0.895108
-vn 0.003998 0.056093 0.998418
-vn 0.235030 0.375908 0.896356
-vn 0.235030 0.375908 0.896356
-vn 0.121893 0.433583 0.892832
-vn 0.003998 0.056093 0.998418
-vn 0.029085 0.427176 0.903701
-vn 0.000000 0.418172 0.908368
-vn 0.000000 0.052005 0.998647
-vn 0.029085 0.427176 0.903701
-vn 0.003998 0.056093 0.998418
-vn -0.174140 -0.397386 0.900977
-vn -0.087286 -0.425991 0.900507
-vn -0.000031 -0.052432 0.998624
-vn 0.000000 -0.052096 0.998642
-vn 0.087254 -0.426017 0.900498
-vn 0.000000 -0.052126 0.998641
-vn 0.000000 -0.434743 0.900555
-vn 0.000000 -0.052157 0.998639
-vn 0.000000 -0.052309 0.998631
-vn 0.377487 -0.139135 0.915503
-vn 0.000000 -0.052370 0.998628
-vn 0.375234 -0.102697 0.921223
-vn 0.000000 -0.052279 0.998633
-vn 0.000000 0.703021 0.711169
-vn -0.375319 -0.102543 0.921206
-vn -0.329091 0.602117 0.727430
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052339 0.998629
-vn 0.000000 -0.052370 0.998628
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052339 0.998629
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052463 0.998623
-vn 0.000000 -0.052402 0.998626
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052339 0.998629
-vn 0.000000 -0.052248 0.998634
-vn 0.000031 -0.052339 0.998629
-vn 0.000000 -0.052463 0.998623
-vn 0.000000 -0.052402 0.998626
-vn 0.000031 -0.052432 0.998624
-vn -0.000031 -0.052432 0.998624
-vn 0.000000 -0.052463 0.998623
-vn 0.000000 -0.052248 0.998634
-vn 0.000000 -0.052279 0.998633
-vn 0.000031 -0.052432 0.998624
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052463 0.998623
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052279 0.998633
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052279 0.998633
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052339 0.998629
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 0.052126 0.998641
-vn 0.000000 0.052005 0.998647
-vn -0.029177 0.427853 0.903377
-vn 0.000000 0.418172 0.908368
-vn 0.000000 0.048464 0.998825
-vn 0.003998 0.056093 0.998418
-vn 0.000000 0.048434 0.998826
-vn 0.000000 0.052005 0.998647
-vn -0.069248 0.929275 0.362841
-vn -0.029177 0.427853 0.903377
-vn 0.000000 0.928845 0.370470
-vn 0.000000 0.418172 0.908368
-vn 0.000031 -0.052339 0.998629
-vn 0.000000 -0.052248 0.998634
-vn 0.000000 -0.052126 0.998641
-vn 0.000000 -0.052157 0.998639
-vn -0.000031 -0.052432 0.998624
-vn 0.000000 -0.052096 0.998642
-vn 0.000000 -0.052248 0.998634
-vn 0.000000 -0.052157 0.998639
-vn 0.660743 -0.650336 0.374808
-vn 0.789045 -0.614139 0.015504
-vn 0.778579 -0.505401 0.372000
-vn 0.884960 -0.465507 0.012208
-vn 0.310045 -0.595674 0.740976
-vn 0.263930 -0.785352 0.559967
-vn 0.741037 -0.593385 0.314257
-vn 0.621805 -0.753893 0.212141
-vn -0.157268 -0.676224 0.719714
-vn 0.172404 -0.693613 0.699412
-vn -0.121832 -0.784555 0.607972
-vn 0.125158 -0.786652 0.604577
-vn -0.048831 -0.536314 -0.842605
-vn -0.119057 -0.591407 -0.797536
-vn 0.048037 -0.537777 -0.841717
-vn 0.120276 -0.592529 -0.796519
-vn 0.007019 -0.844861 -0.534939
-vn -0.000397 -0.487642 -0.873044
-vn 0.048037 -0.537777 -0.841717
-vn 0.007019 -0.844861 -0.534939
-vn -0.048831 -0.536314 -0.842605
-vn -0.000397 -0.487642 -0.873044
-vn 0.000275 -0.811299 0.584631
-vn 0.046267 -0.491606 0.869588
-vn 0.000031 -0.438709 0.898629
-vn 0.000275 -0.811299 0.584631
-vn 0.000031 -0.438709 0.898629
-vn -0.046175 -0.491786 0.869491
-vn 0.439571 -0.822101 -0.361838
-vn 0.640223 -0.679501 -0.358321
-vn 0.453122 -0.859397 0.236892
-vn 0.640007 -0.753384 0.151006
-vn 0.304368 -0.320665 -0.896958
-vn 0.640223 -0.679501 -0.358321
-vn 0.184245 -0.380941 -0.906056
-vn 0.439571 -0.822101 -0.361838
-vn 0.374497 -0.244701 -0.894356
-vn 0.802405 -0.482688 -0.350938
-vn 0.304368 -0.320665 -0.896958
-vn 0.640223 -0.679501 -0.358321
-vn -0.382251 -0.857281 -0.344896
-vn -0.429001 -0.879885 0.204353
-vn -0.584690 -0.736127 -0.340962
-vn -0.633088 -0.762062 0.135871
-vn -0.176492 -0.781012 -0.599058
-vn 0.183848 -0.767314 -0.614352
-vn -0.140114 -0.669504 -0.729474
-vn 0.138436 -0.667855 -0.731304
-vn -0.604308 -0.711613 -0.358355
-vn -0.176492 -0.781012 -0.599058
-vn -0.140114 -0.669504 -0.729474
-vn 0.004517 -0.992742 -0.120182
-vn -0.000855 -0.999608 0.027986
-vn -0.250746 -0.957540 -0.142281
-vn -0.297408 -0.954362 0.027223
-vn 0.568818 0.822464 0.000000
-vn 0.780580 0.625056 0.000000
-vn 0.568762 0.822502 0.000000
-vn 0.780499 0.625156 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.992964 0.118414 0.000000
-vn -0.992942 0.118598 0.000000
-vn 0.780499 0.625156 0.000000
-vn 0.939213 0.343335 0.000000
-vn 0.780446 0.625223 0.000000
-vn 0.939190 0.343399 0.000000
-vn 0.568762 0.822502 0.000000
-vn 0.780499 0.625156 0.000000
-vn 0.568692 0.822550 0.000000
-vn 0.780446 0.625223 0.000000
-vn 0.939213 0.343335 0.000000
-vn 0.993044 0.117741 0.000000
-vn 0.939190 0.343399 0.000000
-vn 0.993044 0.117741 0.000000
-vn -0.939844 0.341603 0.000000
-vn -0.782234 0.622985 0.000000
-vn -0.939891 0.341476 0.000000
-vn -0.782382 0.622799 0.000000
-vn -0.569521 0.821977 0.000000
-vn -0.313186 0.949692 0.000000
-vn -0.569702 0.821851 0.000000
-vn -0.313370 0.949631 0.000000
-vn -0.313186 0.949692 0.000000
-vn -0.079319 0.996849 0.000000
-vn -0.313370 0.949631 0.000000
-vn -0.079380 0.996844 0.000000
-vn -0.782234 0.622985 0.000000
-vn -0.569521 0.821977 0.000000
-vn -0.782382 0.622799 0.000000
-vn -0.569702 0.821851 0.000000
-vn -0.569305 0.822126 0.000000
-vn -0.313003 0.949752 0.000000
-vn -0.569521 0.821977 0.000000
-vn -0.313186 0.949692 0.000000
-vn -0.939778 0.341785 0.000000
-vn -0.782058 0.623205 0.000000
-vn -0.939844 0.341603 0.000000
-vn -0.782234 0.622985 0.000000
-vn -0.992990 0.118199 0.000000
-vn -0.992986 0.118229 0.000000
-vn -0.939891 0.341476 0.000000
-vn -0.939844 0.341603 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993040 0.117774 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993044 0.117741 0.000000
-vn -0.912094 -0.149238 0.381855
-vn -0.750227 0.586307 0.305621
-vn -0.990001 -0.141058 -0.000305
-vn -0.737682 0.675148 0.000000
-vn -0.991137 -0.132636 -0.007416
-vn -0.992570 -0.121649 -0.002442
-vn -0.734553 0.678551 -0.000092
-vn -0.730939 0.682443 -0.000031
-vn -0.992527 -0.122013 0.001740
-vn -0.992570 -0.121649 -0.002442
-vn -0.954279 -0.298907 0.002472
-vn -0.951202 -0.308125 0.016572
-vn -0.087286 -0.425991 0.900507
-vn -0.174140 -0.397386 0.900977
-vn -0.238259 -0.894775 0.377637
-vn -0.471889 -0.796857 0.377279
-vn 0.000000 -0.925801 0.378011
-vn -0.238259 -0.894775 0.377637
-vn -0.000855 -0.999608 0.027986
-vn -0.297408 -0.954362 0.027223
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn -0.377613 -0.138923 0.915483
-vn -0.353195 -0.211129 0.911415
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052309 0.998631
-vn 0.352987 -0.211408 0.911431
-vn 0.000000 -0.052309 0.998631
-vn 0.319082 -0.282245 0.904723
-vn 0.000000 -0.052339 0.998629
-vn -0.849339 -0.521933 -0.078800
-vn -0.710895 -0.695605 -0.103736
-vn -0.886617 -0.462368 0.011231
-vn -0.788745 -0.614540 0.014893
-vn 0.000000 0.048160 -0.998840
-vn 0.000000 0.048190 -0.998838
-vn 0.002930 0.055209 -0.998470
-vn 0.000000 0.052279 -0.998633
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn -0.916742 -0.125557 -0.379234
-vn -0.909937 -0.184063 -0.371666
-vn -0.991018 -0.133704 -0.002472
-vn -0.939317 -0.333574 0.080082
-vn -0.939703 0.341993 0.000000
-vn -0.781842 0.623477 0.000000
-vn -0.939778 0.341785 0.000000
-vn -0.782058 0.623205 0.000000
-vn -0.569034 0.822314 0.000000
-vn -0.312756 0.949834 0.000000
-vn -0.569305 0.822126 0.000000
-vn -0.313003 0.949752 0.000000
-vn -0.992986 0.118229 0.000000
-vn -0.992979 0.118293 0.000000
-vn -0.939844 0.341603 0.000000
-vn -0.939778 0.341785 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.992990 0.118199 0.000000
-vn -0.992986 0.118229 0.000000
-vn -0.781842 0.623477 0.000000
-vn -0.569034 0.822314 0.000000
-vn -0.782058 0.623205 0.000000
-vn -0.569305 0.822126 0.000000
-vn -0.781571 0.623816 0.000000
-vn -0.568658 0.822574 0.000000
-vn -0.781842 0.623477 0.000000
-vn -0.569034 0.822314 0.000000
-vn -0.079471 0.996837 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.070103 0.929281 -0.362660
-vn 0.000000 0.928819 -0.370533
-vn -0.568658 0.822574 0.000000
-vn -0.312453 0.949933 0.000000
-vn -0.569034 0.822314 0.000000
-vn -0.312756 0.949834 0.000000
-vn -0.939600 0.342275 0.000000
-vn -0.781571 0.623816 0.000000
-vn -0.939703 0.341993 0.000000
-vn -0.781842 0.623477 0.000000
-vn -0.992979 0.118293 0.000000
-vn -0.992975 0.118323 0.000000
-vn -0.939778 0.341785 0.000000
-vn -0.939703 0.341993 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.992986 0.118229 0.000000
-vn -0.992979 0.118293 0.000000
-vn -0.939332 0.343010 0.000000
-vn -0.780839 0.624732 0.000000
-vn -0.939600 0.342275 0.000000
-vn -0.781571 0.623816 0.000000
-vn -0.567682 0.823248 0.000000
-vn -0.311600 0.950213 0.000000
-vn -0.568658 0.822574 0.000000
-vn -0.312453 0.949933 0.000000
-vn -0.780839 0.624732 0.000000
-vn -0.567682 0.823248 0.000000
-vn -0.781571 0.623816 0.000000
-vn -0.568658 0.822574 0.000000
-vn -0.992975 0.118323 0.000000
-vn -0.992964 0.118414 0.000000
-vn -0.939703 0.341993 0.000000
-vn -0.939600 0.342275 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.992979 0.118293 0.000000
-vn -0.992975 0.118323 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.992975 0.118323 0.000000
-vn -0.992964 0.118414 0.000000
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn -0.079471 0.996837 0.000000
-vn -0.079380 0.996844 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 0.699991 -0.714152
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 0.699991 -0.714152
-vn 0.078190 0.996939 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.311664 0.950192 0.000000
-vn 0.078190 0.996939 0.000000
-vn 0.311536 0.950234 0.000000
-vn 0.311664 0.950192 0.000000
-vn 0.568692 0.822550 0.000000
-vn 0.311536 0.950234 0.000000
-vn 0.568602 0.822613 0.000000
-vn 0.780446 0.625223 0.000000
-vn 0.939190 0.343399 0.000000
-vn 0.780351 0.625342 0.000000
-vn 0.939143 0.343526 0.000000
-vn 0.568692 0.822550 0.000000
-vn 0.780446 0.625223 0.000000
-vn 0.568602 0.822613 0.000000
-vn 0.780351 0.625342 0.000000
-vn 0.939190 0.343399 0.000000
-vn 0.993044 0.117741 0.000000
-vn 0.939143 0.343526 0.000000
-vn 0.993040 0.117774 0.000000
-vn -0.939891 0.341476 0.000000
-vn -0.782382 0.622799 0.000000
-vn -0.939966 0.341268 0.000000
-vn -0.782587 0.622541 0.000000
-vn -0.569702 0.821851 0.000000
-vn -0.313370 0.949631 0.000000
-vn -0.569973 0.821663 0.000000
-vn -0.313581 0.949562 0.000000
-vn -0.313370 0.949631 0.000000
-vn -0.079380 0.996844 0.000000
-vn -0.313581 0.949562 0.000000
-vn -0.079471 0.996837 0.000000
-vn -0.782382 0.622799 0.000000
-vn -0.569702 0.821851 0.000000
-vn -0.782587 0.622541 0.000000
-vn -0.569973 0.821663 0.000000
-vn -0.919325 0.124518 -0.373278
-vn -0.992997 0.118139 0.000000
-vn -0.870643 0.329573 -0.365189
-vn -0.939966 0.341268 0.000000
-vn 0.922348 0.060580 -0.381580
-vn 0.919351 0.124242 -0.373307
-vn 0.998866 0.047610 0.000000
-vn 0.993040 0.117774 0.000000
-vn -0.734964 0.678106 0.000061
-vn -0.730909 0.682475 0.000000
-vn -0.990831 -0.134986 0.005646
-vn -0.992527 -0.122013 0.001740
-vn -0.379990 -0.085209 -0.921058
-vn -0.916742 -0.125557 -0.379234
-vn -0.316758 0.606690 -0.729103
-vn -0.745103 0.591285 -0.308552
-vn 0.990046 -0.140663 -0.004853
-vn 0.913199 -0.133217 -0.385123
-vn 0.737157 0.675722 -0.000092
-vn 0.747977 0.586436 -0.310843
-vn 0.778579 -0.505401 0.372000
-vn 0.884960 -0.465507 0.012208
-vn 0.857781 -0.346641 0.379541
-vn 0.951306 -0.308211 0.004853
-vn 0.984351 -0.176215 -0.001099
-vn 0.901970 -0.203534 0.380821
-vn 0.951306 -0.308211 0.004853
-vn 0.857781 -0.346641 0.379541
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.366104 -0.154792 -0.917610
-vn 0.362879 -0.103340 -0.926089
-vn 0.904830 -0.170541 -0.390126
-vn 0.877705 -0.298509 -0.374869
-vn 0.362879 -0.103340 -0.926089
-vn 0.366104 -0.154792 -0.917610
-vn -0.385668 -0.101262 -0.917064
-vn -0.386469 -0.166759 -0.907102
-vn -0.909937 -0.184063 -0.371666
-vn -0.859060 -0.359823 -0.364066
-vn 0.897571 -0.428521 0.103613
-vn 0.985937 -0.163336 -0.035341
-vn 0.934625 -0.355612 0.004151
-vn -0.922339 0.060549 -0.381607
-vn -0.998866 0.047610 0.000000
-vn -0.919325 0.124518 -0.373278
-vn -0.992997 0.118139 0.000000
-vn 0.568888 0.822415 0.000000
-vn 0.780675 0.624937 0.000000
-vn 0.568818 0.822464 0.000000
-vn 0.780580 0.625056 0.000000
-vn 0.780675 0.624937 0.000000
-vn 0.939279 0.343154 0.000000
-vn 0.780580 0.625056 0.000000
-vn 0.939246 0.343245 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993044 0.117741 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993044 0.117741 0.000000
-vn 0.939279 0.343154 0.000000
-vn 0.993052 0.117681 0.000000
-vn 0.939246 0.343245 0.000000
-vn 0.993048 0.117711 0.000000
-vn 0.939335 0.343000 0.000000
-vn 0.993055 0.117650 0.000000
-vn 0.939279 0.343154 0.000000
-vn 0.993052 0.117681 0.000000
-vn 0.780797 0.624784 0.000000
-vn 0.939335 0.343000 0.000000
-vn 0.780675 0.624937 0.000000
-vn 0.939279 0.343154 0.000000
-vn 0.568999 0.822338 0.000000
-vn 0.780797 0.624784 0.000000
-vn 0.568888 0.822415 0.000000
-vn 0.780675 0.624937 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993044 0.117741 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993048 0.117711 0.000000
-vn -0.311879 -0.598488 -0.737932
-vn 0.000000 -0.679106 -0.734040
-vn -0.233778 -0.773910 -0.588566
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 1.000000 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.000000 0.418594 -0.908174
-vn 0.000000 0.052279 -0.998633
-vn -0.029329 0.427604 -0.903490
-vn 0.000000 0.052309 -0.998631
-vn 0.311664 0.950192 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.311692 0.950183 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.311692 0.950183 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.311692 0.950183 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.069399 0.929325 0.362684
-vn 0.286943 0.888480 0.358145
-vn 0.078433 0.996919 0.000000
-vn 0.312178 0.950024 0.000000
-vn 0.286943 0.888480 0.358145
-vn 0.527037 0.768230 0.363393
-vn 0.312178 0.950024 0.000000
-vn 0.569396 0.822064 0.000000
-vn 0.992243 -0.124275 0.003082
-vn 0.992707 -0.120552 -0.000946
-vn 0.731704 0.681622 0.000031
-vn 0.730525 0.682886 0.000000
-vn 0.568762 0.822502 0.000000
-vn 0.568692 0.822550 0.000000
-vn 0.311692 0.950183 0.000000
-vn 0.311664 0.950192 0.000000
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.992707 -0.120552 -0.000946
-vn 0.990875 -0.134469 -0.009247
-vn 0.730525 0.682886 0.000000
-vn 0.735447 0.677583 -0.000153
-vn 0.311756 0.950162 0.000000
-vn 0.568999 0.822338 0.000000
-vn 0.311720 0.950174 0.000000
-vn 0.568888 0.822415 0.000000
-vn 0.311756 0.950162 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.312178 0.950024 0.000000
-vn 0.078433 0.996919 0.000000
-vn 0.311692 0.950183 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.311720 0.950174 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.568818 0.822464 0.000000
-vn 0.568762 0.822502 0.000000
-vn 0.311692 0.950183 0.000000
-vn 0.311692 0.950183 0.000000
-vn 0.311720 0.950174 0.000000
-vn 0.568888 0.822415 0.000000
-vn 0.311692 0.950183 0.000000
-vn 0.568818 0.822464 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078433 0.996919 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.079319 0.996849 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.079380 0.996844 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.886617 -0.462368 0.011231
-vn -0.952300 -0.305104 0.005982
-vn -0.849339 -0.521933 -0.078800
-vn -0.913458 -0.399399 -0.077945
-vn -0.952300 -0.305104 0.005982
-vn -0.984672 -0.174417 0.000336
-vn -0.913458 -0.399399 -0.077945
-vn -0.939019 -0.338459 -0.060733
-vn -0.990831 -0.134986 0.005646
-vn -0.989839 -0.142190 0.001251
-vn -0.734964 0.678106 0.000061
-vn -0.738163 0.674622 0.000000
-vn -0.990001 -0.141058 -0.000305
-vn -0.989839 -0.142190 0.001251
-vn -0.984672 -0.174417 0.000336
-vn -0.939019 -0.338459 -0.060733
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.000000 0.418594 -0.908174
-vn -0.029329 0.427604 -0.903490
-vn 0.000000 0.928819 -0.370533
-vn -0.070103 0.929281 -0.362660
-vn 0.078220 0.996936 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.311720 0.950174 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.311756 0.950162 0.000000
-vn 0.078220 0.996936 0.000000
-vn 0.312178 0.950024 0.000000
-vn 0.569396 0.822064 0.000000
-vn 0.311756 0.950162 0.000000
-vn 0.568999 0.822338 0.000000
-vn 0.569396 0.822064 0.000000
-vn 0.781137 0.624360 0.000000
-vn 0.568999 0.822338 0.000000
-vn 0.780797 0.624784 0.000000
-vn 0.781137 0.624360 0.000000
-vn 0.939468 0.342637 0.000000
-vn 0.780797 0.624784 0.000000
-vn 0.939335 0.343000 0.000000
-vn 0.939468 0.342637 0.000000
-vn 0.993066 0.117560 0.000000
-vn 0.939335 0.343000 0.000000
-vn 0.993055 0.117650 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993048 0.117711 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993052 0.117681 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.078738 0.996895 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 1.000000 0.000000
-vn 0.078190 0.996939 0.000000
-vn 0.000000 0.928819 -0.370533
-vn 0.068943 0.929284 -0.362875
-vn -0.079165 0.996861 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.079259 0.996854 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.079044 0.996871 0.000000
-vn -0.079165 0.996861 0.000000
-vn -0.313003 0.949752 0.000000
-vn -0.079259 0.996854 0.000000
-vn -0.313186 0.949692 0.000000
-vn -0.079319 0.996849 0.000000
-vn -0.312756 0.949834 0.000000
-vn -0.079165 0.996861 0.000000
-vn -0.313003 0.949752 0.000000
-vn -0.079259 0.996854 0.000000
-vn -0.312453 0.949933 0.000000
-vn -0.079044 0.996871 0.000000
-vn -0.312756 0.949834 0.000000
-vn -0.079165 0.996861 0.000000
-vn -0.311600 0.950213 0.000000
-vn -0.078738 0.996895 0.000000
-vn -0.312453 0.949933 0.000000
-vn -0.079044 0.996871 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.079319 0.996849 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.079259 0.996854 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.078738 0.996895 0.000000
-vn -0.079044 0.996871 0.000000
-vn 0.949811 -0.310561 0.037569
-vn 0.934625 -0.355612 0.004151
-vn 0.985937 -0.163336 -0.035341
-vn 0.950440 -0.308980 0.034579
-vn 0.949811 -0.310561 0.037569
-vn 0.985937 -0.163336 -0.035341
-vn 0.990046 -0.140663 -0.004853
-vn 0.990875 -0.134469 -0.009247
-vn 0.985937 -0.163336 -0.035341
-vn 0.950440 -0.308980 0.034579
-vn 0.992243 -0.124275 0.003082
-vn 0.731704 0.681622 0.000031
-vn 0.990438 -0.137855 0.005310
-vn 0.736588 0.676342 0.000092
-vn 0.990438 -0.137855 0.005310
-vn 0.736588 0.676342 0.000092
-vn 0.989089 -0.147315 0.001312
-vn 0.739720 0.672914 0.000000
-vn 0.989641 -0.143562 -0.000641
-vn 0.984351 -0.176215 -0.001099
-vn 0.989089 -0.147315 0.001312
-vn 0.981702 -0.190316 0.006439
-vn 0.898822 -0.432030 -0.073948
-vn 0.981702 -0.190316 0.006439
-vn 0.951306 -0.308211 0.004853
-vn 0.984351 -0.176215 -0.001099
-vn 0.898822 -0.432030 -0.073948
-vn 0.922100 -0.382311 -0.059756
-vn 0.981702 -0.190316 0.006439
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 -0.052339 -0.998629
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.078738 0.996895 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.078433 0.996919 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.069399 0.929325 0.362684
-vn 0.078433 0.996919 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.078738 0.996895 0.000000
-vn -0.069248 0.929275 0.362841
-vn 0.000000 1.000000 0.000000
-vn -0.069248 0.929275 0.362841
-vn 0.000000 0.928845 0.370470
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.069399 0.929325 0.362684
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.928845 0.370470
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.552338 0.770490 -0.318225
-vn 0.000000 1.000000 0.000000
-vn 0.318864 0.770272 -0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.318864 0.770272 -0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.770266 -0.637723
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.770266 -0.637723
-vn 0.000000 1.000000 0.000000
-vn -0.318864 0.770272 -0.552274
-vn 0.000000 1.000000 0.000000
-vn -0.318864 0.770272 -0.552274
-vn 0.000000 1.000000 0.000000
-vn -0.552336 0.770518 -0.318162
-vn 0.000000 1.000000 0.000000
-vn -0.552336 0.770518 -0.318162
-vn 0.000000 1.000000 0.000000
-vn -0.637722 0.770266 0.001282
-vn 0.000000 1.000000 0.000000
-vn -0.637722 0.770266 0.001282
-vn 0.000000 1.000000 0.000000
-vn -0.552246 0.770001 0.319567
-vn 0.000000 1.000000 0.000000
-vn -0.552246 0.770001 0.319567
-vn 0.000000 1.000000 0.000000
-vn -0.318864 0.770272 0.552274
-vn 0.000000 1.000000 0.000000
-vn -0.318864 0.770272 0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.770266 0.637723
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.770266 0.637723
-vn 0.000000 1.000000 0.000000
-vn 0.318864 0.770272 0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.318864 0.770272 0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.552244 0.770028 0.319505
-vn 0.000000 1.000000 0.000000
-vn 0.552244 0.770028 0.319505
-vn 0.000000 1.000000 0.000000
-vn 0.637722 0.770266 0.001160
-vn 0.000000 1.000000 0.000000
-vn 0.637722 0.770266 0.001160
-vn 0.000000 1.000000 0.000000
-vn 0.552338 0.770490 -0.318225
-vn 0.000000 1.000000 0.000000
-vn 0.318864 0.770272 0.552274
-vn 0.552244 0.770028 0.319505
-vn 0.499989 -0.000000 0.866032
-vn 0.865566 -0.000000 0.500796
-vn -0.552246 0.770001 0.319567
-vn -0.318864 0.770272 0.552274
-vn -0.865518 -0.000000 0.500877
-vn -0.499989 -0.000000 0.866032
-vn 0.000000 0.770266 0.637723
-vn 0.318864 0.770272 0.552274
-vn 0.000000 -0.000000 1.000000
-vn 0.499989 -0.000000 0.866032
-vn -0.318864 0.770272 -0.552274
-vn -0.552336 0.770518 -0.318162
-vn -0.499989 0.000000 -0.866032
-vn -0.866523 0.000000 -0.499137
-vn 0.318864 0.770272 -0.552274
-vn 0.000000 0.770266 -0.637723
-vn 0.499989 0.000000 -0.866032
-vn 0.000000 0.000000 -1.000000
-vn 0.637722 0.770266 0.001160
-vn 0.552338 0.770490 -0.318225
-vn 0.999998 -0.000000 0.001831
-vn 0.866482 0.000000 -0.499209
-vn -0.552336 0.770518 -0.318162
-vn -0.637722 0.770266 0.001282
-vn -0.866523 0.000000 -0.499137
-vn -0.999998 -0.000000 0.002014
-vn -0.637722 0.770266 0.001282
-vn -0.552246 0.770001 0.319567
-vn -0.999998 -0.000000 0.002014
-vn -0.865518 -0.000000 0.500877
-vn -0.318864 0.770272 0.552274
-vn 0.000000 0.770266 0.637723
-vn -0.499989 -0.000000 0.866032
-vn 0.000000 -0.000000 1.000000
-vn 0.552338 0.770490 -0.318225
-vn 0.318864 0.770272 -0.552274
-vn 0.866482 0.000000 -0.499209
-vn 0.499989 0.000000 -0.866032
-vn 0.552244 0.770028 0.319505
-vn 0.637722 0.770266 0.001160
-vn 0.865566 -0.000000 0.500796
-vn 0.999998 -0.000000 0.001831
-vn 0.000000 0.770266 -0.637723
-vn -0.318864 0.770272 -0.552274
-vn 0.000000 0.000000 -1.000000
-vn -0.499989 0.000000 -0.866032
-vn 0.502506 0.783714 -0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.191936 0.783706 -0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.191936 0.783706 -0.590733
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 -0.590733
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 -0.590733
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 -0.365076
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 -0.365076
-vn 0.000000 1.000000 0.000000
-vn -0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.502506 0.783714 -0.365076
-vn 0.000000 1.000000 0.000000
-vn -0.191964 0.783728 -0.590695
-vn 0.000000 1.000000 0.000000
-vn -0.502529 0.783702 -0.365070
-vn 0.000000 1.000000 0.000000
-vn -0.502529 0.783702 -0.365070
-vn 0.000000 1.000000 0.000000
-vn -0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.502529 0.783702 -0.365070
-vn 0.000000 1.000000 0.000000
-vn 0.502529 0.783702 -0.365070
-vn 0.000000 1.000000 0.000000
-vn 0.191964 0.783728 -0.590695
-vn 0.000000 1.000000 0.000000
-vn 0.191964 0.783728 -0.590695
-vn 0.000000 1.000000 0.000000
-vn -0.191964 0.783728 -0.590695
-vn 0.000000 1.000000 0.000000
-vn -0.621130 0.783707 0.000000
-vn -0.502506 0.783714 0.365076
-vn -1.000000 0.000000 0.000000
-vn -0.809030 -0.000000 0.587767
-vn -0.502506 0.783714 0.365076
-vn -0.191936 0.783706 0.590733
-vn -0.809030 -0.000000 0.587767
-vn -0.309004 -0.000000 0.951061
-vn 0.502529 0.783702 -0.365070
-vn 0.191964 0.783728 -0.590695
-vn 0.809045 0.000000 -0.587747
-vn 0.309068 0.000000 -0.951040
-vn -0.502529 0.783702 -0.365070
-vn -0.621130 0.783707 0.000000
-vn -0.809045 0.000000 -0.587747
-vn -1.000000 0.000000 0.000000
-vn 0.191964 0.783728 -0.590695
-vn -0.191964 0.783728 -0.590695
-vn 0.309068 0.000000 -0.951040
-vn -0.309068 0.000000 -0.951040
-vn -0.191936 0.783706 0.590733
-vn 0.191936 0.783706 0.590733
-vn -0.309004 -0.000000 0.951061
-vn 0.309004 -0.000000 0.951061
-vn 0.502506 0.783714 0.365076
-vn 0.621130 0.783707 0.000000
-vn 0.809030 -0.000000 0.587767
-vn 1.000000 0.000000 0.000000
-vn 0.191936 0.783706 0.590733
-vn 0.502506 0.783714 0.365076
-vn 0.309004 -0.000000 0.951061
-vn 0.809030 -0.000000 0.587767
-vn 0.621130 0.783707 0.000000
-vn 0.502529 0.783702 -0.365070
-vn 1.000000 0.000000 0.000000
-vn 0.809045 0.000000 -0.587747
-vn -0.191964 0.783728 -0.590695
-vn -0.502529 0.783702 -0.365070
-vn -0.309068 0.000000 -0.951040
-vn -0.809045 0.000000 -0.587747
-vn -0.502506 0.783714 0.365076
-vn -0.191936 0.783706 0.590733
-vn -0.809030 -0.000000 0.587767
-vn -0.309004 -0.000000 0.951061
-vn -0.191936 0.783706 0.590733
-vn 0.191936 0.783706 0.590733
-vn -0.309004 -0.000000 0.951061
-vn 0.309004 -0.000000 0.951061
-vn -0.621130 0.783707 0.000000
-vn -0.502506 0.783714 0.365076
-vn -1.000000 0.000000 0.000000
-vn -0.809030 -0.000000 0.587767
-vn 0.621130 0.783707 0.000000
-vn 0.502506 0.783714 -0.365076
-vn 1.000000 0.000000 0.000000
-vn 0.809030 0.000000 -0.587767
-vn 0.191936 0.783706 0.590733
-vn 0.502506 0.783714 0.365076
-vn 0.309004 -0.000000 0.951061
-vn 0.809030 -0.000000 0.587767
-vn 0.502506 0.783714 0.365076
-vn 0.621130 0.783707 0.000000
-vn 0.809030 -0.000000 0.587767
-vn 1.000000 0.000000 0.000000
-vn -0.191936 0.783706 -0.590733
-vn -0.502506 0.783714 -0.365076
-vn -0.309004 0.000000 -0.951061
-vn -0.809030 0.000000 -0.587767
-vn 0.191936 0.783706 -0.590733
-vn -0.191936 0.783706 -0.590733
-vn 0.309004 0.000000 -0.951061
-vn -0.309004 0.000000 -0.951061
-vn 0.502506 0.783714 -0.365076
-vn 0.191936 0.783706 -0.590733
-vn 0.809030 0.000000 -0.587767
-vn 0.309004 0.000000 -0.951061
-vn -0.502506 0.783714 -0.365076
-vn -0.621130 0.783707 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -1.000000 0.000000 0.000000
-vn -0.730909 0.682475 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.730939 0.682443 -0.000031
-vn -0.670866 0.741578 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993052 0.117681 0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.993055 0.117650 0.000000
-vn -0.737682 0.675148 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.738163 0.674622 0.000000
-vn -0.670866 0.741578 0.000000
-vn 0.735447 0.677583 -0.000153
-vn 0.737157 0.675722 -0.000092
-vn 0.670866 0.741578 0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.000000 0.699991 -0.714152
-vn 0.000000 0.732851 -0.680389
-vn 0.000000 0.699991 -0.714152
-vn 0.000000 0.732866 -0.680373
-vn 0.000000 -0.675849 0.737040
-vn 0.000000 -0.675849 0.737040
-vn 0.000000 -0.675817 0.737069
-vn 0.000000 -0.675866 0.737025
-vn 0.321855 0.605804 -0.727606
-vn 0.000000 0.699991 -0.714152
-vn 0.214916 0.828380 -0.517299
-vn 0.000000 0.732866 -0.680373
-vn -0.329091 0.602117 0.727430
-vn 0.000000 0.703021 0.711169
-vn -0.230361 0.846581 0.479828
-vn 0.000000 0.736456 0.676486
-vn 0.329149 0.602020 0.727484
-vn 0.230361 0.846581 0.479828
-vn 0.000000 0.702975 0.711215
-vn 0.000000 0.736456 0.676486
-vn -0.311879 -0.598488 -0.737932
-vn -0.233778 -0.773910 -0.588566
-vn -0.739452 -0.596163 -0.312731
-vn -0.590148 -0.771523 -0.237652
-vn 0.311907 -0.598482 -0.737925
-vn 0.233778 -0.773910 -0.588566
-vn 0.000000 -0.679106 -0.734040
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 0.699991 -0.714152
-vn 0.000000 0.699991 -0.714152
-vn 0.000000 0.732866 -0.680373
-vn 0.000000 0.732866 -0.680373
-vn 0.000000 0.043978 -0.999033
-vn 0.000000 0.043978 -0.999033
-vn 0.000000 -0.679106 -0.734040
-vn 0.000000 -0.679106 -0.734040
-vn 0.738513 0.674239 0.000000
-vn 0.739720 0.672914 0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.670866 0.741578 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.922245 0.060458 0.381850
-vn -0.741037 -0.593385 0.314257
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn -0.730939 0.682443 -0.000031
-vn -0.670866 0.741578 0.000000
-vn -0.734553 0.678551 -0.000092
-vn -0.670866 0.741578 0.000000
-vn 0.741037 -0.593385 0.314257
-vn 0.621805 -0.753893 0.212141
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn -0.922245 0.060458 0.381850
-vn -0.741037 -0.593385 0.314257
-vn -0.381763 0.058475 0.922409
-vn -0.310013 -0.595732 0.740942
-vn 0.750260 0.586248 0.305652
-vn 0.738513 0.674239 0.000000
-vn 0.531041 0.824090 0.197157
-vn 0.670866 0.741578 0.000000
-vn -0.310013 -0.595732 0.740942
-vn -0.741037 -0.593385 0.314257
-vn -0.263930 -0.785352 0.559967
-vn -0.621790 -0.753906 0.212136
-vn -0.381975 0.058596 -0.922313
-vn -0.311879 -0.598488 -0.737932
-vn -0.922339 0.060549 -0.381607
-vn -0.739452 -0.596163 -0.312731
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn 0.922245 0.060458 0.381850
-vn 0.381762 0.058535 0.922405
-vn 0.741037 -0.593385 0.314257
-vn 0.310045 -0.595674 0.740976
-vn 0.922348 0.060580 -0.381580
-vn 0.739459 -0.596169 -0.312703
-vn 0.382011 0.058628 -0.922296
-vn 0.311907 -0.598482 -0.737925
-vn 0.736588 0.676342 0.000092
-vn 0.731704 0.681622 0.000031
-vn 0.670866 0.741578 0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.000000 0.043978 -0.999033
-vn 0.000000 0.043978 -0.999033
-vn 0.000000 -0.679106 -0.734040
-vn 0.000000 -0.679106 -0.734040
-vn -0.741037 -0.593385 0.314257
-vn -0.742650 -0.669679 -0.000000
-vn -0.621790 -0.753906 0.212136
-vn -0.742346 -0.670016 -0.000000
-vn 0.000000 -0.675866 0.737025
-vn 0.000000 0.736456 0.676486
-vn 0.000000 -0.675849 0.737040
-vn 0.000000 0.736456 0.676486
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 0.732866 -0.680373
-vn 0.000000 0.732866 -0.680373
-vn 0.500093 0.836968 -0.222243
-vn 0.214916 0.828380 -0.517299
-vn 0.590148 -0.771523 -0.237652
-vn 0.233778 -0.773910 -0.588566
-vn 0.621805 -0.753893 0.212141
-vn 0.263930 -0.785352 0.559967
-vn 0.531041 0.824090 0.197157
-vn 0.230361 0.846581 0.479828
-vn -0.233778 -0.773910 -0.588566
-vn -0.214888 0.828363 -0.517338
-vn -0.590148 -0.771523 -0.237652
-vn -0.500057 0.836990 -0.222241
-vn -0.621790 -0.753906 0.212136
-vn -0.531041 0.824090 0.197157
-vn -0.263930 -0.785352 0.559967
-vn -0.230361 0.846581 0.479828
-vn -0.742346 -0.670016 -0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.621790 -0.753906 0.212136
-vn -0.531041 0.824090 0.197157
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 0.732851 -0.680389
-vn 0.000000 0.732866 -0.680373
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn -0.500057 0.836990 -0.222241
-vn -0.670866 0.741578 0.000000
-vn -0.590148 -0.771523 -0.237652
-vn -0.742346 -0.670016 -0.000000
-vn 0.500093 0.836968 -0.222243
-vn 0.590148 -0.771523 -0.237652
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.531041 0.824090 0.197157
-vn 0.621805 -0.753893 0.212141
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.000000 -0.679867 -0.733336
-vn 0.233778 -0.773910 -0.588566
-vn 0.000000 0.732866 -0.680373
-vn 0.214916 0.828380 -0.517299
-vn 0.000000 0.736456 0.676486
-vn 0.000000 0.736456 0.676486
-vn 0.000000 -0.675849 0.737040
-vn 0.000000 -0.675866 0.737025
-vn -0.214888 0.828363 -0.517338
-vn -0.233778 -0.773910 -0.588566
-vn 0.000000 0.732851 -0.680389
-vn 0.000000 -0.679867 -0.733336
-vn 0.230361 0.846581 0.479828
-vn 0.263930 -0.785352 0.559967
-vn 0.000000 0.736456 0.676486
-vn 0.000000 -0.675849 0.737040
-vn -0.230361 0.846581 0.479828
-vn 0.000000 0.736456 0.676486
-vn -0.263930 -0.785352 0.559967
-vn 0.000000 -0.675849 0.737040
-vn -0.670866 0.741578 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn 0.730525 0.682886 0.000000
-vn 0.735447 0.677583 -0.000153
-vn 0.670866 0.741578 0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.329149 0.602020 0.727484
-vn 0.750260 0.586248 0.305652
-vn 0.230361 0.846581 0.479828
-vn 0.531041 0.824090 0.197157
-vn 0.000000 -0.679106 -0.734040
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 -0.679106 -0.734040
-vn 0.000000 -0.679867 -0.733336
-vn -0.329091 0.602117 0.727430
-vn -0.230361 0.846581 0.479828
-vn -0.750227 0.586307 0.305621
-vn -0.531041 0.824090 0.197157
-vn -0.310013 -0.595732 0.740942
-vn -0.263930 -0.785352 0.559967
-vn 0.000000 -0.675849 0.737040
-vn 0.000000 -0.675849 0.737040
-vn 0.000000 -0.675817 0.737069
-vn 0.000000 -0.675817 0.737069
-vn 0.000000 -0.675849 0.737040
-vn 0.000000 -0.675866 0.737025
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn 0.000000 -0.679106 -0.734040
-vn 0.000000 -0.679106 -0.734040
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 -0.679867 -0.733336
-vn 0.000000 0.703021 0.711169
-vn 0.000000 0.702990 0.711200
-vn 0.000000 0.736456 0.676486
-vn 0.000000 0.736456 0.676486
-vn 0.747977 0.586436 -0.310843
-vn 0.500093 0.836968 -0.222243
-vn 0.737157 0.675722 -0.000092
-vn 0.670866 0.741578 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.000000 0.702975 0.711215
-vn 0.000000 0.736456 0.676486
-vn 0.000000 0.702990 0.711200
-vn 0.000000 0.736456 0.676486
-vn -0.734553 0.678551 -0.000092
-vn -0.670866 0.741578 0.000000
-vn -0.734685 0.678408 0.000000
-vn -0.670866 0.741578 0.000000
-vn 0.321855 0.605804 -0.727606
-vn 0.214916 0.828380 -0.517299
-vn 0.747977 0.586436 -0.310843
-vn 0.500093 0.836968 -0.222243
-vn 0.731704 0.681622 0.000031
-vn 0.730525 0.682886 0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.670866 0.741578 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn -0.739452 -0.596163 -0.312731
-vn -0.590148 -0.771523 -0.237652
-vn -0.742650 -0.669679 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn 0.739459 -0.596169 -0.312703
-vn 0.742650 -0.669679 -0.000000
-vn 0.590148 -0.771523 -0.237652
-vn 0.742346 -0.670016 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.738163 0.674622 0.000000
-vn -0.670866 0.741578 0.000000
-vn -0.734964 0.678106 0.000061
-vn -0.670866 0.741578 0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn 0.739720 0.672914 0.000000
-vn 0.736588 0.676342 0.000092
-vn 0.670866 0.741578 0.000000
-vn 0.670866 0.741578 0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.742346 -0.670016 -0.000000
-vn -0.750227 0.586307 0.305621
-vn -0.531041 0.824090 0.197157
-vn -0.737682 0.675148 0.000000
-vn -0.670866 0.741578 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.742346 -0.670016 -0.000000
-vn 0.000000 0.044038 0.999030
-vn 0.000000 0.044069 0.999029
-vn 0.000000 -0.675817 0.737069
-vn 0.000000 -0.675817 0.737069
-vn 0.000000 0.048434 0.998826
-vn 0.000000 0.044069 0.999029
-vn 0.000000 0.048464 0.998825
-vn 0.000000 0.044038 0.999030
-vn 0.000000 0.048190 -0.998838
-vn 0.000000 0.048160 -0.998840
-vn 0.000000 0.043978 -0.999033
-vn 0.000000 0.043978 -0.999033
-vn 0.922348 0.060580 -0.381580
-vn 0.382011 0.058628 -0.922296
-vn 0.919351 0.124242 -0.373307
-vn 0.395989 0.090856 -0.913750
-vn 0.396174 0.091223 0.913633
-vn 0.381762 0.058535 0.922405
-vn 0.919256 0.124211 0.373550
-vn 0.922245 0.060458 0.381850
-vn -0.396046 0.091008 -0.913710
-vn -0.381975 0.058596 -0.922313
-vn -0.919325 0.124518 -0.373278
-vn -0.922339 0.060549 -0.381607
-vn -0.922245 0.060458 0.381850
-vn -0.381763 0.058475 0.922409
-vn -0.919299 0.124793 0.373250
-vn -0.395796 0.091006 0.913818
-vn -0.992942 0.118598 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.919299 0.124793 0.373250
-vn -0.922245 0.060458 0.381850
-vn 0.000000 0.048190 -0.998838
-vn 0.000000 0.048190 -0.998838
-vn 0.000000 0.043978 -0.999033
-vn 0.000000 0.043978 -0.999033
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn -0.739452 -0.596163 -0.312731
-vn -0.742650 -0.669679 -0.000000
-vn -0.922339 0.060549 -0.381607
-vn -0.998866 0.047610 0.000000
-vn 0.739459 -0.596169 -0.312703
-vn 0.922348 0.060580 -0.381580
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.741037 -0.593385 0.314257
-vn 0.922245 0.060458 0.381850
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.742650 -0.669679 -0.000000
-vn 0.998866 0.047610 0.000000
-vn 0.000000 0.043978 -0.999033
-vn 0.382011 0.058628 -0.922296
-vn 0.000000 -0.679106 -0.734040
-vn 0.311907 -0.598482 -0.737925
-vn 0.000000 -0.675849 0.737040
-vn 0.000000 -0.675817 0.737069
-vn 0.000000 0.044008 0.999031
-vn 0.000000 0.044069 0.999029
-vn -0.311879 -0.598488 -0.737932
-vn -0.381975 0.058596 -0.922313
-vn 0.000000 -0.679106 -0.734040
-vn 0.000000 0.043978 -0.999033
-vn 0.310045 -0.595674 0.740976
-vn 0.381762 0.058535 0.922405
-vn 0.000000 -0.675817 0.737069
-vn 0.000000 0.044038 0.999030
-vn -0.310013 -0.595732 0.740942
-vn 0.000000 -0.675849 0.737040
-vn -0.381763 0.058475 0.922409
-vn 0.000000 0.044008 0.999031
-vn -0.742650 -0.669679 -0.000000
-vn -0.742650 -0.669679 -0.000000
-vn -0.998866 0.047610 0.000000
-vn -0.998866 0.047610 0.000000
-vn 0.738513 0.674239 0.000000
-vn 0.989641 -0.143562 -0.000641
-vn 0.739720 0.672914 0.000000
-vn 0.989089 -0.147315 0.001312
-vn 0.946362 -0.321059 -0.036318
-vn 0.990438 -0.137855 0.005310
-vn 0.981702 -0.190316 0.006439
-vn 0.989089 -0.147315 0.001312
-vn 0.949985 -0.312053 -0.012299
-vn 0.992243 -0.124275 0.003082
-vn 0.946362 -0.321059 -0.036318
-vn 0.990438 -0.137855 0.005310
-vn 0.737157 0.675722 -0.000092
-vn 0.735447 0.677583 -0.000153
-vn 0.990046 -0.140663 -0.004853
-vn 0.990875 -0.134469 -0.009247
-vn -0.737682 0.675148 0.000000
-vn -0.738163 0.674622 0.000000
-vn -0.990001 -0.141058 -0.000305
-vn -0.989839 -0.142190 0.001251
-vn -0.949451 -0.312272 -0.032076
-vn -0.939019 -0.338459 -0.060733
-vn -0.990831 -0.134986 0.005646
-vn -0.989839 -0.142190 0.001251
-vn 0.957065 -0.289866 0.002228
-vn 0.950440 -0.308980 0.034579
-vn 0.992707 -0.120552 -0.000946
-vn 0.990875 -0.134469 -0.009247
-vn 0.949985 -0.312053 -0.012299
-vn 0.957065 -0.289866 0.002228
-vn 0.992243 -0.124275 0.003082
-vn 0.992707 -0.120552 -0.000946
-vn 0.985937 -0.163336 -0.035341
-vn 0.904830 -0.170541 -0.390126
-vn 0.990046 -0.140663 -0.004853
-vn 0.913199 -0.133217 -0.385123
-vn -0.909937 -0.184063 -0.371666
-vn -0.916742 -0.125557 -0.379234
-vn -0.385668 -0.101262 -0.917064
-vn -0.379990 -0.085209 -0.921058
-vn -0.990831 -0.134986 0.005646
-vn -0.992527 -0.122013 0.001740
-vn -0.949451 -0.312272 -0.032076
-vn -0.954279 -0.298907 0.002472
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn -0.745103 0.591285 -0.308552
-vn -0.916742 -0.125557 -0.379234
-vn -0.734685 0.678408 0.000000
-vn -0.991018 -0.133704 -0.002472
-vn -0.730909 0.682475 0.000000
-vn -0.730939 0.682443 -0.000031
-vn -0.992527 -0.122013 0.001740
-vn -0.992570 -0.121649 -0.002442
-vn -0.949874 -0.309738 0.042452
-vn -0.951202 -0.308125 0.016572
-vn -0.991137 -0.132636 -0.007416
-vn -0.992570 -0.121649 -0.002442
-vn -0.912094 -0.149238 0.381855
-vn -0.990001 -0.141058 -0.000305
-vn -0.902001 -0.203565 0.380730
-vn -0.984672 -0.174417 0.000336
-vn 0.000000 0.703021 0.711169
-vn 0.000000 -0.052279 0.998633
-vn 0.000000 0.702990 0.711200
-vn 0.000000 -0.052339 0.998629
-vn 0.000000 -0.052339 0.998629
-vn 0.000000 -0.052370 0.998628
-vn 0.000000 0.702990 0.711200
-vn 0.000000 0.702975 0.711215
-vn 0.000000 -0.052309 0.998631
-vn 0.000000 -0.052279 0.998633
-vn -0.377613 -0.138923 0.915483
-vn -0.375319 -0.102543 0.921206
-vn 0.000000 -0.052370 0.998628
-vn 0.375234 -0.102697 0.921223
-vn 0.000000 0.702975 0.711215
-vn 0.329149 0.602020 0.727484
-vn -0.385668 -0.101262 -0.917064
-vn -0.379990 -0.085209 -0.921058
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.362879 -0.103340 -0.926089
-vn 0.372764 -0.088140 -0.923731
-vn -0.750227 0.586307 0.305621
-vn -0.912094 -0.149238 0.381855
-vn -0.329091 0.602117 0.727430
-vn -0.375319 -0.102543 0.921206
-vn 0.377487 -0.139135 0.915503
-vn 0.901970 -0.203534 0.380821
-vn 0.375234 -0.102697 0.921223
-vn 0.912059 -0.149299 0.381914
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.000000 -0.052309 -0.998631
-vn 0.984351 -0.176215 -0.001099
-vn 0.989641 -0.143562 -0.000641
-vn 0.901970 -0.203534 0.380821
-vn 0.912059 -0.149299 0.381914
-vn -0.991137 -0.132636 -0.007416
-vn -0.991018 -0.133704 -0.002472
-vn -0.949874 -0.309738 0.042452
-vn -0.939317 -0.333574 0.080082
-vn 0.362879 -0.103340 -0.926089
-vn 0.372764 -0.088140 -0.923731
-vn 0.904830 -0.170541 -0.390126
-vn 0.913199 -0.133217 -0.385123
-f 96/173/1 91/443/2 296/560/3
-f 296/560/3 91/443/2 293/381/4
-f 585/367/5 178/687/6 589/699/7
-f 589/699/7 178/687/6 124/80/8
-f 386/509/9 334/510/10 387/48/11
-f 387/48/11 334/510/10 335/178/12
-f 353/597/13 352/373/14 337/266/15
-f 337/266/15 352/373/14 343/631/16
-f 100/392/17 97/511/18 295/614/19
-f 295/614/19 97/511/18 292/726/20
-f 420/481/21 37/2/22 82/707/23
-f 82/707/23 37/2/22 38/423/24
-f 51/340/25 44/153/26 42/598/27
-f 42/598/27 44/153/26 43/692/28
-f 84/536/29 38/423/30 419/121/31
-f 419/121/31 38/423/30 37/2/32
-f 83/260/33 84/536/34 41/290/35
-f 41/290/35 84/536/34 419/121/36
-f 46/513/37 45/357/38 168/291/39
-f 168/291/39 45/357/38 152/292/40
-f 152/292/41 45/357/42 48/6/43
-f 48/6/43 45/357/42 49/505/44
-f 87/72/45 86/177/46 44/153/47
-f 44/153/47 86/177/46 43/692/48
-f 153/460/49 152/292/50 151/596/51
-f 151/596/51 152/292/50 48/6/52
-f 168/291/53 152/292/54 167/479/55
-f 167/479/55 152/292/54 153/460/56
-f 52/322/57 49/165/58 51/424/59
-f 47/228/60 48/136/61 49/165/62
-f 52/322/63 47/228/64 49/165/65
-f 50/489/66 51/424/67 42/189/68
-f 50/489/69 52/322/70 51/424/71
-f 50/489/72 42/189/73 39/120/74
-f 223/611/75 39/120/76 40/172/77
-f 50/489/78 39/120/79 223/611/80
-f 54/87/81 40/172/82 53/499/83
-f 223/611/84 40/172/85 54/87/86
-f 222/546/87 53/499/88 36/309/89
-f 54/87/90 53/499/91 222/546/92
-f 222/546/93 36/309/94 35/644/95
-f 55/405/96 35/644/97 56/331/98
-f 222/546/99 35/644/100 55/405/101
-f 120/355/102 429/179/103 119/682/104
-f 119/682/104 429/179/103 379/558/105
-f 55/405/106 56/331/107 57/602/108
-f 219/12/109 57/602/110 59/89/111
-f 64/388/112 63/429/113 58/603/114
-f 58/603/114 63/429/113 60/148/115
-f 55/405/116 57/602/117 219/12/118
-f 61/704/119 59/89/120 60/439/121
-f 219/12/122 59/89/123 61/704/124
-f 68/197/125 62/154/126 64/388/127
-f 64/388/127 62/154/126 63/429/128
-f 61/704/129 60/439/130 63/249/131
-f 65/615/132 63/249/133 62/629/134
-f 61/704/135 63/249/136 65/615/137
-f 67/105/138 62/629/139 69/244/140
-f 65/615/141 62/629/142 67/105/143
-f 76/725/144 69/635/145 68/197/146
-f 68/197/146 69/635/145 62/154/147
-f 67/105/148 69/244/149 66/393/150
-f 66/47/151 75/430/152 70/425/153
-f 70/425/153 75/430/152 285/382/154
-f 214/293/155 66/393/156 70/262/157
-f 67/105/158 66/393/159 214/293/160
-f 73/693/161 71/338/162 285/382/163
-f 285/382/163 71/338/162 70/425/164
-f 71/245/165 213/76/166 70/262/167
-f 73/693/168 285/382/169 173/123/170
-f 173/123/170 285/382/169 72/106/171
-f 166/52/172 130/708/173 128/356/174
-f 128/356/174 130/708/173 131/537/175
-f 213/76/176 71/245/177 128/694/178
-f 177/180/179 74/49/180 76/725/181
-f 76/725/181 74/49/180 75/430/182
-f 165/107/183 166/52/184 173/652/185
-f 173/652/185 166/52/184 73/703/186
-f 77/514/187 177/180/188 68/197/189
-f 68/197/189 177/180/188 76/725/190
-f 176/181/191 77/514/192 64/388/193
-f 64/388/193 77/514/192 68/197/194
-f 598/108/195 324/182/196 599/184/197
-f 599/184/197 324/182/196 371/183/198
-f 229/516/199 308/639/200 170/515/201
-f 170/515/201 308/639/200 307/103/202
-f 472/288/203 469/406/204 528/93/205
-f 528/93/205 469/406/204 525/672/206
-f 233/696/207 88/50/208 311/467/209
-f 311/467/209 88/50/208 305/201/210
-f 230/246/211 309/376/212 346/198/213
-f 346/198/213 309/376/212 345/150/214
-f 85/554/215 234/640/216 79/689/217
-f 79/689/217 234/640/216 312/204/218
-f 235/538/219 347/691/220 84/536/221
-f 84/536/221 347/691/220 38/423/222
-f 170/539/223 154/557/224 229/88/225
-f 229/88/225 154/557/224 155/94/226
-f 347/691/227 81/285/228 38/423/229
-f 38/423/229 81/285/228 82/707/230
-f 88/263/231 233/303/232 46/377/233
-f 46/377/233 233/303/232 87/72/234
-f 234/195/235 85/101/236 86/177/237
-f 86/177/237 85/101/236 83/260/238
-f 168/291/239 232/54/240 46/513/241
-f 46/513/241 232/54/240 88/445/242
-f 85/101/243 235/538/244 83/260/245
-f 83/260/245 235/538/244 84/536/246
-f 104/464/247 103/695/248 100/392/249
-f 100/392/249 103/695/248 101/482/250
-f 297/520/251 127/122/252 112/555/253
-f 112/555/253 127/122/252 111/264/254
-f 98/51/255 97/511/256 101/482/257
-f 101/482/257 97/511/256 100/392/258
-f 294/636/259 104/464/260 295/614/261
-f 295/614/261 104/464/260 100/392/262
-f 91/443/263 226/547/264 95/77/265
-f 95/77/265 226/547/264 92/196/266
-f 373/78/267 388/427/268 99/167/269
-f 99/167/269 388/427/268 107/374/270
-f 374/428/271 370/540/272 109/690/273
-f 109/690/273 370/540/272 89/541/274
-f 226/547/275 91/443/276 225/92/277
-f 225/92/277 91/443/276 96/173/278
-f 388/427/279 374/428/280 107/374/281
-f 107/374/281 374/428/280 109/690/282
-f 387/48/283 373/78/284 106/265/285
-f 106/265/285 373/78/284 99/167/286
-f 91/443/287 95/77/288 293/381/289
-f 293/381/289 95/77/288 291/304/290
-f 225/92/291 96/173/292 98/51/293
-f 98/51/293 96/173/292 97/511/294
-f 181/250/295 182/174/296 99/167/297
-f 99/167/297 182/174/296 106/265/298
-f 97/511/299 96/173/300 292/726/301
-f 292/726/301 96/173/300 296/560/302
-f 108/422/303 181/250/304 107/374/305
-f 107/374/305 181/250/304 99/167/306
-f 180/527/307 108/422/308 109/690/309
-f 109/690/309 108/422/308 107/374/310
-f 90/310/311 180/527/312 89/541/313
-f 89/541/313 180/527/312 109/690/314
-f 564/599/315 559/56/316 386/509/317
-f 386/509/317 559/56/316 334/510/318
-f 271/586/319 270/583/320 182/585/321
-f 182/585/321 270/583/320 105/341/322
-f 360/556/323 516/342/324 354/559/325
-f 354/559/325 516/342/324 515/507/326
-f 93/612/327 227/426/328 94/723/329
-f 94/723/329 227/426/328 117/124/330
-f 113/202/331 116/604/332 298/96/333
-f 298/96/333 116/604/332 115/461/334
-f 227/426/335 115/461/336 117/124/337
-f 117/124/337 115/461/336 116/604/338
-f 376/600/339 384/185/340 114/53/341
-f 114/53/341 384/185/340 110/199/342
-f 474/251/343 471/102/344 530/380/345
-f 530/380/345 471/102/344 527/632/346
-f 375/44/347 385/301/348 118/483/349
-f 118/483/349 385/301/348 123/253/350
-f 385/301/351 376/600/352 123/253/353
-f 123/253/353 376/600/352 114/53/354
-f 112/555/355 113/202/356 297/520/357
-f 297/520/357 113/202/356 298/96/358
-f 377/653/359 375/44/360 121/378/361
-f 121/378/361 375/44/360 118/483/362
-f 372/542/363 377/653/364 119/682/365
-f 119/682/365 377/653/364 121/378/366
-f 266/186/367 123/253/368 184/75/369
-f 184/75/369 123/253/368 114/53/370
-f 569/252/371 573/543/372 103/552/373
-f 103/552/373 573/543/372 302/3/374
-f 402/55/375 399/512/376 397/57/377
-f 397/57/377 399/512/376 394/407/378
-f 347/462/379 235/648/380 344/1/381
-f 344/1/381 235/648/380 313/155/382
-f 209/633/383 128/694/384 131/95/385
-f 209/633/386 213/76/387 128/694/388
-f 164/613/389 162/465/390 129/100/391
-f 129/100/391 162/465/390 135/110/392
-f 209/633/393 131/95/394 129/484/395
-f 132/176/396 129/484/397 135/156/398
-f 132/176/399 209/633/400 129/484/401
-f 133/411/402 135/156/403 137/286/404
-f 133/411/405 132/176/406 135/156/407
-f 159/408/408 134/446/409 161/375/410
-f 161/375/410 134/446/409 162/465/411
-f 133/411/412 137/286/413 136/544/414
-f 137/637/415 135/110/416 134/446/417
-f 134/446/417 135/110/416 162/465/418
-f 206/553/419 136/544/420 138/412/421
-f 206/553/422 133/411/423 136/544/424
-f 206/553/425 138/412/426 140/409/427
-f 430/372/428 137/637/429 160/74/430
-f 160/74/430 137/637/429 134/446/431
-f 202/545/432 140/409/433 139/688/434
-f 202/545/435 206/553/436 140/409/437
-f 202/545/438 139/688/439 141/709/440
-f 145/203/441 141/709/442 143/438/443
-f 145/203/444 202/545/445 141/709/446
-f 587/404/447 600/410/448 126/305/449
-f 126/305/449 600/410/448 125/37/450
-f 144/638/451 143/438/452 142/379/453
-f 144/638/454 145/203/455 143/438/456
-f 143/91/457 434/63/458 142/306/459
-f 144/638/460 142/379/461 146/104/462
-f 146/444/463 156/607/464 148/97/465
-f 148/97/465 156/607/464 389/673/466
-f 147/649/467 146/104/468 148/31/469
-f 147/649/470 144/638/471 146/104/472
-f 148/97/473 389/673/474 149/248/475
-f 149/248/475 389/673/474 157/32/476
-f 147/649/477 148/31/478 149/39/479
-f 157/32/480 153/460/481 149/248/482
-f 149/248/482 153/460/481 151/596/483
-f 150/582/484 149/39/485 151/490/486
-f 150/582/487 147/649/488 149/39/489
-f 42/598/490 43/692/491 39/299/492
-f 39/299/492 43/692/491 41/290/493
-f 47/228/494 151/490/495 48/136/496
-f 47/228/497 150/582/498 151/490/499
-f 167/479/500 153/460/501 154/557/502
-f 154/557/502 153/460/501 157/32/503
-f 86/177/504 83/260/505 43/692/506
-f 43/692/506 83/260/505 41/290/507
-f 277/151/508 278/616/509 413/525/510
-f 413/525/510 278/616/509 381/526/511
-f 595/323/512 590/663/513 412/41/514
-f 412/41/514 590/663/513 272/135/515
-f 413/525/516 283/175/517 418/320/518
-f 418/320/518 283/175/517 276/664/519
-f 74/49/520 72/106/521 75/430/522
-f 75/430/522 72/106/521 285/382/523
-f 232/54/524 168/291/525 169/298/526
-f 169/298/526 168/291/525 167/479/527
-f 169/298/528 167/479/529 170/539/530
-f 170/539/530 167/479/529 154/557/531
-f 229/88/532 155/94/533 346/98/534
-f 346/98/534 155/94/533 158/33/535
-f 172/276/536 230/330/537 158/33/538
-f 158/33/538 230/330/537 346/98/539
-f 583/267/540 587/404/541 228/643/542
-f 228/643/542 587/404/541 126/305/543
-f 179/205/544 121/378/545 122/34/546
-f 122/34/546 121/378/545 118/483/547
-f 120/355/548 119/682/549 179/205/550
-f 179/205/550 119/682/549 121/378/551
-f 224/706/552 186/324/553 185/674/554
-f 47/228/555 186/324/556 190/584/557
-f 52/322/558 186/324/559 47/228/560
-f 216/300/561 211/463/562 207/650/563
-f 207/650/563 211/463/562 208/79/564
-f 150/582/565 190/584/566 188/573/567
-f 47/228/568 190/584/569 150/582/570
-f 195/403/571 193/261/572 191/43/573
-f 191/43/573 193/261/572 192/227/574
-f 147/649/575 188/573/576 192/227/577
-f 150/582/578 188/573/579 147/649/580
-f 218/346/581 201/339/582 221/99/583
-f 221/99/583 201/339/582 199/35/584
-f 147/649/585 192/227/586 193/261/587
-f 221/99/588 199/35/589 220/64/590
-f 220/64/590 199/35/589 196/651/591
-f 144/638/592 193/261/593 194/454/594
-f 147/649/595 193/261/596 144/638/597
-f 205/335/598 203/466/599 218/346/600
-f 218/346/600 203/466/599 201/339/601
-f 144/638/602 194/454/603 198/601/604
-f 216/300/605 207/650/606 217/152/607
-f 217/152/607 207/650/606 204/20/608
-f 145/203/609 198/601/610 196/651/611
-f 144/638/612 198/601/613 145/203/614
-f 187/705/615 188/573/616 189/36/617
-f 189/36/617 188/573/616 190/584/618
-f 202/545/619 196/651/620 199/35/621
-f 145/203/622 196/651/623 202/545/624
-f 220/64/625 196/651/626 200/4/627
-f 200/4/627 196/651/626 198/601/628
-f 202/545/629 199/35/630 201/339/631
-f 197/675/632 194/454/633 195/403/634
-f 195/403/634 194/454/633 193/261/635
-f 206/553/636 201/339/637 203/466/638
-f 202/545/639 201/339/640 206/553/641
-f 133/411/642 203/466/643 204/20/644
-f 206/553/645 203/466/646 133/411/647
-f 200/4/648 198/601/649 197/675/650
-f 197/675/650 198/601/649 194/454/651
-f 133/411/652 204/20/653 207/650/654
-f 211/463/655 215/605/656 208/79/657
-f 208/79/657 215/605/656 210/354/658
-f 132/176/659 207/650/660 208/79/661
-f 133/411/662 207/650/663 132/176/664
-f 209/633/665 208/79/666 210/354/667
-f 132/176/668 208/79/669 209/633/670
-f 215/605/671 212/287/672 210/354/673
-f 209/633/674 210/354/675 213/76/676
-f 214/293/677 215/605/678 211/463/679
-f 213/76/680 214/293/681 70/262/682
-f 214/293/683 213/76/684 215/605/685
-f 67/105/686 211/463/687 216/300/688
-f 67/105/689 214/293/690 211/463/691
-f 67/105/692 216/300/693 217/152/694
-f 65/615/695 217/152/696 205/335/697
-f 65/615/698 67/105/699 217/152/700
-f 65/615/701 205/335/702 218/346/703
-f 61/704/704 218/346/705 221/99/706
-f 61/704/707 65/615/708 218/346/709
-f 219/12/710 221/99/711 220/64/712
-f 219/12/713 61/704/714 221/99/715
-f 219/12/716 220/64/717 200/4/718
-f 55/405/719 200/4/720 197/675/721
-f 55/405/722 219/12/723 200/4/724
-f 222/546/725 197/675/726 195/403/727
-f 222/546/728 55/405/729 197/675/730
-f 222/546/731 195/403/732 191/43/733
-f 54/87/734 222/546/735 191/43/736
-f 223/611/737 187/705/738 189/36/739
-f 223/611/740 54/87/741 187/705/742
-f 50/489/743 189/36/744 224/706/745
-f 50/489/746 223/611/747 189/36/748
-f 50/489/749 224/706/750 52/322/751
-f 34/38/752 371/183/753 498/289/754
-f 498/289/754 371/183/753 519/40/755
-f 170/515/756 307/103/757 169/149/758
-f 169/149/758 307/103/757 306/109/759
-f 567/297/760 127/634/761 554/247/762
-f 554/247/762 127/634/761 301/508/763
-f 304/337/764 101/157/765 302/3/766
-f 302/3/766 101/157/765 103/552/767
-f 553/302/768 105/341/769 571/134/770
-f 571/134/770 105/341/769 270/583/771
-f 175/662/772 503/42/773 272/135/774
-f 272/135/774 503/42/773 508/321/775
-f 182/174/776 105/284/777 106/265/778
-f 106/265/778 105/284/777 102/125/779
-f 169/149/780 306/109/781 232/336/782
-f 232/336/782 306/109/781 310/200/783
-f 582/480/784 82/707/785 581/5/786
-f 581/5/786 82/707/785 81/285/787
-f 573/543/788 558/641/789 302/3/790
-f 302/3/790 558/641/789 316/343/791
-f 267/229/792 183/587/793 570/665/794
-f 570/665/794 183/587/793 566/491/795
-f 235/648/796 85/554/797 313/155/798
-f 313/155/798 85/554/797 79/689/799
-f 254/115/800 260/81/801 255/7/802
-f 255/7/802 260/81/801 258/311/803
-f 255/7/804 258/311/805 251/698/806
-f 251/698/806 258/311/805 259/394/807
-f 263/82/808 260/81/809 253/158/810
-f 253/158/810 260/81/809 254/115/811
-f 264/83/812 263/82/813 252/208/814
-f 252/208/814 263/82/813 253/158/815
-f 251/698/816 259/394/817 250/161/818
-f 250/161/818 259/394/817 262/193/819
-f 248/171/820 243/504/821 246/574/822
-f 244/421/823 243/504/824 249/468/825
-f 249/468/825 243/504/824 248/171/826
-f 242/395/827 247/722/828 243/504/829
-f 243/504/829 247/722/828 246/574/830
-f 244/421/831 286/528/832 245/469/833
-f 245/469/833 286/528/832 427/8/834
-f 265/70/835 257/283/836 436/485/837
-f 123/253/838 266/186/839 118/483/840
-f 118/483/840 266/186/839 122/34/841
-f 110/199/842 183/710/843 114/53/844
-f 114/53/844 183/710/843 184/75/845
-f 580/455/846 422/472/847 557/194/848
-f 557/194/848 422/472/847 287/561/849
-f 183/587/850 267/229/851 184/588/852
-f 184/588/852 267/229/851 268/589/853
-f 175/239/854 34/38/855 503/344/856
-f 503/344/856 34/38/855 498/289/857
-f 382/590/858 383/277/859 271/586/860
-f 271/586/860 383/277/859 270/583/861
-f 184/588/862 268/589/863 266/591/864
-f 122/230/865 266/591/864 268/589/863
-f 122/230/866 268/589/867 179/231/868
-f 179/231/868 268/589/867 120/628/869
-f 182/585/870 181/16/871 271/586/872
-f 181/16/871 108/232/873 271/586/872
-f 90/233/874 271/586/875 180/112/876
-f 180/112/876 271/586/875 108/232/877
-f 429/126/878 120/628/879 382/590/880
-f 382/590/880 120/628/879 268/589/881
-f 174/617/882 165/358/883 282/359/884
-f 282/359/884 165/358/883 280/486/885
-f 74/618/886 177/345/887 274/654/888
-f 274/654/888 177/345/887 284/399/889
-f 159/413/890 161/666/891 277/151/892
-f 277/151/892 161/666/891 278/616/893
-f 176/332/894 283/175/895 77/21/896
-f 77/21/896 283/175/895 275/127/897
-f 165/358/898 173/17/899 280/486/900
-f 280/486/900 173/17/899 281/333/901
-f 177/345/902 77/21/903 284/399/904
-f 284/399/904 77/21/903 275/127/905
-f 176/332/906 78/608/907 283/175/908
-f 283/175/908 78/608/907 276/664/909
-f 74/618/910 274/654/911 72/655/912
-f 72/655/912 274/654/911 273/656/913
-f 174/617/914 282/359/915 163/312/916
-f 163/312/916 282/359/915 279/487/917
-f 72/655/918 273/656/919 173/17/920
-f 173/17/920 273/656/919 281/333/921
-f 161/666/922 163/312/923 278/616/924
-f 278/616/924 163/312/923 279/487/925
-f 601/137/926 269/325/927 585/492/928
-f 585/492/928 269/325/927 178/326/929
-f 175/662/930 272/135/931 586/493/932
-f 586/493/932 272/135/931 590/663/933
-f 128/356/934 71/243/935 166/52/936
-f 166/52/936 71/243/935 73/703/937
-f 174/206/938 130/708/939 165/107/940
-f 165/107/940 130/708/939 166/52/941
-f 113/202/942 112/555/943 288/447/944
-f 288/447/944 112/555/943 290/702/945
-f 116/604/946 113/202/947 289/619/948
-f 289/619/948 113/202/947 288/447/949
-f 112/555/950 111/264/951 290/702/952
-f 290/702/952 111/264/951 287/561/953
-f 287/561/954 111/264/955 557/194/956
-f 557/194/956 111/264/955 568/347/957
-f 363/313/958 294/636/959 364/278/960
-f 364/278/960 294/636/959 295/614/961
-f 400/169/962 402/55/963 395/163/964
-f 395/163/964 402/55/963 397/57/965
-f 314/419/966 315/128/967 94/723/968
-f 94/723/968 315/128/967 93/612/969
-f 127/634/970 297/521/971 301/508/972
-f 301/508/972 297/521/971 299/645/973
-f 318/676/974 304/337/975 316/343/976
-f 316/343/976 304/337/975 302/3/977
-f 101/157/978 304/337/979 98/606/980
-f 98/606/980 304/337/979 225/129/981
-f 92/226/982 226/327/983 304/337/984
-f 304/337/984 226/327/983 225/129/985
-f 297/521/986 298/431/987 299/645/988
-f 298/431/987 115/569/989 299/645/988
-f 115/569/990 227/476/991 299/645/992
-f 299/645/992 227/476/991 93/548/993
-f 315/236/994 318/676/995 93/548/996
-f 93/548/996 318/676/995 299/645/997
-f 234/640/998 233/696/999 312/204/1000
-f 312/204/1000 233/696/999 311/467/1001
-f 232/336/1002 310/200/1003 88/50/1004
-f 88/50/1004 310/200/1003 305/201/1005
-f 309/376/1006 230/246/1007 591/442/1008
-f 591/442/1008 230/246/1007 583/142/1009
-f 592/434/1010 303/168/1011 581/271/1012
-f 581/271/1012 303/168/1011 231/143/1013
-f 319/147/1014 309/376/1015 593/565/1016
-f 593/565/1016 309/376/1015 591/442/1017
-f 320/23/1018 308/639/1019 348/701/1020
-f 348/701/1020 308/639/1019 345/150/1021
-f 321/164/1022 307/103/1023 320/23/1024
-f 320/23/1024 307/103/1023 308/639/1025
-f 322/571/1026 306/109/1027 321/164/1028
-f 321/164/1028 306/109/1027 307/103/1029
-f 79/689/1030 312/204/1031 321/164/1032
-f 321/164/1032 312/204/1031 322/571/1033
-f 313/155/1034 79/689/1035 320/23/1036
-f 320/23/1036 79/689/1035 321/164/1037
-f 344/1/1038 313/155/1039 348/701/1040
-f 348/701/1040 313/155/1039 320/23/1041
-f 592/434/1042 171/307/1043 593/565/1044
-f 593/565/1044 171/307/1043 319/147/1045
-f 304/337/1046 318/676/1047 92/226/1048
-f 92/226/1048 318/676/1047 315/236/1049
-f 301/508/1050 299/645/1051 316/343/1052
-f 316/343/1052 299/645/1051 318/676/1053
-f 95/77/1054 92/196/1055 314/419/1056
-f 314/419/1056 92/196/1055 315/128/1057
-f 306/109/1058 322/571/1059 310/200/1060
-f 310/200/1060 322/571/1059 305/201/1061
-f 312/204/1062 311/467/1063 322/571/1064
-f 322/571/1064 311/467/1063 305/201/1065
-f 154/557/1066 157/32/1067 155/94/1068
-f 155/94/1068 157/32/1067 389/673/1069
-f 474/256/1070 530/141/1071 475/353/1072
-f 475/353/1072 530/141/1071 531/84/1073
-f 217/152/1074 204/20/1075 205/335/1076
-f 205/335/1076 204/20/1075 203/466/1077
-f 224/706/1078 189/36/1079 186/324/1080
-f 186/324/1080 189/36/1079 190/584/1081
-f 52/322/1082 185/674/1083 186/324/1084
-f 52/322/1085 224/706/1086 185/674/1087
-f 213/76/1088 210/354/1089 212/287/1090
-f 213/76/1091 212/287/1092 215/605/1093
-f 130/708/1094 164/613/1095 131/537/1096
-f 131/537/1096 164/613/1095 129/100/1097
-f 163/215/1098 164/613/1099 174/206/1100
-f 174/206/1100 164/613/1099 130/708/1101
-f 161/375/1102 162/465/1103 163/215/1104
-f 163/215/1104 162/465/1103 164/613/1105
-f 75/430/1106 66/47/1107 76/725/1108
-f 76/725/1108 66/47/1107 69/635/1109
-f 191/43/1110 192/227/1111 187/705/1112
-f 187/705/1112 192/227/1111 188/573/1113
-f 54/87/1114 191/43/1115 187/705/1116
-f 49/308/1117 45/471/1118 51/340/1119
-f 51/340/1119 45/471/1118 44/153/1120
-f 401/575/1121 400/169/1122 396/711/1123
-f 396/711/1123 400/169/1122 395/163/1124
-f 563/368/1125 572/498/1126 363/313/1127
-f 363/313/1127 572/498/1126 294/636/1128
-f 395/163/1129 397/57/1130 333/216/1131
-f 333/216/1131 397/57/1130 330/360/1132
-f 396/711/1133 395/163/1134 329/712/1135
-f 329/712/1135 395/163/1134 333/216/1136
-f 397/57/1137 394/407/1138 330/360/1139
-f 330/360/1139 394/407/1138 332/361/1140
-f 342/334/1141 337/266/1142 335/178/1143
-f 335/178/1143 337/266/1142 327/697/1144
-f 343/631/1145 339/362/1146 336/576/1147
-f 336/576/1147 339/362/1146 328/268/1148
-f 339/362/1149 340/22/1150 328/268/1151
-f 328/268/1151 340/22/1150 323/217/1152
-f 337/266/1153 343/631/1154 327/697/1155
-f 327/697/1155 343/631/1154 336/576/1156
-f 352/373/1157 355/24/1158 343/631/1159
-f 343/631/1159 355/24/1158 339/362/1160
-f 351/58/1161 353/597/1162 342/334/1163
-f 342/334/1163 353/597/1162 337/266/1164
-f 334/510/1165 341/534/1166 335/178/1167
-f 335/178/1167 341/534/1166 342/334/1168
-f 576/116/1169 384/185/1170 574/414/1171
-f 574/414/1171 384/185/1170 332/361/1172
-f 582/480/1173 80/724/1174 588/25/1175
-f 588/25/1175 80/724/1174 33/363/1176
-f 598/108/1177 597/295/1178 324/182/1179
-f 324/182/1179 597/295/1178 338/370/1180
-f 596/61/1181 597/295/1182 56/364/1183
-f 56/364/1183 597/295/1182 57/488/1184
-f 233/303/1185 234/195/1186 87/72/1187
-f 87/72/1187 234/195/1186 86/177/1188
-f 46/377/1189 87/72/1190 45/471/1191
-f 45/471/1191 87/72/1190 44/153/1192
-f 171/307/1193 344/1/1194 319/147/1195
-f 319/147/1195 344/1/1194 348/701/1196
-f 348/701/1197 345/150/1198 319/147/1199
-f 319/147/1199 345/150/1198 309/376/1200
-f 81/73/1201 347/462/1202 171/307/1203
-f 171/307/1203 347/462/1202 344/1/1204
-f 346/198/1205 345/150/1206 229/516/1207
-f 229/516/1207 345/150/1206 308/639/1208
-f 40/562/1209 39/299/1210 419/121/1211
-f 419/121/1211 39/299/1210 41/290/1212
-f 267/229/1213 383/277/1214 268/589/1215
-f 268/589/1215 383/277/1214 382/590/1216
-f 284/399/1217 378/630/1218 274/654/1219
-f 274/654/1219 378/630/1218 349/716/1220
-f 584/684/1221 58/603/1222 599/184/1223
-f 599/184/1223 58/603/1222 60/148/1224
-f 357/391/1225 359/660/1226 351/58/1227
-f 351/58/1227 359/660/1226 353/597/1228
-f 358/622/1229 361/529/1230 352/373/1231
-f 352/373/1231 361/529/1230 355/24/1232
-f 341/534/1233 350/272/1234 342/334/1235
-f 342/334/1235 350/272/1234 351/58/1236
-f 559/56/1237 560/478/1238 334/510/1239
-f 334/510/1239 560/478/1238 341/534/1240
-f 359/660/1241 358/622/1242 353/597/1243
-f 353/597/1243 358/622/1242 352/373/1244
-f 366/420/1245 365/570/1246 359/660/1247
-f 359/660/1247 365/570/1246 358/622/1248
-f 370/540/1249 380/46/1250 89/541/1251
-f 89/541/1251 380/46/1250 379/558/1252
-f 365/570/1253 368/224/1254 358/622/1255
-f 358/622/1255 368/224/1254 361/529/1256
-f 364/278/1257 366/420/1258 357/391/1259
-f 357/391/1259 366/420/1258 359/660/1260
-f 350/272/1261 356/623/1262 351/58/1263
-f 351/58/1263 356/623/1262 357/391/1264
-f 560/478/1265 561/620/1266 341/534/1267
-f 341/534/1267 561/620/1266 350/272/1268
-f 295/614/1269 292/726/1270 364/278/1271
-f 364/278/1271 292/726/1270 366/420/1272
-f 296/560/1273 293/381/1274 365/570/1275
-f 365/570/1275 293/381/1274 368/224/1276
-f 292/726/1277 296/560/1278 366/420/1279
-f 366/420/1279 296/560/1278 365/570/1280
-f 356/623/1281 363/313/1282 357/391/1283
-f 357/391/1283 363/313/1282 364/278/1284
-f 561/620/1285 562/642/1286 350/272/1287
-f 350/272/1287 562/642/1286 356/623/1288
-f 562/642/1289 563/368/1290 356/623/1291
-f 356/623/1291 563/368/1290 363/313/1292
-f 378/630/1293 381/526/1294 279/487/1295
-f 279/487/1295 381/526/1294 278/616/1296
-f 392/328/1297 277/151/1298 418/320/1299
-f 418/320/1299 277/151/1298 413/525/1300
-f 370/540/1301 323/217/1302 380/46/1303
-f 380/46/1303 323/217/1302 237/190/1304
-f 595/323/1305 412/41/1306 601/137/1307
-f 601/137/1307 412/41/1306 269/325/1308
-f 372/542/1309 380/46/1310 326/389/1311
-f 326/389/1311 380/46/1310 237/190/1312
-f 326/389/1313 331/212/1314 372/542/1315
-f 372/542/1315 331/212/1314 377/653/1316
-f 331/212/1317 329/712/1318 377/653/1319
-f 377/653/1319 329/712/1318 375/44/1320
-f 333/216/1321 330/360/1322 385/301/1323
-f 385/301/1323 330/360/1322 376/600/1324
-f 329/712/1325 333/216/1326 375/44/1327
-f 375/44/1327 333/216/1326 385/301/1328
-f 330/360/1329 332/361/1330 376/600/1331
-f 376/600/1331 332/361/1330 384/185/1332
-f 335/178/1333 327/697/1334 387/48/1335
-f 387/48/1335 327/697/1334 373/78/1336
-f 336/576/1337 328/268/1338 388/427/1339
-f 388/427/1339 328/268/1338 374/428/1340
-f 328/268/1341 323/217/1342 374/428/1343
-f 374/428/1343 323/217/1342 370/540/1344
-f 327/697/1345 336/576/1346 373/78/1347
-f 373/78/1347 336/576/1346 388/427/1348
-f 102/125/1349 386/509/1350 106/265/1351
-f 106/265/1351 386/509/1350 387/48/1352
-f 565/610/1353 110/199/1354 576/116/1355
-f 576/116/1355 110/199/1354 384/185/1356
-f 360/556/1357 354/559/1358 594/140/1359
-f 594/140/1359 354/559/1358 596/61/1360
-f 586/209/1361 584/684/1362 175/239/1363
-f 175/239/1363 584/684/1362 34/38/1364
-f 602/387/1365 589/699/1366 369/657/1367
-f 369/657/1367 589/699/1366 124/80/1368
-f 155/94/1369 389/673/1370 158/33/1371
-f 158/33/1371 389/673/1370 156/607/1372
-f 390/26/1373 172/276/1374 156/607/1375
-f 156/607/1375 172/276/1374 158/33/1376
-f 277/151/1377 392/328/1378 159/413/1379
-f 159/413/1379 392/328/1378 391/90/1380
-f 160/74/1381 134/446/1382 391/532/1383
-f 391/532/1383 134/446/1382 159/408/1384
-f 78/609/1385 176/181/1386 58/603/1387
-f 58/603/1387 176/181/1386 64/388/1388
-f 137/637/1389 430/372/1390 136/677/1391
-f 555/530/1392 564/599/1393 102/125/1394
-f 102/125/1394 564/599/1393 386/509/1395
-f 407/500/1396 406/192/1397 401/575/1398
-f 401/575/1398 406/192/1397 400/169/1399
-f 406/192/1400 408/448/1401 400/169/1402
-f 400/169/1402 408/448/1401 402/55/1403
-f 574/414/1404 332/361/1405 577/566/1406
-f 577/566/1406 332/361/1405 394/407/1407
-f 408/448/1408 405/456/1409 402/55/1410
-f 402/55/1410 405/456/1409 399/512/1411
-f 425/269/1412 422/472/1413 408/448/1414
-f 408/448/1414 422/472/1413 405/456/1415
-f 423/577/1416 425/269/1417 406/192/1418
-f 406/192/1418 425/269/1417 408/448/1419
-f 424/433/1420 423/577/1421 407/500/1422
-f 407/500/1422 423/577/1421 406/192/1423
-f 577/566/1424 394/407/1425 578/680/1426
-f 578/680/1426 394/407/1425 399/512/1427
-f 470/329/1428 479/494/1429 526/275/1430
-f 526/275/1430 479/494/1429 535/495/1431
-f 245/469/1432 427/8/1433 403/626/1434
-f 403/626/1434 427/8/1433 414/296/1435
-f 429/126/1436 382/590/1437 90/233/1438
-f 90/233/1438 382/590/1437 271/586/1439
-f 331/212/1440 326/389/1441 411/146/1442
-f 411/146/1442 326/389/1441 410/518/1443
-f 411/146/1444 410/518/1445 409/721/1446
-f 409/721/1446 410/518/1445 416/661/1447
-f 94/723/1448 117/124/1449 286/528/1450
-f 286/528/1450 117/124/1449 417/254/1451
-f 117/124/1452 116/604/1453 417/254/1454
-f 417/254/1454 116/604/1453 289/619/1455
-f 606/27/1456 604/415/1457 398/314/1458
-f 398/314/1458 604/415/1457 393/450/1459
-f 396/711/1460 329/712/1461 411/146/1462
-f 411/146/1462 329/712/1461 331/212/1463
-f 283/175/1464 413/525/1465 275/127/1466
-f 275/127/1466 413/525/1465 381/526/1467
-f 604/415/1468 605/715/1469 393/450/1470
-f 393/450/1470 605/715/1469 325/225/1471
-f 426/671/1472 424/433/1473 415/315/1474
-f 415/315/1474 424/433/1473 407/500/1475
-f 426/671/1476 427/8/1477 417/254/1478
-f 417/254/1478 427/8/1477 286/528/1479
-f 409/721/1480 416/661/1481 415/315/1482
-f 415/315/1482 416/661/1481 414/296/1483
-f 401/575/1484 396/711/1485 409/721/1486
-f 409/721/1486 396/711/1485 411/146/1487
-f 415/315/1488 407/500/1489 409/721/1490
-f 409/721/1490 407/500/1489 401/575/1491
-f 244/421/1492 249/468/1493 286/528/1494
-f 286/528/1494 249/468/1493 250/161/1495
-f 340/22/1496 239/218/1497 323/217/1498
-f 323/217/1498 239/218/1497 237/190/1499
-f 416/661/1500 410/518/1501 236/211/1502
-f 236/211/1502 410/518/1501 240/234/1503
-f 419/121/1504 37/2/1505 40/562/1506
-f 40/562/1506 37/2/1505 53/10/1507
-f 37/2/1508 420/481/1509 53/10/1510
-f 53/10/1510 420/481/1509 36/71/1511
-f 594/140/1512 607/15/1513 360/556/1514
-f 360/556/1514 607/15/1513 367/59/1515
-f 588/25/1516 607/15/1517 420/481/1518
-f 420/481/1518 607/15/1517 36/71/1519
-f 237/190/1520 240/234/1521 326/389/1522
-f 326/389/1522 240/234/1521 410/518/1523
-f 429/179/1524 90/310/1525 379/558/1526
-f 379/558/1526 90/310/1525 89/541/1527
-f 414/296/1528 416/661/1529 403/626/1530
-f 403/626/1530 416/661/1529 236/211/1531
-f 415/315/1532 414/296/1533 426/671/1534
-f 426/671/1534 414/296/1533 427/8/1535
-f 417/254/1536 289/619/1537 426/671/1538
-f 426/671/1538 289/619/1537 424/433/1539
-f 289/619/1540 288/447/1541 424/433/1542
-f 424/433/1542 288/447/1541 423/577/1543
-f 288/447/1544 290/702/1545 423/577/1546
-f 423/577/1546 290/702/1545 425/269/1547
-f 290/702/1548 287/561/1549 425/269/1550
-f 425/269/1550 287/561/1549 422/472/1551
-f 578/680/1552 399/512/1553 579/144/1554
-f 579/144/1554 399/512/1553 405/456/1555
-f 252/208/1556 247/722/1557 291/304/1558
-f 291/304/1558 247/722/1557 242/395/1559
-f 378/630/1560 284/399/1561 381/526/1562
-f 381/526/1562 284/399/1561 275/127/1563
-f 349/716/1564 378/630/1565 282/359/1566
-f 282/359/1566 378/630/1565 279/487/1567
-f 380/46/1568 372/542/1569 379/558/1570
-f 379/558/1570 372/542/1569 119/682/1571
-f 362/294/1572 431/133/1573 428/522/1574
-f 428/522/1574 431/133/1573 238/316/1575
-f 241/119/1576 431/133/1577 432/625/1578
-f 432/625/1578 431/133/1577 362/294/1579
-f 355/24/1580 428/522/1581 339/362/1582
-f 339/362/1582 428/522/1581 340/22/1583
-f 361/529/1584 362/294/1585 355/24/1586
-f 355/24/1586 362/294/1585 428/522/1587
-f 368/224/1588 432/625/1589 361/529/1590
-f 361/529/1590 432/625/1589 362/294/1591
-f 293/381/1592 291/304/1593 368/224/1594
-f 368/224/1594 291/304/1593 432/625/1595
-f 239/218/1596 340/22/1597 238/316/1598
-f 238/316/1598 340/22/1597 428/522/1599
-f 242/395/1600 241/119/1601 291/304/1602
-f 291/304/1602 241/119/1601 432/625/1603
-f 138/473/1604 136/677/1605 430/372/1606
-f 140/113/1607 138/473/1608 430/372/1609
-f 602/387/1610 605/715/1611 430/372/1612
-f 430/372/1612 605/715/1611 140/113/1613
-f 606/27/1614 398/314/1615 603/646/1616
-f 603/646/1616 398/314/1615 404/501/1617
-f 603/646/1618 404/501/1619 608/159/1620
-f 608/159/1620 404/501/1619 421/348/1621
-f 600/410/1622 390/26/1623 608/159/1624
-f 608/159/1624 390/26/1623 434/63/1625
-f 146/444/1626 434/63/1627 156/607/1628
-f 156/607/1628 434/63/1627 390/26/1629
-f 146/444/1630 142/306/1631 434/63/1632
-f 274/654/1633 349/716/1634 273/656/1635
-f 273/656/1635 349/716/1634 281/333/1636
-f 282/359/1637 280/486/1638 349/716/1639
-f 349/716/1639 280/486/1638 281/333/1640
-f 433/60/1641 436/485/1642 256/365/1643
-f 256/365/1643 436/485/1642 257/283/1644
-f 262/193/1645 261/658/1646 435/242/1647
-f 264/83/1648 433/60/1649 256/365/1650
-f 252/208/1651 291/304/1652 264/83/1653
-f 264/83/1653 291/304/1652 433/60/1654
-f 435/242/1655 286/528/1656 262/193/1657
-f 262/193/1657 286/528/1656 250/161/1658
-f 94/723/1659 286/528/1660 435/242/1661
-f 291/304/1662 95/77/1663 433/60/1664
-f 95/77/1665 314/419/1666 433/60/1667
-f 433/60/1667 314/419/1666 436/485/1668
-f 94/723/1669 435/242/1670 314/419/1671
-f 314/419/1671 435/242/1670 436/485/1672
-f 265/70/1673 436/485/1674 261/658/1675
-f 261/658/1675 436/485/1674 435/242/1676
-f 27/578/1677 241/119/1678 26/383/1679
-f 26/383/1679 241/119/1678 242/395/1680
-f 26/383/1681 242/395/1682 25/130/1683
-f 25/130/1683 242/395/1682 243/504/1684
-f 25/130/1685 243/504/1686 24/535/1687
-f 24/535/1687 243/504/1686 244/421/1688
-f 24/535/1689 244/421/1690 23/219/1691
-f 23/219/1691 244/421/1690 245/469/1692
-f 23/219/1693 245/469/1694 22/685/1695
-f 22/685/1695 245/469/1694 403/626/1696
-f 22/685/1697 403/626/1698 32/579/1699
-f 32/579/1699 403/626/1698 236/211/1700
-f 32/579/1701 236/211/1702 28/531/1703
-f 28/531/1703 236/211/1702 240/234/1704
-f 28/531/1705 240/234/1706 31/351/1707
-f 31/351/1707 240/234/1706 237/190/1708
-f 31/351/1709 237/190/1710 29/9/1711
-f 29/9/1711 237/190/1710 239/218/1712
-f 29/9/1713 239/218/1714 30/317/1715
-f 30/317/1715 239/218/1714 238/316/1716
-f 30/317/1717 238/316/1718 21/281/1719
-f 21/281/1719 238/316/1718 431/133/1720
-f 21/281/1721 431/133/1722 27/578/1723
-f 27/578/1723 431/133/1722 241/119/1724
-f 29/9/1725 30/317/1726 445/386/1727
-f 445/386/1727 30/317/1726 446/318/1728
-f 32/579/1729 28/531/1730 448/371/1731
-f 448/371/1731 28/531/1730 444/11/1732
-f 31/351/1733 29/9/1734 447/449/1735
-f 447/449/1735 29/9/1734 445/386/1736
-f 24/535/1737 23/219/1738 440/523/1739
-f 440/523/1739 23/219/1738 439/188/1740
-f 26/383/1741 25/130/1742 442/238/1743
-f 442/238/1743 25/130/1742 441/436/1744
-f 21/281/1745 27/578/1746 437/390/1747
-f 437/390/1747 27/578/1746 443/594/1748
-f 23/219/1749 22/685/1750 439/188/1751
-f 439/188/1751 22/685/1750 438/220/1752
-f 22/685/1753 32/579/1754 438/220/1755
-f 438/220/1755 32/579/1754 448/371/1756
-f 28/531/1757 31/351/1758 444/11/1759
-f 444/11/1759 31/351/1758 447/449/1760
-f 27/578/1761 26/383/1762 443/594/1763
-f 443/594/1763 26/383/1762 442/238/1764
-f 30/317/1765 21/281/1766 446/318/1767
-f 446/318/1767 21/281/1766 437/390/1768
-f 25/130/1769 24/535/1770 441/436/1771
-f 441/436/1771 24/535/1770 440/523/1772
-f 18/396/1773 253/158/1774 19/451/1775
-f 19/451/1775 253/158/1774 254/115/1776
-f 19/451/1777 254/115/1778 20/397/1779
-f 20/397/1779 254/115/1778 255/7/1780
-f 20/397/1781 255/7/1782 16/280/1783
-f 16/280/1783 255/7/1782 251/698/1784
-f 16/280/1785 251/698/1786 15/240/1787
-f 15/240/1787 251/698/1786 250/161/1788
-f 15/240/1789 250/161/1790 14/86/1791
-f 14/86/1791 250/161/1790 249/468/1792
-f 14/86/1793 249/468/1794 13/28/1795
-f 13/28/1795 249/468/1794 248/171/1796
-f 13/28/1797 248/171/1798 11/19/1799
-f 11/19/1799 248/171/1798 246/574/1800
-f 11/19/1801 246/574/1802 12/624/1803
-f 12/624/1803 246/574/1802 247/722/1804
-f 12/624/1805 247/722/1806 17/319/1807
-f 17/319/1807 247/722/1806 252/208/1808
-f 17/319/1809 252/208/1810 18/396/1811
-f 18/396/1811 252/208/1810 253/158/1812
-f 1/274/1813 265/70/1814 5/681/1815
-f 5/681/1815 265/70/1814 261/658/1816
-f 5/681/1817 261/658/1818 4/67/1819
-f 4/67/1819 261/658/1818 262/193/1820
-f 4/67/1821 262/193/1822 7/29/1823
-f 7/29/1823 262/193/1822 259/394/1824
-f 7/29/1825 259/394/1826 8/398/1827
-f 8/398/1827 259/394/1826 258/311/1828
-f 8/398/1829 258/311/1830 6/62/1831
-f 6/62/1831 258/311/1830 260/81/1832
-f 6/62/1833 260/81/1834 3/270/1835
-f 3/270/1835 260/81/1834 263/82/1836
-f 3/270/1837 263/82/1838 2/117/1839
-f 2/117/1839 263/82/1838 264/83/1840
-f 2/117/1841 264/83/1842 10/477/1843
-f 10/477/1843 264/83/1842 256/365/1844
-f 10/477/1845 256/365/1846 9/214/1847
-f 9/214/1847 256/365/1846 257/283/1848
-f 9/214/1849 257/283/1850 1/274/1851
-f 1/274/1851 257/283/1850 265/70/1852
-f 4/67/1853 7/29/1854 452/496/1855
-f 452/496/1855 7/29/1854 455/258/1856
-f 7/29/1857 8/398/1858 455/258/1859
-f 455/258/1859 8/398/1858 456/160/1860
-f 10/477/1861 9/214/1862 458/506/1863
-f 458/506/1863 9/214/1862 457/111/1864
-f 5/681/1865 4/67/1866 453/221/1867
-f 453/221/1867 4/67/1866 452/496/1868
-f 9/214/1869 1/274/1870 457/111/1871
-f 457/111/1871 1/274/1870 449/627/1872
-f 8/398/1873 6/62/1874 456/160/1875
-f 456/160/1875 6/62/1874 454/621/1876
-f 3/270/1877 2/117/1878 451/717/1879
-f 451/717/1879 2/117/1878 450/257/1880
-f 6/62/1881 3/270/1882 454/621/1883
-f 454/621/1883 3/270/1882 451/717/1884
-f 2/117/1885 10/477/1886 450/257/1887
-f 450/257/1887 10/477/1886 458/506/1888
-f 1/274/1889 5/681/1890 449/627/1891
-f 449/627/1891 5/681/1890 453/221/1892
-f 14/86/1893 13/28/1894 462/282/1895
-f 462/282/1895 13/28/1894 461/145/1896
-f 13/28/1897 11/19/1898 461/145/1899
-f 461/145/1899 11/19/1898 459/533/1900
-f 15/240/1901 14/86/1902 463/457/1903
-f 463/457/1903 14/86/1902 462/282/1904
-f 17/319/1905 18/396/1906 465/366/1907
-f 465/366/1907 18/396/1906 466/384/1908
-f 11/19/1909 12/624/1910 459/533/1911
-f 459/533/1911 12/624/1910 460/470/1912
-f 12/624/1913 17/319/1914 460/470/1915
-f 460/470/1915 17/319/1914 465/366/1916
-f 20/397/1917 16/280/1918 468/255/1919
-f 468/255/1919 16/280/1918 464/564/1920
-f 19/451/1921 20/397/1922 467/416/1923
-f 467/416/1923 20/397/1922 468/255/1924
-f 18/396/1925 19/451/1926 466/384/1927
-f 466/384/1927 19/451/1926 467/416/1928
-f 16/280/1929 15/240/1930 464/564/1931
-f 464/564/1931 15/240/1930 463/457/1932
-f 354/559/1933 515/507/1934 338/370/1935
-f 338/370/1935 515/507/1934 514/131/1936
-f 579/144/1937 405/456/1938 580/455/1939
-f 580/455/1939 405/456/1938 422/472/1940
-f 33/363/1941 497/170/1942 367/59/1943
-f 367/59/1943 497/170/1942 517/14/1944
-f 325/225/1945 369/657/1946 513/352/1947
-f 513/352/1947 369/657/1946 518/713/1948
-f 272/135/1949 508/321/1950 412/41/1951
-f 412/41/1951 508/321/1950 523/138/1952
-f 482/581/1953 538/385/1954 483/595/1955
-f 483/595/1955 538/385/1954 539/18/1956
-f 178/326/1957 269/325/1958 504/162/1959
-f 504/162/1959 269/325/1958 507/497/1960
-f 231/143/1961 303/168/1962 506/235/1963
-f 506/235/1963 303/168/1962 510/85/1964
-f 228/458/1965 505/502/1966 300/118/1967
-f 300/118/1967 505/502/1966 509/459/1968
-f 470/453/1969 526/432/1970 473/719/1971
-f 473/719/1971 526/432/1970 529/259/1972
-f 472/139/1973 528/667/1974 478/241/1975
-f 478/241/1975 528/667/1974 534/210/1976
-f 269/325/1977 412/41/1978 507/497/1979
-f 507/497/1979 412/41/1978 523/138/1980
-f 571/134/1981 575/668/1982 479/494/1983
-f 479/494/1983 575/668/1982 487/669/1984
-f 125/37/1985 421/348/1986 501/114/1987
-f 501/114/1987 421/348/1986 524/567/1988
-f 572/498/1989 481/400/1990 556/68/1991
-f 556/68/1991 481/400/1990 477/401/1992
-f 480/349/1993 536/350/1994 496/568/1995
-f 496/568/1995 536/350/1994 552/474/1996
-f 338/370/1997 514/131/1998 324/182/1999
-f 324/182/1999 514/131/1998 512/572/2000
-f 475/353/2001 531/84/2002 480/349/2003
-f 480/349/2003 531/84/2002 536/350/2004
-f 556/68/2005 477/401/2006 569/580/2007
-f 569/580/2007 477/401/2006 476/69/2008
-f 126/305/2009 125/37/2010 502/45/2011
-f 502/45/2011 125/37/2010 501/114/2012
-f 476/69/2013 477/401/2014 532/207/2015
-f 532/207/2015 477/401/2014 533/273/2016
-f 553/647/2017 470/453/2018 555/530/2019
-f 555/530/2019 470/453/2018 473/719/2020
-f 481/400/2021 490/66/2022 537/551/2023
-f 537/551/2023 490/66/2022 546/659/2024
-f 568/347/2025 567/191/2026 475/353/2027
-f 475/353/2027 567/191/2026 474/256/2028
-f 565/610/2029 469/406/2030 566/592/2031
-f 566/592/2031 469/406/2030 472/288/2032
-f 404/501/2033 398/314/2034 522/166/2035
-f 522/166/2035 398/314/2034 521/65/2036
-f 575/668/2037 570/665/2038 487/669/2039
-f 487/669/2039 570/665/2038 478/241/2040
-f 477/401/2041 481/400/2042 533/273/2043
-f 533/273/2043 481/400/2042 537/551/2044
-f 539/18/2045 511/279/2046 527/632/2047
-f 527/632/2047 511/279/2046 509/459/2048
-f 543/670/2049 534/210/2050 523/138/2051
-f 523/138/2051 534/210/2050 507/497/2052
-f 500/503/2053 504/440/2054 525/672/2055
-f 525/672/2055 504/440/2054 528/93/2056
-f 531/84/2057 530/141/2058 502/45/2059
-f 502/45/2059 530/141/2058 505/417/2060
-f 526/432/2061 503/344/2062 529/259/2063
-f 529/259/2063 503/344/2062 498/289/2064
-f 533/273/2065 499/686/2066 532/207/2067
-f 532/207/2067 499/686/2066 506/679/2068
-f 537/551/2069 497/170/2070 533/273/2071
-f 533/273/2071 497/170/2070 499/686/2072
-f 535/495/2073 543/670/2074 508/321/2075
-f 508/321/2075 543/670/2074 523/138/2076
-f 522/166/2077 551/369/2078 524/567/2079
-f 524/567/2079 551/369/2078 552/474/2080
-f 521/65/2081 550/13/2082 522/166/2083
-f 522/166/2083 550/13/2082 551/369/2084
-f 520/452/2085 549/700/2086 521/65/2087
-f 521/65/2087 549/700/2086 550/13/2088
-f 513/352/2089 541/187/2090 520/452/2091
-f 520/452/2091 541/187/2090 549/700/2092
-f 498/289/2093 519/40/2094 529/259/2095
-f 529/259/2095 519/40/2094 548/683/2096
-f 500/503/2097 525/672/2098 518/713/2099
-f 518/713/2099 525/672/2098 547/222/2100
-f 516/342/2101 517/14/2102 545/549/2103
-f 545/549/2103 517/14/2102 546/659/2104
-f 515/507/2105 516/342/2106 544/132/2107
-f 544/132/2107 516/342/2106 545/549/2108
-f 514/131/2109 515/507/2110 542/718/2111
-f 542/718/2111 515/507/2110 544/132/2112
-f 512/572/2113 514/131/2114 540/550/2115
-f 540/550/2115 514/131/2114 542/718/2116
-f 518/713/2117 547/222/2118 513/352/2119
-f 513/352/2119 547/222/2118 541/187/2120
-f 517/14/2121 497/170/2122 546/659/2123
-f 546/659/2123 497/170/2122 537/551/2124
-f 501/114/2125 536/350/2126 502/45/2127
-f 502/45/2127 536/350/2126 531/84/2128
-f 524/567/2129 552/474/2130 501/114/2131
-f 501/114/2131 552/474/2130 536/350/2132
-f 534/210/2133 528/667/2134 507/497/2135
-f 507/497/2135 528/667/2134 504/162/2136
-f 510/85/2137 511/279/2138 538/385/2139
-f 538/385/2139 511/279/2138 539/18/2140
-f 503/42/2141 526/275/2142 508/321/2143
-f 508/321/2143 526/275/2142 535/495/2144
-f 505/502/2145 530/380/2146 509/459/2147
-f 509/459/2147 530/380/2146 527/632/2148
-f 506/235/2149 510/85/2150 532/30/2151
-f 532/30/2151 510/85/2150 538/385/2152
-f 519/40/2153 512/572/2154 548/683/2155
-f 548/683/2155 512/572/2154 540/550/2156
-f 393/450/2157 325/225/2158 520/452/2159
-f 520/452/2159 325/225/2158 513/352/2160
-f 228/643/2161 126/305/2162 505/417/2163
-f 505/417/2163 126/305/2162 502/45/2164
-f 478/241/2165 534/210/2166 487/669/2167
-f 487/669/2167 534/210/2166 543/670/2168
-f 231/223/2169 506/679/2170 80/724/2171
-f 80/724/2171 506/679/2170 499/686/2172
-f 476/720/2173 532/30/2174 482/581/2175
-f 482/581/2175 532/30/2174 538/385/2176
-f 471/102/2177 483/595/2178 527/632/2179
-f 527/632/2179 483/595/2178 539/18/2180
-f 496/568/2181 552/474/2182 495/441/2183
-f 495/441/2183 552/474/2182 551/369/2184
-f 484/517/2185 492/524/2186 540/550/2187
-f 540/550/2187 492/524/2186 548/683/2188
-f 479/494/2189 487/669/2190 535/495/2191
-f 535/495/2191 487/669/2190 543/670/2192
-f 303/168/2193 317/213/2194 510/85/2195
-f 510/85/2195 317/213/2194 511/279/2196
-f 124/80/2197 500/503/2198 369/657/2199
-f 369/657/2199 500/503/2198 518/713/2200
-f 495/441/2201 551/369/2202 494/678/2203
-f 494/678/2203 551/369/2202 550/13/2204
-f 494/678/2205 550/13/2206 493/237/2207
-f 493/237/2207 550/13/2206 549/700/2208
-f 300/118/2209 509/459/2210 317/213/2211
-f 317/213/2211 509/459/2210 511/279/2212
-f 324/182/2213 512/572/2214 371/183/2215
-f 371/183/2215 512/572/2214 519/40/2216
-f 178/687/2217 504/440/2218 124/80/2219
-f 124/80/2219 504/440/2218 500/503/2220
-f 398/314/2221 393/450/2222 521/65/2223
-f 521/65/2223 393/450/2222 520/452/2224
-f 493/237/2225 549/700/2226 485/475/2227
-f 485/475/2227 549/700/2226 541/187/2228
-f 473/719/2229 529/259/2230 492/524/2231
-f 492/524/2231 529/259/2230 548/683/2232
-f 469/406/2233 491/593/2234 525/672/2235
-f 525/672/2235 491/593/2234 547/222/2236
-f 490/66/2237 489/437/2238 546/659/2239
-f 546/659/2239 489/437/2238 545/549/2240
-f 367/59/2241 517/14/2242 360/556/2243
-f 360/556/2243 517/14/2242 516/342/2244
-f 489/437/2245 488/714/2246 545/549/2247
-f 545/549/2247 488/714/2246 544/132/2248
-f 421/348/2249 404/501/2250 524/567/2251
-f 524/567/2251 404/501/2250 522/166/2252
-f 488/714/2253 486/563/2254 544/132/2255
-f 544/132/2255 486/563/2254 542/718/2256
-f 486/563/2257 484/517/2258 542/718/2259
-f 542/718/2259 484/517/2258 540/550/2260
-f 80/724/2261 499/686/2262 33/363/2263
-f 33/363/2263 499/686/2262 497/170/2264
-f 485/475/2265 541/187/2266 491/593/2267
-f 491/593/2267 541/187/2266 547/222/2268
-f 554/247/2269 558/641/2270 471/102/2271
-f 471/102/2271 558/641/2270 483/595/2272
-f 316/343/2273 558/641/2274 301/508/2275
-f 301/508/2275 558/641/2274 554/247/2276
-f 383/277/2277 267/229/2278 575/668/2279
-f 575/668/2279 267/229/2278 570/665/2280
-f 565/610/2281 566/592/2282 110/199/2283
-f 110/199/2283 566/592/2282 183/710/2284
-f 127/122/2285 567/191/2286 111/264/2287
-f 111/264/2287 567/191/2286 568/347/2288
-f 105/284/2289 553/647/2290 102/125/2291
-f 102/125/2291 553/647/2290 555/530/2292
-f 556/68/2293 569/580/2294 104/464/2295
-f 104/464/2295 569/580/2294 103/695/2296
-f 294/636/2297 572/498/2298 104/464/2299
-f 104/464/2299 572/498/2298 556/68/2300
-f 270/583/2301 383/277/2302 571/134/2303
-f 571/134/2303 383/277/2302 575/668/2304
-f 495/441/2305 579/144/2306 496/568/2307
-f 496/568/2307 579/144/2306 580/455/2308
-f 494/678/2309 578/680/2310 495/441/2311
-f 495/441/2311 578/680/2310 579/144/2312
-f 493/237/2313 577/566/2314 494/678/2315
-f 494/678/2315 577/566/2314 578/680/2316
-f 485/475/2317 574/414/2318 493/237/2319
-f 493/237/2319 574/414/2318 577/566/2320
-f 473/719/2321 492/524/2322 555/530/2323
-f 555/530/2323 492/524/2322 564/599/2324
-f 469/406/2325 565/610/2326 491/593/2327
-f 491/593/2327 565/610/2326 576/116/2328
-f 489/437/2329 490/66/2330 562/642/2331
-f 562/642/2331 490/66/2330 563/368/2332
-f 488/714/2333 489/437/2334 561/620/2335
-f 561/620/2335 489/437/2334 562/642/2336
-f 486/563/2337 488/714/2338 560/478/2339
-f 560/478/2339 488/714/2338 561/620/2340
-f 484/517/2341 486/563/2342 559/56/2343
-f 559/56/2343 486/563/2342 560/478/2344
-f 491/593/2345 576/116/2346 485/475/2347
-f 485/475/2347 576/116/2346 574/414/2348
-f 490/66/2349 481/400/2350 563/368/2351
-f 563/368/2351 481/400/2350 572/498/2352
-f 480/349/2353 557/194/2354 475/353/2355
-f 475/353/2355 557/194/2354 568/347/2356
-f 496/568/2357 580/455/2358 480/349/2359
-f 480/349/2359 580/455/2358 557/194/2360
-f 570/665/2361 566/491/2362 478/241/2363
-f 478/241/2363 566/491/2362 472/139/2364
-f 482/581/2365 483/595/2366 573/543/2367
-f 573/543/2367 483/595/2366 558/641/2368
-f 470/329/2369 553/302/2370 479/494/2371
-f 479/494/2371 553/302/2370 571/134/2372
-f 474/251/2373 567/297/2374 471/102/2375
-f 471/102/2375 567/297/2374 554/247/2376
-f 476/720/2377 482/581/2378 569/252/2379
-f 569/252/2379 482/581/2378 573/543/2380
-f 492/524/2381 484/517/2382 564/599/2383
-f 564/599/2383 484/517/2382 559/56/2384
-f 125/37/2385 600/410/2386 421/348/2387
-f 421/348/2387 600/410/2386 608/159/2388
-f 143/91/2389 603/646/2390 434/63/2391
-f 434/63/2391 603/646/2390 608/159/2392
-f 141/418/2393 606/27/2394 143/91/2395
-f 143/91/2395 606/27/2394 603/646/2396
-f 369/657/2397 325/225/2398 602/387/2399
-f 602/387/2399 325/225/2398 605/715/2400
-f 33/363/2401 367/59/2402 588/25/2403
-f 588/25/2403 367/59/2402 607/15/2404
-f 35/519/2405 36/71/2406 594/140/2407
-f 594/140/2407 36/71/2406 607/15/2408
-f 139/402/2409 140/113/2410 604/415/2411
-f 604/415/2411 140/113/2410 605/715/2412
-f 141/418/2413 139/402/2414 606/27/2415
-f 606/27/2415 139/402/2414 604/415/2416
-f 430/372/2417 160/74/2418 602/387/2419
-f 602/387/2419 160/74/2418 589/699/2420
-f 58/603/2421 584/684/2422 78/609/2423
-f 78/609/2423 584/684/2422 586/209/2424
-f 594/140/2425 596/61/2426 35/519/2427
-f 35/519/2427 596/61/2426 56/364/2428
-f 418/320/2429 595/323/2430 392/328/2431
-f 392/328/2431 595/323/2430 601/137/2432
-f 34/38/2433 584/684/2434 371/183/2435
-f 371/183/2435 584/684/2434 599/184/2436
-f 354/559/2437 338/370/2438 596/61/2439
-f 596/61/2439 338/370/2438 597/295/2440
-f 59/435/2441 57/488/2442 598/108/2443
-f 598/108/2443 57/488/2442 597/295/2444
-f 582/480/2445 588/25/2446 82/707/2447
-f 82/707/2447 588/25/2446 420/481/2448
-f 303/168/2449 592/434/2450 317/213/2451
-f 317/213/2451 592/434/2450 593/565/2452
-f 593/565/2453 591/442/2454 317/213/2455
-f 317/213/2455 591/442/2454 300/118/2456
-f 171/307/2457 592/434/2458 81/73/2459
-f 81/73/2459 592/434/2458 581/271/2460
-f 591/442/2461 583/142/2462 300/118/2463
-f 300/118/2463 583/142/2462 228/458/2464
-f 78/608/2465 586/493/2466 276/664/2467
-f 276/664/2467 586/493/2466 590/663/2468
-f 392/328/2469 601/137/2470 391/90/2471
-f 391/90/2471 601/137/2470 585/492/2472
-f 80/724/2473 582/480/2474 231/223/2475
-f 231/223/2475 582/480/2474 581/5/2476
-f 230/330/2477 172/276/2478 583/267/2479
-f 583/267/2479 172/276/2478 587/404/2480
-f 418/320/2481 276/664/2482 595/323/2483
-f 595/323/2483 276/664/2482 590/663/2484
-f 390/26/2485 600/410/2486 172/276/2487
-f 172/276/2487 600/410/2486 587/404/2488
-f 598/108/2489 599/184/2490 59/435/2491
-f 59/435/2491 599/184/2490 60/148/2492
-f 391/532/2493 585/367/2494 160/74/2495
-f 160/74/2495 585/367/2494 589/699/2496
diff --git a/libs/vr/libdvrgraphics/assets/controller_proto2_button.obj b/libs/vr/libdvrgraphics/assets/controller_proto2_button.obj
deleted file mode 100644
index 2057c27..0000000
--- a/libs/vr/libdvrgraphics/assets/controller_proto2_button.obj
+++ /dev/null
@@ -1,595 +0,0 @@
-# This file uses centimeters as units for non-parametric coordinates.
-
-v -0.003544 0.012417 0.078987
-v -0.003544 0.013694 0.078987
-v -0.003544 0.012417 0.078281
-v -0.003544 0.013694 0.078281
-v 0.003544 0.012417 0.078987
-v 0.003544 0.013694 0.078987
-v 0.003544 0.012417 0.078281
-v 0.003544 0.013694 0.078281
-v -0.003685 0.013694 0.078769
-v -0.003685 0.013694 0.078498
-v -0.003685 0.012417 0.078498
-v -0.003685 0.012417 0.078769
-v 0.003685 0.013694 0.078498
-v 0.003685 0.013694 0.078769
-v 0.003685 0.012417 0.078769
-v 0.003685 0.012417 0.078498
-v 0.005601 0.013400 0.078650
-v 0.004531 0.013400 0.081942
-v 0.004531 0.013400 0.075358
-v -0.001731 0.013400 0.073324
-v -0.005601 0.013400 0.078650
-v -0.001731 0.013400 0.083977
-v 0.001731 0.013400 0.083977
-v -0.004531 0.013400 0.081942
-v 0.001731 0.013400 0.073324
-v -0.004531 0.013400 0.075358
-v 0.005463 0.013400 0.078650
-v 0.004420 0.013400 0.081861
-v 0.004420 0.013400 0.075439
-v -0.001688 0.013400 0.073454
-v -0.005463 0.013400 0.078650
-v -0.001688 0.013400 0.083846
-v 0.001688 0.013400 0.083846
-v -0.004420 0.013400 0.081861
-v 0.001688 0.013400 0.073454
-v -0.004420 0.013400 0.075439
-v 0.000000 0.013400 0.078650
-v -0.003544 0.013694 0.078987
-v 0.005601 0.008414 0.078650
-v 0.004531 0.008414 0.081942
-v 0.004531 0.008414 0.075358
-v -0.001731 0.008414 0.073324
-v -0.005601 0.008414 0.078650
-v -0.001731 0.008414 0.083977
-v 0.001731 0.008414 0.083977
-v -0.004531 0.008414 0.081942
-v 0.001731 0.008414 0.073324
-v -0.004531 0.008414 0.075358
-v 0.007115 0.008414 0.078650
-v 0.005756 0.008414 0.082832
-v 0.005756 0.008414 0.074468
-v -0.002199 0.008414 0.071883
-v -0.007115 0.008414 0.078650
-v -0.002199 0.008414 0.085417
-v 0.002199 0.008414 0.085417
-v -0.005756 0.008414 0.082832
-v 0.002199 0.008414 0.071883
-v -0.005756 0.008414 0.074468
-v -0.001731 0.013280 0.083977
-v 0.001731 0.013280 0.083977
-v 0.005601 0.013280 0.078650
-v 0.004531 0.013280 0.075358
-v 0.001731 0.013280 0.073324
-v -0.004531 0.013280 0.081942
-v -0.005601 0.013280 0.078650
-v -0.004531 0.013280 0.075358
-v -0.001731 0.013280 0.073324
-v 0.004531 0.013280 0.081942
-v -0.001731 0.008498 0.083977
-v 0.005601 0.008498 0.078650
-v -0.004531 0.008498 0.081942
-v -0.005601 0.008498 0.078650
-v -0.004531 0.008498 0.075358
-v -0.001731 0.008498 0.073324
-v 0.004531 0.008498 0.081942
-v 0.001731 0.008498 0.083977
-v 0.004531 0.008498 0.075358
-v 0.001731 0.008498 0.073324
-vt 0.842894 0.803524
-vt 0.835648 0.808965
-vt 0.842327 0.831331
-vt 0.887089 0.817309
-vt 0.918325 0.883860
-vt 0.914475 0.893532
-vt 0.851925 0.804110
-vt 0.831948 0.817360
-vt 0.834920 0.826127
-vt 0.835239 0.825914
-vt 0.861947 0.818080
-vt 0.858905 0.826714
-vt 0.796511 0.818262
-vt 0.834940 0.856335
-vt 0.851468 0.832257
-vt 0.879150 0.794052
-vt 0.814609 0.794688
-vt 0.879631 0.793683
-vt 0.859802 0.855418
-vt 0.918325 0.877630
-vt 0.952893 0.877630
-vt 0.917637 0.875247
-vt 0.860005 0.855991
-vt 0.953582 0.876570
-vt 0.954157 0.893532
-vt 0.914475 0.887302
-vt 0.915739 0.887302
-vt 0.831492 0.866397
-vt 0.859621 0.809104
-vt 0.814110 0.794343
-vt 0.955480 0.893532
-vt 0.918325 0.874188
-vt 0.952893 0.874188
-vt 0.953582 0.875247
-vt 0.953582 0.886243
-vt 0.917637 0.886242
-vt 0.953582 0.884920
-vt 0.917637 0.884919
-vt 0.897742 0.817179
-vt 0.842083 0.832031
-vt 0.835347 0.808727
-vt 0.842998 0.803894
-vt 0.842194 0.831691
-vt 0.880142 0.841098
-vt 0.835113 0.855751
-vt 0.952893 0.883860
-vt 0.917637 0.876570
-vt 0.830731 0.769044
-vt 0.852058 0.803750
-vt 0.835058 0.808516
-vt 0.852169 0.803410
-vt 0.887696 0.817293
-vt 0.806054 0.847763
-vt 0.814622 0.841758
-vt 0.888895 0.846984
-vt 0.862304 0.818081
-vt 0.805357 0.788458
-vt 0.815102 0.841390
-vt 0.956743 0.887302
-vt 0.956743 0.893532
-vt 0.851358 0.831917
-vt 0.862760 0.769044
-vt 0.954157 0.887302
-vt 0.915739 0.893532
-vt 0.859312 0.779106
-vt 0.806556 0.818148
-vt 0.834631 0.826337
-vt 0.859194 0.826925
-vt 0.859332 0.809314
-vt 0.859013 0.809527
-vt 0.832305 0.817361
-vt 0.832688 0.817376
-vt 0.847126 0.817721
-vt 0.859139 0.779690
-vt 0.834450 0.780024
-vt 0.834248 0.779451
-vt 0.807163 0.818133
-vt 0.863522 0.866397
-vt 0.952893 0.893532
-vt 0.917062 0.887302
-vt 0.918325 0.887302
-vt 0.918325 0.893532
-vt 0.917062 0.893532
-vt 0.952893 0.887302
-vt 0.955480 0.887302
-vt 0.879643 0.840753
-vt 0.888198 0.787678
-vt 0.861564 0.818065
-vt 0.842784 0.803184
-vt 0.851254 0.831547
-vt 0.858604 0.826476
-vn -0.838651 0.000004 -0.544669
-vn -0.838651 0.000004 -0.544669
-vn -0.838651 0.000004 -0.544669
-vn -0.838651 0.000004 -0.544669
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.838651 0.000004 0.544669
-vn 0.838651 0.000004 0.544669
-vn 0.838651 0.000004 0.544669
-vn 0.838651 0.000004 0.544669
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.838651 -0.000004 -0.544669
-vn 0.838651 -0.000004 -0.544669
-vn 0.838651 -0.000004 -0.544669
-vn 0.838651 -0.000004 -0.544669
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn -0.838651 -0.000004 0.544669
-vn -0.838651 -0.000004 0.544669
-vn -0.838651 -0.000004 0.544669
-vn -0.838651 -0.000004 0.544669
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn 0.619120 0.643718 -0.449797
-vn 0.236462 0.643710 -0.727821
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.619120 0.643718 0.449797
-vn -0.236462 0.643710 0.727821
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.236462 0.643710 -0.727821
-vn -0.236462 0.643710 -0.727821
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.765269 0.643711 0.000000
-vn 0.619120 0.643718 -0.449797
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.236462 0.643710 -0.727821
-vn -0.619120 0.643718 -0.449797
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.236462 0.643710 0.727821
-vn 0.236462 0.643710 0.727821
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.236462 0.643710 0.727821
-vn 0.619120 0.643718 0.449797
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.619120 0.643718 0.449797
-vn 0.765269 0.643711 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.765269 0.643711 0.000000
-vn -0.619120 0.643718 0.449797
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.619120 0.643718 -0.449797
-vn -0.765269 0.643711 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.309004 -0.000000 0.951061
-vn -0.309004 -0.000000 0.951061
-vn 0.191936 0.783706 0.590733
-vn -0.191936 0.783706 0.590733
-vn 0.809030 0.000000 -0.587767
-vn 1.000000 0.000000 0.000000
-vn 0.502506 0.783714 -0.365076
-vn 0.621130 0.783707 0.000000
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 0.000000 -0.587767
-vn 0.191936 0.783706 -0.590733
-vn 0.502506 0.783714 -0.365076
-vn -0.309004 -0.000000 0.951061
-vn -0.809030 -0.000000 0.587767
-vn -0.191936 0.783706 0.590733
-vn -0.502506 0.783714 0.365076
-vn -0.809030 -0.000000 0.587767
-vn -1.000000 0.000000 0.000000
-vn -0.502506 0.783714 0.365076
-vn -0.621130 0.783707 0.000000
-vn -1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -0.621130 0.783707 0.000000
-vn -0.502506 0.783714 -0.365076
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn -0.502506 0.783714 -0.365076
-vn -0.191936 0.783706 -0.590733
-vn 1.000000 0.000000 0.000000
-vn 0.809030 -0.000000 0.587767
-vn 0.621130 0.783707 0.000000
-vn 0.502506 0.783714 0.365076
-vn 0.809030 -0.000000 0.587767
-vn 0.309004 -0.000000 0.951061
-vn 0.502506 0.783714 0.365076
-vn 0.191936 0.783706 0.590733
-vn -0.309004 0.000000 -0.951061
-vn 0.309004 0.000000 -0.951061
-vn -0.191936 0.783706 -0.590733
-vn 0.191936 0.783706 -0.590733
-vn 0.621130 0.783707 0.000000
-vn 0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.502506 0.783714 0.365076
-vn 0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 -0.590733
-vn 0.191936 0.783706 -0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.191936 0.783706 0.590733
-vn -0.191936 0.783706 0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.502506 0.783714 -0.365076
-vn 0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.191936 0.783706 -0.590733
-vn 0.502506 0.783714 -0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 0.590733
-vn -0.502506 0.783714 0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 0.365076
-vn -0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.621130 0.783707 0.000000
-vn -0.502506 0.783714 -0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 -0.365076
-vn -0.191936 0.783706 -0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.236462 0.643710 -0.727821
-vn 0.236462 0.643710 -0.727821
-vn -0.309004 0.000000 -0.951061
-vn 0.309004 0.000000 -0.951061
-vn 0.619120 0.643718 0.449797
-vn 0.236462 0.643710 0.727821
-vn 0.809030 -0.000000 0.587767
-vn 0.309004 -0.000000 0.951061
-vn 0.765269 0.643711 0.000000
-vn 0.619120 0.643718 0.449797
-vn 1.000000 0.000000 0.000000
-vn 0.809030 -0.000000 0.587767
-vn -0.619120 0.643718 -0.449797
-vn -0.236462 0.643710 -0.727821
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn -0.765269 0.643711 0.000000
-vn -0.619120 0.643718 -0.449797
-vn -1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -0.619120 0.643718 0.449797
-vn -0.765269 0.643711 0.000000
-vn -0.809030 -0.000000 0.587767
-vn -1.000000 0.000000 0.000000
-vn -0.236462 0.643710 0.727821
-vn -0.619120 0.643718 0.449797
-vn -0.309004 -0.000000 0.951061
-vn -0.809030 -0.000000 0.587767
-vn 0.236462 0.643710 -0.727821
-vn 0.619120 0.643718 -0.449797
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 0.000000 -0.587767
-vn 0.619120 0.643718 -0.449797
-vn 0.765269 0.643711 0.000000
-vn 0.809030 0.000000 -0.587767
-vn 1.000000 0.000000 0.000000
-vn 0.236462 0.643710 0.727821
-vn -0.236462 0.643710 0.727821
-vn 0.309004 -0.000000 0.951061
-vn -0.309004 -0.000000 0.951061
-vn -0.309004 0.000000 -0.951061
-vn 0.309004 0.000000 -0.951061
-vn -0.309004 0.000000 -0.951061
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 -0.000000 0.587767
-vn 0.309004 -0.000000 0.951061
-vn 0.809030 -0.000000 0.587767
-vn 0.309004 -0.000000 0.951061
-vn 1.000000 0.000000 0.000000
-vn 0.809030 -0.000000 0.587767
-vn 1.000000 0.000000 0.000000
-vn 0.809030 -0.000000 0.587767
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn -1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -0.809030 -0.000000 0.587767
-vn -1.000000 0.000000 0.000000
-vn -0.809030 -0.000000 0.587767
-vn -1.000000 0.000000 0.000000
-vn -0.309004 -0.000000 0.951061
-vn -0.809030 -0.000000 0.587767
-vn -0.309004 -0.000000 0.951061
-vn -0.809030 -0.000000 0.587767
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 0.000000 -0.587767
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 0.000000 -0.587767
-vn 0.809030 0.000000 -0.587767
-vn 1.000000 0.000000 0.000000
-vn 0.809030 0.000000 -0.587767
-vn 1.000000 0.000000 0.000000
-vn 0.309004 -0.000000 0.951061
-vn -0.309004 -0.000000 0.951061
-vn 0.309004 -0.000000 0.951061
-vn -0.309004 -0.000000 0.951061
-f 10/80/1 4/81/2 11/83/3
-f 11/83/3 4/81/2 3/82/4
-f 4/81/5 8/84/6 3/82/7
-f 3/82/7 8/84/6 7/79/8
-f 14/85/9 6/59/10 15/31/11
-f 15/31/11 6/59/10 5/60/12
-f 6/46/13 2/5/14 5/21/15
-f 5/21/15 2/5/14 1/20/16
-f 11/22/17 3/32/18 16/34/19
-f 16/34/19 3/32/18 7/33/20
-f 13/35/21 8/84/22 10/36/23
-f 10/36/23 8/84/22 4/81/24
-f 6/46/25 14/37/26 2/5/27
-f 2/5/27 14/37/26 9/38/28
-f 14/37/29 13/35/30 9/38/31
-f 9/38/31 13/35/30 10/36/32
-f 1/20/33 12/47/34 5/21/35
-f 5/21/35 12/47/34 15/24/36
-f 12/47/37 11/22/38 15/24/39
-f 15/24/39 11/22/38 16/34/40
-f 8/84/41 13/63/42 7/79/43
-f 7/79/43 13/63/42 16/25/44
-f 13/63/45 14/85/46 16/25/47
-f 16/25/47 14/85/46 15/31/48
-f 2/26/49 9/27/50 1/6/51
-f 1/6/51 9/27/50 12/64/52
-f 9/27/53 10/80/54 12/64/55
-f 12/64/55 10/80/54 11/83/56
-f 19/12/57 25/61/58 29/91/59
-f 29/91/59 25/61/58 35/90/60
-f 24/41/61 22/1/62 34/2/63
-f 34/2/63 22/1/62 32/42/64
-f 25/61/65 20/43/66 35/90/67
-f 35/90/67 20/43/66 30/3/68
-f 17/11/69 19/12/70 27/88/71
-f 27/88/71 19/12/70 29/91/72
-f 20/43/73 26/9/74 30/3/75
-f 30/3/75 26/9/74 36/10/76
-f 22/1/77 23/49/78 32/42/79
-f 32/42/79 23/49/78 33/7/80
-f 23/49/81 18/69/82 33/7/83
-f 33/7/83 18/69/82 28/70/84
-f 18/69/85 17/11/86 28/70/87
-f 28/70/87 17/11/86 27/88/88
-f 21/71/89 24/41/90 31/72/91
-f 31/72/91 24/41/90 34/2/92
-f 26/9/93 21/71/94 36/10/95
-f 36/10/95 21/71/94 31/72/96
-f 33/7/97 28/70/98 37/73/99
-f 35/90/100 30/3/101 37/73/102
-f 32/42/103 33/7/104 37/73/105
-f 27/88/106 29/91/107 37/73/108
-f 29/91/109 35/90/110 37/73/111
-f 34/2/112 32/42/113 37/73/114
-f 31/72/115 34/2/116 37/73/117
-f 36/10/118 31/72/119 37/73/120
-f 30/3/121 36/10/122 37/73/123
-f 28/70/124 27/88/125 37/73/126
-f 76/74/127 69/75/128 45/65/129
-f 45/65/129 69/75/128 44/76/130
-f 77/86/131 70/4/132 41/44/133
-f 41/44/133 70/4/132 39/52/134
-f 78/19/135 77/86/136 47/23/137
-f 47/23/137 77/86/136 41/44/138
-f 69/75/139 71/17/140 44/76/141
-f 44/76/141 71/17/140 46/30/142
-f 71/17/143 72/77/144 46/30/145
-f 46/30/145 72/77/144 43/66/146
-f 72/77/147 73/58/148 43/66/149
-f 43/66/149 73/58/148 48/54/150
-f 73/58/151 74/45/152 48/54/153
-f 48/54/153 74/45/152 42/14/154
-f 70/4/155 75/16/156 39/52/157
-f 39/52/157 75/16/156 40/18/158
-f 75/16/159 76/74/160 40/18/161
-f 40/18/161 76/74/160 45/65/162
-f 74/45/163 78/19/164 42/14/165
-f 42/14/165 78/19/164 47/23/166
-f 39/52/167 40/18/168 49/39/169
-f 49/39/169 40/18/168 50/87/170
-f 40/18/171 45/65/172 50/87/173
-f 50/87/173 45/65/172 55/62/174
-f 42/14/175 47/23/176 52/28/177
-f 52/28/177 47/23/176 57/78/178
-f 45/65/179 44/76/180 55/62/181
-f 55/62/181 44/76/180 54/48/182
-f 41/44/183 39/52/184 51/55/185
-f 51/55/185 39/52/184 49/39/186
-f 47/23/187 41/44/188 57/78/189
-f 57/78/189 41/44/188 51/55/190
-f 44/76/191 46/30/192 54/48/193
-f 54/48/193 46/30/192 56/57/194
-f 46/30/195 43/66/196 56/57/197
-f 56/57/197 43/66/196 53/13/198
-f 43/66/199 48/54/200 53/13/201
-f 53/13/201 48/54/200 58/53/202
-f 48/54/203 42/14/204 58/53/205
-f 58/53/205 42/14/204 52/28/206
-f 20/43/207 25/61/208 67/40/209
-f 67/40/209 25/61/208 63/15/210
-f 18/69/211 23/49/212 68/29/213
-f 68/29/213 23/49/212 60/51/214
-f 17/11/215 18/69/216 61/56/217
-f 61/56/217 18/69/216 68/29/218
-f 26/9/219 20/43/220 66/67/221
-f 66/67/221 20/43/220 67/40/222
-f 21/71/223 26/9/224 65/8/225
-f 65/8/225 26/9/224 66/67/226
-f 24/41/227 21/71/228 64/50/229
-f 64/50/229 21/71/228 65/8/230
-f 22/1/231 24/41/232 59/89/233
-f 59/89/233 24/41/232 64/50/234
-f 25/61/235 19/12/236 63/15/237
-f 63/15/237 19/12/236 62/68/238
-f 19/12/239 17/11/240 62/68/241
-f 62/68/241 17/11/240 61/56/242
-f 23/49/243 22/1/244 60/51/245
-f 60/51/245 22/1/244 59/89/246
-f 67/40/247 63/15/248 74/45/249
-f 74/45/249 63/15/248 78/19/250
-f 68/29/251 60/51/252 75/16/253
-f 75/16/253 60/51/252 76/74/254
-f 61/56/255 68/29/256 70/4/257
-f 70/4/257 68/29/256 75/16/258
-f 66/67/259 67/40/260 73/58/261
-f 73/58/261 67/40/260 74/45/262
-f 65/8/263 66/67/264 72/77/265
-f 72/77/265 66/67/264 73/58/266
-f 64/50/267 65/8/268 71/17/269
-f 71/17/269 65/8/268 72/77/270
-f 59/89/271 64/50/272 69/75/273
-f 69/75/273 64/50/272 71/17/274
-f 63/15/275 62/68/276 78/19/277
-f 78/19/277 62/68/276 77/86/278
-f 62/68/279 61/56/280 77/86/281
-f 77/86/281 61/56/280 70/4/282
-f 60/51/283 59/89/284 76/74/285
-f 76/74/285 59/89/284 69/75/286
diff --git a/libs/vr/libdvrgraphics/assets/controller_proto2_button2.obj b/libs/vr/libdvrgraphics/assets/controller_proto2_button2.obj
deleted file mode 100644
index 2f3bd1e..0000000
--- a/libs/vr/libdvrgraphics/assets/controller_proto2_button2.obj
+++ /dev/null
@@ -1,794 +0,0 @@
-# This file uses centimeters as units for non-parametric coordinates.
-
-v 0.001731 0.013400 0.090823
-v -0.005601 0.013400 0.096150
-v 0.001731 0.013400 0.101477
-v -0.004531 0.013400 0.099442
-v 0.004531 0.013400 0.099442
-v 0.005601 0.013400 0.096150
-v -0.001731 0.013400 0.101477
-v -0.001731 0.013400 0.090823
-v 0.004531 0.013400 0.092858
-v -0.004531 0.013400 0.092858
-v 0.001690 0.013400 0.090950
-v -0.005467 0.013400 0.096150
-v 0.001690 0.013400 0.101350
-v -0.004423 0.013400 0.099364
-v 0.004423 0.013400 0.099364
-v 0.005467 0.013400 0.096150
-v -0.001690 0.013400 0.101350
-v -0.001690 0.013400 0.090950
-v 0.004423 0.013400 0.092936
-v -0.004423 0.013400 0.092936
-v 0.000000 0.013400 0.096150
-v 0.001731 0.008414 0.090823
-v -0.005601 0.008414 0.096150
-v 0.001731 0.008414 0.101477
-v -0.004531 0.008414 0.099442
-v 0.004531 0.008414 0.099442
-v 0.005601 0.008414 0.096150
-v -0.001731 0.008414 0.101477
-v -0.001731 0.008414 0.090823
-v 0.004531 0.008414 0.092858
-v -0.004531 0.008414 0.092858
-v 0.002212 0.008414 0.089341
-v -0.007159 0.008414 0.096150
-v 0.002212 0.008414 0.102959
-v -0.005792 0.008414 0.100358
-v 0.005792 0.008414 0.100358
-v 0.007159 0.008414 0.096150
-v -0.002212 0.008414 0.102959
-v -0.002212 0.008414 0.089341
-v 0.005792 0.008414 0.091942
-v -0.005792 0.008414 0.091942
-v -0.001731 0.013209 0.101477
-v 0.001731 0.013209 0.101477
-v -0.004531 0.013209 0.099442
-v -0.005601 0.013209 0.096150
-v -0.004531 0.013209 0.092858
-v 0.004531 0.013209 0.092858
-v 0.005601 0.013209 0.096150
-v 0.004531 0.013209 0.099442
-v -0.001731 0.013209 0.090823
-v 0.001731 0.013209 0.090823
-v 0.001731 0.008535 0.101477
-v -0.005601 0.008535 0.096150
-v 0.004531 0.008535 0.099442
-v 0.001731 0.008535 0.090823
-v -0.001731 0.008535 0.101477
-v -0.004531 0.008535 0.099442
-v -0.004531 0.008535 0.092858
-v 0.004531 0.008535 0.092858
-v 0.005601 0.008535 0.096150
-v -0.001731 0.008535 0.090823
-v 0.001108 0.013694 0.092741
-v -0.003585 0.013694 0.096150
-v 0.001108 0.013694 0.099560
-v -0.002900 0.013694 0.098257
-v 0.002900 0.013694 0.098257
-v 0.003585 0.013694 0.096150
-v -0.001108 0.013694 0.099560
-v -0.001108 0.013694 0.092741
-v 0.002900 0.013694 0.094043
-v -0.002900 0.013694 0.094043
-v 0.000955 0.013694 0.093211
-v -0.003090 0.013694 0.096150
-v 0.000955 0.013694 0.099090
-v -0.002500 0.013694 0.097967
-v 0.002500 0.013694 0.097967
-v 0.003090 0.013694 0.096150
-v -0.000955 0.013694 0.099090
-v -0.000955 0.013694 0.093211
-v 0.002500 0.013694 0.094334
-v -0.002500 0.013694 0.094334
-v 0.001108 0.012417 0.092741
-v -0.003585 0.012417 0.096150
-v 0.001108 0.012417 0.099560
-v -0.002900 0.012417 0.098257
-v 0.002900 0.012417 0.098257
-v 0.003585 0.012417 0.096150
-v -0.001108 0.012417 0.099560
-v -0.001108 0.012417 0.092741
-v 0.002900 0.012417 0.094043
-v -0.002900 0.012417 0.094043
-v 0.000955 0.012417 0.093211
-v -0.003090 0.012417 0.096150
-v 0.000955 0.012417 0.099090
-v -0.002500 0.012417 0.097967
-v 0.002500 0.012417 0.097967
-v 0.003090 0.012417 0.096150
-v -0.000955 0.012417 0.099090
-v -0.000955 0.012417 0.093211
-v 0.002500 0.012417 0.094334
-v -0.002500 0.012417 0.094334
-vt 0.932232 0.937151
-vt 0.945647 0.941314
-vt 0.825593 0.923815
-vt 0.788802 0.909064
-vt 0.935598 0.930484
-vt 0.909311 0.932196
-vt 0.907009 0.929014
-vt 0.922229 0.927744
-vt 0.923371 0.959651
-vt 0.926270 0.980012
-vt 0.923981 0.964843
-vt 0.907571 0.956084
-vt 0.910064 0.946637
-vt 0.932187 0.961332
-vt 0.913791 0.964746
-vt 0.931115 0.938999
-vt 0.906593 0.976987
-vt 0.814667 0.938118
-vt 0.907941 0.945842
-vt 0.817792 0.929265
-vt 0.924220 0.967204
-vt 0.899768 0.959058
-vt 0.834177 0.952426
-vt 0.841570 0.947355
-vt 0.817336 0.900595
-vt 0.797907 0.915598
-vt 0.841862 0.947586
-vt 0.797489 0.962416
-vt 0.863053 0.962016
-vt 0.842840 0.976907
-vt 0.845500 0.938935
-vt 0.900358 0.943670
-vt 0.896353 0.942255
-vt 0.950018 0.956861
-vt 0.914874 0.948129
-vt 0.914648 0.953699
-vt 0.937578 0.926986
-vt 0.925672 0.975465
-vt 0.931991 0.947345
-vt 0.825215 0.952174
-vt 0.842325 0.930150
-vt 0.842016 0.930356
-vt 0.834916 0.924929
-vt 0.844928 0.938934
-vt 0.844556 0.938918
-vt 0.830059 0.938555
-vt 0.790654 0.938738
-vt 0.933703 0.963036
-vt 0.936911 0.954039
-vt 0.813826 0.890060
-vt 0.797202 0.915105
-vt 0.861850 0.915045
-vt 0.817977 0.976306
-vt 0.798179 0.961897
-vt 0.789797 0.938756
-vt 0.842554 0.976087
-vt 0.841940 0.901082
-vt 0.845641 0.890060
-vt 0.950018 0.939483
-vt 0.932035 0.952826
-vt 0.835221 0.924030
-vt 0.909829 0.955422
-vt 0.895358 0.960445
-vt 0.915261 0.939767
-vt 0.923140 0.936945
-vt 0.936417 0.945527
-vt 0.938885 0.954567
-vt 0.909516 0.972375
-vt 0.817813 0.946906
-vt 0.818124 0.946700
-vt 0.917914 0.958206
-vt 0.923549 0.941808
-vt 0.928754 0.943094
-vt 0.846431 0.987663
-vt 0.870407 0.938130
-vt 0.817616 0.901404
-vt 0.842181 0.900257
-vt 0.862534 0.914520
-vt 0.869546 0.938152
-vt 0.834277 0.952786
-vt 0.862338 0.961524
-vt 0.923050 0.934996
-vt 0.915227 0.962597
-vt 0.946468 0.956010
-vt 0.928741 0.957476
-vt 0.922006 0.924371
-vt 0.939379 0.968571
-vt 0.918286 0.943618
-vt 0.942241 0.971610
-vt 0.814114 0.987501
-vt 0.788568 0.968560
-vt 0.779102 0.938526
-vt 0.870794 0.908363
-vt 0.881150 0.937707
-vt 0.834453 0.953332
-vt 0.824904 0.953069
-vt 0.842788 0.929814
-vt 0.842325 0.947924
-vt 0.817349 0.947240
-vt 0.835045 0.924577
-vt 0.825883 0.924738
-vt 0.815235 0.938118
-vt 0.818251 0.929599
-vt 0.818529 0.929812
-vt 0.815603 0.938133
-vt 0.825771 0.924361
-vt 0.825084 0.952524
-vt 0.938637 0.944674
-vt 0.914016 0.937979
-vt 0.872150 0.968124
-vt 0.817725 0.977137
-vn -0.765269 0.643711 0.000000
-vn -0.619128 0.643727 0.449773
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.619128 0.643727 0.449773
-vn -0.236496 0.643720 0.727801
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.236462 0.643710 -0.727821
-vn -0.619120 0.643718 -0.449797
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.619120 0.643718 -0.449797
-vn 0.236462 0.643710 -0.727821
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.236496 0.643720 0.727801
-vn 0.619128 0.643727 0.449773
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.236462 0.643710 -0.727821
-vn -0.236462 0.643710 -0.727821
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.619128 0.643727 0.449773
-vn 0.765269 0.643711 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.236496 0.643720 0.727801
-vn 0.236496 0.643720 0.727801
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.619120 0.643718 -0.449797
-vn -0.765269 0.643711 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.765269 0.643711 0.000000
-vn 0.619120 0.643718 -0.449797
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -0.621130 0.783707 0.000000
-vn -0.502506 0.783714 -0.365076
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 0.000000 -0.587767
-vn 0.191936 0.783706 -0.590733
-vn 0.502506 0.783714 -0.365076
-vn 0.309041 -0.000000 0.951049
-vn -0.309041 -0.000000 0.951049
-vn 0.191935 0.783732 0.590698
-vn -0.191935 0.783732 0.590698
-vn -0.309041 -0.000000 0.951049
-vn -0.809045 -0.000000 0.587747
-vn -0.191935 0.783732 0.590698
-vn -0.502529 0.783702 0.365070
-vn 0.809045 -0.000000 0.587747
-vn 0.309041 -0.000000 0.951049
-vn 0.502529 0.783702 0.365070
-vn 0.191935 0.783732 0.590698
-vn -0.809045 -0.000000 0.587747
-vn -1.000000 0.000000 0.000000
-vn -0.502529 0.783702 0.365070
-vn -0.621130 0.783707 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn -0.502506 0.783714 -0.365076
-vn -0.191936 0.783706 -0.590733
-vn 0.809030 0.000000 -0.587767
-vn 1.000000 0.000000 0.000000
-vn 0.502506 0.783714 -0.365076
-vn 0.621130 0.783707 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.809045 -0.000000 0.587747
-vn 0.621130 0.783707 0.000000
-vn 0.502529 0.783702 0.365070
-vn -0.309004 0.000000 -0.951061
-vn 0.309004 0.000000 -0.951061
-vn -0.191936 0.783706 -0.590733
-vn 0.191936 0.783706 -0.590733
-vn 0.191936 0.783706 -0.590733
-vn 0.502506 0.783714 -0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.191935 0.783732 0.590698
-vn -0.191935 0.783732 0.590698
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.191935 0.783732 0.590698
-vn -0.502529 0.783702 0.365070
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.502506 0.783714 -0.365076
-vn -0.191936 0.783706 -0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.502529 0.783702 0.365070
-vn -0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.502529 0.783702 0.365070
-vn 0.191935 0.783732 0.590698
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.191936 0.783706 -0.590733
-vn 0.191936 0.783706 -0.590733
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.621130 0.783707 0.000000
-vn 0.502529 0.783702 0.365070
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.502506 0.783714 -0.365076
-vn 0.621130 0.783707 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.621130 0.783707 0.000000
-vn -0.502506 0.783714 -0.365076
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.236462 0.643710 -0.727821
-vn 0.236462 0.643710 -0.727821
-vn -0.309004 0.000000 -0.951061
-vn 0.309004 0.000000 -0.951061
-vn 0.765269 0.643711 0.000000
-vn 0.619128 0.643727 0.449773
-vn 1.000000 0.000000 0.000000
-vn 0.809045 -0.000000 0.587747
-vn 0.619120 0.643718 -0.449797
-vn 0.765269 0.643711 0.000000
-vn 0.809030 0.000000 -0.587767
-vn 1.000000 0.000000 0.000000
-vn -0.619120 0.643718 -0.449797
-vn -0.236462 0.643710 -0.727821
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn -0.619128 0.643727 0.449773
-vn -0.765269 0.643711 0.000000
-vn -0.809045 -0.000000 0.587747
-vn -1.000000 0.000000 0.000000
-vn 0.619128 0.643727 0.449773
-vn 0.236496 0.643720 0.727801
-vn 0.809045 -0.000000 0.587747
-vn 0.309041 -0.000000 0.951049
-vn -0.236496 0.643720 0.727801
-vn -0.619128 0.643727 0.449773
-vn -0.309041 -0.000000 0.951049
-vn -0.809045 -0.000000 0.587747
-vn 0.236496 0.643720 0.727801
-vn -0.236496 0.643720 0.727801
-vn 0.309041 -0.000000 0.951049
-vn -0.309041 -0.000000 0.951049
-vn 0.236462 0.643710 -0.727821
-vn 0.619120 0.643718 -0.449797
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 0.000000 -0.587767
-vn -0.765269 0.643711 0.000000
-vn -0.619120 0.643718 -0.449797
-vn -1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn 0.309004 0.000000 -0.951061
-vn -0.309004 0.000000 -0.951061
-vn 0.309004 0.000000 -0.951061
-vn 1.000000 0.000000 0.000000
-vn 0.809045 -0.000000 0.587747
-vn 1.000000 0.000000 0.000000
-vn 0.809045 -0.000000 0.587747
-vn 0.809030 0.000000 -0.587767
-vn 1.000000 0.000000 0.000000
-vn 0.809030 0.000000 -0.587767
-vn 1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn -0.809030 0.000000 -0.587767
-vn -0.309004 0.000000 -0.951061
-vn -0.809045 -0.000000 0.587747
-vn -1.000000 0.000000 0.000000
-vn -0.809045 -0.000000 0.587747
-vn -1.000000 0.000000 0.000000
-vn 0.809045 -0.000000 0.587747
-vn 0.309041 -0.000000 0.951049
-vn 0.809045 -0.000000 0.587747
-vn 0.309041 -0.000000 0.951049
-vn -0.309041 -0.000000 0.951049
-vn -0.809045 -0.000000 0.587747
-vn -0.309041 -0.000000 0.951049
-vn -0.809045 -0.000000 0.587747
-vn 0.309041 -0.000000 0.951049
-vn -0.309041 -0.000000 0.951049
-vn 0.309041 -0.000000 0.951049
-vn -0.309041 -0.000000 0.951049
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 0.000000 -0.587767
-vn 0.309004 0.000000 -0.951061
-vn 0.809030 0.000000 -0.587767
-vn -1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn -1.000000 0.000000 0.000000
-vn -0.809030 0.000000 -0.587767
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.000000 1.000000 0.000000
-vn -0.000000 1.000000 0.000000
-vn -0.000000 1.000000 0.000000
-vn -0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.000000 1.000000 0.000000
-vn -0.000000 1.000000 0.000000
-vn -0.000000 1.000000 0.000000
-vn -0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn -0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.587858 0.000000 -0.808964
-vn 0.587858 0.000000 -0.808964
-vn 0.587858 0.000000 -0.808964
-vn 0.587858 0.000000 -0.808964
-vn 0.951057 -0.000000 0.309014
-vn 0.951057 -0.000000 0.309014
-vn 0.951057 -0.000000 0.309014
-vn 0.951057 -0.000000 0.309014
-vn -0.587858 0.000000 -0.808964
-vn -0.587858 0.000000 -0.808964
-vn -0.587858 0.000000 -0.808964
-vn -0.587858 0.000000 -0.808964
-vn 0.951058 0.000000 -0.309013
-vn 0.951058 0.000000 -0.309013
-vn 0.951058 0.000000 -0.309013
-vn 0.951058 0.000000 -0.309013
-vn -0.587785 0.000000 -0.809017
-vn -0.587785 0.000000 -0.809017
-vn -0.587785 0.000000 -0.809017
-vn -0.587785 0.000000 -0.809017
-vn 0.951057 0.000000 -0.309014
-vn 0.951057 0.000000 -0.309014
-vn 0.951057 0.000000 -0.309014
-vn 0.951057 0.000000 -0.309014
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn -0.951057 0.000000 -0.309014
-vn -0.951057 0.000000 -0.309014
-vn -0.951057 0.000000 -0.309014
-vn -0.951057 0.000000 -0.309014
-vn 0.587785 0.000000 -0.809017
-vn 0.587785 0.000000 -0.809017
-vn 0.587785 0.000000 -0.809017
-vn 0.587785 0.000000 -0.809017
-vn -0.951058 0.000000 -0.309013
-vn -0.951058 0.000000 -0.309013
-vn -0.951058 0.000000 -0.309013
-vn -0.951058 0.000000 -0.309013
-vn -0.951058 -0.000000 0.309012
-vn -0.951058 -0.000000 0.309012
-vn -0.951058 -0.000000 0.309012
-vn -0.951058 -0.000000 0.309012
-vn 0.587785 -0.000000 0.809018
-vn 0.587785 -0.000000 0.809018
-vn 0.587785 -0.000000 0.809018
-vn 0.587785 -0.000000 0.809018
-vn -0.587857 -0.000000 0.808965
-vn -0.587857 -0.000000 0.808965
-vn -0.587857 -0.000000 0.808965
-vn -0.587857 -0.000000 0.808965
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 0.000000 -1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.000000 -0.000000 1.000000
-vn 0.587857 -0.000000 0.808965
-vn 0.587857 -0.000000 0.808965
-vn 0.587857 -0.000000 0.808965
-vn 0.587857 -0.000000 0.808965
-vn -0.587785 -0.000000 0.809018
-vn -0.587785 -0.000000 0.809018
-vn -0.587785 -0.000000 0.809018
-vn -0.587785 -0.000000 0.809018
-vn 0.951058 -0.000000 0.309012
-vn 0.951058 -0.000000 0.309012
-vn 0.951058 -0.000000 0.309012
-vn 0.951058 -0.000000 0.309012
-vn -0.951057 -0.000000 0.309014
-vn -0.951057 -0.000000 0.309014
-vn -0.951057 -0.000000 0.309014
-vn -0.951057 -0.000000 0.309014
-f 2/102/1 4/103/2 12/105/3
-f 12/105/3 4/103/2 14/104/4
-f 4/103/5 7/106/6 14/104/7
-f 14/104/7 7/106/6 17/101/8
-f 8/107/9 10/69/10 18/40/11
-f 18/40/11 10/69/10 20/70/12
-f 9/27/13 1/80/14 19/24/15
-f 19/24/15 1/80/14 11/23/16
-f 3/100/17 5/41/18 13/43/19
-f 13/43/19 5/41/18 15/42/20
-f 1/80/21 8/107/22 11/23/23
-f 11/23/23 8/107/22 18/40/24
-f 5/41/25 6/44/26 15/42/27
-f 15/42/27 6/44/26 16/45/28
-f 7/106/29 3/100/30 17/101/31
-f 17/101/31 3/100/30 13/43/32
-f 10/69/33 2/102/34 20/70/35
-f 20/70/35 2/102/34 12/105/36
-f 6/44/37 9/27/38 16/45/39
-f 16/45/39 9/27/38 19/24/40
-f 12/105/41 14/104/42 21/46/43
-f 18/40/44 20/70/45 21/46/46
-f 14/104/47 17/101/48 21/46/49
-f 13/43/50 15/42/51 21/46/52
-f 15/42/53 16/45/54 21/46/55
-f 17/101/56 13/43/57 21/46/58
-f 16/45/59 19/24/60 21/46/61
-f 19/24/62 11/23/63 21/46/64
-f 11/23/65 18/40/66 21/46/67
-f 20/70/68 12/105/69 21/46/70
-f 53/47/71 58/54/72 23/55/73
-f 23/55/73 58/54/72 31/28/74
-f 55/56/75 59/81/76 22/30/77
-f 22/30/77 59/81/76 30/29/78
-f 52/57/79 56/76/80 24/77/81
-f 24/77/81 56/76/80 28/25/82
-f 56/76/83 57/26/84 28/25/85
-f 28/25/85 57/26/84 25/51/86
-f 54/52/87 52/57/88 26/78/89
-f 26/78/89 52/57/88 24/77/90
-f 57/26/91 53/47/92 25/51/93
-f 25/51/93 53/47/92 23/55/94
-f 58/54/95 61/53/96 31/28/97
-f 31/28/97 61/53/96 29/111/98
-f 59/81/99 60/79/100 30/29/101
-f 30/29/101 60/79/100 27/75/102
-f 60/79/103 54/52/104 27/75/105
-f 27/75/105 54/52/104 26/78/106
-f 61/53/107 55/56/108 29/111/109
-f 29/111/109 55/56/108 22/30/110
-f 22/30/111 30/29/112 32/74/113
-f 32/74/113 30/29/112 40/110/114
-f 24/77/115 28/25/116 34/58/117
-f 34/58/117 28/25/116 38/50/118
-f 28/25/119 25/51/120 38/50/121
-f 38/50/121 25/51/120 35/4/122
-f 31/28/123 29/111/124 41/91/125
-f 41/91/125 29/111/124 39/90/126
-f 25/51/127 23/55/128 35/4/129
-f 35/4/129 23/55/128 33/92/130
-f 26/78/131 24/77/132 36/93/133
-f 36/93/133 24/77/132 34/58/134
-f 29/111/135 22/30/136 39/90/137
-f 39/90/137 22/30/136 32/74/138
-f 27/75/139 26/78/140 37/94/141
-f 37/94/141 26/78/140 36/93/142
-f 30/29/143 27/75/144 40/110/145
-f 40/110/145 27/75/144 37/94/146
-f 23/55/147 31/28/148 33/92/149
-f 33/92/149 31/28/148 41/91/150
-f 8/107/151 1/80/152 50/96/153
-f 50/96/153 1/80/152 51/95/154
-f 6/44/155 5/41/156 48/31/157
-f 48/31/157 5/41/156 49/97/158
-f 9/27/159 6/44/160 47/98/161
-f 47/98/161 6/44/160 48/31/162
-f 10/69/163 8/107/164 46/99/165
-f 46/99/165 8/107/164 50/96/166
-f 4/103/167 2/102/168 44/20/169
-f 44/20/169 2/102/168 45/18/170
-f 5/41/171 3/100/172 49/97/173
-f 49/97/173 3/100/172 43/61/174
-f 7/106/175 4/103/176 42/3/177
-f 42/3/177 4/103/176 44/20/178
-f 3/100/179 7/106/180 43/61/181
-f 43/61/181 7/106/180 42/3/182
-f 1/80/183 9/27/184 51/95/185
-f 51/95/185 9/27/184 47/98/186
-f 2/102/187 10/69/188 45/18/189
-f 45/18/189 10/69/188 46/99/190
-f 50/96/191 51/95/192 61/53/193
-f 61/53/193 51/95/192 55/56/194
-f 48/31/195 49/97/196 60/79/197
-f 60/79/197 49/97/196 54/52/198
-f 47/98/199 48/31/200 59/81/201
-f 59/81/201 48/31/200 60/79/202
-f 46/99/203 50/96/204 58/54/205
-f 58/54/205 50/96/204 61/53/206
-f 44/20/207 45/18/208 57/26/209
-f 57/26/209 45/18/208 53/47/210
-f 49/97/211 43/61/212 54/52/213
-f 54/52/213 43/61/212 52/57/214
-f 42/3/215 44/20/216 56/76/217
-f 56/76/217 44/20/216 57/26/218
-f 43/61/219 42/3/220 52/57/221
-f 52/57/221 42/3/220 56/76/222
-f 51/95/223 47/98/224 55/56/225
-f 55/56/225 47/98/224 59/81/226
-f 45/18/227 46/99/228 53/47/229
-f 53/47/229 46/99/228 58/54/230
-f 62/15/231 69/12/232 72/83/233
-f 72/83/233 69/12/232 79/62/234
-f 64/108/235 74/66/236 68/1/237
-f 68/1/237 74/66/236 78/16/238
-f 63/109/239 65/82/240 73/64/241
-f 73/64/241 65/82/240 75/65/242
-f 63/109/243 73/64/244 71/19/245
-f 71/19/245 73/64/244 81/13/246
-f 62/15/247 72/83/248 70/21/249
-f 70/21/249 72/83/248 80/11/250
-f 66/67/251 67/48/252 76/49/253
-f 76/49/253 67/48/252 77/14/254
-f 65/82/255 68/1/256 75/65/257
-f 75/65/257 68/1/256 78/16/258
-f 69/12/259 71/19/260 79/62/261
-f 79/62/261 71/19/260 81/13/262
-f 67/48/263 70/21/264 77/14/265
-f 77/14/265 70/21/264 80/11/266
-f 64/108/267 66/67/268 74/66/269
-f 74/66/269 66/67/268 76/49/270
-f 82/68/271 92/17/272 89/22/273
-f 89/22/273 92/17/272 99/63/274
-f 84/2/275 88/5/276 94/59/277
-f 94/59/277 88/5/276 98/37/278
-f 83/6/279 93/7/280 85/8/281
-f 85/8/281 93/7/280 95/86/282
-f 83/6/283 91/32/284 93/7/285
-f 93/7/285 91/32/284 101/33/286
-f 82/68/287 90/38/288 92/17/289
-f 92/17/289 90/38/288 100/10/290
-f 86/84/291 96/34/292 87/87/293
-f 87/87/293 96/34/292 97/89/294
-f 85/8/295 95/86/296 88/5/297
-f 88/5/297 95/86/296 98/37/298
-f 89/22/299 99/63/300 91/32/301
-f 91/32/301 99/63/300 101/33/302
-f 87/87/303 97/89/304 90/38/305
-f 90/38/305 97/89/304 100/10/306
-f 84/2/307 94/59/308 86/84/309
-f 86/84/309 94/59/308 96/34/310
-f 75/65/311 78/16/312 95/72/313
-f 95/72/313 78/16/312 98/73/314
-f 67/48/315 66/67/316 87/87/317
-f 87/87/317 66/67/316 86/84/318
-f 74/66/319 76/49/320 94/39/321
-f 94/39/321 76/49/320 96/60/322
-f 70/21/323 67/48/324 90/38/325
-f 90/38/325 67/48/324 87/87/326
-f 71/19/327 69/12/328 91/32/329
-f 91/32/329 69/12/328 89/22/330
-f 73/64/331 75/65/332 93/88/333
-f 93/88/333 75/65/332 95/72/334
-f 64/108/335 68/1/336 84/2/337
-f 84/2/337 68/1/336 88/5/338
-f 69/12/339 62/15/340 89/22/341
-f 89/22/341 62/15/340 82/68/342
-f 76/49/343 77/14/344 96/60/345
-f 96/60/345 77/14/344 97/85/346
-f 62/15/347 70/21/348 82/68/349
-f 82/68/349 70/21/348 90/38/350
-f 63/109/351 71/19/352 83/6/353
-f 83/6/353 71/19/352 91/32/354
-f 77/14/355 80/11/356 97/85/357
-f 97/85/357 80/11/356 100/9/358
-f 79/62/359 81/13/360 99/36/361
-f 99/36/361 81/13/360 101/35/362
-f 68/1/363 65/82/364 88/5/365
-f 88/5/365 65/82/364 85/8/366
-f 78/16/367 74/66/368 98/73/369
-f 98/73/369 74/66/368 94/39/370
-f 72/83/371 79/62/372 92/71/373
-f 92/71/373 79/62/372 99/36/374
-f 66/67/375 64/108/376 86/84/377
-f 86/84/377 64/108/376 84/2/378
-f 80/11/379 72/83/380 100/9/381
-f 100/9/381 72/83/380 92/71/382
-f 81/13/383 73/64/384 101/35/385
-f 101/35/385 73/64/384 93/88/386
-f 65/82/387 63/109/388 85/8/389
-f 85/8/389 63/109/388 83/6/390
diff --git a/libs/vr/libdvrgraphics/assets/controller_proto2_joystick.obj b/libs/vr/libdvrgraphics/assets/controller_proto2_joystick.obj
deleted file mode 100644
index c4daae3..0000000
--- a/libs/vr/libdvrgraphics/assets/controller_proto2_joystick.obj
+++ /dev/null
@@ -1,556 +0,0 @@
-# This file uses centimeters as units for non-parametric coordinates.
-
-v 0.013683 0.008414 0.043000
-v 0.013683 0.013400 0.058800
-v 0.013683 0.008414 0.058800
-v 0.013683 0.013400 0.043000
-v -0.013683 0.013400 0.043000
-v -0.015800 0.013400 0.050900
-v 0.007900 0.013400 0.064583
-v 0.015800 0.013400 0.050900
-v -0.013683 0.013400 0.058800
-v -0.007900 0.013400 0.064583
-v -0.000000 0.013400 0.066700
-v 0.007900 0.013400 0.037217
-v 0.000000 0.013400 0.035100
-v -0.007900 0.013400 0.037217
-v 0.013247 0.013400 0.058548
-v 0.013247 0.013400 0.043252
-v -0.013247 0.013400 0.043252
-v -0.015297 0.013400 0.050900
-v 0.007648 0.013400 0.064148
-v 0.015297 0.013400 0.050900
-v -0.013247 0.013400 0.058548
-v -0.007648 0.013400 0.064148
-v -0.000000 0.013400 0.066197
-v 0.007648 0.013400 0.037652
-v 0.000000 0.013400 0.035603
-v -0.007648 0.013400 0.037652
-v 0.000000 0.013400 0.050900
-v -0.013683 0.008414 0.043000
-v -0.015800 0.008414 0.050900
-v 0.007900 0.008414 0.064583
-v 0.015800 0.008414 0.050900
-v -0.013683 0.008414 0.058800
-v -0.007900 0.008414 0.064583
-v -0.000000 0.008414 0.066700
-v 0.007900 0.008414 0.037217
-v 0.000000 0.008414 0.035100
-v -0.007900 0.008414 0.037217
-v 0.015123 0.008414 0.042169
-v 0.015123 0.008414 0.059631
-v -0.015123 0.008414 0.042169
-v -0.017462 0.008414 0.050900
-v 0.008731 0.008414 0.066023
-v 0.017462 0.008414 0.050900
-v -0.015123 0.008414 0.059631
-v -0.008731 0.008414 0.066023
-v -0.000000 0.008414 0.068362
-v 0.008731 0.008414 0.035777
-v 0.000000 0.008414 0.033438
-v -0.008731 0.008414 0.035777
-v -0.007900 0.013082 0.037217
-v 0.000000 0.013082 0.035100
-v 0.007900 0.013082 0.037217
-v -0.000000 0.013082 0.066700
-v -0.007900 0.013082 0.064583
-v -0.013683 0.013082 0.058800
-v 0.013683 0.013082 0.043000
-v 0.015800 0.013082 0.050900
-v 0.013683 0.013082 0.058800
-v 0.007900 0.013082 0.064583
-v -0.015800 0.013082 0.050900
-v -0.013683 0.013082 0.043000
-v -0.007900 0.008785 0.064583
-v 0.015800 0.008785 0.050900
-v 0.007900 0.008785 0.064583
-v -0.013683 0.008785 0.043000
-v -0.007900 0.008785 0.037217
-v 0.000000 0.008785 0.035100
-v 0.007900 0.008785 0.037217
-v -0.000000 0.008785 0.066700
-v -0.013683 0.008785 0.058800
-v 0.013683 0.008785 0.043000
-v 0.013683 0.008785 0.058800
-v -0.015800 0.008785 0.050900
-vt 0.598611 0.792613
-vt 0.581181 0.842714
-vt 0.572095 0.840361
-vt 0.583337 0.843249
-vt 0.583900 0.891691
-vt 0.740650 0.932332
-vt 0.764677 0.890275
-vt 0.764114 0.841833
-vt 0.623873 0.817102
-vt 0.649036 0.776482
-vt 0.607278 0.849202
-vt 0.609406 0.849762
-vt 0.609695 0.884296
-vt 0.626984 0.914208
-vt 0.624971 0.818153
-vt 0.626666 0.819833
-vt 0.740622 0.848600
-vt 0.740736 0.884322
-vt 0.738608 0.883762
-vt 0.738319 0.849228
-vt 0.742081 0.848175
-vt 0.605933 0.885349
-vt 0.698978 0.957041
-vt 0.724141 0.916422
-vt 0.650543 0.957262
-vt 0.691947 0.798514
-vt 0.742213 0.884683
-vt 0.697472 0.776262
-vt 0.657036 0.931225
-vt 0.691585 0.931208
-vt 0.625435 0.915771
-vt 0.747828 0.791704
-vt 0.766832 0.890810
-vt 0.766241 0.841221
-vt 0.775920 0.838541
-vt 0.775919 0.893164
-vt 0.741246 0.798397
-vt 0.607392 0.884924
-vt 0.739706 0.799996
-vt 0.723631 0.816655
-vt 0.655425 0.798733
-vt 0.650009 0.959409
-vt 0.647491 0.969131
-vt 0.648421 0.774349
-vt 0.700524 0.764393
-vt 0.674007 0.866762
-vt 0.699593 0.959175
-vt 0.742243 0.933868
-vt 0.749403 0.940910
-vt 0.702098 0.968221
-vt 0.581773 0.892303
-vt 0.606768 0.935127
-vt 0.600187 0.941819
-vt 0.572095 0.894983
-vt 0.698005 0.774114
-vt 0.607364 0.801191
-vt 0.692589 0.934791
-vt 0.656067 0.935009
-vt 0.608309 0.933528
-vt 0.605801 0.848841
-vt 0.624384 0.916869
-vt 0.692164 0.933331
-vt 0.656428 0.933533
-vt 0.655850 0.800192
-vt 0.691586 0.799991
-vt 0.690978 0.802299
-vt 0.656429 0.802316
-vt 0.723043 0.915371
-vt 0.721348 0.913691
-vt 0.722579 0.817753
-vt 0.721030 0.819316
-vt 0.645916 0.765302
-vt 0.605771 0.799655
-vn 0.552274 0.770272 0.318864
-vn 0.318864 0.770272 0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.318864 0.770272 0.552274
-vn 0.000000 0.770266 0.637723
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.378558 0.653230 -0.655732
-vn -0.655715 0.653243 -0.378566
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.655715 0.653243 -0.378566
-vn 0.378558 0.653230 -0.655732
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.378558 0.653230 -0.655732
-vn 0.000000 0.653236 -0.757154
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.653236 -0.757154
-vn -0.378558 0.653230 -0.655732
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.655715 0.653243 -0.378566
-vn -0.757167 0.653221 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.378558 0.653230 0.655732
-vn 0.655715 0.653243 0.378566
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.655715 0.653243 0.378566
-vn -0.378558 0.653230 0.655732
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.757167 0.653221 0.000000
-vn 0.655715 0.653243 -0.378566
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.653236 0.757154
-vn 0.378558 0.653230 0.655732
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.378558 0.653230 0.655732
-vn 0.000000 0.653236 0.757154
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.655715 0.653243 0.378566
-vn 0.757167 0.653221 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.757167 0.653221 0.000000
-vn -0.655715 0.653243 0.378566
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.552274 0.770272 -0.318864
-vn 0.637723 0.770266 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.318864 0.770272 -0.552274
-vn 0.000000 0.770266 -0.637723
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.770266 0.637723
-vn -0.318864 0.770272 0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.318864 0.770272 -0.552274
-vn 0.552274 0.770272 -0.318864
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.318864 0.770272 0.552274
-vn -0.552274 0.770272 0.318864
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.552274 0.770272 0.318864
-vn -0.637723 0.770266 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.552274 0.770272 -0.318864
-vn -0.318864 0.770272 -0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.637723 0.770266 0.000000
-vn 0.552274 0.770272 0.318864
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 0.000000 0.770266 -0.637723
-vn 0.318864 0.770272 -0.552274
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.637723 0.770266 0.000000
-vn -0.552274 0.770272 -0.318864
-vn 0.000000 1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn -0.866032 0.000000 -0.499989
-vn -0.499989 0.000000 -0.866032
-vn -0.552274 0.770272 -0.318864
-vn -0.318864 0.770272 -0.552274
-vn 1.000000 0.000000 0.000000
-vn 0.866032 -0.000000 0.499989
-vn 0.637723 0.770266 0.000000
-vn 0.552274 0.770272 0.318864
-vn 0.499989 -0.000000 0.866032
-vn 0.000000 -0.000000 1.000000
-vn 0.318864 0.770272 0.552274
-vn 0.000000 0.770266 0.637723
-vn -0.499989 0.000000 -0.866032
-vn 0.000000 0.000000 -1.000000
-vn -0.318864 0.770272 -0.552274
-vn 0.000000 0.770266 -0.637723
-vn 0.000000 0.000000 -1.000000
-vn 0.499989 0.000000 -0.866032
-vn 0.000000 0.770266 -0.637723
-vn 0.318864 0.770272 -0.552274
-vn 0.499989 0.000000 -0.866032
-vn 0.866032 0.000000 -0.499989
-vn 0.318864 0.770272 -0.552274
-vn 0.552274 0.770272 -0.318864
-vn -0.499989 -0.000000 0.866032
-vn -0.866032 -0.000000 0.499989
-vn -0.318864 0.770272 0.552274
-vn -0.552274 0.770272 0.318864
-vn 0.000000 -0.000000 1.000000
-vn -0.499989 -0.000000 0.866032
-vn 0.000000 0.770266 0.637723
-vn -0.318864 0.770272 0.552274
-vn -0.866032 -0.000000 0.499989
-vn -1.000000 0.000000 0.000000
-vn -0.552274 0.770272 0.318864
-vn -0.637723 0.770266 0.000000
-vn 0.866032 0.000000 -0.499989
-vn 1.000000 0.000000 0.000000
-vn 0.552274 0.770272 -0.318864
-vn 0.637723 0.770266 0.000000
-vn 0.866032 -0.000000 0.499989
-vn 0.499989 -0.000000 0.866032
-vn 0.552274 0.770272 0.318864
-vn 0.318864 0.770272 0.552274
-vn -1.000000 0.000000 0.000000
-vn -0.866032 0.000000 -0.499989
-vn -0.637723 0.770266 0.000000
-vn -0.552274 0.770272 -0.318864
-vn -0.757167 0.653221 0.000000
-vn -0.655715 0.653243 -0.378566
-vn -1.000000 0.000000 0.000000
-vn -0.866032 0.000000 -0.499989
-vn 0.655715 0.653243 0.378566
-vn 0.378558 0.653230 0.655732
-vn 0.866032 -0.000000 0.499989
-vn 0.499989 -0.000000 0.866032
-vn 0.655715 0.653243 -0.378566
-vn 0.757167 0.653221 0.000000
-vn 0.866032 0.000000 -0.499989
-vn 1.000000 0.000000 0.000000
-vn -0.655715 0.653243 0.378566
-vn -0.757167 0.653221 0.000000
-vn -0.866032 -0.000000 0.499989
-vn -1.000000 0.000000 0.000000
-vn 0.000000 0.653236 0.757154
-vn -0.378558 0.653230 0.655732
-vn 0.000000 -0.000000 1.000000
-vn -0.499989 -0.000000 0.866032
-vn -0.378558 0.653230 0.655732
-vn -0.655715 0.653243 0.378566
-vn -0.499989 -0.000000 0.866032
-vn -0.866032 -0.000000 0.499989
-vn 0.378558 0.653230 -0.655732
-vn 0.655715 0.653243 -0.378566
-vn 0.499989 0.000000 -0.866032
-vn 0.866032 0.000000 -0.499989
-vn 0.000000 0.653236 -0.757154
-vn 0.378558 0.653230 -0.655732
-vn 0.000000 0.000000 -1.000000
-vn 0.499989 0.000000 -0.866032
-vn -0.378558 0.653230 -0.655732
-vn 0.000000 0.653236 -0.757154
-vn -0.499989 0.000000 -0.866032
-vn 0.000000 0.000000 -1.000000
-vn 0.378558 0.653230 0.655732
-vn 0.000000 0.653236 0.757154
-vn 0.499989 -0.000000 0.866032
-vn 0.000000 -0.000000 1.000000
-vn 0.757167 0.653221 0.000000
-vn 0.655715 0.653243 0.378566
-vn 1.000000 0.000000 0.000000
-vn 0.866032 -0.000000 0.499989
-vn -0.655715 0.653243 -0.378566
-vn -0.378558 0.653230 -0.655732
-vn -0.866032 0.000000 -0.499989
-vn -0.499989 0.000000 -0.866032
-vn -1.000000 0.000000 0.000000
-vn -0.866032 0.000000 -0.499989
-vn -1.000000 0.000000 0.000000
-vn -0.866032 0.000000 -0.499989
-vn 0.866032 -0.000000 0.499989
-vn 0.499989 -0.000000 0.866032
-vn 0.866032 -0.000000 0.499989
-vn 0.499989 -0.000000 0.866032
-vn 0.866032 0.000000 -0.499989
-vn 1.000000 0.000000 0.000000
-vn 0.866032 0.000000 -0.499989
-vn 1.000000 0.000000 0.000000
-vn -0.866032 -0.000000 0.499989
-vn -1.000000 0.000000 0.000000
-vn -0.866032 -0.000000 0.499989
-vn -1.000000 0.000000 0.000000
-vn 0.000000 -0.000000 1.000000
-vn -0.499989 -0.000000 0.866032
-vn 0.000000 -0.000000 1.000000
-vn -0.499989 -0.000000 0.866032
-vn -0.499989 -0.000000 0.866032
-vn -0.866032 -0.000000 0.499989
-vn -0.499989 -0.000000 0.866032
-vn -0.866032 -0.000000 0.499989
-vn 0.499989 0.000000 -0.866032
-vn 0.866032 0.000000 -0.499989
-vn 0.499989 0.000000 -0.866032
-vn 0.866032 0.000000 -0.499989
-vn 0.000000 0.000000 -1.000000
-vn 0.499989 0.000000 -0.866032
-vn 0.000000 0.000000 -1.000000
-vn 0.499989 0.000000 -0.866032
-vn -0.499989 0.000000 -0.866032
-vn 0.000000 0.000000 -1.000000
-vn -0.499989 0.000000 -0.866032
-vn 0.000000 0.000000 -1.000000
-vn 0.499989 -0.000000 0.866032
-vn 0.000000 -0.000000 1.000000
-vn 0.499989 -0.000000 0.866032
-vn 0.000000 -0.000000 1.000000
-vn 1.000000 0.000000 0.000000
-vn 0.866032 -0.000000 0.499989
-vn 1.000000 0.000000 0.000000
-vn 0.866032 -0.000000 0.499989
-vn -0.866032 0.000000 -0.499989
-vn -0.499989 0.000000 -0.866032
-vn -0.866032 0.000000 -0.499989
-vn -0.499989 0.000000 -0.866032
-f 3/33/1 30/34/2 39/36/3
-f 39/36/3 30/34/2 42/35/4
-f 30/34/5 34/37/6 42/35/7
-f 42/35/7 34/37/6 46/32/8
-f 14/38/9 5/11/10 26/13/11
-f 26/13/11 5/11/10 17/12/12
-f 4/62/13 12/63/14 16/30/15
-f 16/30/15 12/63/14 24/29/16
-f 12/63/17 13/31/18 24/29/19
-f 24/29/19 13/31/18 25/14/20
-f 13/31/21 14/38/22 25/14/23
-f 25/14/23 14/38/22 26/13/24
-f 5/11/25 6/15/26 17/12/27
-f 17/12/27 6/15/26 18/16/28
-f 7/17/29 2/18/30 19/20/31
-f 19/20/31 2/18/30 15/19/32
-f 9/64/33 10/65/34 21/67/35
-f 21/67/35 10/65/34 22/66/36
-f 8/68/37 4/62/38 20/69/39
-f 20/69/39 4/62/38 16/30/40
-f 11/70/41 7/17/42 23/71/43
-f 23/71/43 7/17/42 19/20/44
-f 10/65/45 11/70/46 22/66/47
-f 22/66/47 11/70/46 23/71/48
-f 2/18/49 8/68/50 15/19/51
-f 15/19/51 8/68/50 20/69/52
-f 6/15/53 9/64/54 18/16/55
-f 18/16/55 9/64/54 21/67/56
-f 20/69/57 16/30/58 27/46/59
-f 19/20/60 15/19/61 27/46/62
-f 16/30/63 24/29/64 27/46/65
-f 22/66/66 23/71/67 27/46/68
-f 21/67/69 22/66/70 27/46/71
-f 18/16/72 21/67/73 27/46/74
-f 23/71/75 19/20/76 27/46/77
-f 26/13/78 17/12/79 27/46/80
-f 24/29/81 25/14/82 27/46/83
-f 15/19/84 20/69/85 27/46/86
-f 17/12/87 18/16/88 27/46/89
-f 25/14/90 26/13/91 27/46/92
-f 1/47/93 31/48/94 38/50/95
-f 38/50/95 31/48/94 43/49/96
-f 37/51/97 36/52/98 49/54/99
-f 49/54/99 36/52/98 48/53/100
-f 34/37/101 33/55/102 46/32/103
-f 46/32/103 33/55/102 45/45/104
-f 35/42/105 1/47/106 47/43/107
-f 47/43/107 1/47/106 38/50/108
-f 33/55/109 32/44/110 45/45/111
-f 45/45/111 32/44/110 44/72/112
-f 32/44/113 29/73/114 44/72/115
-f 44/72/115 29/73/114 41/1/116
-f 28/2/117 37/51/118 40/3/119
-f 40/3/119 37/51/118 49/54/120
-f 31/48/121 3/33/122 43/49/123
-f 43/49/123 3/33/122 39/36/124
-f 36/52/125 35/42/126 48/53/127
-f 48/53/127 35/42/126 47/43/128
-f 29/73/129 28/2/130 41/1/131
-f 41/1/131 28/2/130 40/3/132
-f 65/4/133 66/5/134 28/2/135
-f 28/2/135 66/5/134 37/51/136
-f 63/6/137 72/7/138 31/48/139
-f 31/48/139 72/7/138 3/33/140
-f 64/8/141 69/39/142 30/34/143
-f 30/34/143 69/39/142 34/37/144
-f 66/5/145 67/59/146 37/51/147
-f 37/51/147 67/59/146 36/52/148
-f 67/59/149 68/25/150 36/52/151
-f 36/52/151 68/25/150 35/42/152
-f 68/25/153 71/23/154 35/42/155
-f 35/42/155 71/23/154 1/47/156
-f 62/28/157 70/10/158 33/55/159
-f 33/55/159 70/10/158 32/44/160
-f 69/39/161 62/28/162 34/37/163
-f 34/37/163 62/28/162 33/55/164
-f 70/10/165 73/56/166 32/44/167
-f 32/44/167 73/56/166 29/73/168
-f 71/23/169 63/6/170 1/47/171
-f 1/47/171 63/6/170 31/48/172
-f 72/7/173 64/8/174 3/33/175
-f 3/33/175 64/8/174 30/34/176
-f 73/56/177 65/4/178 29/73/179
-f 29/73/179 65/4/178 28/2/180
-f 6/15/181 5/11/182 60/9/183
-f 60/9/183 5/11/182 61/60/184
-f 2/18/185 7/17/186 58/27/187
-f 58/27/187 7/17/186 59/21/188
-f 4/62/189 8/68/190 56/57/191
-f 56/57/191 8/68/190 57/24/192
-f 9/64/193 6/15/194 55/41/195
-f 55/41/195 6/15/194 60/9/196
-f 11/70/197 10/65/198 53/40/199
-f 53/40/199 10/65/198 54/26/200
-f 10/65/201 9/64/202 54/26/203
-f 54/26/203 9/64/202 55/41/204
-f 12/63/205 4/62/206 52/58/207
-f 52/58/207 4/62/206 56/57/208
-f 13/31/209 12/63/210 51/61/211
-f 51/61/211 12/63/210 52/58/212
-f 14/38/213 13/31/214 50/22/215
-f 50/22/215 13/31/214 51/61/216
-f 7/17/217 11/70/218 59/21/219
-f 59/21/219 11/70/218 53/40/220
-f 8/68/221 2/18/222 57/24/223
-f 57/24/223 2/18/222 58/27/224
-f 5/11/225 14/38/226 61/60/227
-f 61/60/227 14/38/226 50/22/228
-f 60/9/229 61/60/230 73/56/231
-f 73/56/231 61/60/230 65/4/232
-f 58/27/233 59/21/234 72/7/235
-f 72/7/235 59/21/234 64/8/236
-f 56/57/237 57/24/238 71/23/239
-f 71/23/239 57/24/238 63/6/240
-f 55/41/241 60/9/242 70/10/243
-f 70/10/243 60/9/242 73/56/244
-f 53/40/245 54/26/246 69/39/247
-f 69/39/247 54/26/246 62/28/248
-f 54/26/249 55/41/250 62/28/251
-f 62/28/251 55/41/250 70/10/252
-f 52/58/253 56/57/254 68/25/255
-f 68/25/255 56/57/254 71/23/256
-f 51/61/257 52/58/258 67/59/259
-f 67/59/259 52/58/258 68/25/260
-f 50/22/261 51/61/262 66/5/263
-f 66/5/263 51/61/262 67/59/264
-f 59/21/265 53/40/266 64/8/267
-f 64/8/267 53/40/266 69/39/268
-f 57/24/269 58/27/270 63/6/271
-f 63/6/271 58/27/270 72/7/272
-f 61/60/273 50/22/274 65/4/275
-f 65/4/275 50/22/274 66/5/276
diff --git a/libs/vr/libdvrgraphics/assets/controller_proto2_trigger.obj b/libs/vr/libdvrgraphics/assets/controller_proto2_trigger.obj
deleted file mode 100644
index 7b87239..0000000
--- a/libs/vr/libdvrgraphics/assets/controller_proto2_trigger.obj
+++ /dev/null
@@ -1,1240 +0,0 @@
-# This file uses centimeters as units for non-parametric coordinates.
-
-v 0.012469 0.002342 0.063363
-v 0.009351 -0.007408 0.065472
-v 0.010658 -0.006647 0.065307
-v 0.006441 -0.008510 0.065710
-v 0.003284 -0.009190 0.065857
-v 0.012469 -0.001545 0.064204
-v 0.012469 -0.003489 0.064624
-v 0.012469 0.002342 0.037855
-v 0.012469 0.002342 0.035622
-v 0.012469 0.002342 0.040088
-v 0.012469 0.002342 0.042320
-v 0.010019 -0.002861 0.035742
-v 0.010019 -0.009748 0.045459
-v 0.008153 -0.014181 0.046940
-v 0.006671 -0.015226 0.047180
-v 0.010019 -0.012511 0.046558
-v 0.010019 -0.004041 0.040214
-v 0.010019 -0.007400 0.044006
-v 0.010019 -0.005473 0.042235
-v 0.010019 -0.003159 0.038022
-v 0.004895 -0.016332 0.047274
-v 0.002649 -0.002861 0.035742
-v 0.002649 -0.009748 0.045459
-v 0.002649 -0.014181 0.046940
-v 0.002649 -0.015226 0.047180
-v 0.002649 -0.012511 0.046558
-v 0.002649 -0.004041 0.040214
-v 0.002649 -0.007400 0.044006
-v 0.002649 -0.005473 0.042235
-v 0.002649 -0.003159 0.038022
-v 0.002649 -0.016789 0.047312
-v 0.012469 -0.001216 0.035704
-v 0.012469 -0.001420 0.037969
-v 0.012469 -0.002023 0.040174
-v 0.012469 -0.003002 0.042262
-v 0.010658 -0.013756 0.048907
-v 0.003284 -0.017321 0.049383
-v 0.006441 -0.016360 0.049298
-v 0.009351 -0.014801 0.049145
-v 0.012469 -0.009331 0.047481
-v 0.012469 -0.006949 0.046118
-v 0.012469 0.002342 0.046118
-v 0.012469 -0.001298 0.035706
-v 0.011089 -0.002861 0.035742
-v 0.012469 -0.001595 0.037974
-v 0.011089 -0.003159 0.038022
-v 0.012469 -0.002483 0.040183
-v 0.011089 -0.004041 0.040214
-v 0.012469 -0.003949 0.042252
-v 0.011089 -0.005473 0.042235
-v 0.012469 -0.007147 0.045190
-v 0.011089 -0.007400 0.044006
-v 0.012469 -0.009503 0.046649
-v 0.011089 -0.009748 0.045459
-v 0.011089 -0.012511 0.046558
-v 0.012469 -0.010955 0.047226
-v 0.011466 -0.013144 0.048119
-v 0.011466 -0.006105 0.065190
-v 0.012469 -0.004454 0.064833
-v 0.007971 -0.015226 0.047180
-v 0.009351 -0.014935 0.048529
-v 0.010658 -0.013889 0.048289
-v 0.009277 -0.014181 0.046940
-v 0.003284 -0.017462 0.048733
-v 0.002990 -0.017308 0.047351
-v 0.006441 -0.016497 0.048661
-v 0.005551 -0.016526 0.047290
-v 0.012469 -0.010781 0.048032
-v 0.011466 -0.013010 0.048737
-v 0.000000 -0.003159 0.038022
-v 0.000000 -0.009748 0.045459
-v 0.000000 -0.007400 0.044006
-v 0.000000 -0.002861 0.035742
-v 0.000000 -0.009419 0.065907
-v 0.000000 -0.005473 0.042235
-v -0.012469 0.002342 0.063363
-v 0.000000 -0.014181 0.046940
-v 0.000000 -0.015226 0.047180
-v 0.000000 -0.012511 0.046558
-v 0.000000 -0.004041 0.040214
-v 0.000000 -0.016789 0.047312
-v -0.009351 -0.007408 0.065472
-v -0.010658 -0.006647 0.065307
-v -0.006441 -0.008510 0.065710
-v -0.003284 -0.009190 0.065857
-v -0.012469 -0.001545 0.064204
-v -0.012469 -0.003489 0.064624
-v -0.012469 0.002342 0.037855
-v -0.012469 0.002342 0.035622
-v -0.012469 0.002342 0.040088
-v -0.012469 0.002342 0.042320
-v -0.010019 -0.002861 0.035742
-v -0.010019 -0.009748 0.045459
-v -0.008153 -0.014181 0.046940
-v -0.006671 -0.015226 0.047180
-v -0.010019 -0.012511 0.046558
-v -0.010019 -0.004041 0.040214
-v -0.010019 -0.007400 0.044006
-v -0.010019 -0.005473 0.042235
-v -0.010019 -0.003159 0.038022
-v -0.004895 -0.016332 0.047274
-v -0.002649 -0.002861 0.035742
-v -0.002649 -0.009748 0.045459
-v -0.002649 -0.014181 0.046940
-v -0.002649 -0.015226 0.047180
-v -0.002649 -0.012511 0.046558
-v -0.002649 -0.004041 0.040214
-v -0.002649 -0.007400 0.044006
-v -0.002649 -0.005473 0.042235
-v -0.002649 -0.003159 0.038022
-v -0.002649 -0.016789 0.047312
-v -0.012469 -0.001216 0.035704
-v -0.012469 -0.001420 0.037969
-v -0.012469 -0.002023 0.040174
-v -0.012469 -0.003002 0.042262
-v -0.010658 -0.013756 0.048907
-v 0.000000 -0.017646 0.049412
-v -0.003284 -0.017321 0.049383
-v -0.006441 -0.016360 0.049298
-v -0.009351 -0.014801 0.049145
-v -0.012469 -0.009331 0.047481
-v -0.012469 -0.006949 0.046118
-v -0.012469 0.002342 0.046118
-v -0.012469 -0.001298 0.035706
-v -0.011089 -0.002861 0.035742
-v -0.012469 -0.001595 0.037974
-v -0.011089 -0.003159 0.038022
-v -0.012469 -0.002483 0.040183
-v -0.011089 -0.004041 0.040214
-v -0.012469 -0.003949 0.042252
-v -0.011089 -0.005473 0.042235
-v -0.012469 -0.007147 0.045190
-v -0.011089 -0.007400 0.044006
-v -0.012469 -0.009503 0.046649
-v -0.011089 -0.009748 0.045459
-v -0.011089 -0.012511 0.046558
-v -0.012469 -0.010955 0.047226
-v -0.011466 -0.013144 0.048119
-v -0.011466 -0.006105 0.065190
-v -0.012469 -0.004454 0.064833
-v -0.007971 -0.015226 0.047180
-v -0.009351 -0.014935 0.048529
-v -0.010658 -0.013889 0.048289
-v -0.009277 -0.014181 0.046940
-v -0.003284 -0.017462 0.048733
-v -0.002990 -0.017308 0.047351
-v 0.000000 -0.017604 0.047373
-v 0.000000 -0.017787 0.048757
-v -0.006441 -0.016497 0.048661
-v -0.005551 -0.016526 0.047290
-v -0.012469 -0.010781 0.048032
-v -0.011466 -0.013010 0.048737
-v 0.000000 -0.016909 0.052819
-v 0.003284 -0.016586 0.052783
-v 0.006441 -0.015629 0.052675
-v 0.012469 -0.008622 0.050921
-v 0.012469 -0.006181 0.049710
-v 0.012469 0.002342 0.049484
-v 0.010658 -0.013032 0.052252
-v 0.009351 -0.014078 0.052488
-v 0.011466 -0.012286 0.052084
-v 0.012469 -0.010048 0.051420
-v -0.003284 -0.016586 0.052783
-v -0.006441 -0.015629 0.052675
-v -0.012469 -0.008622 0.050921
-v -0.012469 -0.006181 0.049710
-v -0.012469 0.002342 0.049484
-v -0.010658 -0.013032 0.052252
-v -0.009351 -0.014078 0.052488
-v -0.011466 -0.012286 0.052084
-v -0.012469 -0.010048 0.051420
-vt 0.389626 0.855156
-vt 0.390521 0.876103
-vt 0.497178 0.870536
-vt 0.484333 0.855130
-vt 0.412289 0.967976
-vt 0.478403 0.774806
-vt 0.463433 0.778867
-vt 0.412380 0.809901
-vt 0.409798 0.834762
-vt 0.396714 0.803798
-vt 0.445493 0.843045
-vt 0.390505 0.834206
-vt 0.408648 0.830875
-vt 0.389815 0.844760
-vt 0.330514 0.823054
-vt 0.432027 0.965825
-vt 0.391682 0.823360
-vt 0.437068 0.901524
-vt 0.402269 0.864596
-vt 0.493086 0.959935
-vt 0.480141 0.959822
-vt 0.407446 0.893095
-vt 0.404279 0.890129
-vt 0.494272 0.915752
-vt 0.405408 0.893816
-vt 0.445499 0.867230
-vt 0.458613 0.855135
-vt 0.434528 0.906466
-vt 0.478084 0.921347
-vt 0.433534 0.865962
-vt 0.458054 0.868399
-vt 0.392761 0.817328
-vt 0.404255 0.820169
-vt 0.336182 0.937153
-vt 0.405821 0.786943
-vt 0.413215 0.855147
-vt 0.416743 0.904914
-vt 0.413479 0.906889
-vt 0.389822 0.865551
-vt 0.328339 0.855183
-vt 0.406268 0.863663
-vt 0.405868 0.923348
-vt 0.393637 0.897111
-vt 0.478510 0.773673
-vt 0.409635 0.808495
-vt 0.403113 0.836120
-vt 0.402263 0.845706
-vt 0.407910 0.840728
-vt 0.497174 0.839720
-vt 0.478060 0.788901
-vt 0.329051 0.838946
-vt 0.334987 0.787175
-vt 0.401168 0.835782
-vt 0.448778 0.784859
-vt 0.447886 0.797316
-vt 0.462582 0.792299
-vt 0.412210 0.742297
-vt 0.422076 0.845553
-vt 0.416711 0.805374
-vt 0.464373 0.798874
-vt 0.431956 0.744434
-vt 0.450212 0.930782
-vt 0.427474 0.913081
-vt 0.423235 0.915539
-vt 0.399149 0.912516
-vt 0.335447 0.927703
-vt 0.335050 0.923173
-vt 0.412698 0.863505
-vt 0.416158 0.863975
-vt 0.411799 0.881077
-vt 0.409812 0.875534
-vt 0.493410 0.773030
-vt 0.413445 0.803401
-vt 0.402794 0.825572
-vt 0.437042 0.808751
-vt 0.400328 0.864755
-vt 0.408394 0.855149
-vt 0.333617 0.909517
-vt 0.332644 0.902621
-vt 0.403126 0.874181
-vt 0.422082 0.864736
-vt 0.416711 0.855146
-vt 0.402042 0.855151
-vt 0.422934 0.899416
-vt 0.334248 0.913876
-vt 0.450172 0.779477
-vt 0.493052 0.750284
-vt 0.458048 0.841870
-vt 0.433528 0.844320
-vt 0.434498 0.803810
-vt 0.494257 0.794492
-vt 0.410463 0.825689
-vt 0.415040 0.889351
-vt 0.471407 0.855132
-vt 0.446098 0.855138
-vt 0.479212 0.914296
-vt 0.493852 0.922939
-vt 0.410483 0.884606
-vt 0.447916 0.912950
-vt 0.434120 0.855141
-vt 0.470937 0.869361
-vt 0.406318 0.889536
-vt 0.493399 0.772491
-vt 0.332599 0.807735
-vt 0.467185 0.749518
-vt 0.413259 0.817561
-vt 0.393606 0.813194
-vt 0.423197 0.794742
-vt 0.479191 0.795954
-vt 0.406262 0.846637
-vt 0.406068 0.855150
-vt 0.407893 0.847406
-vt 0.406295 0.820760
-vt 0.406924 0.838997
-vt 0.399108 0.797782
-vt 0.422669 0.855144
-vt 0.407898 0.862892
-vt 0.391706 0.886948
-vt 0.401182 0.874520
-vt 0.404771 0.884253
-vt 0.483983 0.870072
-vt 0.400087 0.855152
-vt 0.329066 0.871418
-vt 0.330545 0.887307
-vt 0.497404 0.855128
-vt 0.416152 0.846318
-vt 0.454204 0.747884
-vt 0.404751 0.826046
-vt 0.411782 0.829217
-vt 0.400321 0.845549
-vt 0.463943 0.775990
-vt 0.337941 0.751811
-vt 0.333566 0.800837
-vt 0.412692 0.846790
-vt 0.483978 0.840187
-vt 0.334192 0.796476
-vt 0.493834 0.787302
-vt 0.450179 0.803181
-vt 0.408665 0.879421
-vt 0.406935 0.871302
-vt 0.407920 0.869569
-vt 0.467237 0.960717
-vt 0.454263 0.962359
-vt 0.450205 0.907085
-vt 0.464397 0.911384
-vt 0.462610 0.917958
-vt 0.402814 0.884728
-vt 0.425386 0.895350
-vt 0.336106 0.773189
-vt 0.422907 0.810868
-vt 0.338033 0.958524
-vt 0.412410 0.900390
-vt 0.409666 0.901797
-vt 0.396751 0.906503
-vt 0.463979 0.934259
-vt 0.478433 0.935435
-vt 0.493434 0.937204
-vt 0.493422 0.937742
-vt 0.478541 0.936568
-vt 0.463468 0.931384
-vt 0.448815 0.925403
-vt 0.427439 0.797198
-vt 0.480098 0.750404
-vt 0.425362 0.814933
-vt 0.335380 0.782643
-vt 0.470932 0.840902
-vt 0.405382 0.816481
-vt 0.415019 0.820940
-vt 0.407421 0.817201
-vt 0.392788 0.892978
-vt 0.413283 0.892731
-vn 0.941739 -0.326680 -0.080053
-vn 0.945242 -0.323626 -0.042239
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.933306 -0.319627 -0.163644
-vn 0.941739 -0.326680 -0.080053
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.919246 -0.303577 -0.250656
-vn 0.933306 -0.319627 -0.163644
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.911448 -0.243205 -0.331832
-vn 0.919246 -0.303577 -0.250656
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.911448 -0.243205 -0.331832
-vn 1.000000 0.000000 0.000000
-vn 0.916678 -0.176432 -0.358571
-vn 1.000000 0.000000 0.000000
-vn 0.916678 -0.176432 -0.358571
-vn 1.000000 0.000000 0.000000
-vn 0.910980 -0.276630 -0.305928
-vn 0.979394 -0.197399 0.042666
-vn 0.973672 -0.216165 0.072360
-vn 1.000000 0.000000 0.000000
-vn 0.978343 -0.189186 0.083988
-vn 1.000000 0.000000 0.000000
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.223005 -0.974817
-vn 0.161752 -0.860157 0.483701
-vn 0.000000 -0.869145 0.494557
-vn 0.178204 -0.920500 0.347740
-vn 0.000000 -0.934880 0.354963
-vn 0.325059 -0.831219 0.451012
-vn 0.161752 -0.860157 0.483701
-vn 0.352896 -0.876974 0.326161
-vn 0.178204 -0.920500 0.347740
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.154215 -0.988037
-vn -0.000092 -0.079746 -0.996815
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.079380 -0.996844
-vn 0.596627 -0.720598 0.353234
-vn 0.491395 -0.774189 0.398951
-vn 0.629820 -0.732455 0.258526
-vn 0.520259 -0.802134 0.293106
-vn 0.352896 -0.876974 0.326161
-vn 0.520259 -0.802134 0.293106
-vn 0.325059 -0.831219 0.451012
-vn 0.491395 -0.774189 0.398951
-vn 0.382681 -0.903004 0.195293
-vn 0.195076 -0.958627 0.207314
-vn 0.395898 -0.918084 -0.019654
-vn 0.200818 -0.979187 0.029421
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.291820 -0.619012 -0.729154
-vn 0.221873 -0.646208 -0.730197
-vn 0.000000 -0.154215 -0.988037
-vn -0.000244 -0.081790 -0.996650
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.877817 -0.478995
-vn 0.341206 -0.695262 -0.632605
-vn 0.383839 -0.804668 -0.452965
-vn 0.395898 -0.918084 -0.019654
-vn 0.552792 -0.829295 -0.081791
-vn 0.382681 -0.903004 0.195293
-vn 0.555564 -0.812685 0.175758
-vn 0.772999 -0.620157 -0.133706
-vn 0.819595 -0.559998 0.121101
-vn 0.635399 -0.761197 -0.129796
-vn 0.661102 -0.733340 0.158607
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.991581 -0.129491
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.991581 -0.129491
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.991581 -0.129491
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.991581 -0.129491
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.449678 -0.893191
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.449678 -0.893191
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.154215 -0.988037
-vn -0.000244 -0.081790 -0.996650
-vn 0.000000 -0.154215 -0.988037
-vn -0.000092 -0.079746 -0.996815
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.223005 -0.974817
-vn 0.195076 -0.958627 0.207314
-vn 0.000000 -0.977405 0.211375
-vn 0.200818 -0.979187 0.029421
-vn 0.000000 -0.999153 0.041139
-vn 0.221873 -0.646208 -0.730197
-vn 0.120368 -0.692302 -0.711498
-vn -0.000244 -0.081790 -0.996650
-vn -0.000092 -0.079746 -0.996815
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.750417 -0.660964
-vn 0.333728 -0.575562 -0.746561
-vn 0.341206 -0.695262 -0.632605
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.991581 -0.129491
-vn 0.412992 -0.879180 -0.237657
-vn 0.422817 -0.898585 -0.117347
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.967377 -0.253342
-vn 0.383839 -0.804668 -0.452965
-vn 0.412992 -0.879180 -0.237657
-vn 0.457368 -0.496250 -0.737936
-vn 0.313953 -0.551668 -0.772720
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.449666 -0.893197
-vn 0.457368 -0.496250 -0.737936
-vn 0.350609 -0.424894 -0.834589
-vn 0.635399 -0.761197 -0.129796
-vn 0.661102 -0.733340 0.158607
-vn 0.552792 -0.829295 -0.081791
-vn 0.555564 -0.812685 0.175758
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.223005 -0.974817
-vn 0.291820 -0.619012 -0.729154
-vn 0.313953 -0.551668 -0.772720
-vn 0.120368 -0.692302 -0.711498
-vn 0.000000 -0.707900 -0.706313
-vn -0.000092 -0.079746 -0.996815
-vn 0.000000 -0.079380 -0.996844
-vn 0.788994 -0.557075 0.259142
-vn 0.596627 -0.720598 0.353234
-vn 0.791884 -0.577089 0.199718
-vn 0.629820 -0.732455 0.258526
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.604128 -0.796887
-vn 0.350609 -0.424894 -0.834589
-vn 0.333728 -0.575562 -0.746561
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.457368 -0.496250 -0.737936
-vn 0.910980 -0.276630 -0.305928
-vn 0.772999 -0.620157 -0.133706
-vn 0.313953 -0.551668 -0.772720
-vn 0.457368 -0.496250 -0.737936
-vn 0.635399 -0.761197 -0.129796
-vn 0.772999 -0.620157 -0.133706
-vn 0.945242 -0.323626 -0.042239
-vn 0.941739 -0.326680 -0.080053
-vn 0.422817 -0.898585 -0.117347
-vn 0.412992 -0.879180 -0.237657
-vn 0.941739 -0.326680 -0.080053
-vn 0.933306 -0.319627 -0.163644
-vn 0.412992 -0.879180 -0.237657
-vn 0.383839 -0.804668 -0.452965
-vn 0.933306 -0.319627 -0.163644
-vn 0.919246 -0.303577 -0.250656
-vn 0.383839 -0.804668 -0.452965
-vn 0.341206 -0.695262 -0.632605
-vn 0.919246 -0.303577 -0.250656
-vn 0.911448 -0.243205 -0.331832
-vn 0.341206 -0.695262 -0.632605
-vn 0.333728 -0.575562 -0.746561
-vn 0.916678 -0.176432 -0.358571
-vn 0.350609 -0.424894 -0.834589
-vn 0.911448 -0.243205 -0.331832
-vn 0.333728 -0.575562 -0.746561
-vn 0.916678 -0.176432 -0.358571
-vn 0.910980 -0.276630 -0.305928
-vn 0.350609 -0.424894 -0.834589
-vn 0.457368 -0.496250 -0.737936
-vn 0.819595 -0.559998 0.121101
-vn 0.772999 -0.620157 -0.133706
-vn 0.979394 -0.197399 0.042666
-vn 0.910980 -0.276630 -0.305928
-vn 0.552792 -0.829295 -0.081791
-vn 0.395898 -0.918084 -0.019654
-vn 0.291820 -0.619012 -0.729154
-vn 0.221873 -0.646208 -0.730197
-vn 0.395898 -0.918084 -0.019654
-vn 0.200818 -0.979187 0.029421
-vn 0.221873 -0.646208 -0.730197
-vn 0.120368 -0.692302 -0.711498
-vn 0.200818 -0.979187 0.029421
-vn 0.000000 -0.999153 0.041139
-vn 0.120368 -0.692302 -0.711498
-vn 0.000000 -0.707900 -0.706313
-vn 0.291820 -0.619012 -0.729154
-vn 0.313953 -0.551668 -0.772720
-vn 0.552792 -0.829295 -0.081791
-vn 0.635399 -0.761197 -0.129796
-vn 0.791884 -0.577089 0.199718
-vn 0.819595 -0.559998 0.121101
-vn 0.973672 -0.216165 0.072360
-vn 0.979394 -0.197399 0.042666
-vn -0.941739 -0.326680 -0.080053
-vn -1.000000 0.000000 0.000000
-vn -0.945242 -0.323626 -0.042239
-vn -1.000000 0.000000 0.000000
-vn -0.933306 -0.319627 -0.163644
-vn -1.000000 0.000000 0.000000
-vn -0.941739 -0.326680 -0.080053
-vn -1.000000 0.000000 0.000000
-vn -0.919246 -0.303577 -0.250656
-vn -1.000000 0.000000 0.000000
-vn -0.933306 -0.319627 -0.163644
-vn -1.000000 0.000000 0.000000
-vn -0.911448 -0.243205 -0.331832
-vn -1.000000 0.000000 0.000000
-vn -0.919246 -0.303577 -0.250656
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -0.916678 -0.176432 -0.358571
-vn -0.911448 -0.243205 -0.331832
-vn -0.979394 -0.197399 0.042666
-vn -1.000000 0.000000 0.000000
-vn -0.910980 -0.276630 -0.305928
-vn -0.916678 -0.176432 -0.358571
-vn -0.973672 -0.216165 0.072360
-vn -0.978343 -0.189186 0.083988
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.934880 0.354963
-vn 0.000000 -0.869145 0.494557
-vn -0.178204 -0.920500 0.347740
-vn -0.161752 -0.860157 0.483701
-vn -0.178204 -0.920500 0.347740
-vn -0.161752 -0.860157 0.483701
-vn -0.352896 -0.876974 0.326161
-vn -0.325059 -0.831219 0.451012
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.154215 -0.988037
-vn 0.000092 -0.079746 -0.996815
-vn 0.000000 -0.079380 -0.996844
-vn -0.520259 -0.802134 0.293106
-vn -0.491395 -0.774189 0.398951
-vn -0.629820 -0.732455 0.258526
-vn -0.596627 -0.720598 0.353234
-vn -0.352896 -0.876974 0.326161
-vn -0.325059 -0.831219 0.451012
-vn -0.520259 -0.802134 0.293106
-vn -0.491395 -0.774189 0.398951
-vn -0.200818 -0.979187 0.029421
-vn -0.195076 -0.958627 0.207314
-vn -0.395898 -0.918084 -0.019654
-vn -0.382681 -0.903004 0.195293
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -0.291820 -0.619012 -0.729154
-vn 0.000000 -0.154215 -0.988037
-vn -0.221873 -0.646208 -0.730197
-vn 0.000244 -0.081790 -0.996650
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn 0.000000 -0.750417 -0.660964
-vn -0.341206 -0.695262 -0.632605
-vn 0.000000 -0.877817 -0.478995
-vn -0.383839 -0.804668 -0.452965
-vn -0.395898 -0.918084 -0.019654
-vn -0.382681 -0.903004 0.195293
-vn -0.552792 -0.829295 -0.081791
-vn -0.555564 -0.812685 0.175758
-vn -0.772999 -0.620157 -0.133706
-vn -0.635399 -0.761197 -0.129796
-vn -0.819595 -0.559998 0.121101
-vn -0.661102 -0.733340 0.158607
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.991581 -0.129491
-vn 0.000000 -0.991581 -0.129491
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.991581 -0.129491
-vn 0.000000 -0.991581 -0.129491
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.967377 -0.253342
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.877817 -0.478995
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.750417 -0.660964
-vn 0.000000 -0.449678 -0.893191
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.604128 -0.796887
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.449678 -0.893191
-vn 0.000000 -0.449666 -0.893197
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.154215 -0.988037
-vn 0.000244 -0.081790 -0.996650
-vn 0.000092 -0.079746 -0.996815
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.297194 -0.954817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.154215 -0.988037
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.999153 0.041139
-vn 0.000000 -0.977405 0.211375
-vn -0.200818 -0.979187 0.029421
-vn -0.195076 -0.958627 0.207314
-vn -0.221873 -0.646208 -0.730197
-vn 0.000244 -0.081790 -0.996650
-vn -0.120368 -0.692302 -0.711498
-vn 0.000092 -0.079746 -0.996815
-vn 0.000000 -0.604128 -0.796887
-vn -0.333728 -0.575562 -0.746561
-vn 0.000000 -0.750417 -0.660964
-vn -0.341206 -0.695262 -0.632605
-vn 0.000000 -0.967377 -0.253342
-vn -0.412992 -0.879180 -0.237657
-vn 0.000000 -0.991581 -0.129491
-vn -0.422817 -0.898585 -0.117347
-vn 0.000000 -0.877817 -0.478995
-vn -0.383839 -0.804668 -0.452965
-vn 0.000000 -0.967377 -0.253342
-vn -0.412992 -0.879180 -0.237657
-vn -0.457368 -0.496250 -0.737936
-vn 0.000000 -0.297194 -0.954817
-vn -0.313953 -0.551668 -0.772720
-vn 0.000000 -0.223005 -0.974817
-vn 0.000000 -0.297194 -0.954817
-vn -0.457368 -0.496250 -0.737936
-vn 0.000000 -0.449666 -0.893197
-vn -0.350609 -0.424894 -0.834589
-vn -0.635399 -0.761197 -0.129796
-vn -0.552792 -0.829295 -0.081791
-vn -0.661102 -0.733340 0.158607
-vn -0.555564 -0.812685 0.175758
-vn 0.000000 -0.154215 -0.988037
-vn -0.291820 -0.619012 -0.729154
-vn 0.000000 -0.223005 -0.974817
-vn -0.313953 -0.551668 -0.772720
-vn -0.120368 -0.692302 -0.711498
-vn 0.000092 -0.079746 -0.996815
-vn 0.000000 -0.707900 -0.706313
-vn 0.000000 -0.079380 -0.996844
-vn -0.629820 -0.732455 0.258526
-vn -0.596627 -0.720598 0.353234
-vn -0.791884 -0.577089 0.199718
-vn -0.788994 -0.557075 0.259142
-vn 0.000000 -0.449666 -0.893197
-vn -0.350609 -0.424894 -0.834589
-vn 0.000000 -0.604128 -0.796887
-vn -0.333728 -0.575562 -0.746561
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -0.457368 -0.496250 -0.737936
-vn -0.772999 -0.620157 -0.133706
-vn -0.910980 -0.276630 -0.305928
-vn -0.313953 -0.551668 -0.772720
-vn -0.635399 -0.761197 -0.129796
-vn -0.457368 -0.496250 -0.737936
-vn -0.772999 -0.620157 -0.133706
-vn -0.945242 -0.323626 -0.042239
-vn -0.422817 -0.898585 -0.117347
-vn -0.941739 -0.326680 -0.080053
-vn -0.412992 -0.879180 -0.237657
-vn -0.941739 -0.326680 -0.080053
-vn -0.412992 -0.879180 -0.237657
-vn -0.933306 -0.319627 -0.163644
-vn -0.383839 -0.804668 -0.452965
-vn -0.933306 -0.319627 -0.163644
-vn -0.383839 -0.804668 -0.452965
-vn -0.919246 -0.303577 -0.250656
-vn -0.341206 -0.695262 -0.632605
-vn -0.919246 -0.303577 -0.250656
-vn -0.341206 -0.695262 -0.632605
-vn -0.911448 -0.243205 -0.331832
-vn -0.333728 -0.575562 -0.746561
-vn -0.333728 -0.575562 -0.746561
-vn -0.350609 -0.424894 -0.834589
-vn -0.911448 -0.243205 -0.331832
-vn -0.916678 -0.176432 -0.358571
-vn -0.916678 -0.176432 -0.358571
-vn -0.350609 -0.424894 -0.834589
-vn -0.910980 -0.276630 -0.305928
-vn -0.457368 -0.496250 -0.737936
-vn -0.819595 -0.559998 0.121101
-vn -0.979394 -0.197399 0.042666
-vn -0.772999 -0.620157 -0.133706
-vn -0.910980 -0.276630 -0.305928
-vn -0.552792 -0.829295 -0.081791
-vn -0.291820 -0.619012 -0.729154
-vn -0.395898 -0.918084 -0.019654
-vn -0.221873 -0.646208 -0.730197
-vn -0.395898 -0.918084 -0.019654
-vn -0.221873 -0.646208 -0.730197
-vn -0.200818 -0.979187 0.029421
-vn -0.120368 -0.692302 -0.711498
-vn -0.200818 -0.979187 0.029421
-vn -0.120368 -0.692302 -0.711498
-vn 0.000000 -0.999153 0.041139
-vn 0.000000 -0.707900 -0.706313
-vn -0.291820 -0.619012 -0.729154
-vn -0.552792 -0.829295 -0.081791
-vn -0.313953 -0.551668 -0.772720
-vn -0.635399 -0.761197 -0.129796
-vn -0.791884 -0.577089 0.199718
-vn -0.973672 -0.216165 0.072360
-vn -0.819595 -0.559998 0.121101
-vn -0.979394 -0.197399 0.042666
-vn -0.978343 -0.189186 0.083988
-vn -0.973672 -0.216165 0.072360
-vn -0.788994 -0.557075 0.259142
-vn -0.791884 -0.577089 0.199718
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -0.819595 -0.559998 0.121101
-vn -0.661102 -0.733340 0.158607
-vn -0.791884 -0.577089 0.199718
-vn -0.629820 -0.732455 0.258526
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -0.382681 -0.903004 0.195293
-vn -0.352896 -0.876974 0.326161
-vn -0.555564 -0.812685 0.175758
-vn -0.520259 -0.802134 0.293106
-vn -0.661102 -0.733340 0.158607
-vn -0.555564 -0.812685 0.175758
-vn -0.629820 -0.732455 0.258526
-vn -0.520259 -0.802134 0.293106
-vn -0.195076 -0.958627 0.207314
-vn -0.178204 -0.920500 0.347740
-vn -0.382681 -0.903004 0.195293
-vn -0.352896 -0.876974 0.326161
-vn 0.000000 -0.977405 0.211375
-vn 0.000000 -0.934880 0.354963
-vn -0.195076 -0.958627 0.207314
-vn -0.178204 -0.920500 0.347740
-vn -0.973672 -0.216165 0.072360
-vn -1.000000 0.000000 0.000000
-vn -0.979394 -0.197399 0.042666
-vn -1.000000 0.000000 0.000000
-vn 0.791884 -0.577089 0.199718
-vn 0.973672 -0.216165 0.072360
-vn 0.788994 -0.557075 0.259142
-vn 0.978343 -0.189186 0.083988
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.819595 -0.559998 0.121101
-vn 0.791884 -0.577089 0.199718
-vn 0.661102 -0.733340 0.158607
-vn 0.629820 -0.732455 0.258526
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.382681 -0.903004 0.195293
-vn 0.555564 -0.812685 0.175758
-vn 0.352896 -0.876974 0.326161
-vn 0.520259 -0.802134 0.293106
-vn 0.661102 -0.733340 0.158607
-vn 0.629820 -0.732455 0.258526
-vn 0.555564 -0.812685 0.175758
-vn 0.520259 -0.802134 0.293106
-vn 0.352896 -0.876974 0.326161
-vn 0.178204 -0.920500 0.347740
-vn 0.382681 -0.903004 0.195293
-vn 0.195076 -0.958627 0.207314
-vn 0.178204 -0.920500 0.347740
-vn 0.000000 -0.934880 0.354963
-vn 0.195076 -0.958627 0.207314
-vn 0.000000 -0.977405 0.211375
-vn 1.000000 0.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.979394 -0.197399 0.042666
-vn 0.973672 -0.216165 0.072360
-f 45/156/1 43/157/2 33/159/3
-f 33/159/3 43/157/2 32/158/4
-f 47/160/5 45/156/6 34/155/7
-f 34/155/7 45/156/6 33/159/8
-f 49/161/9 47/160/10 35/62/11
-f 35/62/11 47/160/10 34/155/12
-f 51/63/13 49/161/14 41/64/15
-f 41/64/15 49/161/14 35/62/16
-f 51/63/17 41/64/18 53/37/19
-f 53/37/19 41/64/18 40/38/20
-f 53/37/21 40/38/22 56/152/23
-f 56/152/23 40/38/22 68/153/24
-f 162/154/25 156/65/26 59/67/27
-f 59/67/27 156/65/26 7/66/28
-f 25/68/29 24/69/30 15/71/31
-f 15/71/31 24/69/30 14/70/32
-f 5/123/33 74/40/34 154/39/35
-f 154/39/35 74/40/34 153/1/36
-f 4/124/37 5/123/38 155/2/39
-f 155/2/39 5/123/38 154/39/40
-f 26/81/41 24/69/42 79/116/43
-f 79/116/43 24/69/42 77/82/44
-f 25/68/45 31/117/46 78/36/47
-f 78/36/47 31/117/46 81/77/48
-f 3/78/49 2/79/50 159/170/51
-f 159/170/51 2/79/50 160/118/52
-f 155/2/53 160/118/54 4/124/55
-f 4/124/55 160/118/54 2/79/56
-f 38/119/57 37/76/58 66/80/59
-f 66/80/59 37/76/58 64/19/60
-f 33/159/61 32/158/62 8/21/63
-f 8/21/63 32/158/62 9/20/64
-f 157/42/65 6/34/66 156/65/67
-f 156/65/67 6/34/66 7/66/68
-f 60/139/69 67/140/70 15/71/71
-f 15/71/71 67/140/70 21/141/72
-f 35/62/73 34/155/74 11/143/75
-f 11/143/75 34/155/74 10/142/76
-f 34/155/77 33/159/78 10/142/79
-f 10/142/79 33/159/78 8/21/80
-f 19/144/81 17/145/82 50/99/83
-f 50/99/83 17/145/82 48/146/84
-f 66/80/85 61/120/86 38/119/87
-f 38/119/87 61/120/86 39/147/88
-f 57/22/89 69/25/90 62/102/91
-f 62/102/91 69/25/90 36/23/92
-f 26/81/93 23/30/94 16/93/95
-f 16/93/95 23/30/94 13/148/96
-f 23/30/97 28/26/98 13/148/99
-f 13/148/99 28/26/98 18/18/100
-f 28/26/101 29/31/102 18/18/103
-f 18/18/103 29/31/102 19/144/104
-f 29/31/105 27/101/106 19/144/107
-f 19/144/107 27/101/106 17/145/108
-f 27/101/109 30/121/110 17/145/111
-f 17/145/111 30/121/110 20/96/112
-f 30/121/113 22/3/114 20/96/115
-f 20/96/115 22/3/114 12/24/116
-f 70/4/117 73/125/118 30/121/119
-f 30/121/119 73/125/118 22/3/120
-f 80/94/121 70/4/122 27/101/123
-f 27/101/123 70/4/122 30/121/124
-f 75/27/125 80/94/126 29/31/127
-f 29/31/127 80/94/126 27/101/128
-f 72/95/129 75/27/130 28/26/131
-f 28/26/131 75/27/130 29/31/132
-f 71/100/133 72/95/134 23/30/135
-f 23/30/135 72/95/134 28/26/136
-f 79/116/137 71/100/138 26/81/139
-f 26/81/139 71/100/138 23/30/140
-f 15/71/141 21/141/142 25/68/143
-f 25/68/143 21/141/142 31/117/144
-f 16/93/145 14/70/146 26/81/147
-f 26/81/147 14/70/146 24/69/148
-f 78/36/149 77/82/150 25/68/151
-f 25/68/151 77/82/150 24/69/152
-f 37/76/153 117/122/154 64/19/155
-f 64/19/155 117/122/154 148/83/156
-f 67/140/157 65/41/158 21/141/159
-f 21/141/159 65/41/158 31/117/160
-f 18/18/161 19/144/162 52/28/163
-f 52/28/163 19/144/162 50/99/164
-f 20/96/165 12/24/166 46/29/167
-f 46/29/167 12/24/166 44/97/168
-f 17/145/169 20/96/170 48/146/171
-f 48/146/171 20/96/170 46/29/172
-f 55/171/173 63/98/174 16/93/175
-f 16/93/175 63/98/174 14/70/176
-f 16/93/177 13/148/178 55/171/179
-f 55/171/179 13/148/178 54/84/180
-f 62/102/181 36/23/182 61/120/183
-f 61/120/183 36/23/182 39/147/184
-f 15/71/185 14/70/186 60/139/187
-f 60/139/187 14/70/186 63/98/188
-f 65/41/189 147/111/190 31/117/191
-f 31/117/191 147/111/190 81/77/192
-f 58/85/193 3/78/194 161/43/195
-f 161/43/195 3/78/194 159/170/196
-f 13/148/197 18/18/198 54/84/199
-f 54/84/199 18/18/198 52/28/200
-f 11/143/201 42/16/202 35/62/203
-f 35/62/203 42/16/202 41/64/204
-f 41/64/205 42/16/206 157/42/207
-f 157/42/207 42/16/206 158/5/208
-f 55/171/209 56/152/210 57/22/211
-f 63/98/212 55/171/213 62/102/214
-f 62/102/214 55/171/213 57/22/215
-f 43/157/216 45/156/217 44/97/218
-f 44/97/218 45/156/217 46/29/219
-f 45/156/220 47/160/221 46/29/222
-f 46/29/222 47/160/221 48/146/223
-f 47/160/224 49/161/225 48/146/226
-f 48/146/226 49/161/225 50/99/227
-f 49/161/228 51/63/229 50/99/230
-f 50/99/230 51/63/229 52/28/231
-f 53/37/232 54/84/233 51/63/234
-f 51/63/234 54/84/233 52/28/235
-f 53/37/236 56/152/237 54/84/238
-f 54/84/238 56/152/237 55/171/239
-f 69/25/240 57/22/241 68/153/242
-f 68/153/242 57/22/241 56/152/243
-f 61/120/244 66/80/245 60/139/246
-f 60/139/246 66/80/245 67/140/247
-f 66/80/248 64/19/249 67/140/250
-f 67/140/250 64/19/249 65/41/251
-f 64/19/252 148/83/253 65/41/254
-f 65/41/254 148/83/253 147/111/255
-f 60/139/256 63/98/257 61/120/258
-f 61/120/258 63/98/257 62/102/259
-f 161/43/260 69/25/261 162/154/262
-f 162/154/262 69/25/261 68/153/263
-f 126/6/264 113/44/265 124/72/266
-f 124/72/266 113/44/265 112/103/267
-f 128/7/268 114/131/269 126/6/270
-f 126/6/270 114/131/269 113/44/271
-f 130/54/272 115/86/273 128/7/274
-f 128/7/274 115/86/273 114/131/275
-f 132/162/276 122/108/277 130/54/278
-f 130/54/278 122/108/277 115/86/279
-f 121/73/280 122/108/281 134/59/282
-f 134/59/282 122/108/281 132/162/283
-f 151/45/284 121/73/285 137/8/286
-f 137/8/286 121/73/285 134/59/287
-f 171/10/288 140/52/289 165/115/290
-f 165/115/290 140/52/289 87/165/291
-f 105/134/292 95/9/293 104/126/294
-f 104/126/294 95/9/293 94/129/295
-f 153/1/296 74/40/297 163/14/298
-f 163/14/298 74/40/297 85/51/299
-f 163/14/300 85/51/301 164/12/302
-f 164/12/302 85/51/301 84/15/303
-f 106/58/304 79/116/305 104/126/306
-f 104/126/306 79/116/305 77/82/307
-f 105/134/308 78/36/309 111/112/310
-f 111/112/310 78/36/309 81/77/311
-f 169/17/312 82/104/313 168/32/314
-f 168/32/314 82/104/313 83/133/315
-f 164/12/316 84/15/317 169/17/318
-f 169/17/318 84/15/317 82/104/319
-f 145/47/320 118/130/321 149/46/322
-f 149/46/322 118/130/321 119/53/323
-f 113/44/324 88/163/325 112/103/326
-f 112/103/326 88/163/325 89/87/327
-f 87/165/328 86/149/329 165/115/330
-f 165/115/330 86/149/329 166/35/331
-f 141/13/332 95/9/333 150/114/334
-f 150/114/334 95/9/333 101/48/335
-f 115/86/336 91/127/337 114/131/338
-f 114/131/338 91/127/337 90/105/339
-f 114/131/340 90/105/341 113/44/342
-f 113/44/342 90/105/341 88/163/343
-f 99/138/344 131/55/345 97/60/346
-f 97/60/346 131/55/345 129/56/347
-f 149/46/348 119/53/349 142/128/350
-f 142/128/350 119/53/349 120/74/351
-f 138/169/352 143/113/353 152/167/354
-f 152/167/354 143/113/353 116/33/355
-f 106/58/356 96/168/357 103/89/358
-f 103/89/358 96/168/357 93/164/359
-f 103/89/360 93/164/361 108/11/362
-f 108/11/362 93/164/361 98/75/363
-f 108/11/364 98/75/365 109/88/366
-f 109/88/366 98/75/365 99/138/367
-f 109/88/368 99/138/369 107/166/370
-f 107/166/370 99/138/369 97/60/371
-f 107/166/372 97/60/373 110/135/374
-f 110/135/374 97/60/373 100/109/375
-f 110/135/376 100/109/377 102/49/378
-f 102/49/378 100/109/377 92/91/379
-f 70/4/380 110/135/381 73/125/382
-f 73/125/382 110/135/381 102/49/383
-f 80/94/384 107/166/385 70/4/386
-f 70/4/386 107/166/385 110/135/387
-f 75/27/388 109/88/389 80/94/390
-f 80/94/390 109/88/389 107/166/391
-f 72/95/392 108/11/393 75/27/394
-f 75/27/394 108/11/393 109/88/395
-f 71/100/396 103/89/397 72/95/398
-f 72/95/398 103/89/397 108/11/399
-f 79/116/400 106/58/401 71/100/402
-f 71/100/402 106/58/401 103/89/403
-f 95/9/404 105/134/405 101/48/406
-f 101/48/406 105/134/405 111/112/407
-f 96/168/408 106/58/409 94/129/410
-f 94/129/410 106/58/409 104/126/411
-f 78/36/412 105/134/413 77/82/414
-f 77/82/414 105/134/413 104/126/415
-f 148/83/416 117/122/417 145/47/418
-f 145/47/418 117/122/417 118/130/419
-f 150/114/420 101/48/421 146/110/422
-f 146/110/422 101/48/421 111/112/423
-f 98/75/424 133/90/425 99/138/426
-f 99/138/426 133/90/425 131/55/427
-f 100/109/428 127/50/429 92/91/430
-f 92/91/430 127/50/429 125/137/431
-f 97/60/432 129/56/433 100/109/434
-f 100/109/434 129/56/433 127/50/435
-f 136/106/436 96/168/437 144/92/438
-f 144/92/438 96/168/437 94/129/439
-f 96/168/440 136/106/441 93/164/442
-f 93/164/442 136/106/441 135/150/443
-f 143/113/444 142/128/445 116/33/446
-f 116/33/446 142/128/445 120/74/447
-f 95/9/448 141/13/449 94/129/450
-f 94/129/450 141/13/449 144/92/451
-f 146/110/452 111/112/453 147/111/454
-f 147/111/454 111/112/453 81/77/455
-f 168/32/456 83/133/457 170/107/458
-f 170/107/458 83/133/457 139/136/459
-f 93/164/460 135/150/461 98/75/462
-f 98/75/462 135/150/461 133/90/463
-f 91/127/464 115/86/465 123/61/466
-f 123/61/466 115/86/465 122/108/467
-f 167/57/468 123/61/469 166/35/470
-f 166/35/470 123/61/469 122/108/471
-f 136/106/472 138/169/473 137/8/474
-f 144/92/475 143/113/476 136/106/477
-f 136/106/477 143/113/476 138/169/478
-f 124/72/479 125/137/480 126/6/481
-f 126/6/481 125/137/480 127/50/482
-f 126/6/483 127/50/484 128/7/485
-f 128/7/485 127/50/484 129/56/486
-f 128/7/487 129/56/488 130/54/489
-f 130/54/489 129/56/488 131/55/490
-f 130/54/491 131/55/492 132/162/493
-f 132/162/493 131/55/492 133/90/494
-f 133/90/495 135/150/496 132/162/497
-f 132/162/497 135/150/496 134/59/498
-f 134/59/499 135/150/500 137/8/501
-f 137/8/501 135/150/500 136/106/502
-f 152/167/503 151/45/504 138/169/505
-f 138/169/505 151/45/504 137/8/506
-f 142/128/507 141/13/508 149/46/509
-f 149/46/509 141/13/508 150/114/510
-f 149/46/511 150/114/512 145/47/513
-f 145/47/513 150/114/512 146/110/514
-f 145/47/515 146/110/516 148/83/517
-f 148/83/517 146/110/516 147/111/518
-f 141/13/519 142/128/520 144/92/521
-f 144/92/521 142/128/520 143/113/522
-f 170/107/523 171/10/524 152/167/525
-f 152/167/525 171/10/524 151/45/526
-f 140/52/527 171/10/528 139/136/529
-f 139/136/529 171/10/528 170/107/530
-f 76/132/531 167/57/532 86/149/533
-f 86/149/533 167/57/532 166/35/534
-f 152/167/535 116/33/536 170/107/537
-f 170/107/537 116/33/536 168/32/538
-f 165/115/539 166/35/540 121/73/541
-f 121/73/541 166/35/540 122/108/542
-f 119/53/543 164/12/544 120/74/545
-f 120/74/545 164/12/544 169/17/546
-f 116/33/547 120/74/548 168/32/549
-f 168/32/549 120/74/548 169/17/550
-f 118/130/551 163/14/552 119/53/553
-f 119/53/553 163/14/552 164/12/554
-f 117/122/555 153/1/556 118/130/557
-f 118/130/557 153/1/556 163/14/558
-f 171/10/559 165/115/560 151/45/561
-f 151/45/561 165/115/560 121/73/562
-f 161/43/563 162/154/564 58/85/565
-f 58/85/565 162/154/564 59/67/566
-f 157/42/567 158/5/568 6/34/569
-f 6/34/569 158/5/568 1/151/570
-f 69/25/571 161/43/572 36/23/573
-f 36/23/573 161/43/572 159/170/574
-f 41/64/575 157/42/576 40/38/577
-f 40/38/577 157/42/576 156/65/578
-f 38/119/579 39/147/580 155/2/581
-f 155/2/581 39/147/580 160/118/582
-f 36/23/583 159/170/584 39/147/585
-f 39/147/585 159/170/584 160/118/586
-f 155/2/587 154/39/588 38/119/589
-f 38/119/589 154/39/588 37/76/590
-f 154/39/591 153/1/592 37/76/593
-f 37/76/593 153/1/592 117/122/594
-f 40/38/595 156/65/596 68/153/597
-f 68/153/597 156/65/596 162/154/598
diff --git a/libs/vr/libdvrgraphics/assets/laser.obj b/libs/vr/libdvrgraphics/assets/laser.obj
deleted file mode 100644
index 32737e4..0000000
--- a/libs/vr/libdvrgraphics/assets/laser.obj
+++ /dev/null
@@ -1,28 +0,0 @@
-# This file uses centimeters as units for non-parametric coordinates.
-
-v -0.010000 -0.000000 -1.000000
-v 0.010000 -0.000000 -1.000000
-v -0.010000 -0.000000 0.000000
-v 0.010000 -0.000000 0.000000
-v 0.000000 0.010000 -1.000000
-v 0.000000 -0.010000 -1.000000
-v 0.000000 0.010000 -0.000000
-v 0.000000 -0.010000 0.000000
-vt 0.000000 0.000000
-vt 1.000000 0.000000
-vt 0.000000 1.000000
-vt 1.000000 1.000000
-vt 0.000000 0.000000
-vt 1.000000 0.000000
-vt 1.000000 1.000000
-vt 0.000000 1.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn 0.000000 -1.000000 -0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-vn -1.000000 0.000000 0.000000
-f 1/1/1 2/2/2 4/4/3 3/3/4
-f 5/5/5 6/6/6 8/7/7 7/8/8
diff --git a/libs/vr/libdvrgraphics/assets/laser.png b/libs/vr/libdvrgraphics/assets/laser.png
deleted file mode 100644
index a96c68d..0000000
--- a/libs/vr/libdvrgraphics/assets/laser.png
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libdvrgraphics/blur.cpp b/libs/vr/libdvrgraphics/blur.cpp
deleted file mode 100644
index 90e271e..0000000
--- a/libs/vr/libdvrgraphics/blur.cpp
+++ /dev/null
@@ -1,246 +0,0 @@
-#include "include/private/dvr/graphics/blur.h"
-
-// clang-format off
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-// clang-format on
-#include <hardware/gralloc.h>
-
-#include <string>
-
-#include <log/log.h>
-#include <private/dvr/debug.h>
-#include <private/dvr/graphics/egl_image.h>
-#include <private/dvr/graphics/shader_program.h>
-#include <private/dvr/types.h>
-
-#define POSITION_ATTR 0
-#define OFFSET_BINDING 0
-#define SAMPLER_BINDING 1
-
-namespace {
-
-std::string screen_space_vert_shader = SHADER0([]() {  // NOLINT
-  layout(location = 0) in vec4 position_uv;
-  out vec2 texCoords;
-
-  void main() {
-    gl_Position = vec4(position_uv.xy, 0.0, 1.0);
-    texCoords = position_uv.zw;
-  }
-});
-
-std::string kawase_blur_frag_shader = SHADER0([]() {  // NOLINT
-  precision mediump float;
-  layout(location = 0) uniform vec2 uSampleOffsets[4];
-  layout(binding = 1) uniform APP_SAMPLER_2D uTexture;
-  in vec2 texCoords;
-  out vec4 color;
-
-  void main() {
-    vec2 tc = texCoords;
-    color = texture(uTexture, tc + uSampleOffsets[0]);
-    color += texture(uTexture, tc + uSampleOffsets[1]);
-    color += texture(uTexture, tc + uSampleOffsets[2]);
-    color += texture(uTexture, tc + uSampleOffsets[3]);
-    color *= (1.0 / 4.0);
-  }
-});
-
-constexpr int g_num_samples = 4;
-
-// Modified kernel patterns originally based on:
-// https://software.intel.com/en-us/blogs/2014/07/15/an-investigation-of-fast-real-time-gpu-based-image-blur-algorithms
-// The modification is left and right rotations of the 3rd and 4th patterns.
-const android::dvr::vec2 g_blur_samples[][g_num_samples] = {
-    {{0.5f, 0.5f}, {-0.5f, 0.5f}, {0.5f, -0.5f}, {-0.5f, -0.5f}},
-    {{1.5f, 1.5f}, {-1.5f, 1.5f}, {1.5f, -1.5f}, {-1.5f, -1.5f}},
-    {{2.5f, 1.5f}, {-1.5f, 2.5f}, {1.5f, -2.5f}, {-2.5f, -1.5f}},
-    {{2.5f, 3.5f}, {-3.5f, 2.5f}, {3.5f, -2.5f}, {-2.5f, -3.5f}},
-    // Last pass disabled, because it is more blur than we need.
-    // {{3.5f, 3.5f}, {-3.5f, 3.5f}, {3.5f, -3.5f}, {-3.5f, -3.5f}},
-};
-
-}  // namespace
-
-namespace android {
-namespace dvr {
-
-Blur::Blur(int w, int h, GLuint source_texture, GLint source_texture_target,
-           GLint target_texture_target, bool is_external, EGLDisplay display,
-           int num_blur_outputs)
-    : display_(display),
-      target_texture_target_(target_texture_target),
-      width_(w),
-      height_(h),
-      fbo_q_free_(1 + num_blur_outputs) {
-  LOG_ALWAYS_FATAL_IF(num_blur_outputs <= 0);
-  source_fbo_ =
-      CreateFbo(w, h, source_texture, source_texture_target, is_external);
-  fbo_half_ = CreateFbo(w / 2, h / 2, 0, target_texture_target, is_external);
-  // Create the quarter res fbos.
-  for (size_t i = 0; i < fbo_q_free_.GetCapacity(); ++i)
-    fbo_q_.push_back(
-        CreateFbo(w / 4, h / 4, 0, target_texture_target, is_external));
-  scale_ = 1.0f;
-}
-
-Blur::~Blur() {
-  glFinish();
-  glDeleteFramebuffers(1, &source_fbo_.fbo);
-  glDeleteFramebuffers(1, &fbo_half_.fbo);
-  // Note: source_fbo_.texture is not deleted because it was created externally.
-  glDeleteTextures(1, &fbo_half_.texture);
-  if (fbo_half_.egl_image)
-    eglDestroyImageKHR(display_, fbo_half_.egl_image);
-  for (const auto& fbo : fbo_q_) {
-    glDeleteFramebuffers(1, &fbo.fbo);
-    glDeleteTextures(1, &fbo.texture);
-    if (fbo.egl_image)
-      eglDestroyImageKHR(display_, fbo.egl_image);
-  }
-  CHECK_GL();
-}
-
-void Blur::StartFrame() {
-  fbo_q_free_.Clear();
-  for (const auto& fbo : fbo_q_)
-    fbo_q_free_.Append(fbo);
-}
-
-GLuint Blur::DrawBlur(GLuint source_texture) {
-  LOG_ALWAYS_FATAL_IF(fbo_q_free_.GetSize() < 2);
-
-  // Downsample to half w x half h.
-  glBindFramebuffer(GL_READ_FRAMEBUFFER, source_fbo_.fbo);
-  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_half_.fbo);
-  glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                         target_texture_target_, source_texture, 0);
-  glBlitFramebuffer(0, 0, width_, height_, 0, 0, width_ / 2, height_ / 2,
-                    GL_COLOR_BUFFER_BIT, GL_LINEAR);
-  CHECK_GL();
-
-  // Downsample to quarter w x quarter h.
-  glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_half_.fbo);
-  Fbo fbo_out = fbo_q_free_.Front();
-  fbo_q_free_.PopFront();
-  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_out.fbo);
-  glBlitFramebuffer(0, 0, width_ / 2, height_ / 2, 0, 0, width_ / 4,
-                    height_ / 4, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-  glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
-  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-  CHECK_GL();
-
-  // Blur shader is initialized statically to share between multiple blur
-  // instances.
-  static ShaderProgram kawase_prog[2];
-  int prog_index = (target_texture_target_ == GL_TEXTURE_EXTERNAL_OES) ? 1 : 0;
-  if (!kawase_prog[prog_index].IsUsable()) {
-    std::string prefix = "#version 310 es\n";
-    if (target_texture_target_ == GL_TEXTURE_EXTERNAL_OES) {
-      prefix += "#extension GL_OES_EGL_image_external_essl3 : require\n";
-      prefix += "#define APP_SAMPLER_2D samplerExternalOES\n";
-    } else {
-      prefix += "#define APP_SAMPLER_2D sampler2D\n";
-    }
-    std::string vert = prefix + screen_space_vert_shader;
-    std::string frag = prefix + kawase_blur_frag_shader;
-    kawase_prog[prog_index].Link(vert, frag);
-    CHECK_GL();
-  }
-
-  int blur_w = width_ / 4;
-  int blur_h = height_ / 4;
-  float pix_w = 1.0f / static_cast<float>(blur_w);
-  float pix_h = 1.0f / static_cast<float>(blur_h);
-  vec2 pixel_size(pix_w, pix_h);
-  constexpr int num_passes = sizeof(g_blur_samples) / sizeof(g_blur_samples[0]);
-  vec2 blur_offsets[num_passes][g_num_samples];
-  for (int i = 0; i < num_passes; ++i) {
-    for (int dir = 0; dir < g_num_samples; ++dir) {
-      blur_offsets[i][dir] = pixel_size.array() *
-          g_blur_samples[i][dir].array() * scale_;
-    }
-  }
-
-  kawase_prog[prog_index].Use();
-
-  vec4 screen_tri_strip[4] = {vec4(-1, 1, 0, 1), vec4(-1, -1, 0, 0),
-                              vec4(1, 1, 1, 1), vec4(1, -1, 1, 0)};
-
-  glViewport(0, 0, blur_w, blur_h);
-  glVertexAttribPointer(POSITION_ATTR, 4, GL_FLOAT, GL_FALSE, sizeof(vec4),
-                        screen_tri_strip);
-  glEnableVertexAttribArray(POSITION_ATTR);
-  CHECK_GL();
-
-  // Ping-pong between fbos from fbo_q_free_ to compute the passes.
-  Fbo fbo_in = fbo_out;
-  for (int i = 0; i < num_passes; ++i) {
-    fbo_out = fbo_q_free_.Front();
-    fbo_q_free_.PopFront();
-    glBindFramebuffer(GL_FRAMEBUFFER, fbo_out.fbo);
-    glActiveTexture(GL_TEXTURE0 + SAMPLER_BINDING);
-    glBindTexture(target_texture_target_, fbo_in.texture);
-    glUniform2fv(OFFSET_BINDING, 4, &blur_offsets[i][0][0]);
-    glClear(GL_COLOR_BUFFER_BIT);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-    CHECK_GL();
-    // Put fbo_in back into the free fbo pool.
-    fbo_q_free_.Append(fbo_in);
-    // Next iteration's in buffer is this iteration's out buffer.
-    fbo_in = fbo_out;
-  }
-  glDisableVertexAttribArray(POSITION_ATTR);
-  glBindTexture(target_texture_target_, 0);
-  glUseProgram(0);
-  glActiveTexture(GL_TEXTURE0);
-  CHECK_GL();
-  // fbo_out remains out of the fbo_q_free_ list, since the application will be
-  // using it as a texture.
-  return fbo_out.texture;
-}
-
-Blur::Fbo Blur::CreateFbo(int w, int h, GLuint source_texture, GLint tex_target,
-                          bool is_external) {
-  Fbo fbo;
-  glGenFramebuffers(1, &fbo.fbo);
-  if (source_texture) {
-    fbo.texture = source_texture;
-  } else {
-    glGenTextures(1, &fbo.texture);
-  }
-
-  glBindFramebuffer(GL_FRAMEBUFFER, fbo.fbo);
-  CHECK_GL();
-
-  if (!source_texture) {
-    glBindTexture(tex_target, fbo.texture);
-    glTexParameteri(tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri(tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    if (is_external) {
-      fbo.egl_image =
-          CreateEglImage(display_, w, h, HAL_PIXEL_FORMAT_RGBA_8888,
-                         GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER);
-      glEGLImageTargetTexture2DOES(tex_target, fbo.egl_image);
-    } else {
-      glTexImage2D(tex_target, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
-                   nullptr);
-    }
-  }
-  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_target,
-                         fbo.texture, 0);
-  CHECK_GL();
-  CHECK_GL_FBO();
-
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-  return fbo;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvrgraphics/debug_text.cpp b/libs/vr/libdvrgraphics/debug_text.cpp
deleted file mode 100644
index 1875b14..0000000
--- a/libs/vr/libdvrgraphics/debug_text.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-#include "include/private/dvr/graphics/debug_text.h"
-
-#include <algorithm>
-
-#include <private/dvr/debug.h>
-
-namespace android {
-namespace dvr {
-namespace {
-
-// 658x11 alpha texture with ascii characters starting with !: "!"#$%&'("...
-// Each character is 7x11 pixels, monospace.
-// clang-format off
-const uint8_t ascii_texture[] = {
-  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xff,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  ,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x49,0x92,0x49,0x92,0x00,0x00,0x24,0xdb,0xff,0xff,0xdb,0x00,0x49,0xff,0x49,0x00,0x24,0xb6,0x00,0x00,0x6d,0xff,0xff,0x49,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0xff,0x49,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0xb6,0xdb,0xb6,0x00,0x00,0x00,0x24,0xb6,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xb6,0x24,0x00,0x00,0xff,0xff,0xff,0xb6,0x24,0x00,0x00,0x00,0x00,0x00,0x6d,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x6d,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x24,0xdb,0xff,0xdb,0x24,0x00,0x00,0x24,0xdb,0xff,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xff,0xff,0x6d,0x00,0x00,0x00,0x6d,0xff,0xff,0x92,0x00,0x00,0x00,0x00,0x24,0xff,0x24,0x00,0x00,0x00,0xff,0xff,0xff,0xdb,0x49,0x00,0x00,0x24,0xb6,0xff,0xff,0xb6,0x00,0x00,0xff,0xff,0xdb,0x6d,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x24,0xb6,0xff,0xff,0xdb,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x6d,0x6d,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x49,0x00,0x49,0xff,0x00,0x00,0xff,0x6d,0x00,0x00,0xff,0x00,0x00,0x00,0xb6,0xdb,0xb6,0x00,0x00,0x00,0xff,0xff,0xff,0xdb,0x24,0x00,0x00,0x00,0xb6,0xdb,0xb6,0x00,0x00,0x00,0xff,0xff,0xff,0xdb,0x49,0x00,0x00,0x24,0xb6,0xff,0xff,0xdb,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xb6,0x24,0x00,0x24,0xb6,0x00,0x00,0xdb,0x24,0x00,0x24,0xdb,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xdb,0x6d,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  ,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x92,0x6d,0x92,0x6d,0x00,0x00,0xdb,0x6d,0xff,0x00,0x00,0x00,0xb6,0x24,0xb6,0x00,0xb6,0x24,0x00,0x00,0xff,0x24,0x24,0xb6,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x24,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0xb6,0xff,0xb6,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0x92,0x6d,0x00,0x6d,0x92,0x00,0x00,0xb6,0x24,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xdb,0x00,0x00,0x00,0x00,0x00,0x49,0xff,0x00,0x00,0x00,0x00,0x24,0xb6,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x49,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xb6,0x00,0x00,0xff,0x49,0x00,0x49,0xff,0x00,0x00,0xb6,0x6d,0x00,0x49,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x24,0x00,0x00,0x00,0x00,0x92,0x00,0x24,0xff,0x00,0x00,0x24,0xdb,0x24,0x00,0xdb,0x6d,0x00,0x00,0x00,0x6d,0xff,0x6d,0x00,0x00,0x00,0xff,0x00,0x00,0x49,0xff,0x00,0x00,0xdb,0x6d,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x24,0xdb,0x49,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x6d,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x6d,0x6d,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xb6,0x00,0x92,0xff,0x00,0x00,0xff,0xdb,0x00,0x00,0xff,0x00,0x00,0x92,0x6d,0x00,0x6d,0x92,0x00,0x00,0xff,0x00,0x00,0x49,0xff,0x00,0x00,0x92,0x6d,0x00,0x6d,0x92,0x00,0x00,0xff,0x00,0x00,0x49,0xff,0x00,0x00,0xdb,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xb6,0x49,0x00,0x49,0xb6,0x00,0x00,0xdb,0x24,0x00,0x00,0xdb,0x00,0x00,0x24,0xb6,0x00,0xb6,0x24,0x00,0x00,0x6d,0x92,0x00,0x92,0x6d,0x00,0x00,0x00,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x92,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x49,0xb6,0x00,0xb6,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  ,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0xb6,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0x49,0xff,0x00,0x00,0x00,0xb6,0x24,0xb6,0x24,0xb6,0x00,0x00,0x00,0xb6,0x49,0xdb,0x49,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x92,0x00,0x00,0x00,0x00,0xb6,0xff,0xb6,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x24,0x92,0xb6,0x00,0x00,0x00,0x00,0xdb,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0x00,0x00,0xb6,0x49,0x00,0x49,0xb6,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x24,0xb6,0xb6,0x24,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x24,0xb6,0xb6,0x24,0x00,0x00,0x00,0x00,0x49,0xdb,0x00,0x00,0xb6,0x6d,0x6d,0xff,0x92,0xdb,0x00,0x00,0x00,0xb6,0x92,0xb6,0x00,0x00,0x00,0xff,0x00,0x00,0x49,0xdb,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x49,0xdb,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x6d,0x6d,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xb6,0x49,0xb6,0xff,0x00,0x00,0xff,0xb6,0x49,0x00,0xff,0x00,0x00,0xdb,0x24,0x00,0x24,0xdb,0x00,0x00,0xff,0x00,0x00,0x49,0xdb,0x00,0x00,0xdb,0x24,0x00,0x24,0xdb,0x00,0x00,0xff,0x00,0x00,0x49,0xdb,0x00,0x00,0xdb,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x6d,0x92,0x00,0x92,0x6d,0x00,0x00,0x92,0x24,0x00,0x00,0xdb,0x00,0x00,0x00,0xb6,0x6d,0xb6,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xb6,0x24,0x00,0x24,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0xff,0xff,0xdb,0x49,0x00,0x00,0xff,0x6d,0xff,0xdb,0x24,0x00,0x00,0x00,0x92,0xff,0xff,0xdb,0x00,0x00,0x24,0xdb,0xff,0x6d,0xff,0x00,0x00,0x00,0xb6,0xff,0xdb,0x24,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x49,0xff,0xdb,0xb6,0xff,0x00,0x00,0xff,0x00,0x92,0xb6,0x24,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x6d,0x6d,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0xb6,0x6d,0xdb,0x49,0x00,0x00,0xff,0x00,0x92,0xb6,0x24,0x00,0x00,0x00,0xb6,0xff,0xb6,0x00,0x00,0x00,0xff,0x6d,0xff,0xdb,0x24,0x00,0x00,0x24,0xdb,0xff,0x6d,0xff,0x00,0x00,0x00,0xff,0x49,0xff,0xdb,0x00,0x00,0x49,0xdb,0xff,0xff,0xdb,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xdb,0x24,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xb6,0x49,0x00,0x49,0xb6,0x00,0x00,0xdb,0x24,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  ,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x24,0xdb,0xff,0x49,0x00,0x00,0x49,0xff,0x49,0xb6,0x24,0x00,0x00,0x00,0x6d,0xff,0x6d,0x00,0x24,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xb6,0x49,0xff,0x49,0xb6,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0xff,0x00,0xb6,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xb6,0x24,0x00,0xff,0x00,0x00,0x00,0xff,0xff,0xdb,0x24,0x00,0x00,0xff,0x92,0xff,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0xdb,0xff,0xdb,0x00,0x00,0x00,0xdb,0x6d,0x00,0x92,0xff,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0xff,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xff,0x00,0x00,0x00,0x49,0xff,0x24,0x00,0x00,0xdb,0x00,0xdb,0xdb,0x49,0xff,0x00,0x00,0x00,0xff,0x24,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x24,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x6d,0xb6,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x6d,0xff,0x6d,0xff,0x00,0x00,0xff,0x24,0xdb,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xdb,0x24,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0x92,0x00,0x00,0x00,0x24,0xdb,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x24,0xdb,0x00,0xdb,0x24,0x00,0x00,0x6d,0x6d,0xff,0x24,0xb6,0x00,0x00,0x00,0x24,0xff,0x24,0x00,0x00,0x00,0x00,0x92,0xdb,0x92,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xff,0x00,0x00,0xff,0x92,0x00,0x49,0xb6,0x00,0x00,0x92,0x6d,0x00,0x00,0x00,0x00,0x00,0xb6,0x92,0x00,0x6d,0xff,0x00,0x00,0xb6,0x49,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x24,0x24,0xff,0x00,0x00,0x00,0xff,0xb6,0x00,0x49,0xdb,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x49,0xff,0x49,0xdb,0x00,0x00,0xff,0xb6,0x00,0x49,0xdb,0x00,0x00,0xb6,0x92,0x00,0x92,0xb6,0x00,0x00,0xff,0x6d,0x00,0x92,0xb6,0x00,0x00,0xb6,0x92,0x00,0x6d,0xff,0x00,0x00,0x00,0xff,0xb6,0x00,0x00,0x00,0x00,0xff,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x6d,0x6d,0x00,0x6d,0x92,0x00,0x00,0xdb,0x24,0x00,0x24,0xdb,0x00,0x00,0x00,0xdb,0x24,0xdb,0x00,0x00,0x00,0x6d,0x6d,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0x00,0xb6,0x24,0x00,0x00,0x00,0x49,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  ,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xb6,0x24,0xb6,0x00,0x00,0x00,0x00,0x00,0xff,0xdb,0x49,0x00,0x00,0x00,0x24,0xb6,0x49,0xff,0x49,0x49,0xdb,0x49,0xdb,0x00,0xb6,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0x00,0x00,0x00,0x00,0xff,0x00,0xb6,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0x24,0x92,0xb6,0x00,0x00,0x92,0x6d,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x6d,0xdb,0x00,0x00,0xff,0x92,0x00,0x6d,0xdb,0x00,0x00,0x00,0x00,0x92,0x6d,0x00,0x00,0x00,0xb6,0x6d,0x00,0x6d,0xb6,0x00,0x00,0x24,0xdb,0xff,0x92,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xdb,0xb6,0x24,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x24,0xb6,0xdb,0x49,0x00,0x00,0x00,0xff,0x24,0x00,0x00,0x00,0xff,0x00,0xff,0xdb,0x24,0xff,0x00,0x00,0x24,0xdb,0x00,0xdb,0x24,0x00,0x00,0xff,0x00,0x00,0x92,0xb6,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x49,0xb6,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x6d,0xb6,0x49,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x24,0xff,0x24,0xff,0x00,0x00,0xff,0x00,0xb6,0x24,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0xb6,0x49,0x00,0x00,0x00,0x00,0x00,0x6d,0xdb,0x24,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x24,0xff,0x00,0x00,0x00,0x49,0xb6,0xff,0x6d,0x92,0x00,0x00,0x00,0x24,0xff,0x24,0x00,0x00,0x00,0x00,0x24,0xff,0x24,0x00,0x00,0x00,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x92,0xdb,0xff,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xdb,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x24,0x24,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x6d,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x49,0xdb,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xdb,0x00,0xdb,0x24,0x00,0x00,0xb6,0x49,0x92,0x49,0xb6,0x00,0x00,0x00,0x49,0xff,0x49,0x00,0x00,0x00,0x00,0xdb,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x92,0x6d,0x00,0x00,0x00,0x00,0xff,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xff,0x00,0x00,0x49,0xb6,0x92,0x24,0x00,0x92,0x00
-  ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0xb6,0x24,0xb6,0x24,0xb6,0xff,0x00,0x00,0x24,0xb6,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x49,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0xdb,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x49,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0xff,0x6d,0xb6,0x00,0x00,0x6d,0xff,0xff,0xff,0x6d,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x49,0xdb,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x24,0xdb,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xdb,0x24,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x49,0xb6,0xff,0x00,0x00,0xdb,0x24,0x00,0x24,0xdb,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x24,0xff,0x00,0x00,0xff,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x24,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xb6,0xb6,0xb6,0x00,0x00,0x00,0x00,0xdb,0xdb,0xdb,0x6d,0x00,0x00,0x00,0xb6,0x6d,0xb6,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x92,0x24,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xdb,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x49,0xff,0xff,0x49,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x92,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xdb,0x6d,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xdb,0x49,0xdb,0x00,0x00,0x00,0x92,0x92,0xff,0xdb,0x92,0x00,0x00,0x00,0x49,0xff,0x49,0x00,0x00,0x00,0x00,0xb6,0x49,0xdb,0x00,0x00,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0x00,0x49,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0x00,0x00,0x92,0x00,0x24,0x92,0xb6,0x49,0x00
-  ,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0xb6,0x49,0x00,0x00,0x00,0x00,0x00,0xff,0x6d,0xdb,0x00,0x00,0x24,0xb6,0x00,0xb6,0x24,0xb6,0xdb,0x6d,0x00,0x24,0xdb,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x92,0x6d,0x00,0x00,0x00,0x00,0x00,0x92,0x6d,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x49,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x6d,0xb6,0x00,0x00,0x6d,0x92,0x00,0x24,0xdb,0x00,0x00,0x00,0x49,0x92,0x00,0x00,0x00,0x00,0xdb,0x6d,0x00,0x6d,0xdb,0x00,0x00,0x00,0x00,0x24,0xdb,0x49,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0xdb,0x49,0xb6,0xdb,0xdb,0x00,0x00,0x00,0xb6,0x49,0x00,0x49,0xb6,0x00,0x00,0xff,0x00,0x00,0x92,0xdb,0x00,0x00,0xdb,0x6d,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x24,0xdb,0x49,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x6d,0x00,0x24,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xdb,0x00,0x00,0x00,0xff,0x00,0x00,0x24,0xdb,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xdb,0xff,0x00,0x00,0x92,0x6d,0x00,0x6d,0x92,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x6d,0x00,0x6d,0xb6,0x00,0x00,0xff,0x00,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0x6d,0xdb,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xdb,0x6d,0x00,0x6d,0xdb,0x00,0x00,0x00,0x6d,0xff,0x6d,0x00,0x00,0x00,0x00,0xff,0x92,0xff,0x49,0x00,0x00,0x24,0xb6,0x00,0xb6,0x24,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x92,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x24,0x00,0x92,0xff,0x00,0x00,0xff,0x92,0x00,0x49,0xb6,0x00,0x00,0x92,0x6d,0x00,0x00,0x00,0x00,0x00,0xb6,0x92,0x00,0x6d,0xff,0x00,0x00,0x92,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xb6,0x49,0x00,0x6d,0xb6,0x00,0x00,0xff,0x6d,0x00,0x92,0xb6,0x00,0x00,0xb6,0x92,0x00,0x6d,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xff,0x00,0x00,0x00,0x00,0xff,0x24,0x00,0x00,0x00,0xff,0x49,0x00,0xb6,0xff,0x00,0x00,0x00,0x6d,0xff,0x6d,0x00,0x00,0x00,0x6d,0xff,0xb6,0xff,0x49,0x00,0x00,0x00,0xdb,0x24,0xdb,0x00,0x00,0x00,0x00,0x6d,0xff,0x6d,0x00,0x00,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  ,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xb6,0x24,0x00,0x00,0xb6,0x24,0x00,0x49,0xff,0x49,0x24,0xb6,0xff,0xdb,0x49,0x49,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0xdb,0xb6,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0xff,0xdb,0x00,0x00,0x00,0x00,0xdb,0xdb,0xff,0x49,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x24,0xdb,0xff,0xdb,0x24,0x00,0x00,0xff,0xff,0xff,0x6d,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x49,0xff,0x24,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xdb,0x00,0x00,0xff,0xff,0xff,0xb6,0x00,0x00,0x00,0x24,0xb6,0xff,0xff,0xb6,0x00,0x00,0xff,0xff,0xdb,0x6d,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0xff,0xff,0x92,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x00,0xdb,0xff,0xdb,0x49,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x49,0x92,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x6d,0xff,0x00,0x00,0x00,0xb6,0xdb,0xb6,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0xdb,0xff,0x24,0x00,0x00,0xff,0x00,0x00,0x00,0x6d,0x92,0x00,0xff,0xff,0xff,0xb6,0x24,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x24,0xdb,0xff,0xdb,0x24,0x00,0x00,0x00,0x24,0xff,0x24,0x00,0x00,0x00,0x00,0xdb,0x49,0xff,0x49,0x00,0x00,0xb6,0x24,0x00,0x24,0xb6,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xff,0xdb,0x6d,0xff,0x00,0x00,0xff,0x6d,0xff,0xdb,0x00,0x00,0x00,0x00,0x92,0xff,0xff,0xff,0x00,0x00,0x24,0xdb,0xff,0x6d,0xff,0x00,0x00,0x00,0x92,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x92,0xff,0xff,0xff,0xb6,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xb6,0xdb,0xb6,0x00,0x00,0x00,0xff,0x6d,0xff,0xdb,0x00,0x00,0x00,0x24,0xdb,0xff,0x6d,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xdb,0x49,0x00,0x00,0x00,0x00,0x49,0xff,0xff,0x00,0x00,0x49,0xb6,0x92,0x24,0xff,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x49,0xff,0x00,0xff,0x24,0x00,0x00,0xb6,0x49,0x00,0x49,0xb6,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x24,0x00,0x00,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x49,0x00,0x49,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x24,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x24,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x00,0x92,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xff,0xff,0xb6,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdb,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-};
-// clang-format on
-
-constexpr char kTextureFirstChar = '!';
-constexpr char kTextureLastChar = '~';
-constexpr int kTextureTotalChars = kTextureLastChar - kTextureFirstChar + 1;
-constexpr int kCharWidth = 7;
-constexpr int kCharHeight = 11;
-constexpr int kTextureWidth = kTextureTotalChars * kCharWidth;
-constexpr int kTextureHeight = kCharHeight;
-
-std::string vert_shader = SHADER0([]() {  // NOLINT
-  layout(location = 0) in vec2 position;
-  layout(location = 1) in vec2 uv;
-
-  out vec2 texCoords;
-
-  void main() {
-    gl_Position = vec4(position, 0.0, 1.0f);
-    texCoords = vec2(uv.x, 1.0 - uv.y);
-  }
-});
-
-// Uniform locations used in the following shader
-#define UNIFORM_LOCATION_DIGITS 0
-#define UNIFORM_LOCATION_COLOR 1
-
-std::string frag_shader = SHADER0([]() {  // NOLINT
-  precision mediump float;
-
-  out vec4 color;
-  in vec2 texCoords;
-  layout(location = 0) uniform sampler2D digitsTexture;
-  layout(location = 1) uniform vec4 mixColor;
-
-  void main() {
-    float alpha = texture(digitsTexture, texCoords).r;
-    color = vec4(mixColor.rgb, alpha * mixColor.a);
-  }
-});
-
-}  // anonymous namespace
-
-void DebugText::SetViewportSize(int viewport_width, int viewport_height) {
-  pixel_size_screen_space_ = vec2(2.0f / static_cast<float>(viewport_width),
-                                  2.0f / static_cast<float>(viewport_height));
-}
-
-DebugText::DebugText(int max_digits, int viewport_width, int viewport_height) {
-  max_digits_ = max_digits;
-  SetViewportSize(viewport_width, viewport_height);
-
-  shader_.Link(vert_shader, frag_shader);
-  shader_.Use();
-  glUniform1i(UNIFORM_LOCATION_DIGITS, 0);
-
-  // Num quads * 6 vertices per quad.
-  mesh_.SetVertices(max_digits * 6, nullptr, GL_TRIANGLES, GL_DYNAMIC_DRAW);
-
-  glGenTextures(1, &texture_);
-  glBindTexture(GL_TEXTURE_2D, texture_);
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, kTextureWidth, kTextureHeight, 0,
-               GL_RED, GL_UNSIGNED_BYTE, ascii_texture);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-  glBindTexture(GL_TEXTURE_2D, 0);
-  CHECK_GL();
-}
-
-DebugText::~DebugText() {}
-
-void DebugText::Draw(float x, float y, float scale, float r, float g, float b,
-                     float a, const char* str, float stereo_offset,
-                     uint8_t axis) {
-  assert(axis < 2);
-  shader_.Use();
-  glUniform4f(UNIFORM_LOCATION_COLOR, r, g, b, a);
-  glActiveTexture(GL_TEXTURE0);
-  glBindTexture(GL_TEXTURE_2D, texture_);
-  CHECK_GL();
-
-  float px = x;
-  float py = y;
-  float x_advance = scale * static_cast<float>(kCharWidth);
-  float y_advance = 0.0f;
-  float x_height = 0.0f;
-  float y_height = scale * static_cast<float>(kCharHeight);
-  if (axis) {
-    std::swap(x_advance, y_advance);
-    std::swap(x_height, y_height);
-  }
-  x_advance *= pixel_size_screen_space_[0];
-  x_height *= pixel_size_screen_space_[0];
-  y_advance *= pixel_size_screen_space_[1];
-  y_height *= pixel_size_screen_space_[1];
-  int max_digits = stereo_offset != 0.0f ? max_digits_ / 2 : max_digits_;
-  int len = std::min(max_digits, static_cast<int>(strlen(str)));
-
-  int num_quads = stereo_offset != 0.0f ? len * 2 : len;
-  std::tuple<vec2, vec2>* vbo =
-      mesh_.Map(GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT, num_quads * 6);
-
-  int v = 0;
-  for (int i = 0; i < len; ++i) {
-    char digit = str[i];
-    if (digit == '\n') {
-      if (axis == 0) {
-        py += y_height;
-        px = x;
-      } else {
-        px -= x_height;
-        py = y;
-      }
-      continue;
-    }
-    if (digit < kTextureFirstChar || digit > kTextureLastChar) {
-      px += x_advance;
-      py += y_advance;
-      continue;
-    }
-
-    int tex_digit = digit - kTextureFirstChar;
-
-    // Add screenspace tri vertices in CCW order starting with bottom left.
-    float tx =
-        static_cast<float>(tex_digit) / static_cast<float>(kTextureTotalChars);
-    float tx2 = tx + 1.0f / static_cast<float>(kTextureTotalChars);
-    vbo[v * 6 + 0] = {vec2(px, py), vec2(tx, 0.0f)};
-    vbo[v * 6 + 1] = {vec2(px + x_advance, py + y_advance), vec2(tx2, 0.0f)};
-    vbo[v * 6 + 2] = {
-        vec2(px + x_advance + x_height, py + y_advance + y_height),
-        vec2(tx2, 1.0f)};
-    vbo[v * 6 + 3] = vbo[v * 6 + 0];
-    vbo[v * 6 + 4] = vbo[v * 6 + 2];
-    vbo[v * 6 + 5] = {vec2(px + x_height, py + y_height), vec2(tx, 1.0f)};
-    px += x_advance;
-    py += y_advance;
-    ++v;
-  }
-
-  if (stereo_offset != 0.0f) {
-    int num_chars = v;
-    for (int i = 0; i < num_chars; ++i) {
-      for (int j = 0; j < 6; ++j) {
-        vbo[v * 6 + j] = vbo[i * 6 + j];
-        // The 0th tuple element is the vertex position vec2.
-        std::get<0>(vbo[v * 6 + j])[axis] += stereo_offset;
-      }
-      ++v;
-    }
-  }
-
-  mesh_.Unmap();
-
-  mesh_.Draw(v * 6);
-  glBindTexture(GL_TEXTURE_2D, texture_);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvrgraphics/egl_image.cpp b/libs/vr/libdvrgraphics/egl_image.cpp
deleted file mode 100644
index 26d68cd..0000000
--- a/libs/vr/libdvrgraphics/egl_image.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "include/private/dvr/graphics/egl_image.h"
-
-#include <hardware/gralloc.h>
-
-#include <memory>
-
-#include <private/dvr/native_buffer.h>
-
-namespace android {
-namespace dvr {
-
-EGLImageKHR CreateEglImage(EGLDisplay dpy, int width, int height, int format,
-                           int usage) {
-  auto image = std::make_shared<IonBuffer>(width, height, format, usage);
-
-  return eglCreateImageKHR(
-      dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-      static_cast<ANativeWindowBuffer*>(new NativeBuffer(image)), nullptr);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvrgraphics/gpu_profiler.cpp b/libs/vr/libdvrgraphics/gpu_profiler.cpp
deleted file mode 100644
index c8c978d..0000000
--- a/libs/vr/libdvrgraphics/gpu_profiler.cpp
+++ /dev/null
@@ -1,296 +0,0 @@
-#include "include/private/dvr/graphics/gpu_profiler.h"
-
-#include <log/log.h>
-
-#include <private/dvr/clock_ns.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-constexpr int kMaxPendingQueries = 32;
-
-}  // anonynmous namespace
-
-static int64_t AdjustTimerQueryToNs(int64_t gpu_time) { return gpu_time; }
-
-void GpuProfiler::TimerData::reset() {
-  total_elapsed_ns = 0;
-  num_events = 0;
-}
-
-void GpuProfiler::TimerData::print(const char* name) const {
-  ALOGI("GPU_TIME[%s]: %f ms", name,
-        (float)((double)total_elapsed_ns / 1000000.0 / (double)num_events));
-}
-
-// Enter a scope, records the timestamp for later matching with leave.
-void GpuProfiler::TimerData::enter(int64_t timestamp_ns) {
-  entered = true;
-  enter_timestamp_ns = timestamp_ns;
-}
-
-// Compute the elapsed time for the scope.
-void GpuProfiler::TimerData::leave(int64_t timestamp_ns, const char* name,
-                                   std::weak_ptr<int64_t> duration_ns,
-                                   int print_period) {
-  if (!entered) {
-    // We got the leave event but are missing the enter. This can happen if
-    // OnPendingQueryOverflow() is called, or if the calls to enter()/leave()
-    // aren't properly balanced. Ignore the call but print a warning.
-    ALOGW("Ignoring GpuProfiler::TimerData::leave event with no enter event");
-    return;
-  }
-  entered = false;
-
-  int64_t elapsed = timestamp_ns - enter_timestamp_ns;
-  if (elapsed > 1000 * 1000 * 1000) {
-    // More than one second, drop it as invalid data.
-    return;
-  }
-  if (auto out_ns = duration_ns.lock()) {
-    *out_ns = elapsed;
-  }
-  total_elapsed_ns += elapsed;
-  if (print_period > 0 && ++num_events >= print_period) {
-    print(name);
-    reset();
-  }
-}
-
-GpuProfiler* GpuProfiler::Get() {
-  static GpuProfiler* profiler = new GpuProfiler();
-  return profiler;
-}
-
-GpuProfiler::GpuProfiler()
-    : enable_gpu_tracing_(true),
-      has_gl_context_(false),
-      sync_with_cpu_time_(false),
-      gl_timer_offset_ns_(0) {
-}
-
-GpuProfiler::~GpuProfiler() { Clear(); }
-
-bool GpuProfiler::IsGpuProfilingSupported() const {
-  // TODO(jbates) check for GL_EXT_disjoint_timer_query
-  return true;
-}
-
-GLuint GpuProfiler::TryAllocateGlQueryId() {
-  if (pending_gpu_queries_.size() >= kMaxPendingQueries)
-    OnPendingQueryOverflow();
-
-  GLuint query_id = 0;
-  if (gl_timer_query_id_pool_.empty()) {
-    glGenQueries(1, &query_id);
-  } else {
-    query_id = gl_timer_query_id_pool_.top();
-    gl_timer_query_id_pool_.pop();
-  }
-  return query_id;
-}
-
-void GpuProfiler::EnterGlScope(const char* scope_name) {
-  GLuint query_id = TryAllocateGlQueryId();
-  if (query_id != 0) {
-    glQueryCounter(query_id, GL_TIMESTAMP_EXT);
-    pending_gpu_queries_.push_back(
-        GpuTimerQuery(GetSystemClockNs(), scope_name, std::weak_ptr<int64_t>(),
-                      -1, query_id, GpuTimerQuery::kQueryBeginScope));
-  }
-}
-
-void GpuProfiler::LeaveGlScope(const char* scope_name,
-                               std::weak_ptr<int64_t> duration_ns,
-                               int print_period) {
-  GLuint query_id = TryAllocateGlQueryId();
-  if (query_id != 0) {
-    glQueryCounter(query_id, GL_TIMESTAMP_EXT);
-    pending_gpu_queries_.push_back(
-        GpuTimerQuery(GetSystemClockNs(), scope_name, duration_ns, print_period,
-                      query_id, GpuTimerQuery::kQueryEndScope));
-  }
-}
-
-void GpuProfiler::OnGlContextCreated() {
-  has_gl_context_ = true;
-  gl_timer_offset_ns_ = 0;
-  SyncGlTimebase();
-}
-
-void GpuProfiler::OnGlContextDestroyed() {
-  has_gl_context_ = false;
-  Clear();
-}
-
-void GpuProfiler::Clear() {
-  events_.clear();
-  for (auto& query : pending_gpu_queries_)
-    glDeleteQueries(1, &query.query_id);
-  pending_gpu_queries_.clear();
-  while (!gl_timer_query_id_pool_.empty()) {
-    GLuint id = gl_timer_query_id_pool_.top();
-    gl_timer_query_id_pool_.pop();
-    glDeleteQueries(1, &id);
-  }
-}
-
-void GpuProfiler::OnPendingQueryOverflow() {
-  ALOGW("Reached limit of %d pending queries in GpuProfiler."
-        " Clearing all queries.", kMaxPendingQueries);
-  Clear();
-}
-
-void GpuProfiler::SyncGlTimebase() {
-  if (!sync_with_cpu_time_) {
-    return;
-  }
-
-  // Clear disjoint error status.
-  // This error status indicates that we need to ignore the result of the
-  // timer query because of some kind of disjoint GPU event such as heat
-  // throttling.
-  GLint disjoint = 0;
-  glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint);
-
-  // Try to get the current GL timestamp. Since the GPU can supposedly fail to
-  // produce a timestamp occasionally we try a few times before giving up.
-  int attempts_remaining = 3;
-  do {
-    GLint64 gl_timestamp = 0;
-    glGetInteger64v(GL_TIMESTAMP_EXT, &gl_timestamp);
-    gl_timestamp = AdjustTimerQueryToNs(gl_timestamp);
-
-    // Now get the CPU timebase.
-    int64_t cpu_timebase_ns = static_cast<int64_t>(GetSystemClockNs());
-
-    disjoint = 0;
-    glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint);
-    if (!disjoint) {
-      gl_timer_offset_ns_ = cpu_timebase_ns - gl_timestamp;
-      break;
-    }
-    ALOGW("WARNING: Skipping disjoint GPU timestamp");
-  } while (--attempts_remaining > 0);
-
-  if (attempts_remaining == 0) {
-    ALOGE("ERROR: Failed to sync GL timebase due to disjoint results\n");
-    gl_timer_offset_ns_ = 0;
-  }
-}
-
-void GpuProfiler::QueryFrameBegin() {
-  GLuint begin_frame_id = TryAllocateGlQueryId();
-  if (begin_frame_id != 0) {
-    glQueryCounter(begin_frame_id, GL_TIMESTAMP_EXT);
-    pending_gpu_queries_.push_back(
-        GpuTimerQuery(GetSystemClockNs(), 0, std::weak_ptr<int64_t>(), -1,
-                      begin_frame_id, GpuTimerQuery::kQueryBeginFrame));
-  }
-}
-
-void GpuProfiler::PollGlTimerQueries() {
-  if (!enabled()) {
-    return;
-  }
-
-#ifdef ENABLE_DISJOINT_TIMER_IGNORING
-  bool has_checked_disjoint = false;
-  bool was_disjoint = false;
-#endif
-  for (;;) {
-    if (pending_gpu_queries_.empty()) {
-      // No queries pending.
-      return;
-    }
-
-    GpuTimerQuery query = pending_gpu_queries_.front();
-
-    GLint available = 0;
-    glGetQueryObjectiv(query.query_id, GL_QUERY_RESULT_AVAILABLE_EXT,
-                       &available);
-    if (!available) {
-      // No queries available.
-      return;
-    }
-
-    // Found an available query, remove it from pending queue.
-    pending_gpu_queries_.pop_front();
-    gl_timer_query_id_pool_.push(query.query_id);
-
-#ifdef ENABLE_DISJOINT_TIMER_IGNORING
-    if (!has_checked_disjoint) {
-      // Check if we need to ignore the result of the timer query because
-      // of some kind of disjoint GPU event such as heat throttling.
-      // If so, we ignore all events that are available during this loop.
-      has_checked_disjoint = true;
-      GLint disjoint_occurred = 0;
-      glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_occurred);
-      was_disjoint = !!disjoint_occurred;
-      if (was_disjoint) {
-        ALOGW("Skipping disjoint GPU events");
-      }
-    }
-
-    if (was_disjoint) {
-      continue;
-    }
-#endif
-
-    GLint64 timestamp_ns = 0;
-    glGetQueryObjecti64v(query.query_id, GL_QUERY_RESULT_EXT, &timestamp_ns);
-    timestamp_ns = AdjustTimerQueryToNs(timestamp_ns);
-
-    int64_t adjusted_timestamp_ns;
-
-    if (sync_with_cpu_time_) {
-      adjusted_timestamp_ns = timestamp_ns + gl_timer_offset_ns_;
-
-      if (query.type == GpuTimerQuery::kQueryBeginFrame ||
-          query.type == GpuTimerQuery::kQueryBeginScope) {
-        if (adjusted_timestamp_ns < query.timestamp_ns) {
-          // GPU clock is behind, adjust our offset to correct it.
-          gl_timer_offset_ns_ += query.timestamp_ns - adjusted_timestamp_ns;
-          adjusted_timestamp_ns = query.timestamp_ns;
-        }
-      }
-    } else {
-      adjusted_timestamp_ns = timestamp_ns;
-    }
-
-    switch (query.type) {
-      case GpuTimerQuery::kQueryBeginFrame:
-        break;
-      case GpuTimerQuery::kQueryBeginScope:
-        events_[query.scope_name].enter(adjusted_timestamp_ns);
-        break;
-      case GpuTimerQuery::kQueryEndScope:
-        events_[query.scope_name].leave(adjusted_timestamp_ns, query.scope_name,
-                                        query.duration_ns, query.print_period);
-        break;
-    }
-  }
-}
-
-void GpuProfiler::FinishGlTimerQueries() {
-  if (!enabled()) {
-    return;
-  }
-
-  glFlush();
-  PollGlTimerQueries();
-  int max_iterations = 100;
-  while (!pending_gpu_queries_.empty()) {
-    if (--max_iterations <= 0) {
-      ALOGE("Error: GL timer queries failed to finish.");
-      break;
-    }
-    PollGlTimerQueries();
-    usleep(1000);
-  }
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/blur.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/blur.h
deleted file mode 100644
index c1c2b91..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/blur.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef ANDROID_DVR_GRAPHICS_BLUR_H_
-#define ANDROID_DVR_GRAPHICS_BLUR_H_
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-
-#include <algorithm>
-#include <vector>
-
-#include <private/dvr/ring_buffer.h>
-
-namespace android {
-namespace dvr {
-
-class Blur {
- public:
-  // Construct a blur kernel for GL that works on source textures of the given
-  // size. The given source_texture is configured for linear filtering.
-  // |source_texture_target| is for |source_texture| while
-  // |target_texture_target| is used for all the intermediate and output
-  // buffers.
-  // |num_blur_outputs| determines how many blurs this instance can be used for
-  // in a single frame.
-  Blur(int w, int h, GLuint source_texture, GLint source_texture_target,
-       GLint target_texture_target, bool is_external, EGLDisplay display,
-       int num_blur_outputs);
-  ~Blur();
-
-  // Place all output textures back into the FBO pool for a new frame.
-  // Call this at the start of each frame before doing one or more blurs.
-  void StartFrame();
-
-  // Draw a multipass blur from the given source_texture. The resulting texture
-  // is returned. The given source_texture is configured for linear filtering.
-  // A segfault will occur if the application calls DrawBlur more times than
-  // |num_blur_outputs| without calling StartFrame.
-  // It is up to the calling code to change the framebuffer after this method.
-  GLuint DrawBlur(GLuint source_texture);
-
-  float width() const { return width_; }
-  float height() const { return height_; }
-  float scale() const { return scale_; }
-
-  // Set the scale of the blur, usually between 0 and 1. This is only useful for
-  // animation.
-  // At the steady state, the scale should be set to 1. To change the steady
-  // state blur appearance, the kernel patterns in DrawBlur should be modified
-  // instead of using scale.
-  void set_scale(float scale) { scale_ = scale; }
-
-  // Animate the blur by |delta|. Clamp the result between |low| and |high|.
-  // Recommended range is between 0 and 1, but other values will also work.
-  void animate(float delta, float low, float high) {
-    scale_ += delta;
-    scale_ = std::min(high, std::max(low, scale_));
-  }
-
- private:
-  struct Fbo {
-    Fbo() : fbo(0), renderbuffer(0), texture(0), egl_image(0) {}
-    GLuint fbo;
-    GLuint renderbuffer;
-    GLuint texture;
-    EGLImageKHR egl_image;
-  };
-
-  Fbo CreateFbo(int w, int h, GLuint source_texture, GLint tex_target,
-                bool is_external);
-
-  // EGL display for when target texture format is EGL image.
-  EGLDisplay display_;
-  GLint target_texture_target_;
-  int width_;
-  int height_;
-  Fbo source_fbo_;
-  Fbo fbo_half_;
-  std::vector<Fbo> fbo_q_;
-  RingBuffer<Fbo> fbo_q_free_;
-  float scale_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_GRAPHICS_BLUR_H_
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/debug_text.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/debug_text.h
deleted file mode 100644
index bbe891b..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/debug_text.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef ANDROID_DVR_GRAPHICS_FPS_GRAPH_H
-#define ANDROID_DVR_GRAPHICS_FPS_GRAPH_H
-
-#include <private/dvr/graphics/mesh.h>
-#include <private/dvr/graphics/shader_program.h>
-
-namespace android {
-namespace dvr {
-
-// Debug text class that draws small text with Open GL.
-class DebugText {
- public:
-  DebugText(int max_digits, int viewport_width, int viewport_height);
-  ~DebugText();
-
-  void SetViewportSize(int viewport_width, int viewport_height);
-
-  // Draw text at given screen-space location, scale and color.
-  // A |scale| of 1.0 means 1:1 pixel mapping with current viewport size.
-  // If |stereo_offset| is not zero, the string will be rendered again
-  // with the given offset for stereo rendering. The stereo axis can be on
-  // screenspace x or y axis, which is given by |axis| as 0 or 1,
-  // respectively. |axis| also determines the direction that text is rendered.
-  void Draw(float x, float y, float scale, float r, float g, float b, float a,
-            const char* str, float stereo_offset, uint8_t axis);
-
-  // Helper that draws green text at render target resolution.
-  void Draw(float x, float y, const char* str, float stereo_offset,
-            uint8_t axis) {
-    Draw(x, y, 1.0f, 0, 1, 0, 1, str, stereo_offset, axis);
-  }
-
- private:
-  int max_digits_;
-  vec2 pixel_size_screen_space_;
-  ShaderProgram shader_;
-  GLuint texture_;
-  Mesh<vec2, vec2> mesh_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_GRAPHICS_FPS_GRAPH_H
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/egl_image.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/egl_image.h
deleted file mode 100644
index 59de61e..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/egl_image.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef ANDROID_DVR_GRAPHICS_EGL_IMAGE_H_
-#define ANDROID_DVR_GRAPHICS_EGL_IMAGE_H_
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-namespace android {
-namespace dvr {
-
-// Create an EGLImage with texture storage defined by the given format and
-// usage flags.
-// For example, to create an RGBA texture for rendering to, specify:
-//   format = HAL_PIXEL_FORMAT_RGBA_8888;
-//   usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER;
-EGLImageKHR CreateEglImage(EGLDisplay dpy, int width, int height, int format,
-                           int usage);
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_GRAPHICS_EGL_IMAGE_H_
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/gpu_profiler.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/gpu_profiler.h
deleted file mode 100644
index c6e752b..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/gpu_profiler.h
+++ /dev/null
@@ -1,236 +0,0 @@
-#ifndef ANDROID_DVR_GPU_PROFILER_H_
-#define ANDROID_DVR_GPU_PROFILER_H_
-
-// This file contains classes and macros related to run-time performance
-// profiling of GPU processing.
-
-#include <deque>
-#include <map>
-#include <memory>
-#include <stack>
-#include <vector>
-
-#include <private/dvr/graphics/vr_gl_extensions.h>
-
-namespace android {
-namespace dvr {
-
-// While enabled, GL commands will be submitted each frame to query timestamps
-// of GPU workloads that have been traced using the ION_PROFILE_GPU macro
-// defined below.
-//
-// Basic workflow:
-//  - have the app framework call PollGlTimerQueries at the start of each frame.
-//  - place ION_PROFILE_GPU("MyGlWorkload") at the start of code scopes where
-//    GL draw commands are performed that you want to trace.
-class GpuProfiler {
- public:
-  // Gets the GpuProfiler singleton instance.
-  static GpuProfiler* Get();
-
-  GpuProfiler();
-  ~GpuProfiler();
-
-  bool IsGpuProfilingSupported() const;
-
-  // Enables runtime GPU tracing. While enabled, GL commands will be submitted
-  // each frame to query timestamps of GPU workloads that have been traced using
-  // one of the TRACE_GPU* macros defined below.
-  void SetEnableGpuTracing(bool enabled) { enable_gpu_tracing_ = enabled; }
-
-  bool enabled() const { return enable_gpu_tracing_ && has_gl_context_; }
-
-  // Attempt to keep the GPU times in sync with CPU times.
-  void SetEnableSyncCpuTime(bool enabled) { sync_with_cpu_time_ = enabled; }
-
-  // When sync cpu time is enabled because of mobile GPU timer query issues,
-  // it can sometimes help to put a beginning timer query at the start of the
-  // frame to sync the CPU time when GPU work begins.
-  void QueryFrameBegin();
-
-  // Polls (non-blocking) for completed GL timer query data and adds events into
-  // the trace buffer. Must call once close to the start of each frame.
-  void PollGlTimerQueries();
-
-  // Call glFinish and process all pending timer queries.
-  void FinishGlTimerQueries();
-
-  // Records the beginning of a scoped GL trace event.
-  void EnterGlScope(const char* scope_name);
-
-  // Records the end of a scoped GL trace event.
-  void LeaveGlScope(const char* scope_name, std::weak_ptr<int64_t> duration_ns,
-                    int print_period);
-
-  // Must be called when the GL context is created. The GpuProfiler will be
-  // inactive until this is called.
-  void OnGlContextCreated();
-
-  // Must be called before the GL context is destroyed. The GpuProfiler will be
-  // inactive until a call to OnGlContextCreated().
-  void OnGlContextDestroyed();
-
- private:
-  // Data to queue the pending GPU timer queries that need to be polled
-  // for completion.
-  struct GpuTimerQuery {
-    enum QueryType {
-      kQueryBeginFrame,
-      kQueryBeginScope,
-      kQueryEndScope,
-    };
-
-    // scope_id is only required for kQueryBeginScope query types.
-    GpuTimerQuery(int64_t timestamp_ns, const char* scope_name,
-                  std::weak_ptr<int64_t> duration_ns, int print_period,
-                  GLuint query_id, QueryType type)
-        : timestamp_ns(timestamp_ns),
-          scope_name(scope_name),
-          duration_ns(duration_ns),
-          print_period(print_period),
-          query_id(query_id),
-          type(type) {}
-
-    int64_t timestamp_ns;
-    const char* scope_name;
-    std::weak_ptr<int64_t> duration_ns;
-    int print_period;
-    GLuint query_id;
-    QueryType type;
-  };
-
-  // Struct that tracks timing data for a particular trace scope.
-  struct TimerData {
-    void reset();
-
-    // Print the profiling data.
-    void print(const char* name) const;
-
-    // Enter a scope, records the timestamp for later matching with leave.
-    void enter(int64_t timestamp_ns);
-
-    // Compute the elapsed time for the scope.
-    void leave(int64_t timestamp_ns, const char* name,
-               std::weak_ptr<int64_t> duration_ns, int print_period);
-
-    bool entered = false;
-    int64_t total_elapsed_ns = 0;
-    int64_t enter_timestamp_ns = 0;
-    int num_events = 0;
-  };
-
-  // Clear out events and free GL resources.
-  void Clear();
-
-  // Called when we detect that we've overflowed the pending query queue. This
-  // shouldn't occur in practice, and probably indicates some internal
-  // mismanagement of the gl query objects.
-  void OnPendingQueryOverflow();
-
-  // Synchronises the GL timebase with the CallTraceManager timebase.
-  void SyncGlTimebase();
-
-  // Returns a GL timer query ID if possible. Otherwise returns 0.
-  GLuint TryAllocateGlQueryId();
-
-  // Setting for enabling GPU tracing.
-  bool enable_gpu_tracing_;
-
-  // True if we have a GL context, false otherwise. When the GpuProfiler is
-  // first created we assume no GL context.
-  bool has_gl_context_;
-
-  // Setting for synchronizing GPU timestamps with CPU time.
-  bool sync_with_cpu_time_;
-
-  // Nanosecond offset to the GL timebase to compute the CallTraceManager time.
-  int64_t gl_timer_offset_ns_;
-
-  std::map<const char*, TimerData> events_;
-
-  // For GPU event TraceRecords, this tracks the pending queries that will
-  // be asynchronously polled (in order) and then added to the TraceRecorder
-  // buffer with the GPU timestamps.
-  std::deque<GpuTimerQuery> pending_gpu_queries_;
-
-  // Available ids for use with GLTimerQuery as needed. This will generally
-  // reach a steady state after a few frames. Always push and pop from the back
-  // to avoid shifting the vector.
-  std::stack<GLuint, std::vector<GLuint> > gl_timer_query_id_pool_;
-};
-
-// Traces the GPU start and end times of the GL commands submitted in the
-// same scope. Typically used via the TRACE_GPU macro.
-class ScopedGlTracer {
- public:
-  ScopedGlTracer(const char* name, std::weak_ptr<int64_t> duration_ns,
-                 int print_period, bool finish)
-      : name_(name),
-        duration_ns_(duration_ns),
-        print_period_(print_period),
-        is_finish_(finish) {
-    GpuProfiler* profiler = GpuProfiler::Get();
-    if (profiler->enabled()) {
-      profiler->EnterGlScope(name);
-    }
-  }
-
-  ~ScopedGlTracer() {
-    GpuProfiler* profiler = GpuProfiler::Get();
-    if (profiler->enabled()) {
-      profiler->LeaveGlScope(name_, duration_ns_, print_period_);
-      if (is_finish_) {
-        GpuProfiler::Get()->FinishGlTimerQueries();
-      }
-    }
-  }
-
- private:
-  const char* name_;
-  std::weak_ptr<int64_t> duration_ns_;
-  int print_period_;
-  bool is_finish_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#define PROFILING_PASTE1(x, y) x##y
-#define PROFILING_PASTE2(x, y) PROFILING_PASTE1(x, y)
-#define PROFILING_PASTE3(x) PROFILING_PASTE2(x, __LINE__)
-
-// This macro can be used in any GL operation scope to trace the resulting
-// GPU work. The argument must be a literal string. Specify the number of frames
-// to wait before printing an average result in the num_frames_period argument.
-#define TRACE_GPU_PRINT(group_name, num_frames_period)        \
-  (void)group_name " must be a literal string.";              \
-  android::dvr::ScopedGlTracer PROFILING_PASTE3(gpu_tracer_)( \
-      group_name, std::weak_ptr<int64_t>(), num_frames_period, false)
-
-// This macro can be used in any GL operation scope to trace the resulting
-// GPU work. The argument must be a literal string. The duration parameter
-// is a weak_ptr to a int64_t that will receive duration values asynchronously
-// during calls to PollGlTimerQueries.
-#define TRACE_GPU(group_name, duration_ns_weak_ptr)           \
-  (void)group_name " must be a literal string.";              \
-  android::dvr::ScopedGlTracer PROFILING_PASTE3(gpu_tracer_)( \
-      group_name, duration_ns_weak_ptr, -1, false)
-
-// This macro can be used in any GL operation scope to trace the resulting
-// GPU work. The argument must be a literal string. Specify the number of frames
-// to wait before printing an average result in the num_frames_period argument.
-#define TRACE_GPU_PRINT_FINISH(group_name)                    \
-  (void)group_name " must be a literal string.";              \
-  android::dvr::ScopedGlTracer PROFILING_PASTE3(gpu_tracer_)( \
-      group_name, std::weak_ptr<int64_t>(), 1, true)
-
-// This macro can be used in any GL operation scope to trace the resulting
-// GPU work. The argument must be a literal string. The duration parameter
-// is a weak_ptr to a int64_t that will receive duration values asynchronously
-// during calls to PollGlTimerQueries.
-#define TRACE_GPU_FINISH(group_name, duration_ns_weak_ptr)    \
-  (void)group_name " must be a literal string.";              \
-  android::dvr::ScopedGlTracer PROFILING_PASTE3(gpu_tracer_)( \
-      group_name, duration_ns_weak_ptr, -1, true)
-
-#endif  // ANDROID_DVR_GPU_PROFILER_H_
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/indexed_mesh.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/indexed_mesh.h
deleted file mode 100644
index 7e74a75..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/indexed_mesh.h
+++ /dev/null
@@ -1,154 +0,0 @@
-#ifndef ANDROID_DVR_GRAPHICS_INDEXED_MESH_H_
-#define ANDROID_DVR_GRAPHICS_INDEXED_MESH_H_
-
-#include <private/dvr/graphics/vertex_attributes.h>
-#include <private/dvr/types.h>
-
-#include <EGL/egl.h>
-#include <GLES3/gl3.h>
-#include <tuple>
-
-namespace android {
-namespace dvr {
-
-namespace Details {
-
-// We can have 16 and 32bit indices.
-template <typename T>
-GLenum GetIndexType();
-template <>
-inline GLenum GetIndexType<uint16_t>() {
-  return GL_UNSIGNED_SHORT;
-}
-template <>
-inline GLenum GetIndexType<uint32_t>() {
-  return GL_UNSIGNED_INT;
-}
-
-}  // namespace Details
-
-template <typename INDEX_TYPE, typename... Attributes>
-class IndexedMesh {
- public:
-  static const int attribute_size = sizeof(std::tuple<Attributes...>);
-
-  IndexedMesh() {}
-  IndexedMesh(INDEX_TYPE number_of_vertices, const void* vertices,
-              INDEX_TYPE number_of_indices, const void* indices) {
-    SetVertices(number_of_vertices, vertices, number_of_indices, indices);
-  }
-
-  IndexedMesh(INDEX_TYPE number_of_vertices, const void* vertices,
-              INDEX_TYPE number_of_indices, const void* indices,
-              GLenum element_type) {
-    SetVertices(number_of_vertices, vertices, number_of_indices, indices,
-                element_type);
-  }
-
-  IndexedMesh(IndexedMesh&& to_move) { Swap(to_move); }
-
-  ~IndexedMesh() { DeleteGLData(); }
-
-  IndexedMesh& operator=(IndexedMesh&& to_move) {
-    Swap(to_move);
-    return *this;
-  }
-
-  operator bool() const { return mesh_vbo_ != 0; }
-
-  void Swap(IndexedMesh& to_swap) {
-    std::swap(mesh_vbo_, to_swap.mesh_vbo_);
-    std::swap(mesh_vao_, to_swap.mesh_vao_);
-    std::swap(mesh_ibo_, to_swap.mesh_ibo_);
-    std::swap(number_of_indices_, to_swap.number_of_indices_);
-    std::swap(element_type_, to_swap.element_type_);
-  }
-
-  void Draw() {
-    if (!mesh_vbo_)
-      return;
-
-    glBindVertexArray(mesh_vao_);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_ibo_);
-
-    glDrawElements(element_type_, number_of_indices_,
-                   Details::GetIndexType<INDEX_TYPE>(), nullptr);
-
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    glBindVertexArray(0);
-  }
-
-  void SetVertices(INDEX_TYPE number_of_vertices, const void* vertices,
-                   INDEX_TYPE number_of_indices, const void* indices,
-                   GLenum element_type) {
-    element_type_ = element_type;
-    SetVertices(number_of_vertices, vertices, number_of_indices, indices);
-  }
-
-  void SetVertices(INDEX_TYPE number_of_vertices, const void* vertices,
-                   INDEX_TYPE number_of_indices, const void* indices) {
-    DeleteGLData();
-    number_of_indices_ = number_of_indices;
-    glGenBuffers(1, &mesh_vbo_);
-    glGenVertexArrays(1, &mesh_vao_);
-    glGenBuffers(1, &mesh_ibo_);
-    glBindVertexArray(mesh_vao_);
-
-    glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo_);
-    glBufferData(GL_ARRAY_BUFFER, attribute_size * number_of_vertices, vertices,
-                 GL_STATIC_DRAW);
-
-    SetupAttributes();
-
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_ibo_);
-    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
-                 sizeof(INDEX_TYPE) * number_of_indices_, indices,
-                 GL_STATIC_DRAW);
-
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindVertexArray(0);
-  }
-
-  size_t GetAttributesSize() const { return attribute_size; }
-
- private:
-  IndexedMesh(const IndexedMesh&) = delete;
-  IndexedMesh& operator=(const IndexedMesh&) = delete;
-
-  void DeleteGLData() {
-    if (mesh_vbo_) {
-      glDeleteBuffers(1, &mesh_vbo_);
-      glDeleteVertexArrays(1, &mesh_vao_);
-      glDeleteBuffers(1, &mesh_ibo_);
-      mesh_vbo_ = 0;
-      mesh_vao_ = 0;
-      mesh_ibo_ = 0;
-      number_of_indices_ = 0;
-    }
-  }
-
-  void SetupAttributes() {
-    const auto size = std::tuple_size<std::tuple<Attributes...>>::value;
-    Details::VertexAttribHelper<size - 1, Attributes...>{}();
-  }
-
- private:
-  GLuint mesh_vbo_ = 0;
-  GLuint mesh_vao_ = 0;
-  GLuint mesh_ibo_ = 0;
-  INDEX_TYPE number_of_indices_ = 0;
-
-  GLenum element_type_ = GL_TRIANGLES;
-};
-
-template <typename... Attributes>
-using Indexed16Mesh = IndexedMesh<uint16_t, Attributes...>;
-
-template <typename... Attributes>
-using Indexed32Mesh = IndexedMesh<uint32_t, Attributes...>;
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_GRAPHICS_INDEXED_MESH_H_
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/mesh.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/mesh.h
deleted file mode 100644
index 45bc108..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/mesh.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifndef ANDROID_DVR_GRAPHICS_MESH_H_
-#define ANDROID_DVR_GRAPHICS_MESH_H_
-
-#include <private/dvr/graphics/vertex_attributes.h>
-#include <private/dvr/types.h>
-
-#include <EGL/egl.h>
-#include <GLES3/gl3.h>
-#include <tuple>
-
-namespace android {
-namespace dvr {
-
-template <typename... Attributes>
-class Mesh {
- public:
-  static const int attribute_size = sizeof(std::tuple<Attributes...>);
-
-  Mesh() {}
-
-  Mesh(uint32_t number_of_vertices, const void* vertices) {
-    SetVertices(number_of_vertices, vertices);
-  }
-
-  Mesh(uint32_t number_of_vertices, const void* vertices, GLenum element_type) {
-    SetVertices(number_of_vertices, vertices, element_type);
-  }
-
-  Mesh(Mesh&& to_move) { Swap(to_move); }
-
-  ~Mesh() { DeleteGLData(); }
-
-  Mesh& operator=(const Mesh&& to_move) {
-    Swap(to_move);
-    return *this;
-  }
-
-  operator bool() const { return mesh_vbo_ != 0; }
-
-  void Swap(Mesh& to_swap) {
-    std::swap(mesh_vbo_, to_swap.mesh_vbo_);
-    std::swap(mesh_vao_, to_swap.mesh_vao_);
-    std::swap(number_of_vertices_, to_swap.number_of_vertices_);
-    std::swap(element_type_, to_swap.element_type_);
-  }
-
-  void Draw(uint32_t number_of_vertices) {
-    if (!mesh_vbo_)
-      return;
-
-    glBindVertexArray(mesh_vao_);
-    glDrawArrays(element_type_, 0, number_of_vertices);
-    glBindVertexArray(0);
-  }
-
-  void Draw() { Draw(number_of_vertices_); }
-
-  void SetVertices(uint32_t number_of_vertices, const void* vertices,
-                   GLenum element_type, GLenum usage) {
-    DeleteGLData();
-    element_type_ = element_type;
-    number_of_vertices_ = number_of_vertices;
-    glGenBuffers(1, &mesh_vbo_);
-    glGenVertexArrays(1, &mesh_vao_);
-    glBindVertexArray(mesh_vao_);
-
-    glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo_);
-    glBufferData(GL_ARRAY_BUFFER, attribute_size * number_of_vertices, vertices,
-                 usage);
-
-    SetupAttributes();
-
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindVertexArray(0);
-  }
-
-  void SetVertices(uint32_t number_of_vertices, const void* vertices) {
-    SetVertices(number_of_vertices, vertices, element_type_, GL_STATIC_DRAW);
-  }
-
-  void SetVertices(uint32_t number_of_vertices, const void* vertices,
-                   GLenum element_type) {
-    SetVertices(number_of_vertices, vertices, element_type, GL_STATIC_DRAW);
-  }
-
-  std::tuple<Attributes...>* Map(GLbitfield access, int num_vertices) {
-    glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo_);
-    void* ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0,
-                                 attribute_size * num_vertices, access);
-    return static_cast<std::tuple<Attributes...>*>(ptr);
-  }
-
-  void Unmap() {
-    glUnmapBuffer(GL_ARRAY_BUFFER);
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-  }
-
- private:
-  Mesh(const Mesh&) = delete;
-  Mesh& operator=(const Mesh&) = delete;
-
-  void DeleteGLData() {
-    if (mesh_vbo_) {
-      glDeleteBuffers(1, &mesh_vbo_);
-      glDeleteVertexArrays(1, &mesh_vao_);
-      mesh_vbo_ = 0;
-      mesh_vao_ = 0;
-      number_of_vertices_ = 0;
-    }
-  }
-
-  void SetupAttributes() {
-    const auto size = std::tuple_size<std::tuple<Attributes...>>::value;
-    Details::VertexAttribHelper<size - 1, Attributes...>{}();
-  }
-
- private:
-  GLuint mesh_vbo_ = 0;
-  GLuint mesh_vao_ = 0;
-  uint32_t number_of_vertices_ = 0;
-
-  GLenum element_type_ = GL_TRIANGLES;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_GRAPHICS_MESH_H_
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/shader_program.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/shader_program.h
deleted file mode 100644
index 4218a73..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/shader_program.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef ANDROID_DVR_SHADER_PROGRAM_H_
-#define ANDROID_DVR_SHADER_PROGRAM_H_
-
-#include <EGL/egl.h>
-#include <GLES3/gl31.h>
-#include <sys/cdefs.h>
-#include <string>
-#include <vector>
-
-namespace android {
-namespace dvr {
-
-// Helper function that allows you to write a shader as a Lambda.  This allows
-// an IDE to syntax highlight the contents of a shader, as well as preventing
-// quotations on each line. Usage: std::string vs = SHADER0([]() { ... });
-template <size_t size>
-std::string StripLambda(const char (&shader)[size]) {
-  return std::string(shader + 6, shader + size - 2);
-}
-
-#define SHADER0(Src) ::android::dvr::StripLambda(#Src)
-
-// Helper function that takes a shader source string containing %0, %1, %n,
-// tokens and replaces them with replacements[0], replacements[1],
-// replacements[n].  For example:
-// shader = "{
-//   uniform vec2 %0;
-//   %1
-//   ...
-//     %0.x = 1.0; ...
-//     %1(%0);
-// }"
-// -> %0 = "myVarName", %1 = "void f(vec2 v) { ... }"
-std::string ComposeShader(const std::string& shader_code,
-                          const std::vector<std::string>& replacements);
-
-class ShaderProgram {
- public:
-  ShaderProgram();
-  ShaderProgram(const std::string& vertext_source,
-                const std::string& fragment_source);
-  ShaderProgram(ShaderProgram&&);
-  ~ShaderProgram();
-
-  ShaderProgram& operator=(ShaderProgram&&);
-
-  void Link(const std::string& vertext_source,
-            const std::string& fragment_source);
-
-  void Link(const std::string& compute_source);
-
-  void Use() const;
-
-  GLuint GetProgram() const { return program_; }
-  GLuint GetUniformLocation(const GLchar* name) const {
-    return glGetUniformLocation(program_, name);
-  }
-  GLuint GetAttribLocation(const GLchar* name) const {
-    return glGetAttribLocation(program_, name);
-  }
-
-  bool IsUsable() const { return program_ != 0; }
-  explicit operator bool() const { return IsUsable(); }
-
- private:
-  ShaderProgram(const ShaderProgram&) = delete;
-  ShaderProgram& operator=(const ShaderProgram&) = delete;
-
-  GLuint program_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SHADER_PROGRAM_H_
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/timer_query.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/timer_query.h
deleted file mode 100644
index 11d4d01..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/timer_query.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef ANDROID_DVR_GRAPHICS_TIMER_QUERY_H_
-#define ANDROID_DVR_GRAPHICS_TIMER_QUERY_H_
-
-#include <GLES3/gl3.h>
-
-namespace android {
-namespace dvr {
-
-// Class used to asynchronously query time between draw calls on gpu.
-class TimerQuery {
- public:
-  TimerQuery();
-  ~TimerQuery();
-
-  // Marks the start of the timer on gpu.
-  void Begin();
-
-  // Marks the end of the timer on gpu.
-  void End();
-
-  // Gets the time that has passed from call to Begin to End.
-  // Should be called only after the frame has been presented (after the call to
-  // swapbuffers).
-  double GetTimeInMS();
-
- private:
-  // Generates OpenGL query object.
-  void Init();
-  // Deletes OpenGL query object.
-  void Delete();
-
-  GLuint query_ = 0;
-
-  friend class SyncTimerQuery;
-};
-
-// Simplification of TimerQuery that allows to synchronously query time used
-// for draw calls on gpu by doing glFlush and stalling cpu.
-class SyncTimerQuery {
- public:
-  SyncTimerQuery();
-
-  double FlushAndGetTimeInMS();  // Note: This WILL cause a glFlush()
-
- private:
-  TimerQuery timer_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_GRAPHICS_TIMER_QUERY_H_
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/vertex_attributes.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/vertex_attributes.h
deleted file mode 100644
index dac5b64..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/vertex_attributes.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef ANDROID_DVR_GRAPHICS_VERTEX_ATTRIBUTES_H_
-#define ANDROID_DVR_GRAPHICS_VERTEX_ATTRIBUTES_H_
-
-#include <private/dvr/types.h>
-
-#include <EGL/egl.h>
-#include <GLES3/gl3.h>
-#include <tuple>
-
-namespace android {
-namespace dvr {
-
-namespace Details {
-
-// Set up the vertex attributes by iterating over the variadic template
-// parameters.  The supported attributes are the GetSize and GetType
-// specializations.
-// clang-format off
-template<typename T> GLint GetSize();
-template<> inline GLint GetSize<vec2>() { return 2; }
-template<> inline GLint GetSize<vec3>() { return 3; }
-template<> inline GLint GetSize<vec4>() { return 4; }
-
-template<typename T> GLenum GetType();
-template<> inline GLenum GetType<vec2>() { return GL_FLOAT; }
-template<> inline GLenum GetType<vec3>() { return GL_FLOAT; }
-template<> inline GLenum GetType<vec4>() { return GL_FLOAT; }
-// clang-format on
-
-template <typename T>
-void VertexAttrib(GLuint index, GLsizei stride, const GLvoid* pointer) {
-  glVertexAttribPointer(index, GetSize<T>(), GetType<T>(), GL_FALSE, stride,
-                        pointer);
-  glEnableVertexAttribArray(index);
-}
-
-// Recursion variadic template parameter iterator.
-template <int index, typename... Ts>
-struct VertexAttribHelper {
-  using tuple = std::tuple<Ts...>;
-  size_t operator()() {
-    size_t offset = VertexAttribHelper<index - 1, Ts...>{}();
-    using type = typename std::tuple_element<index, tuple>::type;
-    VertexAttrib<type>(index, sizeof(tuple), reinterpret_cast<void*>(offset));
-    return offset + sizeof(type);
-  }
-};
-
-// Recursion stop point.
-template <typename... Ts>
-struct VertexAttribHelper<0, Ts...> {
-  using tuple = std::tuple<Ts...>;
-  size_t operator()() {
-    using type = typename std::tuple_element<0, tuple>::type;
-    VertexAttrib<type>(0, sizeof(tuple), nullptr);
-    return sizeof(type);
-  }
-};
-}  // namespace Details
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_GRAPHICS_VERTEX_ATTRIBUTES_H_
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/vr_gl_extensions.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/vr_gl_extensions.h
deleted file mode 100644
index 9635dbb..0000000
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/vr_gl_extensions.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef ANDROID_DVR_VR_GL_EXTENSIONS_H_
-#define ANDROID_DVR_VR_GL_EXTENSIONS_H_
-
-// clang-format off
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <GLES3/gl31.h>
-#include <GLES3/gl3ext.h>
-// clang-format on
-
-// GL_EXT_disjoint_timer_query API function declarations
-extern PFNGLGETQUERYOBJECTI64VEXTPROC glGetQueryObjecti64v;
-extern PFNGLGETQUERYOBJECTIVEXTPROC glGetQueryObjectiv;
-extern PFNGLQUERYCOUNTEREXTPROC glQueryCounter;
-
-// EXT_buffer_storage:
-extern PFNGLBUFFERSTORAGEEXTPROC glBufferStorage;
-
-typedef void(GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)(
-    GLenum target, GLenum attachment, GLuint texture, GLint level,
-    GLint baseViewIndex, GLsizei numViews);
-typedef void(GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVR)(
-    GLenum target, GLenum attachement, GLuint texture, GLint level,
-    GLsizei samples, GLint baseViewIndex, GLsizei numViews);
-
-extern PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR glFramebufferTextureMultiview;
-extern PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVR
-    glFramebufferTextureMultisampleMultiview;
-
-// QCOM_gralloc_buffer_data and QCOM_shared_buffer
-typedef void(GL_APIENTRY* PFNGLGRALLOCBUFFERDATAQCOM)(GLenum target,
-                                                      GLsizeiptr sizeInBytes,
-                                                      GLvoid* hostPtr,
-                                                      GLint fd);
-typedef void(GL_APIENTRY* PFNGLSHAREDBUFFERCREATEQCOM)(GLsizeiptr sizeInBytes,
-                                                       GLint* outFd);
-typedef void(GL_APIENTRY* PFNGLSHAREDBUFFERDESTROYQCOM)(GLint fd);
-typedef void(GL_APIENTRY* PFNGLSHAREDBUFFERBINDQCOM)(GLenum target,
-                                                     GLsizeiptr sizeInBytes,
-                                                     GLint fd);
-
-extern PFNGLGRALLOCBUFFERDATAQCOM glGrallocBufferDataQCOM;
-extern PFNGLSHAREDBUFFERCREATEQCOM glCreateSharedBufferQCOM;
-extern PFNGLSHAREDBUFFERDESTROYQCOM glDestroySharedBufferQCOM;
-extern PFNGLSHAREDBUFFERBINDQCOM glBindSharedBufferQCOM;
-
-extern "C" void load_gl_extensions();
-
-#endif  // ANDROID_DVR_VR_GL_EXTENSIONS_H_
diff --git a/libs/vr/libdvrgraphics/shader_program.cpp b/libs/vr/libdvrgraphics/shader_program.cpp
deleted file mode 100644
index 2d36600..0000000
--- a/libs/vr/libdvrgraphics/shader_program.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-#include "include/private/dvr/graphics/shader_program.h"
-
-#include <regex>
-#include <sstream>
-
-#include <log/log.h>
-
-namespace {
-
-static bool CompileShader(GLuint shader, const std::string& shader_string) {
-  std::string prefix;
-  const std::string kVersion = "#version";
-  if (shader_string.substr(0, kVersion.size()) != kVersion) {
-    prefix = "#version 310 es\n";
-  }
-  std::string string_with_prefix = prefix + shader_string;
-  const char* shader_str[] = {string_with_prefix.data()};
-  glShaderSource(shader, 1, shader_str, nullptr);
-  glCompileShader(shader);
-
-  GLint success;
-  glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
-  if (!success) {
-    GLchar infoLog[512];
-    glGetShaderInfoLog(shader, 512, nullptr, infoLog);
-    ALOGE("Shader Failed to compile: %s -- %s", *shader_str, infoLog);
-    return false;
-  }
-  return true;
-}
-
-static bool LinkProgram(GLuint program, GLuint vertex_shader,
-                        GLuint fragment_shader) {
-  glAttachShader(program, vertex_shader);
-  glAttachShader(program, fragment_shader);
-  glLinkProgram(program);
-
-  // Check for linking errors
-  GLint success;
-  glGetProgramiv(program, GL_LINK_STATUS, &success);
-  if (!success) {
-    GLchar infoLog[512];
-    glGetProgramInfoLog(program, 512, nullptr, infoLog);
-    ALOGE("Shader failed to link: %s", infoLog);
-    return false;
-  }
-
-  return true;
-}
-
-static bool LinkProgram(GLuint program, GLuint compute_shader) {
-  glAttachShader(program, compute_shader);
-  glLinkProgram(program);
-
-  // Check for linking errors
-  GLint success;
-  glGetProgramiv(program, GL_LINK_STATUS, &success);
-  if (!success) {
-    GLchar infoLog[512];
-    glGetProgramInfoLog(program, 512, nullptr, infoLog);
-    ALOGE("Shader failed to link: %s", infoLog);
-    return false;
-  }
-
-  return true;
-}
-
-}  // anonymous namespace
-
-namespace android {
-namespace dvr {
-
-ShaderProgram::ShaderProgram() : program_(0) {}
-
-ShaderProgram::ShaderProgram(const std::string& vertext_source,
-                             const std::string& fragment_source)
-    : program_(0) {
-  Link(vertext_source, fragment_source);
-}
-
-ShaderProgram::ShaderProgram(ShaderProgram&& to_move) {
-  std::swap(program_, to_move.program_);
-}
-
-ShaderProgram::~ShaderProgram() {
-  if (program_)
-    glDeleteProgram(program_);
-}
-
-ShaderProgram& ShaderProgram::operator=(ShaderProgram&& to_move) {
-  std::swap(program_, to_move.program_);
-  return *this;
-}
-
-void ShaderProgram::Link(const std::string& vertext_source,
-                         const std::string& fragment_source) {
-  if (program_)
-    glDeleteProgram(program_);
-  program_ = glCreateProgram();
-  GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
-  GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
-
-  bool success = CompileShader(vertex_shader, vertext_source) &&
-                 CompileShader(fragment_shader, fragment_source) &&
-                 LinkProgram(program_, vertex_shader, fragment_shader);
-
-  glDeleteShader(vertex_shader);
-  glDeleteShader(fragment_shader);
-
-  if (!success) {
-    glDeleteProgram(program_);
-    program_ = 0;
-  }
-}
-
-void ShaderProgram::Link(const std::string& compute_source) {
-  if (program_)
-    glDeleteProgram(program_);
-  program_ = glCreateProgram();
-  GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
-
-  bool success =
-      CompileShader(shader, compute_source) && LinkProgram(program_, shader);
-
-  glDeleteShader(shader);
-
-  if (!success) {
-    glDeleteProgram(program_);
-    program_ = 0;
-  }
-}
-
-void ShaderProgram::Use() const { glUseProgram(program_); }
-
-std::string ComposeShader(const std::string& shader_code,
-                          const std::vector<std::string>& variables) {
-  std::stringstream result_stream;
-  std::regex expression("%([0-9]*)");
-  using reg_iter = std::regex_token_iterator<std::string::const_iterator>;
-  reg_iter rend;
-  // match the string and number (drop the %)
-  std::vector<int> submatches = {-1, 1};
-  reg_iter reg(shader_code.begin(), shader_code.end(), expression, submatches);
-  bool is_even = true;
-  while (reg != rend) {
-    if (is_even) {
-      // even entries is the code between the %n's
-      result_stream << *reg;
-    } else {
-      // odd entries are the index into the passed in variables.
-      size_t i = static_cast<size_t>(std::stoi(*reg));
-      if (i < variables.size()) {
-        result_stream << variables[i];
-      }
-    }
-    is_even = !is_even;
-    ++reg;
-  }
-  return result_stream.str();
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvrgraphics/timer_query.cpp b/libs/vr/libdvrgraphics/timer_query.cpp
deleted file mode 100644
index 23d2b7c..0000000
--- a/libs/vr/libdvrgraphics/timer_query.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "include/private/dvr/graphics/timer_query.h"
-
-#include <GLES2/gl2ext.h>
-#include <log/log.h>
-
-namespace android {
-namespace dvr {
-
-TimerQuery::TimerQuery() {}
-
-TimerQuery::~TimerQuery() { Delete(); }
-
-void TimerQuery::Init() { glGenQueriesEXT(1, &query_); }
-
-void TimerQuery::Delete() {
-  if (query_) {
-    glDeleteQueriesEXT(1, &query_);
-    query_ = 0;
-  }
-}
-
-void TimerQuery::Begin() {
-  if (query_ == 0) {
-    Init();
-  }
-  glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query_);
-}
-
-void TimerQuery::End() { glEndQueryEXT(GL_TIME_ELAPSED_EXT); }
-
-double TimerQuery::GetTimeInMS() {
-  GLuint64 elapsed_time = 0;
-  glGetQueryObjectui64vEXT(query_, GL_QUERY_RESULT, &elapsed_time);
-  return static_cast<double>(elapsed_time) / 1000000.0;
-}
-
-SyncTimerQuery::SyncTimerQuery() { timer_.Begin(); }
-
-double SyncTimerQuery::FlushAndGetTimeInMS() {
-  if (timer_.query_ == 0) {
-    ALOGE("Error: Only call FlushAndGetTimeInMS() once.");
-    return 0.0;
-  }
-  timer_.End();
-  glFlush();
-  GLint done = 0;
-  while (!done) {
-    glGetQueryObjectivEXT(timer_.query_, GL_QUERY_RESULT_AVAILABLE, &done);
-  }
-
-  GLint disjoint_occurred = 0;
-  glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_occurred);
-  if (disjoint_occurred) {
-    ALOGE("Disjoint occurred.");
-    timer_.Delete();
-    return 0.0;
-  }
-
-  double elapsed_time = timer_.GetTimeInMS();
-  timer_.Delete();
-  return elapsed_time;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvrgraphics/vr_gl_extensions.cpp b/libs/vr/libdvrgraphics/vr_gl_extensions.cpp
deleted file mode 100644
index 2c5a698..0000000
--- a/libs/vr/libdvrgraphics/vr_gl_extensions.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "include/private/dvr/graphics/vr_gl_extensions.h"
-
-PFNGLGETQUERYOBJECTI64VEXTPROC glGetQueryObjecti64v = NULL;
-PFNGLGETQUERYOBJECTIVEXTPROC glGetQueryObjectiv = NULL;
-PFNGLQUERYCOUNTEREXTPROC glQueryCounter = NULL;
-PFNGLBUFFERSTORAGEEXTPROC glBufferStorage = NULL;
-PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR glFramebufferTextureMultiview = NULL;
-PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVR
-glFramebufferTextureMultisampleMultiview = NULL;
-
-PFNGLSHAREDBUFFERCREATEQCOM glCreateSharedBufferQCOM = NULL;
-PFNGLSHAREDBUFFERDESTROYQCOM glDestroySharedBufferQCOM = NULL;
-PFNGLSHAREDBUFFERBINDQCOM glBindSharedBufferQCOM = NULL;
-PFNGLGRALLOCBUFFERDATAQCOM glGrallocBufferDataQCOM = NULL;
-
-extern "C" void load_gl_extensions() {
-  if (glGetQueryObjecti64v) {
-    return;
-  }
-  glGetQueryObjecti64v = reinterpret_cast<PFNGLGETQUERYOBJECTI64VEXTPROC>(
-      eglGetProcAddress("glGetQueryObjecti64vEXT"));
-  glGetQueryObjectiv = reinterpret_cast<PFNGLGETQUERYOBJECTIVEXTPROC>(
-      eglGetProcAddress("glGetQueryObjectivEXT"));
-  glQueryCounter = reinterpret_cast<PFNGLQUERYCOUNTEREXTPROC>(
-      eglGetProcAddress("glQueryCounterEXT"));
-  glBufferStorage = reinterpret_cast<PFNGLBUFFERSTORAGEEXTPROC>(
-      eglGetProcAddress("glBufferStorageEXT"));
-
-  glFramebufferTextureMultiview =
-      reinterpret_cast<PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR>(
-          eglGetProcAddress("glFramebufferTextureMultiviewOVR"));
-  glFramebufferTextureMultisampleMultiview =
-      reinterpret_cast<PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVR>(
-          eglGetProcAddress("glFramebufferTextureMultisampleMultiviewOVR"));
-
-  glGrallocBufferDataQCOM = reinterpret_cast<PFNGLGRALLOCBUFFERDATAQCOM>(
-      eglGetProcAddress("glGrallocBufferDataQCOM"));
-  glCreateSharedBufferQCOM = reinterpret_cast<PFNGLSHAREDBUFFERCREATEQCOM>(
-      eglGetProcAddress("glCreateSharedBufferQCOM"));
-  glBindSharedBufferQCOM = reinterpret_cast<PFNGLSHAREDBUFFERBINDQCOM>(
-      eglGetProcAddress("glBindSharedBufferQCOM"));
-  glDestroySharedBufferQCOM = reinterpret_cast<PFNGLSHAREDBUFFERDESTROYQCOM>(
-      eglGetProcAddress("glDestroySharedBufferQCOM"));
-}
diff --git a/libs/vr/libimageio/Android.bp b/libs/vr/libimageio/Android.bp
deleted file mode 100644
index 7dde075..0000000
--- a/libs/vr/libimageio/Android.bp
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-sourceFiles = [
-    "image_io.cpp",
-    "image_io_png.cpp",
-    "image_io_ppm.cpp",
-]
-
-includeFiles = ["include"]
-
-sharedLibraries = [
-    "libcutils",
-    "libpng",
-]
-
-cc_library_static {
-    srcs: sourceFiles,
-    export_include_dirs: includeFiles,
-    shared_libs: sharedLibraries,
-    cflags: [
-        "-Wall",
-        "-Wextra",
-    ],
-    name: "libimageio",
-    tags: ["optional"],
-}
diff --git a/libs/vr/libimageio/image_io.cpp b/libs/vr/libimageio/image_io.cpp
deleted file mode 100644
index 5ad6c2d..0000000
--- a/libs/vr/libimageio/image_io.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-#define LOG_TAG "ImageIo"
-
-#include <private/dvr/image_io.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-
-#include <private/dvr/image_io_base.h>
-#include <private/dvr/image_io_logging.h>
-#include <private/dvr/image_io_png.h>
-#include <private/dvr/image_io_ppm.h>
-
-namespace {
-
-// Returns true if |str| ends with |suffix|.
-bool EndsWith(const std::string& str, const std::string& suffix) {
-  if (str.length() < suffix.length())
-    return false;
-
-  return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
-}
-
-// Returns lower case copy of the input string.
-std::string ToLower(std::string str) {
-  std::transform(str.begin(), str.end(), str.begin(),
-                 [](char x) { return std::tolower(x); });
-  return str;
-}
-
-}  // namespace
-
-std::unique_ptr<ImageIoReader> ImageIoReader::Create(const char* filename) {
-  std::unique_ptr<ImageIoReader> reader;
-  std::string filename_lower = ToLower(filename);
-
-  if (EndsWith(filename_lower, ".ppm"))
-    reader.reset(new ImageIoPpmReader(filename));
-
-  if (!reader) {
-    ALOGE("Unknown/unsupported image file format.");
-    return nullptr;
-  }
-
-  return reader;
-}
-
-std::unique_ptr<ImageIoWriter> ImageIoWriter::Create(const char* filename,
-                                                     int width, int height,
-                                                     const uint8_t* image) {
-  std::unique_ptr<ImageIoWriter> writer;
-  std::string filename_lower = ToLower(filename);
-
-  if (EndsWith(filename_lower, ".ppm"))
-    writer.reset(new ImageIoPpmWriter(filename, width, height, image));
-  else if (EndsWith(filename_lower, ".png"))
-    writer.reset(new ImageIoPngWriter(filename, width, height, image));
-
-  if (!writer) {
-    ALOGE("Unknown/unsupported image file format.");
-    return nullptr;
-  }
-
-  return writer;
-}
-
-extern "C" {
-
-bool image_io_write_rgb888(const char* filename, int width, int height,
-                           const uint8_t* image) {
-  auto writer = ImageIoWriter::Create(filename, width, height, image);
-  if (!writer)
-    return false;
-  return writer->WriteRgb888();
-}
-
-bool image_io_read_rgb888(const char* filename, int* width, int* height,
-                          uint8_t** image) {
-  auto reader = ImageIoReader::Create(filename);
-  if (!reader)
-    return false;
-  if (!reader->ReadRgb888())
-    return false;
-  *width = reader->width();
-  *height = reader->height();
-  *image = reader->ReleaseImage();
-  return true;
-}
-
-void image_io_release_buffer(uint8_t* image) { delete[] image; }
-
-}  // extern "C"
diff --git a/libs/vr/libimageio/image_io_png.cpp b/libs/vr/libimageio/image_io_png.cpp
deleted file mode 100644
index e0a118b..0000000
--- a/libs/vr/libimageio/image_io_png.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#define LOG_TAG "ImageIo"
-
-#include <private/dvr/image_io_png.h>
-
-#include <fstream>
-#include <string>
-#include <vector>
-
-#include <private/dvr/image_io_logging.h>
-
-#include "png.h"
-
-namespace {
-
-void WriteChunkCallback(png_structp out_ptr, png_bytep chunk_ptr,
-                        png_size_t chunk_size) {
-  auto* writer = static_cast<ImageIoPngWriter*>(png_get_io_ptr(out_ptr));
-  const char* chunk = reinterpret_cast<const char*>(chunk_ptr);
-  writer->WriteChunk(chunk, chunk_size);
-}
-
-}  // namespace
-
-ImageIoPngWriter::ImageIoPngWriter(const char* filename, int width, int height,
-                                   const uint8_t* image)
-    : ImageIoWriter(filename, width, height, image),
-      out_(filename_),
-      write_failed_(false) {}
-
-bool ImageIoPngWriter::WriteChunk(const char* chunk, int chunk_size) {
-  out_.write(chunk, chunk_size);
-  if (!out_) {
-    if (write_failed_) {
-      // Error was already logged once.
-      return false;
-    }
-
-    ALOGE("Failed to write .png image to %s.", filename_.c_str());
-    write_failed_ = true;
-    return false;
-  }
-  return true;
-}
-
-// Writes RGB888 image to png file.
-// Refactored from Chromium:
-// WebKit/Source/platform/image-encoders/skia/PNGImageEncoder.cpp
-bool ImageIoPngWriter::WriteRgb888() {
-  if (width_ <= 0 || height_ <= 0) {
-    ALOGE("Invalid width or height.");
-    return false;
-  }
-
-  if (!out_) {
-    ALOGE("Failed to open output file %s.", filename_.c_str());
-    return false;
-  }
-
-  png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
-  png_info* info = png_create_info_struct(png);
-  if (!png || !info || setjmp(png_jmpbuf(png))) {
-    png_destroy_write_struct(png ? &png : 0, info ? &info : 0);
-    return false;
-  }
-
-  png_set_compression_level(png, 3);
-  png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB);
-
-  png_set_write_fn(png, this, WriteChunkCallback, 0);
-  png_set_IHDR(png, info, width_, height_, 8, PNG_COLOR_TYPE_RGB, 0, 0, 0);
-  png_write_info(png, info);
-
-  unsigned char* pixels =
-      reinterpret_cast<unsigned char*>(const_cast<uint8_t*>(image_));
-  const size_t stride = width_ * 3;
-  for (int y = 0; y < height_; ++y) {
-    png_write_row(png, pixels);
-    if (write_failed_)
-      return false;
-    pixels += stride;
-  }
-
-  png_write_end(png, info);
-  png_destroy_write_struct(&png, &info);
-
-  return !write_failed_;
-}
diff --git a/libs/vr/libimageio/image_io_ppm.cpp b/libs/vr/libimageio/image_io_ppm.cpp
deleted file mode 100644
index 2411888..0000000
--- a/libs/vr/libimageio/image_io_ppm.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#define LOG_TAG "ImageIo"
-
-#include <private/dvr/image_io_ppm.h>
-
-#include <cwctype>
-#include <fstream>
-#include <string>
-
-#include <private/dvr/image_io_logging.h>
-
-bool ImageIoPpmWriter::WriteRgb888() {
-  std::ofstream out(filename_);
-  if (!out) {
-    ALOGE("Failed to open output file %s.", filename_.c_str());
-    return false;
-  }
-
-  // Write a PPM header. See http://netpbm.sourceforge.net/doc/ppm.html for
-  // the format specification.
-  constexpr int maximum_intensity = 255;
-  out << "P6\n"
-      << width_ << "\n"
-      << height_ << "\n"
-      << maximum_intensity << "\n";
-
-  // Write out the image itself.
-  out.write(reinterpret_cast<const char*>(image_), 3 * width_ * height_);
-
-  if (!out) {
-    ALOGE("Failed to write .ppm image to %s.", filename_.c_str());
-    return false;
-  }
-  return true;
-}
-
-bool ImageIoPpmReader::ReadRgb888() {
-  std::ifstream in(filename_);
-  if (!in) {
-    ALOGE("Failed to open input file %s.", filename_.c_str());
-    return false;
-  }
-
-  // Read PPM header. See http://netpbm.sourceforge.net/doc/ppm.html for
-  // the format specification.
-  char magic_number[2];
-  in.read(magic_number, 2);
-  if (magic_number[0] != 'P' || magic_number[1] != '6') {
-    ALOGE("Failed to read PPM, not a P6 file %s.", filename_.c_str());
-    return false;
-  }
-
-  int maximum_intensity = 0;
-
-  in >> width_;
-  in >> height_;
-  in >> maximum_intensity;
-
-  char delimiter;
-  in.read(&delimiter, 1);
-
-  if (!iswspace(delimiter) || width_ <= 0 || height_ <= 0 ||
-      maximum_intensity <= 0) {
-    ALOGE("Failed to parse PPM header for %s.", filename_.c_str());
-    return false;
-  }
-
-  if (maximum_intensity != 255) {
-    ALOGE("Failed to read PPM, only 8-bit depth supported %s.",
-          filename_.c_str());
-    return false;
-  }
-
-  // Read RGB data.
-  const int data_begin = in.tellg();
-  in.seekg(0, in.end);
-  const int data_end = in.tellg();
-  in.seekg(data_begin, in.beg);
-
-  const int data_size = data_end - data_begin;
-  if (data_size != 3 * width_ * height_) {
-    ALOGE("Failed to read PPM, unexpected data size %s.", filename_.c_str());
-    return false;
-  }
-
-  image_.reset(new uint8_t[data_size]);
-  char* data = reinterpret_cast<char*>(image_.get());
-
-  const auto it_data_begin = std::istreambuf_iterator<char>(in);
-  const auto it_data_end = std::istreambuf_iterator<char>();
-  std::copy(it_data_begin, it_data_end, data);
-
-  return true;
-}
diff --git a/libs/vr/libimageio/include/CPPLINT.cfg b/libs/vr/libimageio/include/CPPLINT.cfg
deleted file mode 100644
index 2f8a3c0..0000000
--- a/libs/vr/libimageio/include/CPPLINT.cfg
+++ /dev/null
@@ -1 +0,0 @@
-filter=-build/header_guard
diff --git a/libs/vr/libimageio/include/private/dvr/image_io.h b/libs/vr/libimageio/include/private/dvr/image_io.h
deleted file mode 100644
index 5cb115d..0000000
--- a/libs/vr/libimageio/include/private/dvr/image_io.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef DVR_IMAGE_IO_H_
-#define DVR_IMAGE_IO_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-
-// Supported filetypes.
-#define DVR_IMAGE_IO_SUPPORTED_WRITE "png, ppm"
-#define DVR_IMAGE_IO_SUPPORTED_READ "ppm"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Writes an RGB888 image to file. Intended file type is autodetected
-// based on the extension. Currently supported formats: PNG, PPM.
-bool image_io_write_rgb888(const char* filename, int width, int height,
-                           const uint8_t* image);
-
-// Reads an RGB888 image from file. Image buffer needs to be released with
-// image_io_release_image. Currently supported formats: PPM.
-bool image_io_read_rgb888(const char* filename, int* width, int* height,
-                          uint8_t** image);
-
-// Releases image buffer allocated within the library.
-void image_io_release_buffer(uint8_t* image);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // DVR_IMAGE_IO_H_
diff --git a/libs/vr/libimageio/include/private/dvr/image_io_base.h b/libs/vr/libimageio/include/private/dvr/image_io_base.h
deleted file mode 100644
index 5f29de7..0000000
--- a/libs/vr/libimageio/include/private/dvr/image_io_base.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_BASE_H_
-#define LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_BASE_H_
-
-#include <memory>
-#include <string>
-
-class ImageIoReader {
- public:
-  virtual ~ImageIoReader() {}
-
-  static std::unique_ptr<ImageIoReader> Create(const char* filename);
-
-  virtual bool ReadRgb888() = 0;
-
-  int width() const { return width_; }
-
-  int height() const { return height_; }
-
-  uint8_t* ReleaseImage() { return image_.release(); }
-
- protected:
-  int width_;
-  int height_;
-  std::unique_ptr<uint8_t[]> image_;
-  const std::string filename_;
-
-  explicit ImageIoReader(const char* filename)
-      : width_(0), height_(0), filename_(filename) {}
-
-  ImageIoReader() = delete;
-};
-
-class ImageIoWriter {
- public:
-  virtual ~ImageIoWriter() {}
-
-  static std::unique_ptr<ImageIoWriter> Create(const char* filename, int width,
-                                               int height,
-                                               const uint8_t* image);
-
-  virtual bool WriteRgb888() = 0;
-
- protected:
-  const int width_;
-  const int height_;
-  const uint8_t* image_;
-  const std::string filename_;
-
-  ImageIoWriter(const char* filename, int width, int height,
-                const uint8_t* image)
-      : width_(width), height_(height), image_(image), filename_(filename) {}
-
-  ImageIoWriter() = delete;
-};
-
-#endif  // LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_BASE_H_
diff --git a/libs/vr/libimageio/include/private/dvr/image_io_logging.h b/libs/vr/libimageio/include/private/dvr/image_io_logging.h
deleted file mode 100644
index a2629f3..0000000
--- a/libs/vr/libimageio/include/private/dvr/image_io_logging.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_LOGGING_H_
-#define LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_LOGGING_H_
-
-// This header acts as log/log.h if LOG_TO_STDERR is not defined.
-// If LOG_TO_STDERR is defined, then android logging macros (such as ALOGE)
-// would log to stderr. This is useful if the code is also being used/tested on
-// a desktop.
-
-#ifdef LOG_TO_STDERR
-#include <stdarg.h>
-#include <cstdio>
-
-#ifndef LOG_TAG
-#define LOG_TAG " "
-#endif  // LOG_TAG
-
-inline void LogToStderr(const char* severity, const char* fmt, ...) {
-  fprintf(stderr, "%s %s: ", LOG_TAG, severity);
-  va_list args;
-  va_start(args, fmt);
-  vfprintf(stderr, fmt, args);
-  va_end(args);
-  fprintf(stderr, "\n");
-  fflush(stderr);
-}
-
-#define ALOGE(fmt, ...) LogToStderr("ERROR", fmt, ##__VA_ARGS__)
-
-#define ALOGW(fmt, ...) LogToStderr("WARNING", fmt, ##__VA_ARGS__)
-
-#define ALOGI(fmt, ...) LogToStderr("INFO", fmt, ##__VA_ARGS__)
-
-#define ALOGV(fmt, ...) LogToStderr("VERBOSE", fmt, ##__VA_ARGS__)
-
-#else  // LOG_TO_STDERR
-#include <log/log.h>
-#endif  // LOG_TO_STDERR
-
-#endif  // LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_LOGGING_H_
diff --git a/libs/vr/libimageio/include/private/dvr/image_io_png.h b/libs/vr/libimageio/include/private/dvr/image_io_png.h
deleted file mode 100644
index e06a17a..0000000
--- a/libs/vr/libimageio/include/private/dvr/image_io_png.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PNG_H_
-#define LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PNG_H_
-
-#include <fstream>
-
-#include <private/dvr/image_io_base.h>
-
-class ImageIoPngWriter : public ImageIoWriter {
- public:
-  bool WriteRgb888() override;
-
-  bool WriteChunk(const char* chunk, int chunk_size);
-
- private:
-  ImageIoPngWriter(const char* filename, int width, int height,
-                   const uint8_t* image);
-
-  std::ofstream out_;
-  bool write_failed_;
-
-  friend class ImageIoWriter;
-};
-
-#endif  // LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PNG_H_
diff --git a/libs/vr/libimageio/include/private/dvr/image_io_ppm.h b/libs/vr/libimageio/include/private/dvr/image_io_ppm.h
deleted file mode 100644
index 8a1a96c..0000000
--- a/libs/vr/libimageio/include/private/dvr/image_io_ppm.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PPM_H_
-#define LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PPM_H_
-
-#include <private/dvr/image_io_base.h>
-
-class ImageIoPpmReader : public ImageIoReader {
- public:
-  bool ReadRgb888() override;
-
- private:
-  explicit ImageIoPpmReader(const char* filename) : ImageIoReader(filename) {}
-
-  friend class ImageIoReader;
-};
-
-class ImageIoPpmWriter : public ImageIoWriter {
- public:
-  bool WriteRgb888() override;
-
- private:
-  ImageIoPpmWriter(const char* filename, int width, int height,
-                   const uint8_t* image)
-      : ImageIoWriter(filename, width, height, image) {}
-
-  friend class ImageIoWriter;
-};
-
-#endif  // LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PPM_H_
diff --git a/libs/vr/libposepredictor/Android.bp b/libs/vr/libposepredictor/Android.bp
deleted file mode 100644
index 2f1d2f5..0000000
--- a/libs/vr/libposepredictor/Android.bp
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (C) 2008 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.
-
-sourceFiles = [
-    "predictor.cpp",
-    "buffered_predictor.cpp",
-    "linear_predictor.cpp",
-    "polynomial_predictor.cpp",
-    "dvr_pose_predictor.cpp",
-]
-
-includeFiles = [
-    "include",
-]
-
-staticLibraries = ["libvrsensor"]
-
-sharedLibraries = []
-
-headerLibraries = [ "libeigen" ]
-
-cc_library {
-    srcs: sourceFiles,
-    cflags: [
-      "-DLOG_TAG=\"libposepredictor\"",
-      "-DTRACE=0",
-    ],
-    export_include_dirs: includeFiles,
-    static_libs: staticLibraries,
-    shared_libs: sharedLibraries,
-    header_libs: headerLibraries,
-    export_header_lib_headers: headerLibraries,
-    name: "libposepredictor",
-}
-
-cc_test {
-    tags: ["optional"],
-    srcs: [
-        "predictor_tests.cpp",
-        "linear_predictor_tests.cpp",
-        "polynomial_predictor_tests.cpp",
-    ],
-
-    static_libs: ["libposepredictor"] + staticLibraries,
-    shared_libs: sharedLibraries,
-    name: "pose_predictor_tests",
-}
diff --git a/libs/vr/libposepredictor/buffered_predictor.cpp b/libs/vr/libposepredictor/buffered_predictor.cpp
deleted file mode 100644
index f3b41dc..0000000
--- a/libs/vr/libposepredictor/buffered_predictor.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <buffered_predictor.h>
-
-namespace posepredictor {
-
-BufferedPredictor::BufferedPredictor(size_t buffer_size) {
-  buffer_.resize(buffer_size);
-}
-
-void BufferedPredictor::BufferSample(const Pose& sample) {
-  const auto& prev_sample = buffer_[current_pose_index_];
-
-  // If we are updating a sample (the same time stamp), do not advance the
-  // counter.
-  if (sample.time_ns != prev_sample.time_ns) {
-    current_pose_index_ = (current_pose_index_ + 1) % buffer_.size();
-  }
-
-  buffer_[current_pose_index_] = sample;
-
-  // Make sure the subsequent orientations are the closest in quaternion space.
-  if (PrevSample(1).orientation.coeffs().dot(sample.orientation.coeffs()) < 0) {
-    // Flip the quaternion to be closest to the previous sample.
-    buffer_[current_pose_index_].orientation =
-        quat(-sample.orientation.w(), -sample.orientation.x(),
-             -sample.orientation.y(), -sample.orientation.z());
-  }
-
-  ++num_poses_added_;
-}
-
-const Pose& BufferedPredictor::PrevSample(size_t index) const {
-  // We must not request a pose too far in the past.
-  assert(index < buffer_.size());
-  return buffer_[(current_pose_index_ - index + buffer_.size()) %
-                 buffer_.size()];
-}
-
-}  // namespace posepredictor
diff --git a/libs/vr/libposepredictor/dvr_pose_predictor.cpp b/libs/vr/libposepredictor/dvr_pose_predictor.cpp
deleted file mode 100644
index 7f2ecc0..0000000
--- a/libs/vr/libposepredictor/dvr_pose_predictor.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <private/dvr/dvr_pose_predictor.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-template <typename Vec3Type>
-float32x4_t FromVec3(const Vec3Type& from) {
-  return {static_cast<float>(from.x()), static_cast<float>(from.y()),
-          static_cast<float>(from.z()), 0};
-}
-
-template <typename QuatType>
-float32x4_t FromQuat(const QuatType& from) {
-  return {static_cast<float>(from.x()), static_cast<float>(from.y()),
-          static_cast<float>(from.z()), static_cast<float>(from.w())};
-}
-
-}  //  namespace
-
-void AddPredictorPose(posepredictor::Predictor* predictor,
-                      const posepredictor::vec3& start_t_head,
-                      const posepredictor::quat& start_q_head,
-                      int64_t pose_timestamp, DvrPoseAsync* out) {
-  // Feed the predictor.
-  predictor->Add(
-      posepredictor::Pose{pose_timestamp, start_t_head, start_q_head});
-
-  // Fill the output.
-  out->timestamp_ns = pose_timestamp;
-
-  out->translation = FromVec3(start_t_head);
-  out->orientation = FromQuat(start_q_head);
-
-  out->right_translation = out->translation;
-  out->right_orientation = out->orientation;
-
-  const auto velocity = predictor->PredictVelocity(pose_timestamp);
-
-  out->velocity = FromVec3(velocity.linear);
-  out->angular_velocity = FromVec3(velocity.angular);
-
-  out->flags = DVR_POSE_FLAG_HEAD | DVR_POSE_FLAG_VALID;
-  memset(out->pad, 0, sizeof(out->pad));
-}
-
-void PredictPose(const posepredictor::Predictor* predictor, int64_t left_ns,
-                 int64_t right_ns, DvrPoseAsync* out) {
-  const auto left_pose = predictor->Predict(left_ns);
-  const auto right_pose = predictor->Predict(right_ns);
-  const auto velocity = predictor->PredictVelocity((left_ns + right_ns) / 2);
-
-  // Fill the output.
-  out->timestamp_ns = left_ns;
-
-  out->translation = FromVec3(left_pose.position);
-  out->orientation = FromQuat(left_pose.orientation);
-
-  out->right_translation = FromVec3(right_pose.position);
-  out->right_orientation = FromQuat(right_pose.orientation);
-
-  out->velocity = FromVec3(velocity.linear);
-  out->angular_velocity = FromVec3(velocity.angular);
-
-  out->flags = DVR_POSE_FLAG_HEAD | DVR_POSE_FLAG_VALID;
-  memset(out->pad, 0, sizeof(out->pad));
-}
-
-}  //  dvr
-}  //  android
diff --git a/libs/vr/libposepredictor/include/buffered_predictor.h b/libs/vr/libposepredictor/include/buffered_predictor.h
deleted file mode 100644
index eab0150..0000000
--- a/libs/vr/libposepredictor/include/buffered_predictor.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef POSEPREDICTOR_BUFFERED_PREDICTOR_H_
-#define POSEPREDICTOR_BUFFERED_PREDICTOR_H_
-
-#include <vector>
-
-#include "predictor.h"
-
-namespace posepredictor {
-
-// Keeps the previous n poses around in a ring buffer.
-// The orientations are also unrolled so that a . b > 0 for two subsequent
-// quaternions a and b.
-class BufferedPredictor : public Predictor {
- public:
-  BufferedPredictor(size_t buffer_size);
-  ~BufferedPredictor() = default;
-
- protected:
-  // Add a pose sample into the buffer.
-  void BufferSample(const Pose& sample);
-
-  // Grab a previous sample.
-  // index = 0: last sample
-  // index = 1: the one before that
-  // ...
-  const Pose& PrevSample(size_t index) const;
-
-  // Where we keep the last n poses.
-  std::vector<Pose> buffer_;
-
-  // Where the last valid pose is in the buffer.
-  size_t current_pose_index_ = 0;
-
-  // The number of poses we have added.
-  size_t num_poses_added_ = 0;
-};
-
-}  // namespace posepredictor
-
-#endif  // POSEPREDICTOR_BUFFERED_PREDICTOR_H_
diff --git a/libs/vr/libposepredictor/include/linear_predictor.h b/libs/vr/libposepredictor/include/linear_predictor.h
deleted file mode 100644
index 0d17ec5..0000000
--- a/libs/vr/libposepredictor/include/linear_predictor.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef POSEPREDICTOR_LINEAR_POSE_PREDICTOR_H_
-#define POSEPREDICTOR_LINEAR_POSE_PREDICTOR_H_
-
-#include "predictor.h"
-
-namespace posepredictor {
-
-// This class makes a linear prediction using the last two samples we received.
-class LinearPosePredictor : public Predictor {
- public:
-  LinearPosePredictor() = default;
-
-  // Add a new sample.
-  void Add(const Pose& sample) override;
-
-  // Predict using the last two samples.
-  Pose Predict(int64_t time_ns) const override;
-
-  // Just copy the velocity over.
-  Velocity PredictVelocity(int64_t time_ns) const override;
-
- private:
-  // The index of the last sample we received.
-  size_t current_index_ = 0;
-
-  // The previous two samples.
-  Pose samples_[2];
-
-  // Experimental
-  bool forward_predict_angular_speed_ = false;
-
-  // Transient variables updated when a sample is added.
-  vec3 velocity_ = vec3::Zero();
-  vec3 rotational_velocity_ = vec3::Zero();
-  vec3 rotational_axis_ = vec3::Zero();
-  real last_angular_speed_ = 0;
-  real angular_speed_ = 0;
-  real angular_accel_ = 0;
-};
-
-}  // namespace posepredictor
-
-#endif  // POSEPREDICTOR_LINEAR_POSE_PREDICTOR_H_
diff --git a/libs/vr/libposepredictor/include/polynomial_predictor.h b/libs/vr/libposepredictor/include/polynomial_predictor.h
deleted file mode 100644
index 4b8d51b..0000000
--- a/libs/vr/libposepredictor/include/polynomial_predictor.h
+++ /dev/null
@@ -1,168 +0,0 @@
-#ifndef POSEPREDICTOR_POLYNOMIAL_POSE_PREDICTOR_H_
-#define POSEPREDICTOR_POLYNOMIAL_POSE_PREDICTOR_H_
-
-#include <vector>
-
-#include <Eigen/Dense>
-
-#include "buffered_predictor.h"
-
-namespace posepredictor {
-
-// Make a polynomial prediction of the form
-// y = coefficients_[0] + coefficients_[1] * t + coefficients_[2] * t^2 + ...
-// where t is time and y is the position and orientation.
-// We recompute the coefficients whenever we add a new sample using
-// training_window previous samples.
-template <size_t PolynomialDegree, size_t TrainingWindow>
-class PolynomialPosePredictor : public BufferedPredictor {
- public:
-  PolynomialPosePredictor(real regularization = 1e-9)
-      : BufferedPredictor(TrainingWindow), regularization_(regularization) {
-    static_assert(TrainingWindow >= PolynomialDegree + 1,
-                  "Underconstrained polynomial regressor");
-  }
-
-  ~PolynomialPosePredictor() = default;
-
-  // We convert pose samples into a vector for matrix arithmetic using this
-  // mapping.
-  enum Components {
-    kPositionX = 0,
-    kPositionY,
-    kPositionZ,
-    kOrientationX,
-    kOrientationY,
-    kOrientationZ,
-    kOrientationW,
-    kNumComponents
-  };
-
-  // Add a new sample.
-  void Add(const Pose& sample) override {
-    // Add the sample to the ring buffer.
-    BufferedPredictor::BufferSample(sample);
-
-    Eigen::Matrix<real, TrainingWindow, kNumComponents> values;
-
-    // Get the pose samples into matrices for fitting.
-    real t_vector[TrainingWindow];
-    for (size_t i = 0; i < TrainingWindow; ++i) {
-      const auto& prev_sample = PrevSample(i);
-
-      t_vector[i] = NsToT(prev_sample.time_ns);
-
-      // Save the values we will be fitting to at each sample time.
-      values(i, kPositionX) = prev_sample.position.x();
-      values(i, kPositionY) = prev_sample.position.y();
-      values(i, kPositionZ) = prev_sample.position.z();
-      values(i, kOrientationX) = prev_sample.orientation.x();
-      values(i, kOrientationY) = prev_sample.orientation.y();
-      values(i, kOrientationZ) = prev_sample.orientation.z();
-      values(i, kOrientationW) = prev_sample.orientation.w();
-    }
-
-    // Some transient matrices for solving for coefficient matrix.
-    Eigen::Matrix<real, PolynomialDegree + 1, PolynomialDegree + 1> M;
-    Eigen::Matrix<real, PolynomialDegree + 1, 1> d;
-    Eigen::Matrix<real, PolynomialDegree + 1, 1> p;
-
-    // Create a polynomial fit for each component.
-    for (size_t component = 0; component < kNumComponents; ++component) {
-      // A = [ 1 t t^2 ... ]'
-      // x = [ coefficients[0] coefficients[1] .... ]'
-      // b = [ position.x ]'
-      // We would like to solve A' x + regularization * I = b'
-      // given the samples we have in our training window.
-      //
-      // The loop below will compute:
-      // M = A' * A
-      // d = A' * b
-      // so we can solve M * coefficients + regularization * I = b
-
-      M.setIdentity();
-      d.setZero();
-      p[0] = 1;
-
-      // M = regularization * I
-      M = M * regularization_;
-
-      // Accumulate the poses in the training window.
-      for (size_t i = 0; i < TrainingWindow; ++i) {
-        // Compute the polynomial at this sample.
-        for (size_t j = 1; j <= PolynomialDegree; ++j) {
-          p[j] = p[j - 1] * t_vector[i];
-        }
-
-        // Accumulate the left and right hand sides.
-        M = M + p * p.transpose();
-        d = d + p * values(i, component);
-      }
-
-      // M is symmetric, positive semi-definite.
-      // Note: This is not the most accurate solver out there but is fast.
-      coefficients_.row(component) = Eigen::LLT<Eigen::MatrixXd>(M).solve(d);
-    }
-  }
-
-  // Predict using the polynomial coefficients.
-  Pose Predict(int64_t time_ns) const override {
-    // Predict the left side.
-    const auto components = SamplePolynomial(time_ns);
-
-    return {time_ns,
-            vec3(components[kPositionX], components[kPositionY],
-                 components[kPositionZ]),
-            quat(components[kOrientationW], components[kOrientationX],
-                 components[kOrientationY], components[kOrientationZ])
-                .normalized()};
-  }
-
- private:
-  // Evaluate the polynomial at a particular time.
-  Eigen::Matrix<real, kNumComponents, 1> SamplePolynomial(
-      int64_t time_ns) const {
-    const auto t = NsToT(time_ns);
-    Eigen::Matrix<real, PolynomialDegree + 1, 1> polynomial;
-    real current_polynomial = t;
-
-    // Compute polynomial = [ 1 t t^2 ... ]
-    polynomial[0] = 1;
-    for (size_t degree = 1; degree <= PolynomialDegree;
-         ++degree, current_polynomial *= t) {
-      polynomial[degree] = polynomial[degree - 1] * t;
-    }
-
-    // The coefficients_ = [ numComponents x (polynomial degree + 1) ].
-    return coefficients_ * polynomial;
-  }
-
-  // Convert a time in nanoseconds to t.
-  // We could use the seconds as t but this would create make it more difficult
-  // to tweak the regularization amount. So we subtract the last sample time so
-  // the scale of the regularization constant doesn't change as a function of
-  // time.
-  real NsToT(int64_t time_ns) const {
-    return NsToSeconds(time_ns - buffer_[current_pose_index_].time_ns);
-  }
-
-  // The ridge regularization constant.
-  real regularization_;
-
-  // This is where we store the polynomial coefficients.
-  Eigen::Matrix<real, kNumComponents, PolynomialDegree + 1> coefficients_;
-};
-
-// Some common polynomial types.
-extern template class PolynomialPosePredictor<1, 2>;
-extern template class PolynomialPosePredictor<2, 3>;
-extern template class PolynomialPosePredictor<3, 4>;
-extern template class PolynomialPosePredictor<4, 5>;
-
-using QuadricPosePredictor = PolynomialPosePredictor<2, 3>;
-using CubicPosePredictor = PolynomialPosePredictor<3, 4>;
-using QuarticPosePredictor = PolynomialPosePredictor<4, 5>;
-
-}  // namespace posepredictor
-
-#endif  // POSEPREDICTOR_POLYNOMIAL_POSE_PREDICTOR_H_
diff --git a/libs/vr/libposepredictor/include/predictor.h b/libs/vr/libposepredictor/include/predictor.h
deleted file mode 100644
index 78db272..0000000
--- a/libs/vr/libposepredictor/include/predictor.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef POSEPREDICTOR_POSE_PREDICTOR_H_
-#define POSEPREDICTOR_POSE_PREDICTOR_H_
-
-#include <Eigen/Core>
-#include <Eigen/Geometry>
-
-// This is the only file you need to include for pose prediction.
-
-namespace posepredictor {
-
-// The precision for the predictor.
-// TODO(okana): double precision is probably not necessary.
-typedef double real;
-
-using vec3 = Eigen::Matrix<real, 3, 1>;
-using quat = Eigen::Quaternion<real>;
-
-// Encapsulates a pose sample.
-struct Pose {
-  int64_t time_ns = 0;
-  vec3 position = vec3::Zero();
-  quat orientation = quat::Identity();
-};
-
-// Encapsulates the derivative at a time.
-struct Velocity {
-  vec3 linear = vec3::Zero();
-  vec3 angular = vec3::Zero();
-};
-
-// The preset types we support.
-enum class PredictorType { Linear, Quadric, Cubic };
-
-// This is an abstract base class for prediction 6dof pose given
-// a set of samples.
-class Predictor {
- public:
-  Predictor() = default;
-  virtual ~Predictor() = default;
-
-  // The nanoseconds to use for finite differencing.
-  static constexpr int64_t kFiniteDifferenceNs = 100;
-
-  // Instantiate a new pose predictor for a type.
-  static std::unique_ptr<Predictor> Create(PredictorType type);
-
-  // Compute the angular velocity from orientation start_orientation to
-  // end_orientation in delta_time.
-  static vec3 AngularVelocity(const quat& start_orientation,
-                              const quat& end_orientation, real delta_time);
-
-  // Add a pose sample coming from the sensors.
-  virtual void Add(const Pose& sample) = 0;
-
-  // Make a pose prediction for at specific time.
-  virtual Pose Predict(int64_t time_ns) const = 0;
-
-  // Evaluate velocity at a particular time.
-  // The default implementation uses finite differencing.
-  virtual Velocity PredictVelocity(int64_t time_ns) const;
-
-  // Helpers
-  static real NsToSeconds(int64_t time_ns) {
-    return static_cast<real>(time_ns / 1e9);
-  }
-  static int64_t SecondsToNs(real seconds) {
-    return static_cast<int64_t>(seconds * 1e9);
-  }
-};
-
-}  // namespace posepredictor
-
-#endif  // POSEPREDICTOR_POSE_PREDICTOR_H_
diff --git a/libs/vr/libposepredictor/include/private/dvr/dvr_pose_predictor.h b/libs/vr/libposepredictor/include/private/dvr/dvr_pose_predictor.h
deleted file mode 100644
index bd2dcbc..0000000
--- a/libs/vr/libposepredictor/include/private/dvr/dvr_pose_predictor.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef ANDROID_DVR_POSE_PREDICTOR_H_
-#define ANDROID_DVR_POSE_PREDICTOR_H_
-
-#include <dvr/pose_client.h>
-#include <predictor.h>
-
-// Some shim functions for connecting dvr to pose predictor.
-
-namespace android {
-namespace dvr {
-
-// Feed a pose to the predictor.
-void AddPredictorPose(posepredictor::Predictor* predictor,
-                      const posepredictor::vec3& start_t_head,
-                      const posepredictor::quat& start_q_head,
-                      int64_t pose_timestamp, DvrPoseAsync* out);
-
-// Make a prediction for left and right eyes.
-void PredictPose(const posepredictor::Predictor* predictor, int64_t left_ns,
-                 int64_t right_ns, DvrPoseAsync* out);
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_POSE_PREDICTOR_H_
diff --git a/libs/vr/libposepredictor/linear_predictor.cpp b/libs/vr/libposepredictor/linear_predictor.cpp
deleted file mode 100644
index 6f924dc..0000000
--- a/libs/vr/libposepredictor/linear_predictor.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <linear_predictor.h>
-
-namespace posepredictor {
-
-using AngleAxis = Eigen::AngleAxis<real>;
-
-void LinearPosePredictor::Add(const Pose& sample) {
-  // If we are receiving a new sample, move the index to the next item.
-  // If the time stamp is the same as the last frame, we will just overwrite
-  // it with the new data.
-  if (sample.time_ns != samples_[current_index_].time_ns) {
-    current_index_ ^= 1;
-  }
-
-  // Save the sample.
-  samples_[current_index_] = sample;
-
-  // The previous sample we received.
-  const auto& previous_sample = samples_[current_index_ ^ 1];
-
-  // Ready to compute velocities.
-  const auto pose_delta_time =
-      NsToSeconds(sample.time_ns - previous_sample.time_ns);
-
-  if (pose_delta_time > 0.0) {
-    velocity_ = (sample.position - previous_sample.position) / pose_delta_time;
-    rotational_velocity_ = Predictor::AngularVelocity(
-        previous_sample.orientation, sample.orientation, pose_delta_time);
-  } else {
-    velocity_ = vec3::Zero();
-    rotational_velocity_ = vec3::Zero();
-  }
-
-  // Temporary experiment with acceleration estimate.
-  angular_speed_ = rotational_velocity_.norm();
-  angular_accel_ = 0.0;
-  if (forward_predict_angular_speed_) {
-    angular_accel_ =
-        pose_delta_time > 0.0
-            ? (angular_speed_ - last_angular_speed_) / pose_delta_time
-            : 0.0;
-  }
-  last_angular_speed_ = angular_speed_;
-
-  rotational_axis_ = vec3(0.0, 1.0, 0.0);
-  if (angular_speed_ > 0.0) {
-    rotational_axis_ = rotational_velocity_ / angular_speed_;
-  }
-}
-
-Pose LinearPosePredictor::Predict(int64_t time_ns) const {
-  const auto& sample = samples_[current_index_];
-
-  const auto dt = NsToSeconds(time_ns - sample.time_ns);
-
-  // Temporary forward prediction code.
-  auto angle = angular_speed_ * dt;
-  if (__builtin_expect(forward_predict_angular_speed_, 0)) {
-    angle += 0.5 * angular_accel_ * dt * dt;
-  }
-
-  return {time_ns, sample.position + velocity_ * dt,
-          sample.orientation * quat(AngleAxis(angle, rotational_axis_))};
-}
-
-Velocity LinearPosePredictor::PredictVelocity(int64_t /* time_ns */) const {
-  return {velocity_, rotational_velocity_};
-}
-
-}  // namespace posepredictor
diff --git a/libs/vr/libposepredictor/linear_predictor_tests.cpp b/libs/vr/libposepredictor/linear_predictor_tests.cpp
deleted file mode 100644
index d94aa2d..0000000
--- a/libs/vr/libposepredictor/linear_predictor_tests.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-#include <gtest/gtest.h>
-
-#include <linear_predictor.h>
-
-namespace posepredictor {
-
-namespace {
-
-// For comparing expected and actual.
-constexpr real kAbsErrorTolerance = 1e-5;
-
-// The default rotation axis we will be using.
-const vec3 kRotationAxis = vec3(1, 4, 3).normalized();
-
-// Linearly interpolate between a and b.
-vec3 lerp(const vec3& a, const vec3& b, real t) { return (b - a) * t + a; }
-
-// Linearly interpolate between two angles and return the resulting rotation as
-// a quaternion (around the kRotationAxis).
-quat qlerp(real angle1, real angle2, real t) {
-  return quat(
-      Eigen::AngleAxis<real>((angle2 - angle1) * t + angle1, kRotationAxis));
-}
-
-// Compare two positions.
-void TestPosition(const vec3& expected, const vec3& actual) {
-  for (int i = 0; i < 3; ++i) {
-    EXPECT_NEAR(expected[i], actual[i], kAbsErrorTolerance);
-  }
-}
-
-// Compare two orientations.
-void TestOrientation(const quat& expected, const quat& actual) {
-  // abs(expected.dot(actual)) > 1-eps
-  EXPECT_GE(std::abs(actual.coeffs().dot(expected.coeffs())), 0.99);
-}
-}
-
-// Test the extrapolation from two samples.
-TEST(LinearPosePredictorTest, Extrapolation) {
-  LinearPosePredictor predictor;
-
-  // We wil extrapolate linearly from [position|orientation] 1 -> 2.
-  const vec3 position1(0, 0, 0);
-  const vec3 position2(1, 2, 3);
-  const real angle1 = M_PI * 0.3;
-  const real angle2 = M_PI * 0.5;
-  const quat orientation1(Eigen::AngleAxis<real>(angle1, kRotationAxis));
-  const quat orientation2(Eigen::AngleAxis<real>(angle2, kRotationAxis));
-  const int64_t t1_ns = 0;           //< First sample time stamp
-  const int64_t t2_ns = 10;          //< The second sample time stamp
-  const int64_t eval_left_ns = 23;   //< The eval time for left
-  const int64_t eval_right_ns = 31;  //< The eval time for right
-  Pose start_pose, end_pose, extrapolated_pose;
-
-  predictor.Add(Pose{
-      .position = position1, .orientation = orientation1, .time_ns = t1_ns});
-
-  predictor.Add(Pose{
-      .position = position2, .orientation = orientation2, .time_ns = t2_ns});
-
-  // Extrapolate from t1 - t2 to eval_[left/right].
-  extrapolated_pose = predictor.Predict(eval_left_ns);
-
-  // The interpolation factors for left and right.
-  const auto left_t = (eval_left_ns - t1_ns) / static_cast<real>(t2_ns - t1_ns);
-  EXPECT_EQ(2.3, left_t);
-
-  TestPosition(lerp(position1, position2, left_t), extrapolated_pose.position);
-
-  TestOrientation(qlerp(angle1, angle2, left_t), extrapolated_pose.orientation);
-
-  extrapolated_pose = predictor.Predict(eval_right_ns);
-
-  const auto right_t =
-      (eval_right_ns - t1_ns) / static_cast<real>(t2_ns - t1_ns);
-  EXPECT_EQ(3.1, right_t);
-
-  TestPosition(lerp(position1, position2, right_t), extrapolated_pose.position);
-
-  TestOrientation(qlerp(angle1, angle2, right_t),
-                  extrapolated_pose.orientation);
-}
-
-// Test three samples, where the last two samples have the same timestamp.
-TEST(LinearPosePredictorTest, DuplicateSamples) {
-  LinearPosePredictor predictor;
-
-  const vec3 position1(0, 0, 0);
-  const vec3 position2(1, 2, 3);
-  const vec3 position3(2, 2, 3);
-  const real angle1 = M_PI * 0.3;
-  const real angle2 = M_PI * 0.5;
-  const real angle3 = M_PI * 0.65;
-  const quat orientation1(Eigen::AngleAxis<real>(angle1, kRotationAxis));
-  const quat orientation2(Eigen::AngleAxis<real>(angle2, kRotationAxis));
-  const quat orientation3(Eigen::AngleAxis<real>(angle3, kRotationAxis));
-  const int64_t t1_ns = 0;
-  const int64_t t2_ns = 10;
-  const int64_t eval_left_ns = 27;
-  const int64_t eval_right_ns = 31;
-  Pose extrapolated_pose;
-
-  predictor.Add(Pose{
-      .position = position1, .orientation = orientation1, .time_ns = t1_ns});
-
-  predictor.Add(Pose{
-      .position = position2, .orientation = orientation2, .time_ns = t2_ns});
-
-  {
-    // Extrapolate from t1 - t2 to eval_[left/right].
-    extrapolated_pose = predictor.Predict(eval_left_ns);
-
-    // The interpolation factors for left and right.
-    const auto left_t =
-        (eval_left_ns - t1_ns) / static_cast<real>(t2_ns - t1_ns);
-
-    // Test the result.
-    TestPosition(lerp(position1, position2, left_t),
-                 extrapolated_pose.position);
-
-    TestOrientation(qlerp(angle1, angle2, left_t),
-                    extrapolated_pose.orientation);
-
-    extrapolated_pose = predictor.Predict(eval_right_ns);
-
-    const auto right_t =
-        (eval_right_ns - t1_ns) / static_cast<real>(t2_ns - t1_ns);
-
-    TestPosition(lerp(position1, position2, right_t),
-                 extrapolated_pose.position);
-
-    TestOrientation(qlerp(angle1, angle2, right_t),
-                    extrapolated_pose.orientation);
-  }
-
-  // Sending a duplicate sample here.
-  predictor.Add(Pose{
-      .position = position3, .orientation = orientation3, .time_ns = t2_ns});
-
-  {
-    // Extrapolate from t1 - t2 to eval_[left/right].
-    extrapolated_pose = predictor.Predict(eval_left_ns);
-
-    // The interpolation factors for left and right.
-    const auto left_t =
-        (eval_left_ns - t1_ns) / static_cast<real>(t2_ns - t1_ns);
-
-    TestPosition(lerp(position1, position3, left_t),
-                 extrapolated_pose.position);
-
-    TestOrientation(qlerp(angle1, angle3, left_t),
-                    extrapolated_pose.orientation);
-
-    extrapolated_pose = predictor.Predict(eval_right_ns);
-
-    const auto right_t =
-        (eval_right_ns - t1_ns) / static_cast<real>(t2_ns - t1_ns);
-
-    // Test the result.
-
-    TestPosition(lerp(position1, position3, right_t),
-                 extrapolated_pose.position);
-
-    TestOrientation(qlerp(angle1, angle3, right_t),
-                    extrapolated_pose.orientation);
-  }
-}
-
-}  // namespace posepredictor
diff --git a/libs/vr/libposepredictor/polynomial_predictor.cpp b/libs/vr/libposepredictor/polynomial_predictor.cpp
deleted file mode 100644
index 98fd28a..0000000
--- a/libs/vr/libposepredictor/polynomial_predictor.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <polynomial_predictor.h>
-
-namespace posepredictor {
-
-// Instantiate the common polynomial types.
-template class PolynomialPosePredictor<1, 2>;
-template class PolynomialPosePredictor<2, 3>;
-template class PolynomialPosePredictor<3, 4>;
-template class PolynomialPosePredictor<4, 5>;
-
-}  // namespace posepredictor
diff --git a/libs/vr/libposepredictor/polynomial_predictor_tests.cpp b/libs/vr/libposepredictor/polynomial_predictor_tests.cpp
deleted file mode 100644
index 88cb2b9..0000000
--- a/libs/vr/libposepredictor/polynomial_predictor_tests.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-#include <gtest/gtest.h>
-
-#include <polynomial_predictor.h>
-
-namespace posepredictor {
-
-namespace {
-
-// For comparing expected and actual.
-constexpr real kAbsErrorTolerance = 1e-5;
-
-// Test the linear extrapolation from two samples.
-TEST(PolynomialPosePredictor, Linear) {
-  // Degree = 1, simple line, passing through two points.
-  // Note the regularization is 0 so we expect the exact fit.
-  PolynomialPosePredictor<1, 2> predictor(0);
-
-  // Add two samples.
-  predictor.Add(
-      Pose{.position = {0, 0, 0}, .orientation = {0, 0, 0, 1}, .time_ns = 0});
-
-  predictor.Add(
-      Pose{.position = {1, 2, 3}, .orientation = {0, 0, 0, 1}, .time_ns = 10});
-
-  Pose predicted_pose;
-
-  predicted_pose = predictor.Predict(20);
-
-  // Check the x,y,z components for the expected translation.
-  EXPECT_NEAR(predicted_pose.position[0], 2, kAbsErrorTolerance);
-  EXPECT_NEAR(predicted_pose.position[1], 4, kAbsErrorTolerance);
-  EXPECT_NEAR(predicted_pose.position[2], 6, kAbsErrorTolerance);
-
-  predicted_pose = predictor.Predict(30);
-  EXPECT_NEAR(predicted_pose.position[0], 3, kAbsErrorTolerance);
-  EXPECT_NEAR(predicted_pose.position[1], 6, kAbsErrorTolerance);
-  EXPECT_NEAR(predicted_pose.position[2], 9, kAbsErrorTolerance);
-}
-
-// Test the degree two polynomial fit.
-TEST(PolynomialPosePredictor, Quadric) {
-  // Degree = 2, need three samples to fit a polynomial.
-  // Note the regularization is 0 so we expect the exact fit.
-  PolynomialPosePredictor<2, 3> predictor(0);
-
-  // Add three samples.
-  predictor.Add(
-      Pose{.position = {1, 2, 3}, .orientation = {0, 0, 0, 1}, .time_ns = 0});
-
-  predictor.Add(
-      Pose{.position = {0, 0, 0}, .orientation = {0, 0, 0, 1}, .time_ns = 10});
-
-  predictor.Add(
-      Pose{.position = {1, 2, 3}, .orientation = {0, 0, 0, 1}, .time_ns = 20});
-
-  // The expected polynomials for x/y/z.
-
-  // x:  0.01 * t^2 - 0.2 * t + 1
-  const auto x = [](auto t) { return 0.01 * t * t - 0.2 * t + 1; };
-
-  // y:  0.02 * t^2 - 0.4 * t + 2
-  const auto y = [](auto t) { return 0.02 * t * t - 0.4 * t + 2; };
-
-  // z:  0.03 * t^2 - 0.6 * t + 3
-  const auto z = [](auto t) { return 0.03 * t * t - 0.6 * t + 3; };
-
-  Pose predicted_pose;
-  predicted_pose = predictor.Predict(40);
-
-  // Check the x,y,z components for the expected translation.
-  EXPECT_NEAR(predicted_pose.position[0], x(40), kAbsErrorTolerance);
-  EXPECT_NEAR(predicted_pose.position[1], y(40), kAbsErrorTolerance);
-  EXPECT_NEAR(predicted_pose.position[2], z(40), kAbsErrorTolerance);
-
-  predicted_pose = predictor.Predict(50);
-  EXPECT_NEAR(predicted_pose.position[0], x(50), kAbsErrorTolerance);
-  EXPECT_NEAR(predicted_pose.position[1], y(50), kAbsErrorTolerance);
-  EXPECT_NEAR(predicted_pose.position[2], z(50), kAbsErrorTolerance);
-}
-
-// Test the degree two polynomial fit with degenerate input.
-//
-// The input samples all lie in a line which would normally make our system
-// degenerate. We will rely on the regularization term to recover the linear
-// solution in a quadric predictor.
-TEST(PolynomialPosePredictor, QuadricDegenate) {
-  // Degree = 2, need three samples to fit a polynomial.
-  // Note that we are using the default regularization term here.
-  // We cannot use 0 regularizer since the input is degenerate.
-  PolynomialPosePredictor<2, 3> predictor(1e-20);
-
-  // Add three samples.
-  predictor.Add(
-      Pose{.position = {0, 0, 0}, .orientation = {0, 0, 0, 1}, .time_ns = 0});
-
-  predictor.Add(
-      Pose{.position = {1, 2, 3}, .orientation = {0, 0, 0, 1}, .time_ns = 10});
-
-  predictor.Add(
-      Pose{.position = {2, 4, 6}, .orientation = {0, 0, 0, 1}, .time_ns = 20});
-
-  Pose predicted_pose;
-
-  predicted_pose = predictor.Predict(30);
-
-  // Check the x,y,z components for the expected translation.
-  // We are using a higher error threshold since this is now approximate.
-  EXPECT_NEAR(predicted_pose.position[0], 3, 0.001);
-  EXPECT_NEAR(predicted_pose.position[1], 6, 0.001);
-  EXPECT_NEAR(predicted_pose.position[2], 9, 0.001);
-
-  predicted_pose = predictor.Predict(40);
-  EXPECT_NEAR(predicted_pose.position[0], 4, 0.001);
-  EXPECT_NEAR(predicted_pose.position[1], 8, 0.001);
-  EXPECT_NEAR(predicted_pose.position[2], 12, 0.001);
-}
-
-}  // namespace
-
-}  // namespace posepredictor
diff --git a/libs/vr/libposepredictor/predictor.cpp b/libs/vr/libposepredictor/predictor.cpp
deleted file mode 100644
index beba156..0000000
--- a/libs/vr/libposepredictor/predictor.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <linear_predictor.h>
-#include <polynomial_predictor.h>
-#include <predictor.h>
-
-namespace posepredictor {
-
-vec3 Predictor::AngularVelocity(const quat& a, const quat& b, real delta_time) {
-  const auto delta_q = a.inverse() * b;
-  // Check that delta_q.w() == 1, Eigen doesn't respect this convention. If
-  // delta_q.w() == -1, we'll get the opposite velocity.
-  return 2.0 * (delta_q.w() < 0 ? static_cast<vec3>(-delta_q.vec()) : delta_q.vec()) / delta_time;
-}
-
-Velocity Predictor::PredictVelocity(int64_t time_ns) const {
-  const auto a = Predict(time_ns - kFiniteDifferenceNs);
-  const auto b = Predict(time_ns + kFiniteDifferenceNs);
-  const auto delta_time = NsToSeconds(2 * kFiniteDifferenceNs);
-
-  return {(b.position - a.position) / delta_time,
-          AngularVelocity(a.orientation, b.orientation, delta_time)};
-}
-
-// The factory method.
-std::unique_ptr<Predictor> Predictor::Create(PredictorType type) {
-  switch (type) {
-    case PredictorType::Linear:
-      return std::make_unique<LinearPosePredictor>();
-    case PredictorType::Quadric:
-      return std::make_unique<QuadricPosePredictor>();
-    case PredictorType::Cubic:
-      return std::make_unique<CubicPosePredictor>();
-  }
-}
-}  // namespace posepredictor
diff --git a/libs/vr/libposepredictor/predictor_tests.cpp b/libs/vr/libposepredictor/predictor_tests.cpp
deleted file mode 100644
index e84a93a..0000000
--- a/libs/vr/libposepredictor/predictor_tests.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <gtest/gtest.h>
-
-#include <predictor.h>
-
-namespace posepredictor {
-
-namespace {
-
-// For comparing expected and actual.
-constexpr real kAbsErrorTolerance = 1e-4;
-
-// Test the angular velocity computation from two orientations.
-TEST(PosePredictor, AngularVelocity) {
-  // Some random rotation axis we will rotate around.
-  const vec3 kRotationAxis = vec3(1, 2, 3).normalized();
-
-  // Some random angle we will be rotating by.
-  const real kRotationAngle = M_PI / 30;
-
-  // Random start orientation we are currently at.
-  const quat kStartOrientation = quat(5, 3, 4, 1).normalized();
-
-  // The orientation we will end up at.
-  const quat kEndOrientation =
-      kStartOrientation *
-      quat(Eigen::AngleAxis<real>(kRotationAngle, kRotationAxis));
-
-  // The delta time for going from start orientation to end.
-  const real kDeltaTime = 1.0;
-
-  // Compute the angular velocity from start orientation to end.
-  const auto angularVelocity = Predictor::AngularVelocity(
-      kStartOrientation, kEndOrientation, kDeltaTime);
-
-  // Extract the axis and the angular speed.
-  const auto angularSpeed = angularVelocity.norm();
-  const auto rotationAxis = angularVelocity.normalized();
-
-  // The speed must match.
-  EXPECT_NEAR(angularSpeed, kRotationAngle / kDeltaTime, kAbsErrorTolerance);
-
-  // The rotation axis must match.
-  EXPECT_NEAR(rotationAxis[0], kRotationAxis[0], kAbsErrorTolerance);
-  EXPECT_NEAR(rotationAxis[1], kRotationAxis[1], kAbsErrorTolerance);
-  EXPECT_NEAR(rotationAxis[2], kRotationAxis[2], kAbsErrorTolerance);
-}
-
-}  // namespace
-
-}  // namespace posepredictor
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 6218e8e..0fb2d84 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -32,11 +32,12 @@
     "libbufferhubqueue",
     "libdisplay",
     "libdvrcommon",
-    "libdvrgraphics",
     "libperformance",
     "libvrsensor",
+    "libbroadcastring",
     "libpdx_default_transport",
     "libvr_manager",
+    "libbroadcastring",
 ]
 
 sharedLibraries = [
@@ -62,6 +63,10 @@
     "libfmq",
 ]
 
+headerLibraries = [
+    "libdvr_headers"
+]
+
 cc_library_static {
     srcs: sourceFiles,
     export_include_dirs: includeFiles,
@@ -75,5 +80,6 @@
     ],
     shared_libs: sharedLibraries,
     whole_static_libs: staticLibraries,
+    header_libs: headerLibraries,
     name: "libvrflinger",
 }
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index a0b3efe..0e9a6ab 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -78,9 +78,14 @@
           *this, &DisplayManagerService::OnGetSurfaceQueue, message);
       return {};
 
-    case DisplayManagerProtocol::SetupNamedBuffer::Opcode:
-      DispatchRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
-          *this, &DisplayManagerService::OnSetupNamedBuffer, message);
+    case DisplayManagerProtocol::SetupGlobalBuffer::Opcode:
+      DispatchRemoteMethod<DisplayManagerProtocol::SetupGlobalBuffer>(
+          *this, &DisplayManagerService::OnSetupGlobalBuffer, message);
+      return {};
+
+    case DisplayManagerProtocol::DeleteGlobalBuffer::Opcode:
+      DispatchRemoteMethod<DisplayManagerProtocol::DeleteGlobalBuffer>(
+          *this, &DisplayManagerService::OnDeleteGlobalBuffer, message);
       return {};
 
     default:
@@ -130,20 +135,33 @@
 }
 
 pdx::Status<BorrowedNativeBufferHandle>
-DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
-                                          const std::string& name, size_t size,
-                                          uint64_t usage) {
+DisplayManagerService::OnSetupGlobalBuffer(pdx::Message& message,
+                                           DvrGlobalBufferKey key, size_t size,
+                                           uint64_t usage) {
   const int user_id = message.GetEffectiveUserId();
   const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
 
   if (!trusted) {
     ALOGE(
-        "DisplayService::SetupNamedBuffer: Named buffers may only be created "
+        "DisplayService::SetupGlobalBuffer: Global buffers may only be created "
         "by trusted UIDs: user_id=%d",
         user_id);
     return ErrorStatus(EPERM);
   }
-  return display_service_->SetupNamedBuffer(name, size, usage);
+  return display_service_->SetupGlobalBuffer(key, size, usage);
+}
+
+pdx::Status<void> DisplayManagerService::OnDeleteGlobalBuffer(
+    pdx::Message& message, DvrGlobalBufferKey key) {
+  const int user_id = message.GetEffectiveUserId();
+  const bool trusted = (user_id == AID_ROOT) || IsTrustedUid(user_id);
+
+  if (!trusted) {
+    ALOGE("DisplayService::DeleteGlobalBuffer: Untrusted user_id (%d)",
+          user_id);
+    return ErrorStatus(EPERM);
+  }
+  return display_service_->DeleteGlobalBuffer(key);
 }
 
 void DisplayManagerService::OnDisplaySurfaceChange() {
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 0857eb5..c869ceb 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -56,9 +56,11 @@
   pdx::Status<pdx::LocalChannelHandle> OnGetSurfaceQueue(pdx::Message& message,
                                                          int surface_id,
                                                          int queue_id);
-  pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
-      pdx::Message& message, const std::string& name, size_t size,
+  pdx::Status<BorrowedNativeBufferHandle> OnSetupGlobalBuffer(
+      pdx::Message& message, DvrGlobalBufferKey key, size_t size,
       uint64_t usage);
+  pdx::Status<void> OnDeleteGlobalBuffer(pdx::Message& message,
+                                         DvrGlobalBufferKey key);
 
   // Called by the display service to indicate changes to display surfaces that
   // the display manager should evaluate.
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 47efa76..dc9807a 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -3,6 +3,8 @@
 #include <unistd.h>
 #include <vector>
 
+#include <android-base/file.h>
+#include <android-base/properties.h>
 #include <dvr/dvr_display_types.h>
 #include <pdx/default_transport/service_endpoint.h>
 #include <pdx/rpc/remote_method.h>
@@ -18,6 +20,14 @@
 using android::pdx::default_transport::Endpoint;
 using android::pdx::rpc::DispatchRemoteMethod;
 
+namespace {
+
+const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics";
+const char kDvrDeviceMetricsProperty[] = "ro.dvr.device_metrics";
+const char kDvrDeviceConfigProperty[] = "ro.dvr.device_configuration";
+
+}  // namespace
+
 namespace android {
 namespace dvr {
 
@@ -60,14 +70,19 @@
           *this, &DisplayService::OnGetMetrics, message);
       return {};
 
+    case DisplayProtocol::GetConfigurationData::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetConfigurationData>(
+          *this, &DisplayService::OnGetConfigurationData, message);
+      return {};
+
     case DisplayProtocol::CreateSurface::Opcode:
       DispatchRemoteMethod<DisplayProtocol::CreateSurface>(
           *this, &DisplayService::OnCreateSurface, message);
       return {};
 
-    case DisplayProtocol::GetNamedBuffer::Opcode:
-      DispatchRemoteMethod<DisplayProtocol::GetNamedBuffer>(
-          *this, &DisplayService::OnGetNamedBuffer, message);
+    case DisplayProtocol::GetGlobalBuffer::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetGlobalBuffer>(
+          *this, &DisplayService::OnGetGlobalBuffer, message);
       return {};
 
     case DisplayProtocol::IsVrAppRunning::Opcode:
@@ -102,6 +117,35 @@
            {}}};
 }
 
+pdx::Status<std::string> DisplayService::OnGetConfigurationData(
+    pdx::Message& /*message*/, display::ConfigFileType config_type) {
+  std::string property_name;
+  switch (config_type) {
+    case display::ConfigFileType::kLensMetrics:
+      property_name = kDvrLensMetricsProperty;
+      break;
+    case display::ConfigFileType::kDeviceMetrics:
+      property_name = kDvrDeviceMetricsProperty;
+      break;
+    case display::ConfigFileType::kDeviceConfiguration:
+      property_name = kDvrDeviceConfigProperty;
+      break;
+    default:
+      return ErrorStatus(EINVAL);
+  }
+  std::string file_path = base::GetProperty(property_name, "");
+  if (file_path.empty()) {
+    return ErrorStatus(ENOENT);
+  }
+
+  std::string data;
+  if (!base::ReadFileToString(file_path, &data)) {
+    return ErrorStatus(errno);
+  }
+
+  return std::move(data);
+}
+
 // Creates a new DisplaySurface and associates it with this channel. This may
 // only be done once per channel.
 Status<display::SurfaceInfo> DisplayService::OnCreateSurface(
@@ -155,12 +199,12 @@
   }
 }
 
-pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
-    pdx::Message& /* message */, const std::string& name) {
-  ALOGD_IF(TRACE, "displayService::OnGetNamedBuffer: name=%s", name.c_str());
-  auto named_buffer = named_buffers_.find(name);
-  if (named_buffer != named_buffers_.end())
-    return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetGlobalBuffer(
+    pdx::Message& /* message */, DvrGlobalBufferKey key) {
+  ALOGD_IF(TRACE, "DisplayService::OnGetGlobalBuffer: key=%d", key);
+  auto global_buffer = global_buffers_.find(key);
+  if (global_buffer != global_buffers_.end())
+    return {BorrowedNativeBufferHandle(*global_buffer->second, 0)};
   else
     return pdx::ErrorStatus(EINVAL);
 }
@@ -221,18 +265,35 @@
   hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
-pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
-    const std::string& name, size_t size, uint64_t usage) {
-  auto named_buffer = named_buffers_.find(name);
-  if (named_buffer == named_buffers_.end()) {
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupGlobalBuffer(
+    DvrGlobalBufferKey key, size_t size, uint64_t usage) {
+  auto global_buffer = global_buffers_.find(key);
+  if (global_buffer == global_buffers_.end()) {
     auto ion_buffer = std::make_unique<IonBuffer>(static_cast<int>(size), 1,
                                                   HAL_PIXEL_FORMAT_BLOB, usage);
-    named_buffer =
-        named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
+
+    // Some buffers are used internally. If they were configured with an
+    // invalid size or format, this will fail.
+    int result = hardware_composer_.OnNewGlobalBuffer(key, *ion_buffer.get());
+    if (result < 0)
+      return ErrorStatus(result);
+    global_buffer =
+        global_buffers_.insert(std::make_pair(key, std::move(ion_buffer)))
             .first;
   }
 
-  return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
+  return {BorrowedNativeBufferHandle(*global_buffer->second, 0)};
+}
+
+pdx::Status<void> DisplayService::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
+  auto global_buffer = global_buffers_.find(key);
+  if (global_buffer != global_buffers_.end()) {
+    // Some buffers are used internally.
+    hardware_composer_.OnDeletedGlobalBuffer(key);
+    global_buffers_.erase(global_buffer);
+  }
+
+  return {0};
 }
 
 void DisplayService::OnHardwareComposerRefresh() {
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index bb4eeef..cb21e9f 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -1,6 +1,7 @@
 #ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
 #define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
 
+#include <dvr/dvr_api.h>
 #include <pdx/service.h>
 #include <pdx/status.h>
 #include <private/dvr/buffer_hub_client.h>
@@ -40,8 +41,10 @@
   // any change to client/manager attributes that affect visibility or z order.
   void UpdateActiveDisplaySurfaces();
 
-  pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
-      const std::string& name, size_t size, uint64_t usage);
+  pdx::Status<BorrowedNativeBufferHandle> SetupGlobalBuffer(
+      DvrGlobalBufferKey key, size_t size, uint64_t usage);
+
+  pdx::Status<void> DeleteGlobalBuffer(DvrGlobalBufferKey key);
 
   template <class A>
   void ForEachDisplaySurface(SurfaceType surface_type, A action) const {
@@ -82,9 +85,11 @@
   DisplayService(android::Hwc2::Composer* hidl,
                  RequestDisplayCallback request_display_callback);
 
-  pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
-      pdx::Message& message, const std::string& name);
+  pdx::Status<BorrowedNativeBufferHandle> OnGetGlobalBuffer(
+      pdx::Message& message, DvrGlobalBufferKey key);
   pdx::Status<display::Metrics> OnGetMetrics(pdx::Message& message);
+  pdx::Status<std::string> OnGetConfigurationData(
+      pdx::Message& message, display::ConfigFileType config_type);
   pdx::Status<display::SurfaceInfo> OnCreateSurface(
       pdx::Message& message, const display::SurfaceAttributes& attributes);
 
@@ -113,7 +118,8 @@
   EpollEventDispatcher dispatcher_;
   DisplayConfigurationUpdateNotifier update_notifier_;
 
-  std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
+  std::unordered_map<DvrGlobalBufferKey, std::unique_ptr<IonBuffer>>
+      global_buffers_;
 
   DisplayService(const DisplayService&) = delete;
   void operator=(const DisplayService&) = delete;
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index 5829788..babdc0e 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -3,7 +3,6 @@
 #include <private/android_filesystem_config.h>
 #include <utils/Trace.h>
 
-#include <private/dvr/platform_defines.h>
 #include <private/dvr/trusted_uids.h>
 
 #include "display_service.h"
@@ -208,7 +207,9 @@
            surface_id(), meta_size_bytes);
 
   std::lock_guard<std::mutex> autolock(lock_);
-  auto producer = ProducerQueue::Create(meta_size_bytes);
+  auto config =
+      ProducerQueueConfigBuilder().SetMetadataSize(meta_size_bytes).Build();
+  auto producer = ProducerQueue::Create(config, UsagePolicy{});
   if (!producer) {
     ALOGE(
         "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
@@ -269,7 +270,12 @@
 
   std::lock_guard<std::mutex> autolock(lock_);
   if (!direct_queue_) {
-    auto producer = ProducerQueue::Create(meta_size_bytes);
+    // Inject the hw composer usage flag to enable the display to read the
+    // buffers.
+    auto config =
+        ProducerQueueConfigBuilder().SetMetadataSize(meta_size_bytes).Build();
+    auto producer = ProducerQueue::Create(
+        config, UsagePolicy{GraphicBuffer::USAGE_HW_COMPOSER, 0, 0, 0});
     if (!producer) {
       ALOGE(
           "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index 47a07f0..c456b10 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -5,7 +5,6 @@
 #include <pdx/service.h>
 #include <private/dvr/buffer_hub_queue_client.h>
 #include <private/dvr/display_protocol.h>
-#include <private/dvr/graphics_private.h>
 #include <private/dvr/ring_buffer.h>
 
 #include <functional>
@@ -162,6 +161,8 @@
   // The capacity of the pending buffer queue. Should be enough to hold all the
   // buffers of this DisplaySurface, although in practice only 1 or 2 frames
   // will be pending at a time.
+  static constexpr int kSurfaceBufferMaxCount = 4;
+  static constexpr int kSurfaceViewMaxCount = 4;
   static constexpr int kMaxPostedBuffers =
       kSurfaceBufferMaxCount * kSurfaceViewMaxCount;
 
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 4c08284..7a78d1f 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -19,13 +19,12 @@
 #include <chrono>
 #include <functional>
 #include <map>
+#include <tuple>
 
 #include <dvr/dvr_display_types.h>
 #include <dvr/performance_client_api.h>
 #include <private/dvr/clock_ns.h>
 #include <private/dvr/ion_buffer.h>
-#include <private/dvr/pose_client_internal.h>
-#include <private/dvr/sync_util.h>
 
 using android::pdx::LocalHandle;
 using android::pdx::rpc::EmptyVariant;
@@ -38,17 +37,6 @@
 
 namespace {
 
-// If the number of pending fences goes over this count at the point when we
-// are about to submit a new frame to HWC, we will drop the frame. This should
-// be a signal that the display driver has begun queuing frames. Note that with
-// smart displays (with RAM), the fence is signaled earlier than the next vsync,
-// at the point when the DMA to the display completes. Currently we use a smart
-// display and the EDS timing coincides with zero pending fences, so this is 0.
-constexpr int kAllowedPendingFenceCount = 0;
-
-// Offset before vsync to submit frames to hardware composer.
-constexpr int64_t kFramePostOffsetNs = 4000000;  // 4ms
-
 const char kBacklightBrightnessSysFile[] =
     "/sys/class/leds/lcd-backlight/brightness";
 
@@ -222,10 +210,6 @@
 void HardwareComposer::OnPostThreadResumed() {
   hwc2_hidl_->resetCommands();
 
-  // Connect to pose service.
-  pose_client_ = dvrPoseCreate();
-  ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
-
   // HIDL HWC seems to have an internal race condition. If we submit a frame too
   // soon after turning on VSync we don't get any VSync signals. Give poor HWC
   // implementations a chance to enable VSync before we continue.
@@ -254,11 +238,6 @@
   }
   active_layer_count_ = 0;
 
-  if (pose_client_) {
-    dvrPoseDestroy(pose_client_);
-    pose_client_ = nullptr;
-  }
-
   EnableVsync(false);
 
   hwc2_hidl_->resetCommands();
@@ -398,8 +377,8 @@
   }
 
   const bool is_frame_pending = IsFramePendingInDriver();
-  const bool is_fence_pending =
-      retire_fence_fds_.size() > kAllowedPendingFenceCount;
+  const bool is_fence_pending = retire_fence_fds_.size() >
+                                post_thread_config_.allowed_pending_fence_count;
 
   if (is_fence_pending || is_frame_pending) {
     ATRACE_INT("frame_skip_count", ++frame_skip_count_);
@@ -476,6 +455,71 @@
     request_display_callback_(!display_idle);
 }
 
+int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key,
+                                        IonBuffer& ion_buffer) {
+  if (key == DvrGlobalBuffers::kVsyncBuffer) {
+    vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>(
+        &ion_buffer, CPUUsageMode::WRITE_OFTEN);
+
+    if (vsync_ring_->IsMapped() == false) {
+      return -EPERM;
+    }
+  }
+
+  if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
+    return MapConfigBuffer(ion_buffer);
+  }
+
+  return 0;
+}
+
+void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) {
+  if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
+    ConfigBufferDeleted();
+  }
+}
+
+int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) {
+  std::lock_guard<std::mutex> lock(shared_config_mutex_);
+  shared_config_ring_ = DvrVrFlingerConfigRing();
+
+  if (ion_buffer.width() < DvrVrFlingerConfigRing::MemorySize()) {
+    ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size.");
+    return -EINVAL;
+  }
+
+  void* buffer_base = 0;
+  int result = ion_buffer.Lock(ion_buffer.usage(), 0, 0, ion_buffer.width(),
+                               ion_buffer.height(), &buffer_base);
+  if (result != 0) {
+    ALOGE("HardwareComposer::MapConfigBuffer: Failed to map vrflinger config "
+          "buffer.");
+    return -EPERM;
+  }
+
+  shared_config_ring_ =
+      DvrVrFlingerConfigRing::Create(buffer_base, ion_buffer.width());
+  ion_buffer.Unlock();
+
+  return 0;
+}
+
+void HardwareComposer::ConfigBufferDeleted() {
+  std::lock_guard<std::mutex> lock(shared_config_mutex_);
+  shared_config_ring_ = DvrVrFlingerConfigRing();
+}
+
+void HardwareComposer::UpdateConfigBuffer() {
+  std::lock_guard<std::mutex> lock(shared_config_mutex_);
+  if (!shared_config_ring_.is_valid())
+    return;
+  // Copy from latest record in shared_config_ring_ to local copy.
+  DvrVrFlingerConfig record;
+  if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
+    post_thread_config_ = record;
+  }
+}
+
 int HardwareComposer::PostThreadPollInterruptible(
     const pdx::LocalHandle& event_fd, int requested_events) {
   pollfd pfd[2] = {
@@ -740,14 +784,14 @@
   right_eye_photon_offset_ns =
       property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
 
-  // Storage for retrieving fence info.
-  FenceInfoBuffer fence_info_buffer;
-
   bool was_running = false;
 
   while (1) {
     ATRACE_NAME("HardwareComposer::PostThread");
 
+    // Check for updated config once per vsync.
+    UpdateConfigBuffer();
+
     while (post_thread_quiescent_) {
       std::unique_lock<std::mutex> lock(post_thread_mutex_);
       ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
@@ -805,16 +849,20 @@
 
     ++vsync_count_;
 
-    if (pose_client_) {
-      // Signal the pose service with vsync info.
-      // Display timestamp is in the middle of scanout.
-      privateDvrPoseNotifyVsync(pose_client_, vsync_count_,
-                                vsync_timestamp + photon_offset_ns,
-                                ns_per_frame, right_eye_photon_offset_ns);
-    }
-
     const bool layer_config_changed = UpdateLayerConfig();
 
+    // Publish the vsync event.
+    if (vsync_ring_) {
+      DvrVsync vsync;
+      vsync.vsync_count = vsync_count_;
+      vsync.vsync_timestamp_ns = vsync_timestamp;
+      vsync.vsync_left_eye_offset_ns = photon_offset_ns;
+      vsync.vsync_right_eye_offset_ns = right_eye_photon_offset_ns;
+      vsync.vsync_period_ns = ns_per_frame;
+
+      vsync_ring_->Publish(vsync);
+    }
+
     // Signal all of the vsync clients. Because absolute time is used for the
     // wakeup time below, this can take a little time if necessary.
     if (vsync_callback_)
@@ -827,9 +875,10 @@
 
       const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
       const int64_t now_ns = GetSystemClockNs();
-      const int64_t sleep_time_ns =
-          display_time_est_ns - now_ns - kFramePostOffsetNs;
-      const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
+      const int64_t sleep_time_ns = display_time_est_ns - now_ns -
+                                    post_thread_config_.frame_post_offset_ns;
+      const int64_t wakeup_time_ns =
+          display_time_est_ns - post_thread_config_.frame_post_offset_ns;
 
       ATRACE_INT64("sleep_time_ns", sleep_time_ns);
       if (sleep_time_ns > 0) {
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 20327a3..de6f9ff 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -5,6 +5,7 @@
 #include "DisplayHardware/ComposerHal.h"
 #include "hwc_types.h"
 
+#include <dvr/dvr_shared_buffers.h>
 #include <hardware/gralloc.h>
 #include <log/log.h>
 
@@ -16,12 +17,12 @@
 #include <tuple>
 #include <vector>
 
-#include <dvr/pose_client.h>
+#include <dvr/dvr_vrflinger_config.h>
+#include <dvr/dvr_vsync.h>
 #include <pdx/file_handle.h>
 #include <pdx/rpc/variant.h>
 #include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/frame_time_history.h>
-#include <private/dvr/sync_util.h>
+#include <private/dvr/shared_buffer_helpers.h>
 
 #include "acquired_buffer.h"
 #include "display_surface.h"
@@ -286,6 +287,9 @@
   void SetDisplaySurfaces(
       std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces);
 
+  int OnNewGlobalBuffer(DvrGlobalBufferKey key, IonBuffer& ion_buffer);
+  void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
+
   void OnHardwareComposerRefresh();
 
  private:
@@ -367,6 +371,13 @@
   // Called on the post thread when the post thread is paused or quits.
   void OnPostThreadPaused();
 
+  // Map the given shared memory buffer to our broadcast ring to track updates
+  // to the config parameters.
+  int MapConfigBuffer(IonBuffer& ion_buffer);
+  void ConfigBufferDeleted();
+  // Poll for config udpates.
+  void UpdateConfigBuffer();
+
   bool initialized_;
 
   // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own
@@ -437,9 +448,15 @@
   // us to detect when the display driver begins queuing frames.
   std::vector<pdx::LocalHandle> retire_fence_fds_;
 
-  // Pose client for frame count notifications. Pose client predicts poses
-  // out to display frame boundaries, so we need to tell it about vsyncs.
-  DvrPose* pose_client_ = nullptr;
+  // If we are publishing vsync data, we will put it here.
+  std::unique_ptr<CPUMappedBroadcastRing<DvrVsyncRing>> vsync_ring_;
+
+  // Broadcast ring for receiving config data from the DisplayManager.
+  DvrVrFlingerConfigRing shared_config_ring_;
+  uint32_t shared_config_ring_sequence_{0};
+  // Config buffer for reading from the post thread.
+  DvrVrFlingerConfig post_thread_config_;
+  std::mutex shared_config_mutex_;
 
   static constexpr int kPostThreadInterrupted = 1;
 
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index 3588b5e..d022adf 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -23,9 +23,11 @@
 ]
 
 staticLibraries = [
+    "libdisplay",
     "libbufferhub",
     "libbufferhubqueue",
     "libdvrcommon",
+    "libbroadcastring",
     "libpdx_default_transport",
 ]
 
@@ -43,31 +45,7 @@
     export_include_dirs: includeFiles,
     static_libs: staticLibraries,
     shared_libs: sharedLibraries,
+    header_libs: ["libdvr_headers"],
     name: "libvrsensor",
 }
 
-testFiles = ["tests/sensor_app_tests.cpp"]
-
-cc_test {
-    name: "sensor_app_tests",
-    tags: ["optional"],
-
-    srcs: testFiles,
-
-    shared_libs: [
-        "libEGL",
-        "libGLESv1_CM",
-        "libGLESv2",
-        "libvulkan",
-        "libsync",
-    ] + sharedLibraries,
-
-    static_libs: [
-        "libgmock_main",
-        "libgmock",
-        "libdisplay",
-        "libvrsensor",
-        "libdvrgraphics",
-    ] + staticLibraries,
-
-}
diff --git a/libs/vr/libvrsensor/include/dvr/pose_client.h b/libs/vr/libvrsensor/include/dvr/pose_client.h
index 6802fa9..d684ddc 100644
--- a/libs/vr/libvrsensor/include/dvr/pose_client.h
+++ b/libs/vr/libvrsensor/include/dvr/pose_client.h
@@ -14,63 +14,13 @@
 #include <stdbool.h>
 #include <stdint.h>
 
+#include <dvr/dvr_pose.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef struct DvrPose DvrPose;
-
-// Represents the current state provided by the pose service, containing a
-// rotation and translation.
-typedef struct __attribute__((packed, aligned(8))) DvrPoseState {
-  // A quaternion representing the rotation of the HMD in Start Space.
-  struct __attribute__((packed)) {
-    float x, y, z, w;
-  } head_from_start_rotation;
-  // The position of the HMD in Start Space.
-  struct __attribute__((packed)) {
-    float x, y, z;
-  } head_from_start_translation;
-  // Time in nanoseconds for the current pose.
-  uint64_t timestamp_ns;
-  // The rotational velocity of the HMD.
-  struct __attribute__((packed)) {
-    float x, y, z;
-  } sensor_from_start_rotation_velocity;
-} DvrPoseState;
-
-enum {
-  DVR_POSE_FLAG_VALID = (1UL << 0),       // This pose is valid.
-  DVR_POSE_FLAG_HEAD = (1UL << 1),        // This pose is the head.
-  DVR_POSE_FLAG_CONTROLLER = (1UL << 2),  // This pose is a controller.
-};
-
-// Represents an estimated pose, accessed asynchronously through a shared ring
-// buffer. No assumptions should be made about the data in padding space.
-// The size of this struct is 128 bytes.
-typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync {
-  // Left eye head-from-start orientation quaternion x,y,z,w.
-  float32x4_t orientation;
-  // Left eye head-from-start translation x,y,z,pad in meters.
-  float32x4_t translation;
-  // Right eye head-from-start orientation quaternion x,y,z,w.
-  float32x4_t right_orientation;
-  // Right eye head-from-start translation x,y,z,pad in meters.
-  float32x4_t right_translation;
-  // Start-space angular velocity x,y,z,pad in radians per second.
-  float32x4_t angular_velocity;
-  // Start-space positional velocity x,y,z,pad in meters per second.
-  float32x4_t velocity;
-  // Timestamp of when this pose is predicted for, typically halfway through
-  // scanout.
-  int64_t timestamp_ns;
-  // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose.
-  //
-  // If DVR_POSE_FLAG_VALID is not set, the pose is indeterminate.
-  uint64_t flags;
-  // Reserved padding to 128 bytes.
-  uint8_t pad[16];
-} DvrPoseAsync;
+typedef struct DvrPoseClient DvrPoseClient;
 
 // Returned by the async pose ring buffer access API.
 typedef struct DvrPoseRingBufferInfo {
@@ -120,12 +70,12 @@
 // Creates a new pose client.
 //
 // @return Pointer to the created pose client, nullptr on failure.
-DvrPose* dvrPoseCreate();
+DvrPoseClient* dvrPoseClientCreate();
 
 // Destroys a pose client.
 //
 // @param client Pointer to the pose client to be destroyed.
-void dvrPoseDestroy(DvrPose* client);
+void dvrPoseClientDestroy(DvrPoseClient* client);
 
 // Gets the pose for the given vsync count.
 //
@@ -134,10 +84,11 @@
 //     Typically this is the count returned by dvrGetNextVsyncCount.
 // @param out_pose Struct to store pose state.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose);
+int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
+                     DvrPoseAsync* out_pose);
 
 // Gets the current vsync count.
-uint32_t dvrPoseGetVsyncCount(DvrPose* client);
+uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client);
 
 // Gets the pose for the given controller at the given vsync count.
 //
@@ -147,15 +98,15 @@
 //     Typically this is the count returned by dvrGetNextVsyncCount.
 // @param out_pose Struct to store pose state.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGetController(DvrPose* client, int32_t controller_id,
-                         uint32_t vsync_count, DvrPoseAsync* out_pose);
+int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
+                               uint32_t vsync_count, DvrPoseAsync* out_pose);
 
 // Enables/disables logging for the controller fusion.
 //
 // @param client Pointer to the pose client.
 // @param enable True starts logging, False stops.
 // @return Zero on success, negative error code on failure.
-int dvrPoseLogController(DvrPose* client, bool enable);
+int dvrPoseClientLogController(DvrPoseClient* client, bool enable);
 
 // DEPRECATED
 // Polls current pose state.
@@ -163,30 +114,30 @@
 // @param client Pointer to the pose client.
 // @param state Struct to store polled state.
 // @return Zero on success, negative error code on failure.
-int dvrPosePoll(DvrPose* client, DvrPoseState* state);
+int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state);
 
 // Freezes the pose to the provided state.
 //
 // Future poll operations will return this state until a different state is
-// frozen or dvrPoseSetMode() is called with a different mode. The timestamp is
+// frozen or dvrPoseClientModeSet() is called with a different mode. The timestamp is
 // not frozen.
 //
 // @param client Pointer to the pose client.
 // @param frozen_state State pose to be frozen to.
 // @return Zero on success, negative error code on failure.
-int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state);
+int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state);
 
 // Sets the pose service mode.
 //
 // @param mode The requested pose mode.
 // @return Zero on success, negative error code on failure.
-int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode);
+int dvrPoseClientModeSet(DvrPoseClient* client, DvrPoseMode mode);
 
 // Gets the pose service mode.
 //
 // @param mode Return value for the current pose mode.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode);
+int dvrPoseClientModeGet(DvrPoseClient* client, DvrPoseMode* mode);
 
 // Get access to the shared memory pose ring buffer.
 // A future pose at vsync <current> + <offset> is accessed at index:
@@ -197,8 +148,14 @@
 // |out_fd| will be set to the gralloc buffer file descriptor, which is
 //   required for binding this buffer for GPU use.
 // Returns 0 on success.
-int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info);
+int dvrPoseClientGetRingBuffer(DvrPoseClient* client,
+                               DvrPoseRingBufferInfo* out_info);
 
+// Sets enabled state for sensors pose processing.
+//
+// @param enabled Whether sensors are enabled or disabled.
+// @return Zero on success
+int dvrPoseClientSensorsEnable(DvrPoseClient* client, bool enabled);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
index 0616d46..e4455f1 100644
--- a/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
+++ b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
@@ -11,14 +11,12 @@
 #define DVR_POSE_SERVICE_CLIENT (DVR_POSE_SERVICE_BASE "/client")
 
 enum {
-  DVR_POSE_POLL = 0,
-  DVR_POSE_FREEZE,
+  DVR_POSE_FREEZE = 0,
   DVR_POSE_SET_MODE,
-  DVR_POSE_GET_RING_BUFFER,
-  DVR_POSE_NOTIFY_VSYNC,
   DVR_POSE_GET_MODE,
   DVR_POSE_GET_CONTROLLER_RING_BUFFER,
   DVR_POSE_LOG_CONTROLLER,
+  DVR_POSE_SENSORS_ENABLE,
 };
 
 #ifdef __cplusplus
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h b/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
deleted file mode 100644
index 66c4c7c..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
-#define ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
-
-#include <stdint.h>
-
-#include <dvr/pose_client.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/sensor_constants.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Sensord head pose ring buffer.
-typedef struct __attribute__((packed, aligned(16))) DvrPoseRingBuffer {
-  // Ring buffer always at the beginning of the structure, as consumers may
-  // not have access to this parent structure definition.
-  DvrPoseAsync ring[kPoseAsyncBufferTotalCount];
-  // Current vsync_count (where sensord is writing poses from).
-  uint32_t vsync_count;
-} DvrPoseMetadata;
-
-// Called by displayd to give vsync count info to the pose service.
-// |display_timestamp| Display timestamp is in the middle of scanout.
-// |display_period_ns| Nanos between vsyncs.
-// |right_eye_photon_offset_ns| Nanos to shift the prediction timestamp for
-//    the right eye head pose (relative to the left eye prediction).
-int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
-                              int64_t display_timestamp,
-                              int64_t display_period_ns,
-                              int64_t right_eye_photon_offset_ns);
-
-// Get file descriptor for access to the shared memory pose buffer. This can be
-// used with GL extensions that support shared memory buffer objects. The caller
-// takes ownership of the returned fd and must close it or pass on ownership.
-int privateDvrPoseGetRingBufferFd(DvrPose* client,
-                                  android::pdx::LocalHandle* fd);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
diff --git a/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h b/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
deleted file mode 100644
index 8fa87b3..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef ANDROID_DVR_SENSOR_CONSTANTS_H_
-#define ANDROID_DVR_SENSOR_CONSTANTS_H_
-
-namespace android {
-namespace dvr {
-
-// Number of elements in the async pose buffer.
-// Must be power of two.
-// Macro so that shader code can easily include this value.
-#define kPoseAsyncBufferTotalCount 8
-
-// Mask for accessing the current ring buffer array element:
-// index = vsync_count & kPoseAsyncBufferIndexMask
-constexpr uint32_t kPoseAsyncBufferIndexMask = kPoseAsyncBufferTotalCount - 1;
-
-// Number of pose frames including the current frame that are kept updated with
-// pose forecast data. The other poses are left their last known estimates.
-constexpr uint32_t kPoseAsyncBufferMinFutureCount = 4;
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSOR_CONSTANTS_H_
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index 9eae3aa..b21c7cf 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -1,4 +1,5 @@
 #define LOG_TAG "PoseClient"
+#include <dvr/dvr_shared_buffers.h>
 #include <dvr/pose_client.h>
 
 #include <stdint.h>
@@ -8,9 +9,9 @@
 #include <pdx/default_transport/client_channel_factory.h>
 #include <pdx/file_handle.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/display_client.h>
 #include <private/dvr/pose-ipc.h>
-#include <private/dvr/pose_client_internal.h>
-#include <private/dvr/sensor_constants.h>
+#include <private/dvr/shared_buffer_helpers.h>
 
 using android::pdx::LocalHandle;
 using android::pdx::LocalChannelHandle;
@@ -28,39 +29,44 @@
   ~PoseClient() override {}
 
   // Casts C handle into an instance of this class.
-  static PoseClient* FromC(DvrPose* client) {
+  static PoseClient* FromC(DvrPoseClient* client) {
     return reinterpret_cast<PoseClient*>(client);
   }
 
   // Polls the pose service for the current state and stores it in *state.
   // Returns zero on success, a negative error code otherwise.
-  int Poll(DvrPoseState* state) {
-    Transaction trans{*this};
-    Status<int> status =
-        trans.Send<int>(DVR_POSE_POLL, nullptr, 0, state, sizeof(*state));
-    ALOGE_IF(!status, "Pose poll() failed because: %s\n",
-             status.GetErrorMessage().c_str());
-    return ReturnStatusOrError(status);
+  int Poll(DvrPose* state) {
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      if (state) {
+        // Fill the state
+        *state = vsync_buffer->current_pose;
+      }
+      return -EINVAL;
+    }
+
+    return -EAGAIN;
   }
 
   int GetPose(uint32_t vsync_count, DvrPoseAsync* out_pose) {
-    if (!mapped_pose_buffer_) {
-      int ret = GetRingBuffer(nullptr);
-      if (ret < 0)
-        return ret;
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      *out_pose =
+          vsync_buffer
+              ->vsync_poses[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
+      return 0;
+    } else {
+      return -EAGAIN;
     }
-    *out_pose =
-        mapped_pose_buffer_->ring[vsync_count & kPoseAsyncBufferIndexMask];
-    return 0;
   }
 
   uint32_t GetVsyncCount() {
-    if (!mapped_pose_buffer_) {
-      int ret = GetRingBuffer(nullptr);
-      if (ret < 0)
-        return 0;
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      return vsync_buffer->vsync_count;
     }
-    return mapped_pose_buffer_->vsync_count;
+
+    return 0;
   }
 
   int GetControllerPose(int32_t controller_id, uint32_t vsync_count,
@@ -75,7 +81,7 @@
     }
     *out_pose =
         controllers_[controller_id]
-            .mapped_pose_buffer[vsync_count & kPoseAsyncBufferIndexMask];
+            .mapped_pose_buffer[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
     return 0;
   }
 
@@ -92,7 +98,7 @@
   // this state until a different state is frozen or SetMode() is called with a
   // different mode.
   // Returns zero on success, a negative error code otherwise.
-  int Freeze(const DvrPoseState& frozen_state) {
+  int Freeze(const DvrPose& frozen_state) {
     Transaction trans{*this};
     Status<int> status = trans.Send<int>(DVR_POSE_FREEZE, &frozen_state,
                                          sizeof(frozen_state), nullptr, 0);
@@ -124,48 +130,29 @@
     return ReturnStatusOrError(status);
   }
 
-  int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
-    if (pose_buffer_.get()) {
-      if (out_info) {
-        GetPoseRingBufferInfo(out_info);
-      }
-      return 0;
-    }
-
+  // Enables or disables all pose processing from sensors
+  int EnableSensors(bool enabled) {
     Transaction trans{*this};
-    Status<LocalChannelHandle> status =
-        trans.Send<LocalChannelHandle>(DVR_POSE_GET_RING_BUFFER);
-    if (!status) {
-      ALOGE("Pose GetRingBuffer() failed because: %s",
-            status.GetErrorMessage().c_str());
-      return -status.error();
+    Status<int> status = trans.Send<int>(DVR_POSE_SENSORS_ENABLE, &enabled,
+                                         sizeof(enabled), nullptr, 0);
+    ALOGE_IF(!status, "Pose EnableSensors() failed because: %s\n",
+             status.GetErrorMessage().c_str());
+    return ReturnStatusOrError(status);
+  }
+
+  int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
+    // First time mapping the buffer?
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      if (out_info) {
+        out_info->min_future_count = DvrVsyncPoseBuffer::kMinFutureCount;
+        out_info->total_count = DvrVsyncPoseBuffer::kSize;
+        out_info->buffer = vsync_buffer->vsync_poses;
+      }
+      return -EINVAL;
     }
 
-    auto buffer = BufferConsumer::Import(status.take());
-    if (!buffer) {
-      ALOGE("Pose failed to import ring buffer");
-      return -EIO;
-    }
-    void* addr = nullptr;
-    int ret = buffer->GetBlobReadOnlyPointer(sizeof(DvrPoseRingBuffer), &addr);
-    if (ret < 0 || !addr) {
-      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
-      return -EIO;
-    }
-    pose_buffer_.swap(buffer);
-    mapped_pose_buffer_ = static_cast<const DvrPoseRingBuffer*>(addr);
-    ALOGI("Mapped pose data translation %f,%f,%f quat %f,%f,%f,%f",
-          mapped_pose_buffer_->ring[0].translation[0],
-          mapped_pose_buffer_->ring[0].translation[1],
-          mapped_pose_buffer_->ring[0].translation[2],
-          mapped_pose_buffer_->ring[0].orientation[0],
-          mapped_pose_buffer_->ring[0].orientation[1],
-          mapped_pose_buffer_->ring[0].orientation[2],
-          mapped_pose_buffer_->ring[0].orientation[3]);
-    if (out_info) {
-      GetPoseRingBufferInfo(out_info);
-    }
-    return 0;
+    return -EAGAIN;
   }
 
   int GetControllerRingBuffer(int32_t controller_id) {
@@ -190,7 +177,7 @@
       ALOGE("Pose failed to import ring buffer");
       return -EIO;
     }
-    constexpr size_t size = kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync);
+    constexpr size_t size = DvrVsyncPoseBuffer::kSize * sizeof(DvrPoseAsync);
     void* addr = nullptr;
     int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
     if (ret < 0 || !addr) {
@@ -201,9 +188,9 @@
     client_state.mapped_pose_buffer = static_cast<const DvrPoseAsync*>(addr);
     ALOGI(
         "Mapped controller %d pose data translation %f,%f,%f quat %f,%f,%f,%f",
-        controller_id, client_state.mapped_pose_buffer[0].translation[0],
-        client_state.mapped_pose_buffer[0].translation[1],
-        client_state.mapped_pose_buffer[0].translation[2],
+        controller_id, client_state.mapped_pose_buffer[0].position[0],
+        client_state.mapped_pose_buffer[0].position[1],
+        client_state.mapped_pose_buffer[0].position[2],
         client_state.mapped_pose_buffer[0].orientation[0],
         client_state.mapped_pose_buffer[0].orientation[1],
         client_state.mapped_pose_buffer[0].orientation[2],
@@ -211,32 +198,6 @@
     return 0;
   }
 
-  int NotifyVsync(uint32_t vsync_count, int64_t display_timestamp,
-                  int64_t display_period_ns,
-                  int64_t right_eye_photon_offset_ns) {
-    const struct iovec data[] = {
-        {.iov_base = &vsync_count, .iov_len = sizeof(vsync_count)},
-        {.iov_base = &display_timestamp, .iov_len = sizeof(display_timestamp)},
-        {.iov_base = &display_period_ns, .iov_len = sizeof(display_period_ns)},
-        {.iov_base = &right_eye_photon_offset_ns,
-         .iov_len = sizeof(right_eye_photon_offset_ns)},
-    };
-    Transaction trans{*this};
-    Status<int> status =
-        trans.SendVector<int>(DVR_POSE_NOTIFY_VSYNC, data, nullptr);
-    ALOGE_IF(!status, "Pose NotifyVsync() failed because: %s\n",
-             status.GetErrorMessage().c_str());
-    return ReturnStatusOrError(status);
-  }
-
-  int GetRingBufferFd(LocalHandle* fd) {
-    int ret = GetRingBuffer(nullptr);
-    if (ret < 0)
-      return ret;
-    *fd = pose_buffer_->GetBlobFd();
-    return 0;
-  }
-
  private:
   friend BASE;
 
@@ -252,14 +213,29 @@
   PoseClient(const PoseClient&) = delete;
   PoseClient& operator=(const PoseClient&) = delete;
 
-  void GetPoseRingBufferInfo(DvrPoseRingBufferInfo* out_info) const {
-    out_info->min_future_count = kPoseAsyncBufferMinFutureCount;
-    out_info->total_count = kPoseAsyncBufferTotalCount;
-    out_info->buffer = mapped_pose_buffer_->ring;
+  const DvrVsyncPoseBuffer* GetVsyncBuffer() {
+    if (mapped_vsync_pose_buffer_ == nullptr) {
+      if (vsync_pose_buffer_ == nullptr) {
+        // The constructor tries mapping it so we do not need TryMapping after.
+        vsync_pose_buffer_ = std::make_unique<CPUMappedBuffer>(
+            DvrGlobalBuffers::kVsyncPoseBuffer, CPUUsageMode::READ_OFTEN);
+      } else if (vsync_pose_buffer_->IsMapped() == false) {
+        vsync_pose_buffer_->TryMapping();
+      }
+
+      if (vsync_pose_buffer_->IsMapped()) {
+        mapped_vsync_pose_buffer_ =
+            static_cast<DvrVsyncPoseBuffer*>(vsync_pose_buffer_->Address());
+      }
+    }
+
+    return mapped_vsync_pose_buffer_;
   }
 
-  std::unique_ptr<BufferConsumer> pose_buffer_;
-  const DvrPoseRingBuffer* mapped_pose_buffer_ = nullptr;
+  // The vsync pose buffer if already mapped.
+  std::unique_ptr<CPUMappedBuffer> vsync_pose_buffer_;
+
+  const DvrVsyncPoseBuffer* mapped_vsync_pose_buffer_ = nullptr;
 
   struct ControllerClientState {
     std::unique_ptr<BufferConsumer> pose_buffer;
@@ -273,66 +249,55 @@
 
 using android::dvr::PoseClient;
 
-struct DvrPose {};
-
 extern "C" {
 
-DvrPose* dvrPoseCreate() {
-  PoseClient* client = PoseClient::Create().release();
-  return reinterpret_cast<DvrPose*>(client);
+DvrPoseClient* dvrPoseClientCreate() {
+  auto* client = PoseClient::Create().release();
+  return reinterpret_cast<DvrPoseClient*>(client);
 }
 
-void dvrPoseDestroy(DvrPose* client) { delete PoseClient::FromC(client); }
+void dvrPoseClientDestroy(DvrPoseClient* client) {
+  delete PoseClient::FromC(client);
+}
 
-int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose) {
+int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
+                     DvrPoseAsync* out_pose) {
   return PoseClient::FromC(client)->GetPose(vsync_count, out_pose);
 }
 
-uint32_t dvrPoseGetVsyncCount(DvrPose* client) {
+uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client) {
   return PoseClient::FromC(client)->GetVsyncCount();
 }
 
-int dvrPoseGetController(DvrPose* client, int32_t controller_id,
-                         uint32_t vsync_count, DvrPoseAsync* out_pose) {
+int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
+                               uint32_t vsync_count, DvrPoseAsync* out_pose) {
   return PoseClient::FromC(client)->GetControllerPose(controller_id,
                                                       vsync_count, out_pose);
 }
 
-int dvrPoseLogController(DvrPose* client, bool enable) {
+int dvrPoseClientLogController(DvrPoseClient* client, bool enable) {
   return PoseClient::FromC(client)->LogController(enable);
 }
 
-int dvrPosePoll(DvrPose* client, DvrPoseState* state) {
+int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state) {
   return PoseClient::FromC(client)->Poll(state);
 }
 
-int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state) {
+int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state) {
   return PoseClient::FromC(client)->Freeze(*frozen_state);
 }
 
-int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode) {
+int dvrPoseClientModeSet(DvrPoseClient* client, DvrPoseMode mode) {
   return PoseClient::FromC(client)->SetMode(mode);
 }
 
-int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode) {
+int dvrPoseClientModeGet(DvrPoseClient* client, DvrPoseMode* mode) {
   return PoseClient::FromC(client)->GetMode(mode);
 }
 
-int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info) {
-  return PoseClient::FromC(client)->GetRingBuffer(out_info);
-}
 
-int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
-                              int64_t display_timestamp,
-                              int64_t display_period_ns,
-                              int64_t right_eye_photon_offset_ns) {
-  return PoseClient::FromC(client)->NotifyVsync(vsync_count, display_timestamp,
-                                                display_period_ns,
-                                                right_eye_photon_offset_ns);
-}
-
-int privateDvrPoseGetRingBufferFd(DvrPose* client, LocalHandle* fd) {
-  return PoseClient::FromC(client)->GetRingBufferFd(fd);
+int dvrPoseClientSensorsEnable(DvrPoseClient* client, bool enabled) {
+  return PoseClient::FromC(client)->EnableSensors(enabled);
 }
 
 }  // extern "C"
diff --git a/libs/vr/libvrsensor/tests/sensor_app_tests.cpp b/libs/vr/libvrsensor/tests/sensor_app_tests.cpp
deleted file mode 100644
index 64c9864..0000000
--- a/libs/vr/libvrsensor/tests/sensor_app_tests.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <math.h>
-#include <inttypes.h>
-
-#include <dvr/graphics.h>
-#include <dvr/pose_client.h>
-#include <gtest/gtest.h>
-#include <log/log.h>
-#include <private/dvr/types.h>
-
-using android::dvr::vec4;
-
-namespace {
-
-vec4 ToVec4(float32x4_t rhs) { return vec4(rhs[0], rhs[1], rhs[2], rhs[3]); }
-
-}
-
-DvrGraphicsContext* CreateContext() {
-  DvrGraphicsContext* context = nullptr;
-  int display_width = 0, display_height = 0;
-  int surface_width = 0, surface_height = 0;
-  float inter_lens_meters = 0.0f;
-  float left_fov[4] = {0.0f};
-  float right_fov[4] = {0.0f};
-  int disable_warp = 0;
-  DvrSurfaceParameter surface_params[] = {
-      DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, disable_warp),
-      DVR_SURFACE_PARAMETER_OUT(DISPLAY_WIDTH, &display_width),
-      DVR_SURFACE_PARAMETER_OUT(DISPLAY_HEIGHT, &display_height),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &surface_width),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &surface_height),
-      DVR_SURFACE_PARAMETER_OUT(INTER_LENS_METERS, &inter_lens_meters),
-      DVR_SURFACE_PARAMETER_OUT(LEFT_FOV_LRBT, left_fov),
-      DVR_SURFACE_PARAMETER_OUT(RIGHT_FOV_LRBT, right_fov),
-      DVR_SURFACE_PARAMETER_LIST_END,
-  };
-  dvrGraphicsContextCreate(surface_params, &context);
-  return context;
-}
-
-TEST(SensorAppTests, GetPose) {
-  DvrGraphicsContext* context = CreateContext();
-  ASSERT_NE(nullptr, context);
-  DvrPose* client = dvrPoseCreate();
-  ASSERT_NE(nullptr, client);
-
-  DvrPoseAsync last_pose;
-  uint32_t last_vsync_count = 0;
-  for (int i = 0; i < 10; ++i) {
-    DvrFrameSchedule schedule;
-    dvrGraphicsWaitNextFrame(context, 0, &schedule);
-    DvrPoseAsync pose;
-    int ret = dvrPoseGet(client, schedule.vsync_count, &pose);
-    ASSERT_EQ(0, ret);
-
-    // Check for unit-length quaternion to verify valid pose.
-    vec4 quaternion = ToVec4(pose.orientation);
-    float length = quaternion.norm();
-    EXPECT_GT(0.001, fabs(1.0f - length));
-
-    // Check for different data each frame, but skip first few to allow
-    // startup anomalies.
-    if (i > 0) {
-      if (last_vsync_count == schedule.vsync_count)
-        ALOGE("vsync did not increment: %u", schedule.vsync_count);
-      if (pose.timestamp_ns == last_pose.timestamp_ns)
-        ALOGE("timestamp did not change: %" PRIu64, pose.timestamp_ns);
-      // TODO(jbates) figure out why the bots are not passing this check.
-      // EXPECT_NE(last_vsync_count, schedule.vsync_count);
-      // EXPECT_NE(pose.timestamp_ns, last_pose.timestamp_ns);
-    }
-    last_pose = pose;
-    last_vsync_count = schedule.vsync_count;
-    dvrBeginRenderFrame(context);
-    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-    dvrPresent(context);
-  }
-
-  dvrPoseDestroy(client);
-  dvrGraphicsContextDestroy(context);
-}
-
-TEST(SensorAppTests, PoseRingBuffer) {
-  DvrGraphicsContext* context = CreateContext();
-  ASSERT_NE(nullptr, context);
-  DvrPose* client = dvrPoseCreate();
-  ASSERT_NE(nullptr, client);
-
-  DvrPoseRingBufferInfo info;
-  int ret = dvrPoseGetRingBuffer(client, &info);
-  ASSERT_EQ(0, ret);
-  ASSERT_NE(nullptr, info.buffer);
-  EXPECT_LE(2u, info.min_future_count);
-  EXPECT_LE(8u, info.total_count);
-
-  DvrPoseAsync last_pose;
-  uint32_t last_vsync_count = 0;
-  for (int i = 0; i < 10; ++i) {
-    DvrFrameSchedule schedule;
-    dvrGraphicsWaitNextFrame(context, 0, &schedule);
-    DvrPoseAsync pose;
-    ret = dvrPoseGet(client, schedule.vsync_count, &pose);
-    ASSERT_EQ(0, ret);
-
-    // Check for unit-length quaternion to verify valid pose.
-    vec4 quaternion = ToVec4(pose.orientation);
-    float length = quaternion.norm();
-    EXPECT_GT(0.001, fabs(1.0f - length));
-
-    // Check for different data each frame, but skip first few to allow
-    // startup anomalies.
-    if (i > 0) {
-      if (last_vsync_count == schedule.vsync_count)
-        ALOGE("vsync did not increment: %u", schedule.vsync_count);
-      if (pose.timestamp_ns == last_pose.timestamp_ns)
-        ALOGE("timestamp did not change: %" PRIu64, pose.timestamp_ns);
-      // TODO(jbates) figure out why the bots are not passing this check.
-      // EXPECT_NE(last_vsync_count, schedule.vsync_count);
-      // EXPECT_NE(pose.timestamp_ns, last_pose.timestamp_ns);
-    }
-    last_pose = pose;
-    last_vsync_count = schedule.vsync_count;
-    dvrBeginRenderFrame(context);
-    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-    dvrPresent(context);
-  }
-
-  dvrPoseDestroy(client);
-  dvrGraphicsContextDestroy(context);
-}
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 4c13dc8..62e6bd3 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -48,6 +48,7 @@
 
 // retrieve wide-color setting from configstore
 using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
 
 static bool hasWideColorDisplay =
         getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
new file mode 100644
index 0000000..3442cb2
--- /dev/null
+++ b/services/displayservice/Android.bp
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+
+cc_library_shared {
+    name: "libdisplayservicehidl",
+
+    srcs: [
+        "DisplayService.cpp",
+        "DisplayEventReceiver.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libgui",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.frameworks.displayservice@1.0",
+    ],
+
+    export_include_dirs: ["include"],
+    export_shared_lib_headers: [
+        "android.frameworks.displayservice@1.0",
+        "libgui",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ]
+}
diff --git a/services/displayservice/DisplayEventReceiver.cpp b/services/displayservice/DisplayEventReceiver.cpp
new file mode 100644
index 0000000..5993e44
--- /dev/null
+++ b/services/displayservice/DisplayEventReceiver.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "libdisplayservicehidl"
+
+#include <displayservice/DisplayEventReceiver.h>
+
+#include <android-base/logging.h>
+#include <android/frameworks/displayservice/1.0/BpHwEventCallback.h>
+
+#include <thread>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+sp<Looper> getLooper() {
+    static sp<Looper> looper = []() {
+        sp<Looper> looper = new Looper(false /* allowNonCallbacks */);
+
+        std::thread{[&](){
+            int pollResult = looper->pollAll(-1 /* timeout */);
+            LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
+        }}.detach();
+
+        return looper;
+    }();
+
+    return looper;
+}
+
+DisplayEventReceiver::AttachedEvent::AttachedEvent(const sp<IEventCallback> &callback)
+    : mCallback(callback)
+{
+    mLooperAttached = getLooper()->addFd(mFwkReceiver.getFd(),
+            Looper::POLL_CALLBACK,
+            Looper::EVENT_INPUT,
+            this,
+            nullptr);
+}
+
+DisplayEventReceiver::AttachedEvent::~AttachedEvent() {
+    if (!detach()) {
+        LOG(ERROR) << "Could not remove fd from looper.";
+    }
+}
+
+bool DisplayEventReceiver::AttachedEvent::detach() {
+    if (!valid()) {
+        return true;
+    }
+
+    return getLooper()->removeFd(mFwkReceiver.getFd());
+}
+
+bool DisplayEventReceiver::AttachedEvent::valid() const {
+    return mFwkReceiver.initCheck() == OK && mLooperAttached;
+}
+
+DisplayEventReceiver::FwkReceiver &DisplayEventReceiver::AttachedEvent::receiver() {
+    return mFwkReceiver;
+}
+
+int DisplayEventReceiver::AttachedEvent::handleEvent(int fd, int events, void* /* data */) {
+    CHECK(fd == mFwkReceiver.getFd());
+
+    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
+        LOG(ERROR) << "AttachedEvent handleEvent received error or hangup:" << events;
+        return 0; // remove the callback
+    }
+
+    if (!(events & Looper::EVENT_INPUT)) {
+        LOG(ERROR) << "AttachedEvent handleEvent unhandled poll event:" << events;
+        return 1; // keep the callback
+    }
+
+    constexpr size_t SIZE = 1;
+
+    ssize_t n;
+    FwkReceiver::Event buf[SIZE];
+    while ((n = mFwkReceiver.getEvents(buf, SIZE)) > 0) {
+        for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
+            const FwkReceiver::Event &event = buf[i];
+
+            uint32_t type = event.header.type;
+            uint64_t timestamp = event.header.timestamp;
+
+            switch(buf[i].header.type) {
+                case FwkReceiver::DISPLAY_EVENT_VSYNC: {
+                    mCallback->onVsync(timestamp, event.vsync.count);
+                } break;
+                case FwkReceiver::DISPLAY_EVENT_HOTPLUG: {
+                    mCallback->onHotplug(timestamp, event.hotplug.connected);
+                } break;
+                default: {
+                    LOG(ERROR) << "AttachedEvent handleEvent unknown type: " << type;
+                }
+            }
+        }
+    }
+
+    return 1; // keep on going
+}
+
+Return<Status> DisplayEventReceiver::init(const sp<IEventCallback>& callback) {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (mAttached != nullptr || callback == nullptr) {
+        return Status::BAD_VALUE;
+    }
+
+    mAttached = new AttachedEvent(callback);
+
+    return mAttached->valid() ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::setVsyncRate(int32_t count) {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (mAttached == nullptr || count < 0) {
+        return Status::BAD_VALUE;
+    }
+
+    bool success = OK == mAttached->receiver().setVsyncRate(count);
+    return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::requestNextVsync() {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (mAttached == nullptr) {
+        return Status::BAD_VALUE;
+    }
+
+    bool success = OK == mAttached->receiver().requestNextVsync();
+    return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::close() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (mAttached == nullptr) {
+        return Status::BAD_VALUE;
+    }
+
+    bool success = mAttached->detach();
+    mAttached = nullptr;
+
+    return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace displayservice
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/displayservice/DisplayService.cpp b/services/displayservice/DisplayService.cpp
new file mode 100644
index 0000000..18418fd
--- /dev/null
+++ b/services/displayservice/DisplayService.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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 <displayservice/DisplayService.h>
+#include <displayservice/DisplayEventReceiver.h>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+Return<sp<IDisplayEventReceiver>> DisplayService::getEventReceiver() {
+    return new DisplayEventReceiver();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace displayservice
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/displayservice/include/displayservice/DisplayEventReceiver.h b/services/displayservice/include/displayservice/DisplayEventReceiver.h
new file mode 100644
index 0000000..5d569b6
--- /dev/null
+++ b/services/displayservice/include/displayservice/DisplayEventReceiver.h
@@ -0,0 +1,72 @@
+/*
+ * 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 ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
+#define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
+
+#include <android/frameworks/displayservice/1.0/IDisplayEventReceiver.h>
+#include <gui/DisplayEventReceiver.h>
+#include <hidl/Status.h>
+#include <gui/DisplayEventReceiver.h>
+#include <utils/Looper.h>
+
+#include <mutex>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+class DisplayEventReceiver : public IDisplayEventReceiver {
+public:
+    Return<Status> init(const sp<IEventCallback>& callback) override;
+    Return<Status> setVsyncRate(int32_t count) override;
+    Return<Status> requestNextVsync() override;
+    Return<Status> close() override;
+
+private:
+    using FwkReceiver = ::android::DisplayEventReceiver;
+
+    struct AttachedEvent : LooperCallback {
+        AttachedEvent(const sp<IEventCallback> &callback);
+        ~AttachedEvent();
+
+        bool detach();
+        bool valid() const;
+        FwkReceiver &receiver();
+        virtual int handleEvent(int fd, int events, void* /* data */) override;
+
+    private:
+        FwkReceiver mFwkReceiver;
+        sp<IEventCallback> mCallback;
+        bool mLooperAttached;
+    };
+
+    sp<AttachedEvent> mAttached;
+    std::mutex mMutex;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace displayservice
+}  // namespace frameworks
+}  // namespace android
+
+#endif  // ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
diff --git a/services/displayservice/include/displayservice/DisplayService.h b/services/displayservice/include/displayservice/DisplayService.h
new file mode 100644
index 0000000..9722e71
--- /dev/null
+++ b/services/displayservice/include/displayservice/DisplayService.h
@@ -0,0 +1,42 @@
+/*
+ * 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 ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
+#define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
+
+#include <android/frameworks/displayservice/1.0/IDisplayService.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct DisplayService : public IDisplayService {
+    Return<sp<IDisplayEventReceiver>> getEventReceiver() override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace displayservice
+}  // namespace frameworks
+}  // namespace android
+
+#endif  // ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index 91923b3..870635b 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -18,8 +18,6 @@
 #include "SensorDirectConnection.h"
 #include <hardware/sensors.h>
 
-#include <sys/stat.h>
-
 #define UNUSED(x) (void)(x)
 
 namespace android {
@@ -182,13 +180,12 @@
     if (mMem.type == mem->type) {
         switch (mMem.type) {
             case SENSOR_DIRECT_MEM_TYPE_ASHMEM: {
-                struct stat s1, s2;
-                int fd1, fd2;
-                fd1 = mMem.handle->data[0];
-                fd2 = mem->handle->data[0];
-                if (fstat(fd1, &s1) < 0 || fstat(fd2, &s2) < 0 || s1.st_ino == s2.st_ino) {
-                    ret = true;
-                }
+                // there is no known method to test if two ashmem fds are equivalent besides
+                // trivially comparing the fd values (ino number from fstat() are always the
+                // same, pointing to "/dev/ashmem").
+                int fd1 = mMem.handle->data[0];
+                int fd2 = mem->handle->data[0];
+                ret = (fd1 == fd2);
                 break;
             }
             case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 0071851..95a522d 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -80,7 +80,6 @@
     libdl \
     libfmq \
     libhardware \
-    libhwc2on1adapter \
     libhidlbase \
     libhidltransport \
     libhwbinder \
@@ -129,11 +128,13 @@
     main_surfaceflinger.cpp
 
 LOCAL_SHARED_LIBRARIES := \
+    android.frameworks.displayservice@1.0 \
     android.hardware.configstore@1.0 \
     android.hardware.configstore-utils \
     android.hardware.graphics.allocator@2.0 \
     libsurfaceflinger \
     libcutils \
+    libdisplayservicehidl \
     liblog \
     libbinder \
     libhidlbase \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 4d0c085..a0abf12 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -121,8 +121,7 @@
     ANativeWindow* const window = mNativeWindow.get();
 
 #ifdef USE_HWC2
-    // Set defaultColorMode to SRGB if this device supports wide-color
-    mActiveColorMode = (supportWideColor) ? HAL_COLOR_MODE_SRGB : HAL_COLOR_MODE_NATIVE;
+    mActiveColorMode = HAL_COLOR_MODE_NATIVE;
     mDisplayHasWideColor = supportWideColor;
 #else
     (void) supportWideColor;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 1ac203b..0366630 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -593,6 +593,9 @@
         } else {
             ALOGE("getReleaseFences: invalid layer %" PRIu64
                     " found on display %" PRIu64, layerIds[element], mId);
+            for (; element < numElements; ++element) {
+                close(fenceFds[element]);
+            }
             return Error::BadLayer;
         }
     }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 431fa9d..42be935 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -47,7 +47,6 @@
 #include <log/log.h>
 
 #include "HWComposer.h"
-#include "hwc2on1adapter/HWC2On1Adapter.h"
 #include "HWC2.h"
 #include "ComposerHal.h"
 
@@ -61,16 +60,14 @@
 // ---------------------------------------------------------------------------
 
 HWComposer::HWComposer(bool useVrComposer)
-    : mAdapter(),
-      mHwcDevice(),
+    : mHwcDevice(),
       mDisplayData(2),
       mFreeDisplaySlots(),
       mHwcDisplaySlots(),
       mCBContext(),
       mEventHandler(nullptr),
       mVSyncCounts(),
-      mRemainingHwcVirtualDisplays(0),
-      mDumpMayLockUp(false)
+      mRemainingHwcVirtualDisplays(0)
 {
     for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
         mLastHwVSync[i] = 0;
@@ -456,8 +453,6 @@
         return NO_ERROR;
     }
 
-    mDumpMayLockUp = true;
-
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
     auto error = hwcDisplay->validate(&numTypes, &numRequests);
@@ -598,9 +593,6 @@
     auto& displayData = mDisplayData[displayId];
     auto& hwcDisplay = displayData.hwcDisplay;
     auto error = hwcDisplay->present(&displayData.lastPresentFence);
-
-    mDumpMayLockUp = false;
-
     if (error != HWC2::Error::None) {
         ALOGE("presentAndGetReleaseFences: failed for display %d: %s (%d)",
               displayId, to_string(error).c_str(), static_cast<int32_t>(error));
@@ -842,11 +834,6 @@
 }
 
 void HWComposer::dump(String8& result) const {
-    if (mDumpMayLockUp) {
-        result.append("HWComposer dump skipped because present in progress");
-        return;
-    }
-
     // TODO: In order to provide a dump equivalent to HWC1, we need to shadow
     // all the state going into the layers. This is probably better done in
     // Layer itself, but it's going to take a bit of work to get there.
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 78d0307..3eb968d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -58,7 +58,6 @@
 class Fence;
 class FloatRect;
 class GraphicBuffer;
-class HWC2On1Adapter;
 class NativeHandle;
 class Region;
 class String8;
@@ -205,7 +204,6 @@
         HWC2::Vsync vsyncEnabled;
     };
 
-    std::unique_ptr<HWC2On1Adapter> mAdapter;
     std::unique_ptr<HWC2::Device>   mHwcDevice;
     std::vector<DisplayData>        mDisplayData;
     std::set<size_t>                mFreeDisplaySlots;
@@ -224,9 +222,6 @@
 
     // thread-safe
     mutable Mutex mVsyncLock;
-
-    // XXX temporary workaround for b/35806047
-    mutable std::atomic<bool> mDumpMayLockUp;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a91fc8e..d19f964 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -104,7 +104,7 @@
         mLastFrameNumberReceived(0),
         mUpdateTexImageFailed(false),
         mAutoRefresh(false),
-        mFreezePositionUpdates(false)
+        mFreezeGeometryUpdates(false)
 {
 #ifdef USE_HWC2
     ALOGV("Creating Layer %s", name.string());
@@ -126,12 +126,15 @@
         mPremultipliedAlpha = false;
 
     mName = name;
+    mTransactionName = String8("TX - ") + mName;
 
     mCurrentState.active.w = w;
     mCurrentState.active.h = h;
     mCurrentState.active.transform.set(0, 0);
     mCurrentState.crop.makeInvalid();
     mCurrentState.finalCrop.makeInvalid();
+    mCurrentState.requestedFinalCrop = mCurrentState.finalCrop;
+    mCurrentState.requestedCrop = mCurrentState.crop;
     mCurrentState.z = 0;
 #ifdef USE_HWC2
     mCurrentState.alpha = 1.0f;
@@ -297,6 +300,11 @@
     }
 
     mSurfaceFlingerConsumer->abandon();
+
+#ifdef USE_HWC2
+    clearHwcLayers();
+#endif
+
     for (const auto& child : mCurrentChildren) {
         child->onRemoved();
     }
@@ -1491,6 +1499,7 @@
         mFlinger->setTransactionFlags(eTraversalNeeded);
     }
     mPendingStates.push_back(mCurrentState);
+    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
 }
 
 void Layer::popPendingState(State* stateToCommit) {
@@ -1500,6 +1509,7 @@
             (stateToCommit->flags & stateToCommit->mask);
 
     mPendingStates.removeAt(0);
+    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
 }
 
 bool Layer::applyPendingStates(State* stateToCommit) {
@@ -1634,12 +1644,25 @@
         }
     }
 
-    // always set active to requested, unless we're asked not to
-    // this is used by Layer, which special cases resizes.
-    if (flags & eDontUpdateGeometryState)  {
-    } else {
+    // Here we apply various requested geometry states, depending on our
+    // latching configuration. See Layer.h for a detailed discussion of
+    // how geometry latching is controlled.
+    if (!(flags & eDontUpdateGeometryState)) {
         Layer::State& editCurrentState(getCurrentState());
-        if (mFreezePositionUpdates) {
+
+        // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize
+        // mode, which causes attributes which normally latch regardless of scaling mode,
+        // to be delayed. We copy the requested state to the active state making sure
+        // to respect these rules (again see Layer.h for a detailed discussion).
+        //
+        // There is an awkward asymmetry in the handling of the crop states in the position
+        // states, as can be seen below. Largely this arises from position and transform
+        // being stored in the same data structure while having different latching rules.
+        // b/38182305
+        //
+        // Careful that "c" and editCurrentState may not begin as equivalent due to
+        // applyPendingStates in the presence of deferred transactions.
+        if (mFreezeGeometryUpdates) {
             float tx = c.active.transform.tx();
             float ty = c.active.transform.ty();
             c.active = c.requested;
@@ -1700,10 +1723,14 @@
     // we want to apply the position portion of the transform matrix immediately,
     // but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
     mCurrentState.requested.transform.set(x, y);
-    if (immediate && !mFreezePositionUpdates) {
+    if (immediate && !mFreezeGeometryUpdates) {
+        // Here we directly update the active state
+        // unlike other setters, because we store it within
+        // the transform, but use different latching rules.
+        // b/38182305
         mCurrentState.active.transform.set(x, y);
     }
-    mFreezePositionUpdates = mFreezePositionUpdates || !immediate;
+    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
 
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
@@ -1826,26 +1853,30 @@
 }
 
 bool Layer::setCrop(const Rect& crop, bool immediate) {
-    if (mCurrentState.crop == crop)
+    if (mCurrentState.requestedCrop == crop)
         return false;
     mCurrentState.sequence++;
     mCurrentState.requestedCrop = crop;
-    if (immediate) {
+    if (immediate && !mFreezeGeometryUpdates) {
         mCurrentState.crop = crop;
     }
+    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setFinalCrop(const Rect& crop, bool immediate) {
-    if (mCurrentState.finalCrop == crop)
+    if (mCurrentState.requestedFinalCrop == crop)
         return false;
     mCurrentState.sequence++;
     mCurrentState.requestedFinalCrop = crop;
-    if (immediate) {
+    if (immediate && !mFreezeGeometryUpdates) {
         mCurrentState.finalCrop = crop;
     }
+    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
@@ -2139,7 +2170,7 @@
     bool queuedBuffer = false;
     LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                     getProducerStickyTransform() != 0, mName.string(),
-                    mOverrideScalingMode, mFreezePositionUpdates);
+                    mOverrideScalingMode, mFreezeGeometryUpdates);
     status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
             mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
             mLastFrameNumberReceived);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 92353ae..c9ebf99 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -169,25 +169,64 @@
     // the this layer's size and format
     status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
 
-    // modify current state
+    // ------------------------------------------------------------------------
+    // Geometry setting functions.
+    //
+    // The following group of functions are used to specify the layers
+    // bounds, and the mapping of the texture on to those bounds. According
+    // to various settings changes to them may apply immediately, or be delayed until
+    // a pending resize is completed by the producer submitting a buffer. For example
+    // if we were to change the buffer size, and update the matrix ahead of the
+    // new buffer arriving, then we would be stretching the buffer to a different
+    // aspect before and after the buffer arriving, which probably isn't what we wanted.
+    //
+    // The first set of geometry functions are controlled by the scaling mode, described
+    // in window.h. The scaling mode may be set by the client, as it submits buffers.
+    // This value may be overriden through SurfaceControl, with setOverrideScalingMode.
+    //
+    // Put simply, if our scaling mode is SCALING_MODE_FREEZE, then
+    // matrix updates will not be applied while a resize is pending
+    // and the size and transform will remain in their previous state
+    // until a new buffer is submitted. If the scaling mode is another value
+    // then the old-buffer will immediately be scaled to the pending size
+    // and the new matrix will be immediately applied following this scaling
+    // transformation.
 
-    // These members of state (position, crop, and finalCrop)
-    // may be updated immediately or have the update delayed
-    // until a pending surface resize completes (if applicable).
+    // Set the default buffer size for the assosciated Producer, in pixels. This is
+    // also the rendered size of the layer prior to any transformations. Parent
+    // or local matrix transformations will not affect the size of the buffer,
+    // but may affect it's on-screen size or clipping.
+    bool setSize(uint32_t w, uint32_t h);
+    // Set a 2x2 transformation matrix on the layer. This transform
+    // will be applied after parent transforms, but before any final
+    // producer specified transform.
+    bool setMatrix(const layer_state_t::matrix22_t& matrix);
+
+    // This second set of geometry attributes are controlled by
+    // setGeometryAppliesWithResize, and their default mode is to be
+    // immediate. If setGeometryAppliesWithResize is specified
+    // while a resize is pending, then update of these attributes will
+    // be delayed until the resize completes.
+
+    // setPosition operates in parent buffer space (pre parent-transform) or display
+    // space for top-level layers.
     bool setPosition(float x, float y, bool immediate);
+    // Buffer space
     bool setCrop(const Rect& crop, bool immediate);
+    // Parent buffer space/display space
     bool setFinalCrop(const Rect& crop, bool immediate);
 
+    // TODO(b/38182121): Could we eliminate the various latching modes by
+    // using the layer hierarchy?
+    // -----------------------------------------------------------------------
     bool setLayer(int32_t z);
     bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
 
-    bool setSize(uint32_t w, uint32_t h);
 #ifdef USE_HWC2
     bool setAlpha(float alpha);
 #else
     bool setAlpha(uint8_t alpha);
 #endif
-    bool setMatrix(const layer_state_t::matrix22_t& matrix);
     bool setTransparentRegionHint(const Region& transparent);
     bool setFlags(uint8_t flags, uint8_t mask);
     bool setLayerStack(uint32_t layerStack);
@@ -657,6 +696,7 @@
     uint32_t mTextureName;      // from GLES
     bool mPremultipliedAlpha;
     String8 mName;
+    String8 mTransactionName; // A cached version of "TX - " + mName for systraces
     PixelFormat mFormat;
 
     // these are protected by an external lock
@@ -753,7 +793,7 @@
     bool mUpdateTexImageFailed; // This is only accessed on the main thread.
 
     bool mAutoRefresh;
-    bool mFreezePositionUpdates;
+    bool mFreezeGeometryUpdates;
 
     // Child list about to be committed/used for editing.
     LayerVector mCurrentChildren;
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index f152495..e864607 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -38,7 +38,7 @@
     mStickyTransformSet(stickySet),
     mName(name),
     mOverrideScalingMode(overrideScalingMode),
-    mFreezePositionUpdates(freezePositionUpdates) {}
+    mFreezeGeometryUpdates(freezePositionUpdates) {}
 
 bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
     if (buf == NULL) {
@@ -74,6 +74,19 @@
 
             // recompute visible region
             mRecomputeVisibleRegions = true;
+
+            mFreezeGeometryUpdates = false;
+
+            if (mFront.crop != mFront.requestedCrop) {
+                mFront.crop = mFront.requestedCrop;
+                mCurrent.crop = mFront.requestedCrop;
+                mRecomputeVisibleRegions = true;
+            }
+            if (mFront.finalCrop != mFront.requestedFinalCrop) {
+                mFront.finalCrop = mFront.requestedFinalCrop;
+                mCurrent.finalCrop = mFront.requestedFinalCrop;
+                mRecomputeVisibleRegions = true;
+            }
         }
 
         ALOGD_IF(DEBUG_RESIZE,
@@ -101,6 +114,10 @@
     // conservative, but that's fine, worst case we're doing
     // a bit of extra work), we latch the new one and we
     // trigger a visible-region recompute.
+    //
+    // We latch the transparent region here, instead of above where we latch
+    // the rest of the geometry because it is only content but not necessarily
+    // resize dependent.
     if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) {
         mFront.activeTransparentRegion = mFront.requestedTransparentRegion;
 
@@ -116,18 +133,6 @@
         mRecomputeVisibleRegions = true;
     }
 
-    if (mFront.crop != mFront.requestedCrop) {
-        mFront.crop = mFront.requestedCrop;
-        mCurrent.crop = mFront.requestedCrop;
-        mRecomputeVisibleRegions = true;
-    }
-    if (mFront.finalCrop != mFront.requestedFinalCrop) {
-        mFront.finalCrop = mFront.requestedFinalCrop;
-        mCurrent.finalCrop = mFront.requestedFinalCrop;
-        mRecomputeVisibleRegions = true;
-    }
-    mFreezePositionUpdates = false;
-
     return false;
 }
 
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
index c2a9483..828cd8b 100644
--- a/services/surfaceflinger/LayerRejecter.h
+++ b/services/surfaceflinger/LayerRejecter.h
@@ -40,8 +40,8 @@
         bool mStickyTransformSet;
         const char *mName;
         int32_t mOverrideScalingMode;
-        bool &mFreezePositionUpdates;
+        bool &mFreezeGeometryUpdates;
     };
 }  // namespace android
 
-#endif  // ANDROID_LAYER_REJECTER_H
\ No newline at end of file
+#endif  // ANDROID_LAYER_REJECTER_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 32fdc35..12afdf7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3186,7 +3186,8 @@
     if (currentMode == HWC_POWER_MODE_OFF) {
         // Turn on the display
         getHwComposer().setPowerMode(type, mode);
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY &&
+            mode != HWC_POWER_MODE_DOZE_SUSPEND) {
             // FIXME: eventthread only knows about the main display right now
             mEventThread->onScreenAcquired();
             resyncToHardwareVsync(true);
@@ -3218,7 +3219,8 @@
         getHwComposer().setPowerMode(type, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
-    } else if (mode == HWC_POWER_MODE_DOZE) {
+    } else if (mode == HWC_POWER_MODE_DOZE ||
+               mode == HWC_POWER_MODE_NORMAL) {
         // Update display while dozing
         getHwComposer().setPowerMode(type, mode);
         if (type == DisplayDevice::DISPLAY_PRIMARY) {
@@ -3235,6 +3237,7 @@
         }
         getHwComposer().setPowerMode(type, mode);
     } else {
+        ALOGE("Attempting to set unknown power mode: %d\n", mode);
         getHwComposer().setPowerMode(type, mode);
     }
 }
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 290d31e..f6ee660 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -2845,7 +2845,8 @@
     if (currentMode == HWC_POWER_MODE_OFF) {
         // Turn on the display
         getHwComposer().setPowerMode(type, mode);
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY &&
+            mode != HWC_POWER_MODE_DOZE_SUSPEND) {
             // FIXME: eventthread only knows about the main display right now
             mEventThread->onScreenAcquired();
             resyncToHardwareVsync(true);
@@ -2877,7 +2878,8 @@
         getHwComposer().setPowerMode(type, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
-    } else if (mode == HWC_POWER_MODE_DOZE) {
+    } else if (mode == HWC_POWER_MODE_DOZE ||
+               mode == HWC_POWER_MODE_NORMAL) {
         // Update display while dozing
         getHwComposer().setPowerMode(type, mode);
         if (type == DisplayDevice::DISPLAY_PRIMARY) {
@@ -2894,6 +2896,7 @@
         }
         getHwComposer().setPowerMode(type, mode);
     } else {
+        ALOGE("Attempting to set unknown power mode: %d\n", mode);
         getHwComposer().setPowerMode(type, mode);
     }
 }
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index d15376e..e50f3ce 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -18,6 +18,7 @@
 
 #include <sched.h>
 
+#include <android/frameworks/displayservice/1.0/IDisplayService.h>
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <cutils/sched_policy.h>
@@ -25,6 +26,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <displayservice/DisplayService.h>
 #include <hidl/LegacySupport.h>
 #include <configstore/Utils.h>
 #include "GpuService.h"
@@ -32,14 +34,9 @@
 
 using namespace android;
 
-using android::hardware::graphics::allocator::V2_0::IAllocator;
-using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
-using android::hardware::configstore::getBool;
-using android::hardware::configstore::getBool;
-
 static status_t startGraphicsAllocatorService() {
-    hardware::configureRpcThreadpool( 1 /* maxThreads */,
-            false /* callerWillJoin */);
+    using android::hardware::graphics::allocator::V2_0::IAllocator;
+
     status_t result =
         hardware::registerPassthroughServiceImplementation<IAllocator>();
     if (result != OK) {
@@ -50,12 +47,38 @@
     return OK;
 }
 
-int main(int, char**) {
+static status_t startHidlServices() {
+    using android::frameworks::displayservice::V1_0::implementation::DisplayService;
+    using android::frameworks::displayservice::V1_0::IDisplayService;
+    using android::hardware::configstore::getBool;
+    using android::hardware::configstore::getBool;
+    using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+    hardware::configureRpcThreadpool(1 /* maxThreads */,
+            false /* callerWillJoin */);
+
+    status_t err;
+
     if (getBool<ISurfaceFlingerConfigs,
             &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
-        startGraphicsAllocatorService();
+        err = startGraphicsAllocatorService();
+        if (err != OK) {
+           return err;
+        }
     }
 
+    sp<IDisplayService> displayservice = new DisplayService();
+    err = displayservice->registerAsService();
+
+    if (err != OK) {
+        ALOGE("Could not register IDisplayService service.");
+    }
+
+    return err;
+}
+
+int main(int, char**) {
+    startHidlServices();
+
     signal(SIGPIPE, SIG_IGN);
     // When SF is launched in its own process, limit the number of
     // binder threads to 4.
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 1b17e55..68519a1 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -33,7 +33,7 @@
 
 // Fill an RGBA_8888 formatted surface with a single color.
 static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
-        uint8_t r, uint8_t g, uint8_t b) {
+        uint8_t r, uint8_t g, uint8_t b, bool unlock=true) {
     ANativeWindow_Buffer outBuffer;
     sp<Surface> s = sc->getSurface();
     ASSERT_TRUE(s != NULL);
@@ -48,7 +48,9 @@
             pixel[3] = 255;
         }
     }
-    ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+    if (unlock) {
+        ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+    }
 }
 
 // A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check
@@ -479,6 +481,17 @@
         sc->expectFGColor(127, 127);
         sc->expectBGColor(128, 128);
     }
+
+    void lockAndFillFGBuffer() {
+        fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
+    }
+
+    void unlockFGBuffer() {
+        sp<Surface> s = mFGSurfaceControl->getSurface();
+        ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+        waitForPostedBuffers();
+    }
+
     void completeFGResize() {
         fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
         waitForPostedBuffers();
@@ -605,6 +618,65 @@
     EXPECT_CROPPED_STATE("after the resize finishes");
 }
 
+// In this test we ensure that setGeometryAppliesWithResize actually demands
+// a buffer of the new size, and not just any size.
+TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) {
+    EXPECT_INITIAL_STATE("before anything");
+    // Normally the crop applies immediately even while a resize is pending.
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setSize(128, 128);
+    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
+
+    restoreInitialState();
+
+    // In order to prepare to submit a buffer at the wrong size, we acquire it prior to
+    // initiating the resize.
+    lockAndFillFGBuffer();
+
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setSize(128, 128);
+    mFGSurfaceControl->setGeometryAppliesWithResize();
+    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
+
+    // We now submit our old buffer, at the old size, and ensure it doesn't
+    // trigger geometry latching.
+    unlockFGBuffer();
+
+    EXPECT_INITIAL_STATE("after unlocking FG buffer (with geometryAppliesWithResize)");
+
+    completeFGResize();
+
+    EXPECT_CROPPED_STATE("after the resize finishes");
+}
+
+TEST_F(CropLatchingTest, FinalCropLatchingRegressionForb37531386) {
+    EXPECT_INITIAL_STATE("before anything");
+    // In this scenario, we attempt to set the final crop a second time while the resize
+    // is still pending, and ensure we are successful. Success meaning the second crop
+    // is the one which eventually latches and not the first.
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setSize(128, 128);
+    mFGSurfaceControl->setGeometryAppliesWithResize();
+    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
+
+    completeFGResize();
+
+    EXPECT_INITIAL_STATE("after the resize finishes");
+}
+
 TEST_F(LayerUpdateTest, DeferredTransactionTest) {
     sp<ScreenCapture> sc;
     {
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index d27f274..26843c9 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -382,7 +382,7 @@
 }
 
 Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
-    pdx::Message& message, size_t meta_size_bytes,
+    pdx::Message& message, const ProducerQueueConfig& producer_config,
     const UsagePolicy& usage_policy) {
   // Use the producer channel id as the global queue id.
   const int queue_id = message.GetChannelId();
@@ -396,11 +396,11 @@
     return ErrorStatus(EALREADY);
   }
 
-  auto status = ProducerQueueChannel::Create(this, queue_id, meta_size_bytes,
+  auto status = ProducerQueueChannel::Create(this, queue_id, producer_config,
                                              usage_policy);
   if (status) {
     message.SetChannel(status.take());
-    return {{meta_size_bytes, queue_id}};
+    return {{producer_config, queue_id}};
   } else {
     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
     return status.error_status();
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 3bc2635..b0df11f 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -166,9 +166,9 @@
                                              size_t meta_size_bytes);
   pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message,
                                           const std::string& name);
-  pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
-                                               size_t meta_size_bytes,
-                                               const UsagePolicy& usage_policy);
+  pdx::Status<QueueInfo> OnCreateProducerQueue(
+      pdx::Message& message, const ProducerQueueConfig& producer_config,
+      const UsagePolicy& usage_policy);
 
   BufferHubService(const BufferHubService&) = delete;
   void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 886e621..605b8fb 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -16,11 +16,11 @@
 
 ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service,
                                            int channel_id,
-                                           size_t meta_size_bytes,
+                                           const ProducerQueueConfig& config,
                                            const UsagePolicy& usage_policy,
                                            int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerQueueType),
-      meta_size_bytes_(meta_size_bytes),
+      config_(config),
       usage_policy_(usage_policy),
       capacity_(0) {
   *error = 0;
@@ -35,8 +35,8 @@
 
 /* static */
 Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
-    BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    const UsagePolicy& usage_policy) {
+    BufferHubService* service, int channel_id,
+    const ProducerQueueConfig& config, const UsagePolicy& usage_policy) {
   // Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
   // should be mutually exclusive.
   if ((usage_policy.usage_deny_set_mask & usage_policy.usage_deny_clear_mask)) {
@@ -50,7 +50,7 @@
 
   int error = 0;
   std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel(
-      service, channel_id, meta_size_bytes, usage_policy, &error));
+      service, channel_id, config, usage_policy, &error));
   if (error < 0)
     return ErrorStatus(-error);
   else
@@ -134,7 +134,7 @@
 }
 
 Status<QueueInfo> ProducerQueueChannel::OnGetQueueInfo(Message&) {
-  return {{meta_size_bytes_, buffer_id()}};
+  return {{config_, buffer_id()}};
 }
 
 Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
@@ -222,7 +222,7 @@
 
   auto producer_channel_status =
       ProducerChannel::Create(service(), buffer_id, width, height, layer_count,
-                              format, usage, meta_size_bytes_);
+                              format, usage, config_.meta_size_bytes);
   if (!producer_channel_status) {
     ALOGE(
         "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index 28c74cd..212a90d 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -12,8 +12,8 @@
 class ProducerQueueChannel : public BufferHubChannel {
  public:
   static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create(
-      BufferHubService* service, int channel_id, size_t meta_size_bytes,
-      const UsagePolicy& usage_policy);
+      BufferHubService* service, int channel_id,
+      const ProducerQueueConfig& config, const UsagePolicy& usage_policy);
   ~ProducerQueueChannel() override;
 
   bool HandleMessage(pdx::Message& message) override;
@@ -48,8 +48,8 @@
 
  private:
   ProducerQueueChannel(BufferHubService* service, int channel_id,
-                       size_t meta_size_bytes, const UsagePolicy& usage_policy,
-                       int* error);
+                       const ProducerQueueConfig& config,
+                       const UsagePolicy& usage_policy, int* error);
 
   // Allocate one single producer buffer by |OnProducerQueueAllocateBuffers|.
   // Note that the newly created buffer's file handle will be pushed to client
@@ -60,10 +60,9 @@
       pdx::Message& message, uint32_t width, uint32_t height,
       uint32_t layer_count, uint32_t format, uint64_t usage);
 
-  // Size of the meta data associated with all the buffers allocated from the
-  // queue. Now we assume the metadata size is immutable once the queue is
-  // created.
-  size_t meta_size_bytes_;
+  // The producer queue's configuration. Now we assume the configuration is
+  // immutable once the queue is created.
+  ProducerQueueConfig config_;
 
   // A set of variables to control what |usage| bits can this ProducerQueue
   // allocate.
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 5cb201d..9201520 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -7,6 +7,7 @@
   ],
 
   static_libs: [
+    "libbroadcastring",
     "libhwcomposer-client",
     "libdisplay",
     "libbufferhubqueue",
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index a19fcf1..3efc131 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
 define VERSION_MINOR 0
-define VERSION_PATCH 46
+define VERSION_PATCH 49
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -320,7 +320,7 @@
 @extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
 @extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
 
-// 119
+// 120
 @extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
 @extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
 
@@ -409,7 +409,7 @@
     //@extension("VK_KHR_swapchain") // 2
     VK_IMAGE_LAYOUT_PRESENT_SRC_KHR                         = 1000001002,
 
-    //@extension("VK_KHR_shared_presentable_image")
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR                      = 1000111000,
 }
 
@@ -1005,9 +1005,6 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX  = 1000071002,
     VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX            = 1000071003,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX         = 1000071004,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX          = 1000071005,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX             = 1000071006,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX   = 1000071007,
 
     //@extension("VK_KHX_external_memory") // 73
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX    = 1000072000,
@@ -1086,10 +1083,10 @@
     //@extension("VK_EXT_hdr_metadata") // 106
     VK_STRUCTURE_TYPE_HDR_METADATA_EXT                          = 1000105000,
 
-    //@extension("VK_KHR_shared_presentable_image") // 111
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR   = 1000111000,
 
-    //@extension("VK_KHR_get_surface_capabilities2") // 119
+    //@extension("VK_KHR_get_surface_capabilities2") // 120
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR        = 1000119000,
     VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR                = 1000119001,
     VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR                      = 1000119002,
@@ -1179,6 +1176,55 @@
     VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT                  = 1000099000,
 }
 
+enum VkObjectType {
+    VK_OBJECT_TYPE_UNKNOWN                                  = 0,
+    VK_OBJECT_TYPE_INSTANCE                                 = 1,
+    VK_OBJECT_TYPE_PHYSICAL_DEVICE                          = 2,
+    VK_OBJECT_TYPE_DEVICE                                   = 3,
+    VK_OBJECT_TYPE_QUEUE                                    = 4,
+    VK_OBJECT_TYPE_SEMAPHORE                                = 5,
+    VK_OBJECT_TYPE_COMMAND_BUFFER                           = 6,
+    VK_OBJECT_TYPE_FENCE                                    = 7,
+    VK_OBJECT_TYPE_DEVICE_MEMORY                            = 8,
+    VK_OBJECT_TYPE_BUFFER                                   = 9,
+    VK_OBJECT_TYPE_IMAGE                                    = 10,
+    VK_OBJECT_TYPE_EVENT                                    = 11,
+    VK_OBJECT_TYPE_QUERY_POOL                               = 12,
+    VK_OBJECT_TYPE_BUFFER_VIEW                              = 13,
+    VK_OBJECT_TYPE_IMAGE_VIEW                               = 14,
+    VK_OBJECT_TYPE_SHADER_MODULE                            = 15,
+    VK_OBJECT_TYPE_PIPELINE_CACHE                           = 16,
+    VK_OBJECT_TYPE_PIPELINE_LAYOUT                          = 17,
+    VK_OBJECT_TYPE_RENDER_PASS                              = 18,
+    VK_OBJECT_TYPE_PIPELINE                                 = 19,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT                    = 20,
+    VK_OBJECT_TYPE_SAMPLER                                  = 21,
+    VK_OBJECT_TYPE_DESCRIPTOR_POOL                          = 22,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET                           = 23,
+    VK_OBJECT_TYPE_FRAMEBUFFER                              = 24,
+    VK_OBJECT_TYPE_COMMAND_POOL                             = 25,
+
+    //@extension("VK_KHR_surface") // 1
+    VK_OBJECT_TYPE_SURFACE_KHR                              = 1000000000,
+
+    //@extension("VK_KHR_swapchain") // 2
+    VK_OBJECT_TYPE_SWAPCHAIN_KHR                            = 1000001000,
+
+    //@extension("VK_KHR_display") // 3
+    VK_OBJECT_TYPE_DISPLAY_KHR                              = 1000002000,
+    VK_OBJECT_TYPE_DISPLAY_MODE_KHR                         = 1000002001,
+
+    //@extension("VK_KHR_debug_report") // 12
+    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT                = 1000011000,
+
+    //@extension("VK_KHR_descriptor_update_template") // 86
+    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR           = 1000085000,
+
+    //@extension("VK_NVX_device_generated_commands") // 87
+    VK_OBJECT_TYPE_OBJECT_TABLE_NVX                         = 1000086000,
+    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX             = 1000086001,
+}
+
 @extension("VK_KHR_surface") // 1
 enum VkPresentModeKHR {
     VK_PRESENT_MODE_IMMEDIATE_KHR                           = 0x00000000,
@@ -1186,7 +1232,7 @@
     VK_PRESENT_MODE_FIFO_KHR                                = 0x00000002,
     VK_PRESENT_MODE_FIFO_RELAXED_KHR                        = 0x00000003,
 
-    //@extension("VK_KHR_shared_presentable_image")
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR               = 1000111000,
     VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR           = 1000111001,
 }
@@ -4261,28 +4307,28 @@
     f32                                             maxFrameAverageLightLevel
 }
 
-@extension("VK_KHR_shared_presentable_image") // 111
+@extension("VK_KHR_shared_presentable_image") // 112
 class VkSharedPresentSurfaceCapabilitiesKHR {
     VkStructureType                                 sType
     const void*                                     pNext
     VkImageUsageFlags                               sharedPresentSupportedUsageFlags
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 class VkPhysicalDeviceSurfaceInfo2KHR {
     VkStructureType                                 sType
     const void*                                     pNext
     VkSurfaceKHR                                    surface
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 class VkSurfaceCapabilities2KHR {
     VkStructureType                                 sType
     void*                                           pNext
     VkSurfaceCapabilitiesKHR                        surfaceCapabilities
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 class VkSurfaceFormat2KHR {
     VkStructureType                                 sType
     void*                                           pNext
@@ -7462,7 +7508,7 @@
     return ?
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 cmd VkResult vkGetPhysicalDeviceSurfaceCapabilities2KHR(
         VkPhysicalDevice                            physicalDevice,
         const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
@@ -7470,7 +7516,7 @@
     return ?
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 cmd VkResult vkGetPhysicalDeviceSurfaceFormats2KHR(
         VkPhysicalDevice                            physicalDevice,
         const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 67eba86..ee30913 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -43,11 +43,11 @@
 #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
 #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
 // Version of this file
-#define VK_HEADER_VERSION 46
+#define VK_HEADER_VERSION 49
 
 
 #define VK_NULL_HANDLE 0
-
+        
 
 
 #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
@@ -60,7 +60,7 @@
         #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
 #endif
 #endif
-
+        
 
 
 typedef uint32_t VkFlags;
@@ -261,9 +261,6 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX = 1000071002,
     VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX = 1000071003,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX = 1000071004,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX = 1000071005,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX = 1000071006,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX = 1000071007,
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX = 1000072000,
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHX = 1000072001,
     VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHX = 1000072002,
@@ -901,6 +898,47 @@
     VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF
 } VkSubpassContents;
 
+typedef enum VkObjectType {
+    VK_OBJECT_TYPE_UNKNOWN = 0,
+    VK_OBJECT_TYPE_INSTANCE = 1,
+    VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2,
+    VK_OBJECT_TYPE_DEVICE = 3,
+    VK_OBJECT_TYPE_QUEUE = 4,
+    VK_OBJECT_TYPE_SEMAPHORE = 5,
+    VK_OBJECT_TYPE_COMMAND_BUFFER = 6,
+    VK_OBJECT_TYPE_FENCE = 7,
+    VK_OBJECT_TYPE_DEVICE_MEMORY = 8,
+    VK_OBJECT_TYPE_BUFFER = 9,
+    VK_OBJECT_TYPE_IMAGE = 10,
+    VK_OBJECT_TYPE_EVENT = 11,
+    VK_OBJECT_TYPE_QUERY_POOL = 12,
+    VK_OBJECT_TYPE_BUFFER_VIEW = 13,
+    VK_OBJECT_TYPE_IMAGE_VIEW = 14,
+    VK_OBJECT_TYPE_SHADER_MODULE = 15,
+    VK_OBJECT_TYPE_PIPELINE_CACHE = 16,
+    VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17,
+    VK_OBJECT_TYPE_RENDER_PASS = 18,
+    VK_OBJECT_TYPE_PIPELINE = 19,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20,
+    VK_OBJECT_TYPE_SAMPLER = 21,
+    VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET = 23,
+    VK_OBJECT_TYPE_FRAMEBUFFER = 24,
+    VK_OBJECT_TYPE_COMMAND_POOL = 25,
+    VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
+    VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
+    VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
+    VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
+    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
+    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = 1000085000,
+    VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
+    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
+    VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
+    VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL,
+    VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1),
+    VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkObjectType;
+
 typedef VkFlags VkInstanceCreateFlags;
 
 typedef enum VkFormatFeatureFlagBits {
@@ -4107,6 +4145,64 @@
     const void*                                 pData);
 #endif
 
+#define VK_KHR_shared_presentable_image 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
+
+typedef struct VkSharedPresentSurfaceCapabilitiesKHR {
+    VkStructureType      sType;
+    void*                pNext;
+    VkImageUsageFlags    sharedPresentSupportedUsageFlags;
+} VkSharedPresentSurfaceCapabilitiesKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
+    VkDevice                                    device,
+    VkSwapchainKHR                              swapchain);
+#endif
+
+#define VK_KHR_get_surface_capabilities2 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
+
+typedef struct VkPhysicalDeviceSurfaceInfo2KHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkSurfaceKHR       surface;
+} VkPhysicalDeviceSurfaceInfo2KHR;
+
+typedef struct VkSurfaceCapabilities2KHR {
+    VkStructureType             sType;
+    void*                       pNext;
+    VkSurfaceCapabilitiesKHR    surfaceCapabilities;
+} VkSurfaceCapabilities2KHR;
+
+typedef struct VkSurfaceFormat2KHR {
+    VkStructureType       sType;
+    void*                 pNext;
+    VkSurfaceFormatKHR    surfaceFormat;
+} VkSurfaceFormat2KHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
+    VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
+    uint32_t*                                   pSurfaceFormatCount,
+    VkSurfaceFormat2KHR*                        pSurfaceFormats);
+#endif
+
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
@@ -5770,66 +5866,6 @@
     const VkHdrMetadataEXT*                     pMetadata);
 #endif
 
-#define VK_KHR_shared_presentable_image 1
-#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
-#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
-
-typedef struct VkSharedPresentSurfaceCapabilitiesKHR {
-    VkStructureType      sType;
-    void*                pNext;
-    VkImageUsageFlags    sharedPresentSupportedUsageFlags;
-} VkSharedPresentSurfaceCapabilitiesKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain);
-#endif
-
-#define VK_KHR_get_surface_capabilities2 1
-#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
-#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
-
-typedef struct VkPhysicalDeviceSurfaceInfo2KHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkSurfaceKHR       surface;
-} VkPhysicalDeviceSurfaceInfo2KHR;
-
-typedef struct VkSurfaceCapabilities2KHR {
-    VkStructureType             sType;
-    void*                       pNext;
-    VkSurfaceCapabilitiesKHR    surfaceCapabilities;
-} VkSurfaceCapabilities2KHR;
-
-typedef struct VkSurfaceFormat2KHR {
-    VkStructureType       sType;
-    void*                 pNext;
-    VkSurfaceFormatKHR    surfaceFormat;
-} VkSurfaceFormat2KHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-    VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-    uint32_t*                                   pSurfaceFormatCount,
-    VkSurfaceFormat2KHR*                        pSurfaceFormats);
-#endif
-
-
-
 #ifdef VK_USE_PLATFORM_IOS_MVK
 #define VK_MVK_ios_surface 1
 #define VK_MVK_IOS_SURFACE_SPEC_VERSION   2
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index a869317..7b985d1 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -39,9 +39,6 @@
 android_namespace_t* android_get_exported_namespace(const char*);
 }
 
-// Set to true to enable exposing unratified extensions for development
-static const bool kEnableUnratifiedExtensions = false;
-
 // #define ENABLE_ALLOC_CALLSTACKS 1
 #if ENABLE_ALLOC_CALLSTACKS
 #include <utils/CallStack.h>
@@ -717,12 +714,9 @@
     loader_extensions.push_back({
         VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
         VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
-
-    if (kEnableUnratifiedExtensions) {
-        loader_extensions.push_back({
-            VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
-            VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
-    }
+    loader_extensions.push_back({
+        VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
+        VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
 
     static const VkExtensionProperties loader_debug_report_extension = {
         VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
@@ -818,15 +812,12 @@
         VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
 
-    if (kEnableUnratifiedExtensions) {
-        // conditionally add shared_presentable_image if supportable
-        VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
-        if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
-            presentation_properties.sharedImage) {
-            loader_extensions.push_back({
-                VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
-                        VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
-        }
+    VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
+    if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
+        presentation_properties.sharedImage) {
+        loader_extensions.push_back({
+            VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
+            VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
     }
 
     // conditionally add VK_GOOGLE_display_timing if present timestamps are