Merge "Clockwork: add feature android.software.input_methods" into oc-dev
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index 4f1065f..6c5869a 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -16,9 +16,6 @@
         "libz",
         "libbase",
     ],
-    static_libs: [
-        "libpdx_default_transport",
-    ],
 
     init_rc: ["atrace.rc"],
 
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index f8e0ad5..6f2159d 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <zlib.h>
 
+#include <fstream>
 #include <memory>
 
 #include <binder/IBinder.h>
@@ -41,7 +42,6 @@
 #include <hidl/ServiceManagement.h>
 #include <cutils/properties.h>
 
-#include <pdx/default_transport/service_utility.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/Tokenizer.h>
@@ -49,7 +49,6 @@
 #include <android-base/file.h>
 
 using namespace android;
-using pdx::default_transport::ServiceUtility;
 
 using std::string;
 #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
@@ -116,6 +115,7 @@
     { "sched",      "CPU Scheduling",   0, {
         { REQ,      "events/sched/sched_switch/enable" },
         { REQ,      "events/sched/sched_wakeup/enable" },
+        { OPT,      "events/sched/sched_waking/enable" },
         { OPT,      "events/sched/sched_blocked_reason/enable" },
         { OPT,      "events/sched/sched_cpu_hotplug/enable" },
     } },
@@ -216,6 +216,9 @@
 static const char* k_traceBufferSizePath =
     "buffer_size_kb";
 
+static const char* k_traceCmdlineSizePath =
+    "saved_cmdlines_size";
+
 static const char* k_tracingOverwriteEnablePath =
     "options/overwrite";
 
@@ -438,56 +441,37 @@
     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)
+// Set the default size of cmdline hashtable
+static bool setCmdlineSize()
 {
-    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;
+    return writeStr(k_traceCmdlineSizePath, "8192");
 }
 
-// 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)
@@ -783,7 +767,8 @@
     ok &= setCategoriesEnableFromFile(g_categoriesFile);
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
-    ok &= setGlobalClockEnable(true);
+    ok &= setCmdlineSize();
+    ok &= setClock();
     ok &= setPrintTgidEnableIfPresent(true);
     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
 
@@ -816,7 +801,6 @@
     ok &= setAppCmdlineProperty(&packageList[0]);
     ok &= pokeBinderServices();
     pokeHalServices();
-    ok &= ServiceUtility::PokeServices();
 
     // Disable all the sysfs enables.  This is done as a separate loop from
     // the enables to allow the same enable to exist in multiple categories.
@@ -854,12 +838,10 @@
     setTagsProperty(0);
     clearAppProperties();
     pokeBinderServices();
-    ServiceUtility::PokeServices();
 
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
     setTraceBufferSizeKB(1);
-    setGlobalClockEnable(false);
     setPrintTgidEnableIfPresent(false);
     setKernelTraceFuncs(NULL);
 }
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/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index f649a5e..eefdcbd 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -86,6 +86,7 @@
         "/system/bin/sdcard",
         "/system/bin/surfaceflinger",
         "/system/bin/vehicle_network_service",
+        "/vendor/bin/hw/android.hardware.media.omx@1.0-service", // media.codec
         NULL,
 };
 
diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp
index 17eb7ff..515f915 100644
--- a/cmds/installd/CacheItem.cpp
+++ b/cmds/installd/CacheItem.cpp
@@ -67,6 +67,7 @@
 }
 
 int CacheItem::purge() {
+    int res = 0;
     auto path = buildPath();
     if (directory) {
         FTS *fts;
@@ -88,29 +89,47 @@
                 break;
             case FTS_F:
                 if (p->fts_parent->fts_number) {
-                    truncate(p->fts_path, 0);
+                    if (truncate(p->fts_path, 0) != 0) {
+                        PLOG(WARNING) << "Failed to truncate " << p->fts_path;
+                        res = -1;
+                    }
                 } else {
-                    unlink(p->fts_path);
+                    if (unlink(p->fts_path) != 0) {
+                        PLOG(WARNING) << "Failed to unlink " << p->fts_path;
+                        res = -1;
+                    }
                 }
                 break;
             case FTS_DEFAULT:
             case FTS_SL:
             case FTS_SLNONE:
-                unlink(p->fts_path);
+                if (unlink(p->fts_path) != 0) {
+                    PLOG(WARNING) << "Failed to unlink " << p->fts_path;
+                    res = -1;
+                }
                 break;
             case FTS_DP:
-                rmdir(p->fts_path);
+                if (rmdir(p->fts_path) != 0) {
+                    PLOG(WARNING) << "Failed to rmdir " << p->fts_path;
+                    res = -1;
+                }
                 break;
             }
         }
-        return 0;
     } else {
         if (tombstone) {
-            return truncate(path.c_str(), 0);
+            if (truncate(path.c_str(), 0) != 0) {
+                PLOG(WARNING) << "Failed to truncate " << path;
+                res = -1;
+            }
         } else {
-            return unlink(path.c_str());
+            if (unlink(path.c_str()) != 0) {
+                PLOG(WARNING) << "Failed to unlink " << path;
+                res = -1;
+            }
         }
     }
+    return res;
 }
 
 }  // namespace installd
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index 4bfc834..e293948 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -51,22 +51,12 @@
 }
 
 void CacheTracker::loadStats() {
-    int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
-    if (cacheGid != -1 && !mQuotaDevice.empty()) {
-        ATRACE_BEGIN("loadStats quota");
-        struct dqblk dq;
-        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
-                reinterpret_cast<char*>(&dq)) != 0) {
-            ATRACE_END();
-            if (errno != ESRCH) {
-                PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
-            }
-        } else {
-            cacheUsed = dq.dqb_curspace;
-            ATRACE_END();
-            return;
-        }
+    ATRACE_BEGIN("loadStats quota");
+    cacheUsed = 0;
+    if (loadQuotaStats()) {
+        return;
     }
+    ATRACE_END();
 
     ATRACE_BEGIN("loadStats tree");
     cacheUsed = 0;
@@ -79,6 +69,36 @@
     ATRACE_END();
 }
 
+bool CacheTracker::loadQuotaStats() {
+    int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
+    int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
+    if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) {
+        struct dqblk dq;
+        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
+                reinterpret_cast<char*>(&dq)) != 0) {
+            if (errno != ESRCH) {
+                PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
+            }
+            return false;
+        } else {
+            cacheUsed += dq.dqb_curspace;
+        }
+
+        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid,
+                reinterpret_cast<char*>(&dq)) != 0) {
+            if (errno != ESRCH) {
+                PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
+            }
+            return false;
+        } else {
+            cacheUsed += dq.dqb_curspace;
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
+
 void CacheTracker::loadItemsFrom(const std::string& path) {
     FTS *fts;
     FTSENT *p;
diff --git a/cmds/installd/CacheTracker.h b/cmds/installd/CacheTracker.h
index 91692d7..44359b4 100644
--- a/cmds/installd/CacheTracker.h
+++ b/cmds/installd/CacheTracker.h
@@ -66,6 +66,7 @@
 
     std::vector<std::string> mDataPaths;
 
+    bool loadQuotaStats();
     void loadItemsFrom(const std::string& path);
 
     DISALLOW_COPY_AND_ASSIGN(CacheTracker);
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 49a3b23..3041467 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -78,6 +78,7 @@
 static constexpr const char* CACHE_DIR_POSTFIX = "/cache";
 static constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache";
 
+static constexpr const char *kIdMapPath = "/system/bin/idmap";
 static constexpr const char* IDMAP_PREFIX = "/data/resource-cache/";
 static constexpr const char* IDMAP_SUFFIX = "@idmap";
 
@@ -205,15 +206,20 @@
     out << "installd is happy!" << endl;
 
     {
-        std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
-        out << endl << "Devices with quota support:" << endl;
-        for (const auto& n : mQuotaDevices) {
+        std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+        out << endl << "Storage mounts:" << endl;
+        for (const auto& n : mStorageMounts) {
+            out << "    " << n.first << " = " << n.second << endl;
+        }
+
+        out << endl << "Quota reverse mounts:" << endl;
+        for (const auto& n : mQuotaReverseMounts) {
             out << "    " << n.first << " = " << n.second << endl;
         }
     }
 
     {
-        std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+        std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
         out << endl << "Per-UID cache quotas:" << endl;
         for (const auto& n : mCacheQuotas) {
             out << "    " << n.first << " = " << n.second << endl;
@@ -901,7 +907,7 @@
         if (delete_dir_contents_and_dir(path, true) != 0) {
             res = error("Failed to delete " + path);
         }
-        path = create_data_media_path(uuid_, userId);
+        path = findDataMediaPath(uuid, userId);
         if (delete_dir_contents_and_dir(path, true) != 0) {
             res = error("Failed to delete " + path);
         }
@@ -909,15 +915,8 @@
     return res;
 }
 
-/* Try to ensure free_size bytes of storage are available.
- * Returns 0 on success.
- * This is rather simple-minded because doing a full LRU would
- * be potentially memory-intensive, and without atime it would
- * also require that apps constantly modify file metadata even
- * when just reading from the cache, which is pretty awful.
- */
 binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid,
-        int64_t freeStorageSize, int32_t flags) {
+        int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     std::lock_guard<std::recursive_mutex> lock(mLock);
@@ -932,11 +931,12 @@
         return error("Failed to determine free space for " + data_path);
     }
 
-    int64_t needed = freeStorageSize - free;
+    int64_t cleared = 0;
+    int64_t needed = targetFreeBytes - free;
     LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
-            << freeStorageSize << "; needed " << needed;
+            << targetFreeBytes << "; needed " << needed;
 
-    if (free >= freeStorageSize) {
+    if (free >= targetFreeBytes) {
         return ok();
     }
 
@@ -952,13 +952,19 @@
             FTSENT *p;
             auto ce_path = create_data_user_ce_path(uuid_, user);
             auto de_path = create_data_user_de_path(uuid_, user);
-            char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr };
+            auto media_path = findDataMediaPath(uuid, user) + "/Android/data/";
+            char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(),
+                    (char*) media_path.c_str(), nullptr };
             if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
                 return error("Failed to fts_open");
             }
             while ((p = fts_read(fts)) != NULL) {
                 if (p->fts_info == FTS_D && p->fts_level == 1) {
                     uid_t uid = p->fts_statp->st_uid;
+                    if (multiuser_get_app_id(uid) == AID_MEDIA_RW) {
+                        uid = (multiuser_get_app_id(p->fts_statp->st_gid) - AID_EXT_GID_START)
+                                + AID_APP_START;
+                    }
                     auto search = trackers.find(uid);
                     if (search != trackers.end()) {
                         search->second->addDataPath(p->fts_path);
@@ -967,7 +973,7 @@
                                 multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
                         tracker->addDataPath(p->fts_path);
                         {
-                            std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+                            std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
                             tracker->cacheQuota = mCacheQuotas[uid];
                         }
                         if (tracker->cacheQuota == 0) {
@@ -987,6 +993,7 @@
 
         // 2. Populate tracker stats and insert into priority queue
         ATRACE_BEGIN("populate");
+        int64_t cacheTotal = 0;
         auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) {
             return (left->getCacheRatio() < right->getCacheRatio());
         };
@@ -995,6 +1002,7 @@
         for (const auto& it : trackers) {
             it.second->loadStats();
             queue.push(it.second);
+            cacheTotal += it.second->cacheUsed;
         }
         ATRACE_END();
 
@@ -1011,6 +1019,12 @@
                 break;
             }
 
+            // Only keep clearing when we haven't pushed into reserved area
+            if (cacheReservedBytes > 0 && cleared >= (cacheTotal - cacheReservedBytes)) {
+                LOG(DEBUG) << "Refusing to clear cached data in reserved space";
+                break;
+            }
+
             // Find the best tracker to work with; this might involve swapping
             // if the active tracker is no longer the most over quota
             bool nextBetter = active && !queue.empty()
@@ -1040,13 +1054,14 @@
                 }
                 active->cacheUsed -= item->size;
                 needed -= item->size;
+                cleared += item->size;
             }
 
             // Verify that we're actually done before bailing, since sneaky
             // apps might be using hardlinks
             if (needed <= 0) {
                 free = data_disk_free(data_path);
-                needed = freeStorageSize - free;
+                needed = targetFreeBytes - free;
                 if (needed <= 0) {
                     break;
                 } else {
@@ -1061,11 +1076,11 @@
     }
 
     free = data_disk_free(data_path);
-    if (free >= freeStorageSize) {
+    if (free >= targetFreeBytes) {
         return ok();
     } else {
         return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64,
-                freeStorageSize, data_path.c_str(), free));
+                targetFreeBytes, data_path.c_str(), free));
     }
 }
 
@@ -1089,10 +1104,13 @@
 
     ALOGV("unlink %s\n", dex_path);
     if (unlink(dex_path) < 0) {
-        return error(StringPrintf("Failed to unlink %s", dex_path));
-    } else {
-        return ok();
+        // It's ok if we don't have a dalvik cache path. Report error only when the path exists
+        // but could not be unlinked.
+        if (errno != ENOENT) {
+            return error(StringPrintf("Failed to unlink %s", dex_path));
+        }
     }
+    return ok();
 }
 
 struct stats {
@@ -1745,7 +1763,7 @@
         int32_t userId, int32_t appId, int64_t cacheQuota) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
-    std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+    std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
 
     int32_t uid = multiuser_get_uid(userId, appId);
     mCacheQuotas[uid] = cacheQuota;
@@ -1927,14 +1945,58 @@
 
 static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
 {
-    static const char *IDMAP_BIN = "/system/bin/idmap";
-    static const size_t MAX_INT_LEN = 32;
-    char idmap_str[MAX_INT_LEN];
+    execl(kIdMapPath, kIdMapPath, "--fd", target_apk, overlay_apk,
+            StringPrintf("%d", idmap_fd).c_str(), (char*)NULL);
+    PLOG(ERROR) << "execl (" << kIdMapPath << ") failed";
+}
 
-    snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd);
+static void run_verify_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
+{
+    execl(kIdMapPath, kIdMapPath, "--verify", target_apk, overlay_apk,
+            StringPrintf("%d", idmap_fd).c_str(), (char*)NULL);
+    PLOG(ERROR) << "execl (" << kIdMapPath << ") failed";
+}
 
-    execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL);
-    ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno));
+static bool delete_stale_idmap(const char* target_apk, const char* overlay_apk,
+        const char* idmap_path, int32_t uid) {
+    int idmap_fd = open(idmap_path, O_RDWR);
+    if (idmap_fd < 0) {
+        PLOG(ERROR) << "idmap open failed: " << idmap_path;
+        unlink(idmap_path);
+        return true;
+    }
+
+    pid_t pid;
+    pid = fork();
+    if (pid == 0) {
+        /* child -- drop privileges before continuing */
+        if (setgid(uid) != 0) {
+            LOG(ERROR) << "setgid(" << uid << ") failed during idmap";
+            exit(1);
+        }
+        if (setuid(uid) != 0) {
+            LOG(ERROR) << "setuid(" << uid << ") failed during idmap";
+            exit(1);
+        }
+        if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) {
+            PLOG(ERROR) << "flock(" << idmap_path << ") failed during idmap";
+            exit(1);
+        }
+
+        run_verify_idmap(target_apk, overlay_apk, idmap_fd);
+        exit(1); /* only if exec call to deleting stale idmap failed */
+    } else {
+        int status = wait_child(pid);
+        close(idmap_fd);
+
+        if (status != 0) {
+            // Failed on verifying if idmap is made from target_apk and overlay_apk.
+            LOG(DEBUG) << "delete stale idmap: " << idmap_path;
+            unlink(idmap_path);
+            return true;
+        }
+    }
+    return false;
 }
 
 // Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix)
@@ -1983,7 +2045,7 @@
 
     int idmap_fd = -1;
     char idmap_path[PATH_MAX];
-    struct stat target_apk_stat, overlay_apk_stat, idmap_stat;
+    struct stat idmap_stat;
     bool outdated = false;
 
     if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
@@ -1992,17 +2054,13 @@
         goto fail;
     }
 
-    if (stat(idmap_path, &idmap_stat) < 0 ||
-            stat(target_apk, &target_apk_stat) < 0 ||
-            stat(overlay_apk, &overlay_apk_stat) < 0) {
+    if (stat(idmap_path, &idmap_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;
+    } else {
+        outdated = delete_stale_idmap(target_apk, overlay_apk, idmap_path, uid);
     }
 
     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);
@@ -2191,13 +2249,13 @@
 }
 
 binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath,
-        const std::string& instructionSet, const std::string& outputPath) {
+        const std::string& instructionSet, const std::unique_ptr<std::string>& outputPath) {
     ENFORCE_UID(AID_SYSTEM);
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
     const char* apk_path = apkPath.c_str();
     const char* instruction_set = instructionSet.c_str();
-    const char* oat_dir = outputPath.c_str();
+    const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
 
     bool res = delete_odex(apk_path, instruction_set, oat_dir);
     return res ? ok() : error();
@@ -2219,9 +2277,10 @@
 
 binder::Status InstalldNativeService::invalidateMounts() {
     ENFORCE_UID(AID_SYSTEM);
-    std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
+    std::lock_guard<std::recursive_mutex> lock(mMountsLock);
 
-    mQuotaDevices.clear();
+    mStorageMounts.clear();
+    mQuotaReverseMounts.clear();
 
     std::ifstream in("/proc/mounts");
     if (!in.is_open()) {
@@ -2231,17 +2290,25 @@
     std::string source;
     std::string target;
     std::string ignored;
-    struct dqblk dq;
     while (!in.eof()) {
         std::getline(in, source, ' ');
         std::getline(in, target, ' ');
         std::getline(in, ignored);
 
+#if !BYPASS_SDCARDFS
+        if (target.compare(0, 21, "/mnt/runtime/default/") == 0) {
+            LOG(DEBUG) << "Found storage mount " << source << " at " << target;
+            mStorageMounts[source] = target;
+        }
+#endif
+
+#if !BYPASS_QUOTA
         if (source.compare(0, 11, "/dev/block/") == 0) {
+            struct dqblk dq;
             if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
                     reinterpret_cast<char*>(&dq)) == 0) {
-                LOG(DEBUG) << "Found " << source << " with quota";
-                mQuotaDevices[target] = source;
+                LOG(DEBUG) << "Found quota mount " << source << " at " << target;
+                mQuotaReverseMounts[target] = source;
 
                 // ext4 only enables DQUOT_USAGE_ENABLED by default, so we
                 // need to kick it again to enable DQUOT_LIMITS_ENABLED.
@@ -2255,15 +2322,29 @@
                 }
             }
         }
+#endif
     }
     return ok();
 }
 
+std::string InstalldNativeService::findDataMediaPath(
+        const std::unique_ptr<std::string>& uuid, userid_t userid) {
+    std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str());
+    auto resolved = mStorageMounts[path];
+    if (resolved.empty()) {
+        LOG(WARNING) << "Failed to find storage mount for " << path;
+        resolved = path;
+    }
+    return StringPrintf("%s/%u", resolved.c_str(), userid);
+}
+
 std::string InstalldNativeService::findQuotaDeviceForUuid(
         const std::unique_ptr<std::string>& uuid) {
-    std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
+    std::lock_guard<std::recursive_mutex> lock(mMountsLock);
     auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
-    return mQuotaDevices[path];
+    return mQuotaReverseMounts[path];
 }
 
 binder::Status InstalldNativeService::isQuotaSupported(
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 7f73c2a..4011315 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -99,8 +99,8 @@
     binder::Status removeIdmap(const std::string& overlayApkPath);
     binder::Status rmPackageDir(const std::string& packageDir);
     binder::Status markBootComplete(const std::string& instructionSet);
-    binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t freeStorageSize,
-            int32_t flags);
+    binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t targetFreeBytes,
+            int64_t cacheReservedBytes, int32_t flags);
     binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid,
             const std::string& packageName, const std::string& nativeLibPath32, int32_t userId);
     binder::Status createOatDir(const std::string& oatDir, const std::string& instructionSet);
@@ -109,7 +109,7 @@
     binder::Status moveAb(const std::string& apkPath, const std::string& instructionSet,
             const std::string& outputPath);
     binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet,
-            const std::string& outputPath);
+            const std::unique_ptr<std::string>& outputPath);
     binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
         const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
         const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
@@ -121,14 +121,18 @@
 private:
     std::recursive_mutex mLock;
 
-    std::recursive_mutex mQuotaDevicesLock;
-    std::recursive_mutex mCacheQuotasLock;
+    std::recursive_mutex mMountsLock;
+    std::recursive_mutex mQuotasLock;
 
-    /* Map from mount point to underlying device node */
-    std::unordered_map<std::string, std::string> mQuotaDevices;
+    /* Map of all storage mounts from source to target */
+    std::unordered_map<std::string, std::string> mStorageMounts;
+    /* Map of all quota mounts from target to source */
+    std::unordered_map<std::string, std::string> mQuotaReverseMounts;
+
     /* Map from UID to cache quota size */
     std::unordered_map<uid_t, int64_t> mCacheQuotas;
 
+    std::string findDataMediaPath(const std::unique_ptr<std::string>& uuid, userid_t userid);
     std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
 };
 
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 6b99c1d..f09a397 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -64,7 +64,8 @@
     void removeIdmap(@utf8InCpp String overlayApkPath);
     void rmPackageDir(@utf8InCpp String packageDir);
     void markBootComplete(@utf8InCpp String instructionSet);
-    void freeCache(@nullable @utf8InCpp String uuid, long freeStorageSize, int flags);
+    void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes,
+            long cacheReservedBytes, int flags);
     void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid,
             @utf8InCpp String packageName, @utf8InCpp String nativeLibPath32, int userId);
     void createOatDir(@utf8InCpp String oatDir, @utf8InCpp String instructionSet);
@@ -73,7 +74,7 @@
     void moveAb(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
             @utf8InCpp String outputPath);
     void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
-            @utf8InCpp String outputPath);
+            @nullable @utf8InCpp String outputPath);
 
     boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
         int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 3710e6b..296b87d 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -190,7 +190,7 @@
 
 static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
         const char* input_file_name, const char* output_file_name, int swap_fd,
-        const char* instruction_set, const char* compiler_filter, bool vm_safe_mode,
+        const char* instruction_set, const char* compiler_filter,
         bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
@@ -240,7 +240,7 @@
                                  dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
     ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
 
-    // If we booting without the real /data, don't spend time compiling.
+    // If we are booting without the real /data, don't spend time compiling.
     char vold_decrypt[kPropertyValueMax];
     bool have_vold_decrypt = get_property("vold.decrypt", vold_decrypt, "") > 0;
     bool skip_compilation = (have_vold_decrypt &&
@@ -319,20 +319,24 @@
 
     // Compute compiler filter.
 
-    bool have_dex2oat_compiler_filter_flag;
+    bool have_dex2oat_compiler_filter_flag = false;
     if (skip_compilation) {
         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=extract");
         have_dex2oat_compiler_filter_flag = true;
         have_dex2oat_relocation_skip_flag = true;
-    } else if (vm_safe_mode) {
-        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=quicken");
-        have_dex2oat_compiler_filter_flag = true;
-    } else if (compiler_filter != nullptr &&
-            strlen(compiler_filter) + strlen("--compiler-filter=") <
+    } else if (compiler_filter != nullptr) {
+        if (strlen(compiler_filter) + strlen("--compiler-filter=") <
                     arraysize(dex2oat_compiler_filter_arg)) {
-        sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
-        have_dex2oat_compiler_filter_flag = true;
-    } else {
+            sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
+            have_dex2oat_compiler_filter_flag = true;
+        } else {
+            ALOGW("Compiler filter name '%s' is too large (max characters is %zu)",
+                  compiler_filter,
+                  kPropertyValueMax);
+        }
+    }
+
+    if (!have_dex2oat_compiler_filter_flag) {
         char dex2oat_compiler_filter_flag[kPropertyValueMax];
         have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
                                                          dex2oat_compiler_filter_flag, NULL) > 0;
@@ -1178,13 +1182,7 @@
             ALOGE("installd cannot compute input vdex location for '%s'\n", path);
             return false;
         }
-        if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
-            // When we dex2oat because of boot image change, we are going to update
-            // in-place the vdex file.
-            in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
-        } else {
-            in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
-        }
+        in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
     }
 
     // Infer the name of the output VDEX and create it.
@@ -1193,23 +1191,12 @@
         return false;
     }
 
-    // If we are compiling because the boot image is out of date, we do not
-    // need to recreate a vdex, and can use the same existing one.
-    if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE &&
-            in_vdex_wrapper_fd->get() != -1 &&
-            in_vdex_path_str == out_vdex_path_str) {
-        out_vdex_wrapper_fd->reset(in_vdex_wrapper_fd->get());
-        // Disable auto close for the in wrapper fd (it will be done when destructing the out
-        // wrapper).
-        in_vdex_wrapper_fd->DisableAutoClose();
-    } else {
-        out_vdex_wrapper_fd->reset(
-              open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
-              [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
-        if (out_vdex_wrapper_fd->get() < 0) {
-            ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
-            return false;
-        }
+    out_vdex_wrapper_fd->reset(
+          open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
+          [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+    if (out_vdex_wrapper_fd->get() < 0) {
+        ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
+        return false;
     }
     if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
             out_vdex_path_str.c_str(), is_secondary_dex)) {
@@ -1475,7 +1462,6 @@
     }
 
     bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
-    bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
     bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
     bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
     bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
@@ -1573,7 +1559,6 @@
                     swap_fd.get(),
                     instruction_set,
                     compiler_filter,
-                    vm_safe_mode,
                     debuggable,
                     boot_complete,
                     reference_profile_fd.get(),
@@ -1697,10 +1682,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;
@@ -1864,8 +1859,11 @@
     // Derive and delete the app image.
     bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
 
+    // Derive and delete the vdex file.
+    bool return_value_vdex = unlink_and_check(create_vdex_filename(out_path).c_str());
+
     // Report success.
-    return return_value_oat && return_value_art;
+    return return_value_oat && return_value_art && return_value_vdex;
 }
 
 }  // namespace installd
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index d8a754c..6a81cfc 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -38,23 +38,21 @@
  * frameworks/base/services/core/java/com/android/server/pm/Installer.java
  ***************************************************************************/
 constexpr int DEXOPT_PUBLIC         = 1 << 1;
-constexpr int DEXOPT_SAFEMODE       = 1 << 2;
-constexpr int DEXOPT_DEBUGGABLE     = 1 << 3;
-constexpr int DEXOPT_BOOTCOMPLETE   = 1 << 4;
-constexpr int DEXOPT_PROFILE_GUIDED = 1 << 5;
-constexpr int DEXOPT_SECONDARY_DEX  = 1 << 6;
+constexpr int DEXOPT_DEBUGGABLE     = 1 << 2;
+constexpr int DEXOPT_BOOTCOMPLETE   = 1 << 3;
+constexpr int DEXOPT_PROFILE_GUIDED = 1 << 4;
+constexpr int DEXOPT_SECONDARY_DEX  = 1 << 5;
 // DEXOPT_FORCE, DEXOPT_STORAGE_CE, DEXOPT_STORAGE_DE are exposed for secondary
 // dex files only. Primary apks are analyzed in PackageManager and installd
 // does not need to know if the compilation is forced or on what kind of storage
 // the dex files are.
-constexpr int DEXOPT_FORCE          = 1 << 7;
-constexpr int DEXOPT_STORAGE_CE     = 1 << 8;
-constexpr int DEXOPT_STORAGE_DE     = 1 << 9;
+constexpr int DEXOPT_FORCE          = 1 << 6;
+constexpr int DEXOPT_STORAGE_CE     = 1 << 7;
+constexpr int DEXOPT_STORAGE_DE     = 1 << 8;
 
 /* all known values for dexopt flags */
 constexpr int DEXOPT_MASK =
     DEXOPT_PUBLIC
-    | DEXOPT_SAFEMODE
     | DEXOPT_DEBUGGABLE
     | DEXOPT_BOOTCOMPLETE
     | DEXOPT_PROFILE_GUIDED
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index ff838ce..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);
@@ -472,7 +491,8 @@
                 case 6: {
                     // Version 1 had:
                     constexpr int OLD_DEXOPT_PUBLIC         = 1 << 1;
-                    constexpr int OLD_DEXOPT_SAFEMODE       = 1 << 2;
+                    // Note: DEXOPT_SAFEMODE has been removed.
+                    // constexpr int OLD_DEXOPT_SAFEMODE       = 1 << 2;
                     constexpr int OLD_DEXOPT_DEBUGGABLE     = 1 << 3;
                     constexpr int OLD_DEXOPT_BOOTCOMPLETE   = 1 << 4;
                     constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
@@ -480,7 +500,6 @@
                     int input = atoi(param);
                     package_parameters_.dexopt_flags =
                             ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
-                            ReplaceMask(input, OLD_DEXOPT_SAFEMODE, DEXOPT_SAFEMODE) |
                             ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
                             ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
                             ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
@@ -734,6 +753,10 @@
     }
 
     static const char* ParseNull(const char* arg) {
+        // b/38186355. Revert soon.
+        if (strcmp(arg, "!null") == 0) {
+            return nullptr;
+        }
         return (strcmp(arg, "!") == 0) ? nullptr : arg;
     }
 
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index 174ce77..aed068c 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -146,7 +146,7 @@
     EXPECT_EQ(0, exists("com.example/cache/foo/one"));
     EXPECT_EQ(0, exists("com.example/cache/foo/two"));
 
-    service->freeCache(testUuid, kTbInBytes,
+    service->freeCache(testUuid, kTbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(0, exists("com.example/normal"));
@@ -163,13 +163,13 @@
     touch("com.example/cache/foo/one", kMbInBytes, 60);
     touch("com.example/cache/foo/two", kMbInBytes, 120);
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
     EXPECT_EQ(0, exists("com.example/cache/foo/two"));
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
@@ -197,7 +197,7 @@
     EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar1"));
     EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar2"));
 
-    service->freeCache(testUuid, kTbInBytes,
+    service->freeCache(testUuid, kTbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
@@ -219,7 +219,7 @@
 
     setxattr("com.example/cache/foo", "user.cache_group");
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
@@ -264,7 +264,7 @@
     setxattr("com.example/cache/tomb", "user.cache_tombstone");
     setxattr("com.example/cache/tomb/group", "user.cache_group");
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/file1"));
@@ -285,7 +285,7 @@
     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, size("com.example/cache/group/file1"));
@@ -306,7 +306,7 @@
     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
 
-    service->freeCache(testUuid, kTbInBytes,
+    service->freeCache(testUuid, kTbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, size("com.example/cache/group/file1"));
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 4a1f333..34818f6 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -54,10 +54,12 @@
     return false;
 }
 
-bool create_cache_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
-        const char *src ATTRIBUTE_UNUSED,
-        const char *instruction_set ATTRIBUTE_UNUSED) {
-    return false;
+bool create_cache_path(char path[PKG_PATH_MAX],
+        const char *src,
+        const char *instruction_set) {
+    // Not really a valid path but it's good enough for testing.
+    sprintf(path,"/data/dalvik-cache/%s/%s", instruction_set, src);
+    return true;
 }
 
 static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
@@ -151,5 +153,13 @@
     EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
 }
 
+TEST_F(ServiceTest, RmDexNoDalvikCache) {
+    LOG(INFO) << "RmDexNoDalvikCache";
+
+    // Try to remove a non existing dalvik cache dex. The call should be
+    // successful because there's nothing to remove.
+    EXPECT_TRUE(service->rmdex("com.example", "arm").isOk());
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index dd94da9..070da84 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -33,6 +33,9 @@
 #define MEASURE_DEBUG 0
 #define FIXUP_DEBUG 0
 
+#define BYPASS_QUOTA 0
+#define BYPASS_SDCARDFS 0
+
 namespace android {
 namespace installd {
 
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 4740202..38647eb 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",
@@ -25,7 +25,44 @@
         "android.hidl.manager@1.0",
     ],
     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..710b6e4
--- /dev/null
+++ b/cmds/lshal/ListCommand.cpp
@@ -0,0 +1,705 @@
+/*
+ * 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) {
+        mOut << table.description << std::endl;
+        mOut << std::left;
+        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));
+            }
+        }
+        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' },
+        { 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 '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..42c965f
--- /dev/null
+++ b/cmds/lshal/ListCommand.h
@@ -0,0 +1,101 @@
+/*
+ * 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;
+
+    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(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 85d8938..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,407 +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
-        << "           --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) {
@@ -825,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/PipeRelay.cpp b/cmds/lshal/PipeRelay.cpp
index c7b29df..54d19f6 100644
--- a/cmds/lshal/PipeRelay.cpp
+++ b/cmds/lshal/PipeRelay.cpp
@@ -70,7 +70,6 @@
     mInitCheck = mThread->run("RelayThread");
 }
 
-// static
 void PipeRelay::CloseFd(int *fd) {
     if (*fd >= 0) {
         close(*fd);
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/cmds/vr/pose/Android.mk b/cmds/vr/pose/Android.mk
deleted file mode 100644
index 8be3214..0000000
--- a/cmds/vr/pose/Android.mk
+++ /dev/null
@@ -1,35 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
-  pose.cpp
-
-staticLibraries := \
-  libdvrcommon \
-  libvrsensor \
-  libpdx_default_transport \
-
-sharedLibraries := \
-  libcutils \
-  liblog
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := pose
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/vr/pose/pose.cpp b/cmds/vr/pose/pose.cpp
deleted file mode 100644
index 2288a86..0000000
--- a/cmds/vr/pose/pose.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-// pose is a utility to query and manipulate the current pose via the pose
-// service.
-
-#include <cmath>
-#include <cstdio>
-#include <iomanip>
-#include <iostream>
-#include <regex>
-#include <vector>
-
-#include <private/dvr/types.h>
-#include <dvr/pose_client.h>
-
-using android::dvr::vec3;
-using android::dvr::quat;
-
-namespace {
-
-// Prints usage information to stderr.
-void PrintUsage(const char* executable_name) {
-  std::cerr << "Usage: " << executable_name
-            << " [--identity|--set=...|--unfreeze]\n"
-            << "\n"
-            << "  no arguments: display the current pose.\n"
-            << "  --identity: freeze the pose to the identity pose.\n"
-            << "  --set=rx,ry,rz,rw[,px,py,pz]: freeze the pose to the given "
-               "state. rx,ry,rz,rw are interpreted as rotation quaternion. "
-               " px, py, pz as position (0,0,0 if omitted).\n"
-            << "  --mode=mode: sets mode to one of normal, head_turn:slow, "
-               "head_turn:fast, rotate:slow, rotate:medium, rotate:fast, "
-               "circle_strafe.\n"
-            << "  --unfreeze: sets the mode to normal.\n"
-            << "  --log_controller=[true|false]: starts and stops controller"
-               " logs\n"
-            << std::endl;
-}
-
-// If return_code is negative, print out its corresponding string description
-// and exit the program with a non-zero exit code.
-void ExitIfNegative(int return_code) {
-  if (return_code < 0) {
-    std::cerr << "Error: " << strerror(-return_code) << std::endl;
-    std::exit(1);
-  }
-}
-
-// Parses the following command line flags:
-// --identity
-// --set=rx,ry,rz,rw[,px,py,pz]
-// Returns false if parsing fails.
-bool ParseState(const std::string& arg, DvrPoseState* out_state) {
-  if (arg == "--identity") {
-    *out_state = {.head_from_start_rotation = {0.f, 0.f, 0.f, 1.f},
-                  .head_from_start_translation = {0.f, 0.f, 0.f},
-                  .timestamp_ns = 0,
-                  .sensor_from_start_rotation_velocity = {0.f, 0.f, 0.f}};
-    return true;
-  }
-
-  const std::string prefix("--set=");
-  if (arg.size() < 6 || arg.compare(0, prefix.size(), prefix) != 0) {
-    return false;
-  }
-
-  // Tokenize by ','.
-  std::regex split_by_comma("[,]+");
-  std::sregex_token_iterator token_it(arg.begin() + prefix.size(), arg.end(),
-                                      split_by_comma,
-                                      -1 /* return inbetween parts */);
-  std::sregex_token_iterator token_end;
-
-  // Convert to float and store values.
-  std::vector<float> values;
-  for (; token_it != token_end; ++token_it) {
-    std::string token = *(token_it);
-    float value = 0.f;
-    if (sscanf(token.c_str(), "%f", &value) != 1) {
-      std::cerr << "Unable to parse --set value as float: " << token
-                << std::endl;
-      return false;
-    } else {
-      values.push_back(value);
-    }
-  }
-
-  if (values.size() != 4 && values.size() != 7) {
-    std::cerr << "Unable to parse --set, expected either 4 or 7 of values."
-              << std::endl;
-    return false;
-  }
-
-  float norm2 = values[0] * values[0] + values[1] * values[1] +
-                values[2] * values[2] + values[3] * values[3];
-  if (std::abs(norm2 - 1.f) > 1e-4) {
-    if (norm2 < 1e-8) {
-      std::cerr << "--set quaternion norm close to zero." << std::endl;
-      return false;
-    }
-    float norm = std::sqrt(norm2);
-    values[0] /= norm;
-    values[1] /= norm;
-    values[2] /= norm;
-    values[3] /= norm;
-  }
-
-  out_state->head_from_start_rotation = {values[0], values[1], values[2],
-                                         values[3]};
-
-  if (values.size() == 7) {
-    out_state->head_from_start_translation = {values[4], values[5], values[6]};
-  } else {
-    out_state->head_from_start_translation = {0.f, 0.f, 0.f};
-  }
-
-  out_state->timestamp_ns = 0;
-  out_state->sensor_from_start_rotation_velocity = {0.f, 0.f, 0.f};
-
-  return true;
-}
-
-// Parses the command line flag --mode.
-// Returns false if parsing fails.
-bool ParseSetMode(const std::string& arg, DvrPoseMode* mode) {
-  const std::string prefix("--mode=");
-  if (arg.size() < prefix.size() ||
-      arg.compare(0, prefix.size(), prefix) != 0) {
-    return false;
-  }
-
-  std::string value = arg.substr(prefix.size());
-
-  if (value == "normal") {
-    *mode = DVR_POSE_MODE_6DOF;
-    return true;
-  } else if (value == "head_turn:slow") {
-    *mode = DVR_POSE_MODE_MOCK_HEAD_TURN_SLOW;
-    return true;
-  } else if (value == "head_turn:fast") {
-    *mode = DVR_POSE_MODE_MOCK_HEAD_TURN_FAST;
-    return true;
-  } else if (value == "rotate:slow") {
-    *mode = DVR_POSE_MODE_MOCK_ROTATE_SLOW;
-    return true;
-  } else if (value == "rotate:medium") {
-    *mode = DVR_POSE_MODE_MOCK_ROTATE_MEDIUM;
-    return true;
-  } else if (value == "rotate:fast") {
-    *mode = DVR_POSE_MODE_MOCK_ROTATE_FAST;
-    return true;
-  } else if (value == "circle_strafe") {
-    *mode = DVR_POSE_MODE_MOCK_CIRCLE_STRAFE;
-    return true;
-  } else {
-    return false;
-  }
-}
-
-// Parses the command line flag --controller_log.
-// Returns false if parsing fails.
-bool ParseLogController(const std::string& arg, bool* log_enabled) {
-  const std::string prefix("--log_controller=");
-  if (arg.size() < prefix.size() ||
-      arg.compare(0, prefix.size(), prefix) != 0) {
-    return false;
-  }
-
-  std::string value = arg.substr(prefix.size());
-
-  if (value == "false") {
-    *log_enabled = false;
-    return true;
-  } else if (value == "true") {
-    *log_enabled = true;
-    return true;
-  } else {
-    return false;
-  }
-}
-
-// The different actions that the tool can perform.
-enum class Action {
-  Query,                 // Query the current pose.
-  Set,                   // Set the pose and freeze.
-  Unfreeze,              // Set the pose mode to normal.
-  SetMode,               // Sets the pose mode.
-  LogController,         // Start/stop controller logging in sensord.
-};
-
-// The action to perform when no arguments are passed to the tool.
-constexpr Action kDefaultAction = Action::Query;
-
-}  // namespace
-
-int main(int argc, char** argv) {
-  Action action = kDefaultAction;
-  DvrPoseState state;
-  DvrPoseMode pose_mode = DVR_POSE_MODE_6DOF;
-  bool log_controller = false;
-
-  // Parse command-line arguments.
-  for (int i = 1; i < argc; ++i) {
-    const std::string arg = argv[i];
-    if (ParseState(arg, &state) && action == kDefaultAction) {
-      action = Action::Set;
-    } else if (arg == "--unfreeze" && action == kDefaultAction) {
-      action = Action::Unfreeze;
-    } else if (ParseSetMode(arg, &pose_mode) && action == kDefaultAction) {
-      action = Action::SetMode;
-    } else if (ParseLogController(arg, &log_controller)) {
-      action = Action::LogController;
-    } else {
-      PrintUsage(argv[0]);
-      return 1;
-    }
-  }
-
-  auto pose_client = dvrPoseCreate();
-  if (!pose_client) {
-    std::cerr << "Unable to create pose client." << std::endl;
-    return 1;
-  }
-
-  switch (action) {
-    case Action::Query: {
-      ExitIfNegative(dvrPosePoll(pose_client, &state));
-      uint64_t timestamp = state.timestamp_ns;
-      const auto& rotation = state.head_from_start_rotation;
-      const auto& translation = state.head_from_start_translation;
-      const auto& rotation_velocity = state.sensor_from_start_rotation_velocity;
-      quat q(rotation.w, rotation.x, rotation.y, rotation.z);
-      vec3 angles = q.matrix().eulerAngles(0, 1, 2);
-      angles = angles * 180.f / M_PI;
-      vec3 x = q * vec3(1.0f, 0.0f, 0.0f);
-      vec3 y = q * vec3(0.0f, 1.0f, 0.0f);
-      vec3 z = q * vec3(0.0f, 0.0f, 1.0f);
-
-      std::cout << "timestamp_ns: " << timestamp << std::endl
-                << "rotation_quaternion: " << rotation.x << ", " << rotation.y
-                << ", " << rotation.z << ", " << rotation.w << std::endl
-                << "rotation_angles: " << angles.x() << ", " << angles.y()
-                << ", " << angles.z() << std::endl
-                << "translation: " << translation.x << ", " << translation.y
-                << ", " << translation.z << std::endl
-                << "rotation_velocity: " << rotation_velocity.x << ", "
-                << rotation_velocity.y << ", " << rotation_velocity.z
-                << std::endl
-                << "axes: " << std::setprecision(3)
-                << "x(" << x.x() << ", " << x.y() << ", " << x.z() << "), "
-                << "y(" << y.x() << ", " << y.y() << ", " << y.z() << "), "
-                << "z(" << z.x() << ", " << z.y() << ", " << z.z() << "), "
-                << std::endl;
-      break;
-    }
-    case Action::Set: {
-      ExitIfNegative(dvrPoseFreeze(pose_client, &state));
-      break;
-    }
-    case Action::Unfreeze: {
-      ExitIfNegative(dvrPoseSetMode(pose_client, DVR_POSE_MODE_6DOF));
-      break;
-    }
-    case Action::SetMode: {
-      ExitIfNegative(dvrPoseSetMode(pose_client, pose_mode));
-      break;
-    }
-    case Action::LogController: {
-      ExitIfNegative(
-          dvrPoseLogController(pose_client, log_controller));
-      break;
-    }
-  }
-
-  dvrPoseDestroy(pose_client);
-}
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 8f8a931..46d2f4b 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -86,21 +86,20 @@
  *
  * It is a common use case to create a shared memory region, map it read/write locally to intialize
  * content, and then send the shared memory to another process with read only access. Code example
- * as below (error handling ommited).
+ * as below (error handling omited).
  *
- * \code{.c}
- *   int fd = ASharedMemory_create("memory", 128);
  *
- *   // By default it has PROT_READ | PROT_WRITE | PROT_EXEC.
- *   char *buffer = (char *) mmap(NULL, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ *     int fd = ASharedMemory_create("memory", 128);
  *
- *   strcpy(buffer, "This is an example."); // trivially initialize content
+ *     // By default it has PROT_READ | PROT_WRITE | PROT_EXEC.
+ *     char *buffer = (char *) mmap(NULL, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  *
- *   // limit access to read only
- *   ASharedMemory_setProt(fd, PROT_READ);
+ *     strcpy(buffer, "This is an example."); // trivially initialize content
  *
- *   // share fd with another process here and the other process can only map with PROT_READ.
- * \endcode
+ *     // limit access to read only
+ *     ASharedMemory_setProt(fd, PROT_READ);
+ *
+ *     // share fd with another process here and the other process can only map with PROT_READ.
  *
  * \param fd   file descriptor of the shared memory region.
  * \param prot any bitwise-or'ed combination of PROT_READ, PROT_WRITE, PROT_EXEC denoting
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
index 834dcbd..009dc52 100644
--- a/include/audiomanager/AudioManager.h
+++ b/include/audiomanager/AudioManager.h
@@ -26,6 +26,9 @@
 typedef enum {
     PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE = 11,
     PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD = 12,
+    PLAYER_TYPE_AAUDIO = 13,
+    PLAYER_TYPE_HW_SOURCE = 14,
+    PLAYER_TYPE_EXTERNAL_PROXY = 15,
 } player_type_t;
 
 typedef enum {
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 8b1d106..e8dc83e 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -160,6 +160,9 @@
 
     status_t getUniqueId(uint64_t* outId) const;
 
+    // Returns the CLOCK_MONOTONIC start time of the last dequeueBuffer call
+    nsecs_t getLastDequeueStartTime() const;
+
 protected:
     virtual ~Surface();
 
@@ -421,6 +424,9 @@
     nsecs_t mLastDequeueDuration = 0;
     nsecs_t mLastQueueDuration = 0;
 
+    // Stores the time right before we call IGBP::dequeueBuffer
+    nsecs_t mLastDequeueStartTime = 0;
+
     Condition mQueueBufferCondition;
 
     uint64_t mNextFrameNumber = 1;
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
new file mode 100644
index 0000000..86da4d3
--- /dev/null
+++ b/include/input/DisplayViewport.h
@@ -0,0 +1,104 @@
+/*
+ * 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 _LIBINPUT_DISPLAY_VIEWPORT_H
+#define _LIBINPUT_DISPLAY_VIEWPORT_H
+
+#include <ui/DisplayInfo.h>
+#include <input/Input.h>
+
+namespace android {
+
+/*
+ * Describes how coordinates are mapped on a physical display.
+ * See com.android.server.display.DisplayViewport.
+ */
+struct DisplayViewport {
+    int32_t displayId; // -1 if invalid
+    int32_t orientation;
+    int32_t logicalLeft;
+    int32_t logicalTop;
+    int32_t logicalRight;
+    int32_t logicalBottom;
+    int32_t physicalLeft;
+    int32_t physicalTop;
+    int32_t physicalRight;
+    int32_t physicalBottom;
+    int32_t deviceWidth;
+    int32_t deviceHeight;
+    String8 uniqueId;
+
+    DisplayViewport() :
+            displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
+            logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
+            physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
+            deviceWidth(0), deviceHeight(0) {
+    }
+
+    bool operator==(const DisplayViewport& other) const {
+        return displayId == other.displayId
+                && orientation == other.orientation
+                && logicalLeft == other.logicalLeft
+                && logicalTop == other.logicalTop
+                && logicalRight == other.logicalRight
+                && logicalBottom == other.logicalBottom
+                && physicalLeft == other.physicalLeft
+                && physicalTop == other.physicalTop
+                && physicalRight == other.physicalRight
+                && physicalBottom == other.physicalBottom
+                && deviceWidth == other.deviceWidth
+                && deviceHeight == other.deviceHeight
+                && uniqueId == other.uniqueId;
+    }
+
+    bool operator!=(const DisplayViewport& other) const {
+        return !(*this == other);
+    }
+
+    inline bool isValid() const {
+        return displayId >= 0;
+    }
+
+    void setNonDisplayViewport(int32_t width, int32_t height) {
+        displayId = ADISPLAY_ID_NONE;
+        orientation = DISPLAY_ORIENTATION_0;
+        logicalLeft = 0;
+        logicalTop = 0;
+        logicalRight = width;
+        logicalBottom = height;
+        physicalLeft = 0;
+        physicalTop = 0;
+        physicalRight = width;
+        physicalBottom = height;
+        deviceWidth = width;
+        deviceHeight = height;
+        uniqueId.clear();
+    }
+};
+
+/**
+ * Describes the different type of viewports supported by input flinger.
+ * Keep in sync with values in InputManagerService.java.
+ */
+enum class ViewportType : int32_t {
+    VIEWPORT_INTERNAL = 1,
+    VIEWPORT_EXTERNAL = 2,
+    VIEWPORT_VIRTUAL = 3,
+};
+
+} // namespace android
+
+#endif // _LIBINPUT_DISPLAY_VIEWPORT_H
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 3230189..3c81f0f 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -44,10 +44,12 @@
         NAP                          = IBinder::FIRST_CALL_TRANSACTION + 10,
         IS_INTERACTIVE               = IBinder::FIRST_CALL_TRANSACTION + 11,
         IS_POWER_SAVE_MODE           = IBinder::FIRST_CALL_TRANSACTION + 12,
-        SET_POWER_SAVE_MODE          = IBinder::FIRST_CALL_TRANSACTION + 13,
-        REBOOT                       = IBinder::FIRST_CALL_TRANSACTION + 14,
-        SHUTDOWN                     = IBinder::FIRST_CALL_TRANSACTION + 15,
-        CRASH                        = IBinder::FIRST_CALL_TRANSACTION + 16,
+        GET_POWER_SAVE_STATE         = IBinder::FIRST_CALL_TRANSACTION + 13,
+        SET_POWER_SAVE_MODE          = IBinder::FIRST_CALL_TRANSACTION + 14,
+        REBOOT                       = IBinder::FIRST_CALL_TRANSACTION + 17,
+        REBOOT_SAFE_MODE             = IBinder::FIRST_CALL_TRANSACTION + 18,
+        SHUTDOWN                     = IBinder::FIRST_CALL_TRANSACTION + 19,
+        CRASH                        = IBinder::FIRST_CALL_TRANSACTION + 20,
     };
 
     DECLARE_META_INTERFACE(PowerManager)
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d0cd8f2..e832961 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -338,6 +338,11 @@
     gDisableBackgroundScheduling = disable;
 }
 
+bool IPCThreadState::backgroundSchedulingDisabled()
+{
+    return gDisableBackgroundScheduling;
+}
+
 sp<ProcessState> IPCThreadState::process()
 {
     return mProcess;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 39bb078..aec8f10 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -211,7 +211,14 @@
 {
     flat_binder_object obj;
 
-    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+    if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
+        /* minimum priority for all nodes is nice 0 */
+        obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
+    } else {
+        /* minimum priority for all nodes is MAX_NICE(19) */
+        obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+    }
+
     if (binder != NULL) {
         IBinder *local = binder->localBinder();
         if (!local) {
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 7b826d6..245607e 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -83,6 +83,7 @@
     // in to it but doesn't want to acquire locks in its services while in
     // the background.
     static  void                disableBackgroundScheduling(bool disable);
+            bool                backgroundSchedulingDisabled();
 
             // Call blocks until the number of executing binder threads is less than
             // the maximum number of binder threads threads allowed for this process.
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 8159aef..3d57769 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -511,7 +511,7 @@
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
 
-            if (graphicBuffer != NULL && !mCore->mIsAbandoned) {
+            if (error == NO_ERROR && !mCore->mIsAbandoned) {
                 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
                 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
             }
@@ -519,7 +519,7 @@
             mCore->mIsAllocating = false;
             mCore->mIsAllocatingCondition.broadcast();
 
-            if (graphicBuffer == NULL) {
+            if (error != NO_ERROR) {
                 mCore->mFreeSlots.insert(*outSlot);
                 mCore->clearBufferSlotLocked(*outSlot);
                 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
@@ -732,6 +732,7 @@
     mSlots[*outSlot].mFence = Fence::NO_FENCE;
     mSlots[*outSlot].mRequestBufferCalled = true;
     mSlots[*outSlot].mAcquireCalled = false;
+    mSlots[*outSlot].mNeedsReallocation = false;
     mCore->mActiveBuffers.insert(found);
     VALIDATE_CONSISTENCY();
 
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 74117c8..bca645f 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..7b2b5c3 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;
@@ -498,13 +501,13 @@
 
     int buf = -1;
     sp<Fence> fence;
-    nsecs_t now = systemTime();
+    nsecs_t startTime = systemTime();
 
     FrameEventHistoryDelta frameTimestamps;
     status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
             reqWidth, reqHeight, reqFormat, reqUsage,
             enableFrameTimestamps ? &frameTimestamps : nullptr);
-    mLastDequeueDuration = systemTime() - now;
+    mLastDequeueDuration = systemTime() - startTime;
 
     if (result < 0) {
         ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
@@ -513,8 +516,17 @@
         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);
 
+    // Write this while holding the mutex
+    mLastDequeueStartTime = startTime;
+
     sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
 
     // this should never happen
@@ -530,7 +542,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 +1213,9 @@
     }
 
     Mutex::Autolock lock(mMutex);
+    if (mReportRemovedBuffers) {
+        mRemovedBuffers.clear();
+    }
 
     sp<GraphicBuffer> buffer(NULL);
     sp<Fence> fence(NULL);
@@ -1218,13 +1232,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 +1251,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 +1267,6 @@
         return result;
     }
     if (mReportRemovedBuffers && (mSlots[attachedSlot].buffer != nullptr)) {
-        mRemovedBuffers.clear();
         mRemovedBuffers.push_back(mSlots[attachedSlot].buffer);
     }
     mSlots[attachedSlot].buffer = graphicBuffer;
@@ -1690,6 +1702,11 @@
     return mGraphicBufferProducer->getUniqueId(outId);
 }
 
+nsecs_t Surface::getLastDequeueStartTime() const {
+    Mutex::Autolock lock(mMutex);
+    return mLastDequeueStartTime;
+}
+
 status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out) {
     if (out == nullptr) {
         ALOGE("%s: out must not be null!", __FUNCTION__);
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index eafd296..fda5b94 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -1141,7 +1141,7 @@
 
 status_t H2BGraphicBufferProducer::setSidebandStream(
         const sp<NativeHandle>& stream) {
-    return toStatusT(mBase->setSidebandStream(stream->handle()));
+    return toStatusT(mBase->setSidebandStream(stream == nullptr ? nullptr : stream->handle()));
 }
 
 void H2BGraphicBufferProducer::allocateBuffers(uint32_t width, uint32_t height,
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 192bfc8..7efdb14 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -14,6 +14,7 @@
         "FillBuffer.cpp",
         "GLTest.cpp",
         "IGraphicBufferProducer_test.cpp",
+        "Malicious.cpp",
         "MultiTextureConsumer_test.cpp",
         "StreamSplitter_test.cpp",
         "SurfaceTextureClient_test.cpp",
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
new file mode 100644
index 0000000..7ecf08c
--- /dev/null
+++ b/libs/gui/tests/Malicious.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 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 <gui/BufferQueue.h>
+#include <gui/IProducerListener.h>
+#include <gui/Surface.h>
+
+#include <android/native_window.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace test {
+
+class ProxyBQP : public BnGraphicBufferProducer {
+public:
+    ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
+
+    // Pass through calls to mProducer
+    status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
+        return mProducer->requestBuffer(slot, buf);
+    }
+    status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override {
+        return mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+    }
+    status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
+    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
+                           uint32_t usage, FrameEventHistoryDelta* outTimestamps) override {
+        return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outTimestamps);
+    }
+    status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
+    status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
+        return mProducer->detachNextBuffer(outBuffer, outFence);
+    }
+    status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) override {
+        return mProducer->attachBuffer(outSlot, buffer);
+    }
+    status_t queueBuffer(int slot, const QueueBufferInput& input,
+                         QueueBufferOutput* output) override {
+        return mProducer->queueBuffer(slot, input, output);
+    }
+    status_t cancelBuffer(int slot, const sp<Fence>& fence) override {
+        return mProducer->cancelBuffer(slot, fence);
+    }
+    int query(int what, int* value) override { return mProducer->query(what, value); }
+    status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
+                     QueueBufferOutput* output) override {
+        return mProducer->connect(listener, api, producerControlledByApp, output);
+    }
+    status_t disconnect(int api, DisconnectMode mode) override {
+        return mProducer->disconnect(api, mode);
+    }
+    status_t setSidebandStream(const sp<NativeHandle>& stream) override {
+        return mProducer->setSidebandStream(stream);
+    }
+    void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
+                         uint32_t usage) override {
+        mProducer->allocateBuffers(width, height, format, usage);
+    }
+    status_t allowAllocation(bool allow) override { return mProducer->allowAllocation(allow); }
+    status_t setGenerationNumber(uint32_t generationNumber) override {
+        return mProducer->setGenerationNumber(generationNumber);
+    }
+    String8 getConsumerName() const override { return mProducer->getConsumerName(); }
+    status_t setSharedBufferMode(bool sharedBufferMode) override {
+        return mProducer->setSharedBufferMode(sharedBufferMode);
+    }
+    status_t setAutoRefresh(bool autoRefresh) override {
+        return mProducer->setAutoRefresh(autoRefresh);
+    }
+    status_t setDequeueTimeout(nsecs_t timeout) override {
+        return mProducer->setDequeueTimeout(timeout);
+    }
+    status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
+                                 float outTransformMatrix[16]) override {
+        return mProducer->getLastQueuedBuffer(outBuffer, outFence, outTransformMatrix);
+    }
+    void getFrameTimestamps(FrameEventHistoryDelta*) override {}
+    status_t getUniqueId(uint64_t* outId) const override { return mProducer->getUniqueId(outId); }
+
+protected:
+    sp<IGraphicBufferProducer> mProducer;
+};
+
+class MaliciousBQP : public ProxyBQP {
+public:
+    MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
+
+    void beMalicious(int32_t value) { mMaliciousValue = value; }
+
+    void setExpectedSlot(int32_t slot) { mExpectedSlot = slot; }
+
+    // Override dequeueBuffer, optionally corrupting the returned slot number
+    status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
+                           PixelFormat format, uint32_t usage,
+                           FrameEventHistoryDelta* outTimestamps) override {
+        EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
+                  mProducer->dequeueBuffer(buf, fence, width, height, format, usage,
+                                           outTimestamps));
+        EXPECT_EQ(mExpectedSlot, *buf);
+        if (mMaliciousValue != 0) {
+            *buf = mMaliciousValue;
+            return NO_ERROR;
+        } else {
+            return BUFFER_NEEDS_REALLOCATION;
+        }
+    }
+
+private:
+    int32_t mMaliciousValue = 0;
+    int32_t mExpectedSlot = 0;
+};
+
+class DummyListener : public BnConsumerListener {
+public:
+    void onFrameAvailable(const BufferItem&) override {}
+    void onBuffersReleased() override {}
+    void onSidebandStreamChanged() override {}
+};
+
+sp<MaliciousBQP> getMaliciousBQP() {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    sp<IConsumerListener> listener = new DummyListener;
+    consumer->consumerConnect(listener, false);
+
+    sp<MaliciousBQP> malicious = new MaliciousBQP(producer);
+    return malicious;
+}
+
+TEST(Malicious, Bug36991414Max) {
+    sp<MaliciousBQP> malicious = getMaliciousBQP();
+    sp<Surface> surface = new Surface(malicious);
+
+    ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+    ANativeWindow_Buffer buffer;
+    ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+    ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+    malicious->setExpectedSlot(1);
+    malicious->beMalicious(std::numeric_limits<int32_t>::max());
+    ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414Min) {
+    sp<MaliciousBQP> malicious = getMaliciousBQP();
+    sp<Surface> surface = new Surface(malicious);
+
+    ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+    ANativeWindow_Buffer buffer;
+    ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+    ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+    malicious->setExpectedSlot(1);
+    malicious->beMalicious(std::numeric_limits<int32_t>::min());
+    ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414NegativeOne) {
+    sp<MaliciousBQP> malicious = getMaliciousBQP();
+    sp<Surface> surface = new Surface(malicious);
+
+    ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+    ANativeWindow_Buffer buffer;
+    ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+    ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+    malicious->setExpectedSlot(1);
+    malicious->beMalicious(-1);
+    ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414NumSlots) {
+    sp<MaliciousBQP> malicious = getMaliciousBQP();
+    sp<Surface> surface = new Surface(malicious);
+
+    ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+    ANativeWindow_Buffer buffer;
+    ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+    ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+    malicious->setExpectedSlot(1);
+    malicious->beMalicious(BufferQueueDefs::NUM_BUFFER_SLOTS);
+    ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+} // namespace test
+} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 08d6715..81820de 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,93 @@
     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);
+}
+
+TEST_F(SurfaceTest, TestGetLastDequeueStartTime) {
+    sp<ANativeWindow> anw(mSurface);
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU));
+
+    ANativeWindowBuffer* buffer = nullptr;
+    int32_t fenceFd = -1;
+
+    nsecs_t before = systemTime(CLOCK_MONOTONIC);
+    anw->dequeueBuffer(anw.get(), &buffer, &fenceFd);
+    nsecs_t after = systemTime(CLOCK_MONOTONIC);
+
+    nsecs_t lastDequeueTime = mSurface->getLastDequeueStartTime();
+    ASSERT_LE(before, lastDequeueTime);
+    ASSERT_GE(after, lastDequeueTime);
+}
 
 class FakeConsumer : public BnConsumerListener {
 public:
@@ -1496,4 +1584,4 @@
     EXPECT_EQ(-1, outDisplayPresentTime);
 }
 
-}
+} // namespace android
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/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/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index a12bdd7..5290dd5 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -21,6 +21,7 @@
 
 /**
  * @file native_window.h
+ * @brief API for accessing a native window.
  */
 
 #ifndef ANDROID_NATIVE_WINDOW_H
@@ -71,16 +72,16 @@
 
 struct ANativeWindow;
 /**
- * {@link ANativeWindow} is opaque type that provides access to a native window.
+ * Opaque type that provides access to a native window.
  *
- * A pointer can be obtained using ANativeWindow_fromSurface().
+ * A pointer can be obtained using {@link ANativeWindow_fromSurface()}.
  */
 typedef struct ANativeWindow ANativeWindow;
 
 /**
- * {@link ANativeWindow} is a struct that represents a windows buffer.
+ * Struct that represents a windows buffer.
  *
- * A pointer can be obtained using ANativeWindow_lock().
+ * A pointer can be obtained using {@link ANativeWindow_lock()}.
  */
 typedef struct ANativeWindow_Buffer {
     // The number of pixels that are show horizontally.
@@ -90,10 +91,10 @@
     int32_t height;
 
     // The number of *pixels* that a line in the buffer takes in
-    // memory.  This may be >= width.
+    // memory. This may be >= width.
     int32_t stride;
 
-    // The format of the buffer.  One of AHARDWAREBUFFER_FORMAT_*
+    // The format of the buffer. One of AHARDWAREBUFFER_FORMAT_*
     int32_t format;
 
     // The actual bits.
@@ -104,49 +105,53 @@
 } ANativeWindow_Buffer;
 
 /**
- * Acquire a reference on the given ANativeWindow object.  This prevents the object
+ * Acquire a reference on the given {@link ANativeWindow} object. This prevents the object
  * from being deleted until the reference is removed.
  */
 void ANativeWindow_acquire(ANativeWindow* window);
 
 /**
- * Remove a reference that was previously acquired with ANativeWindow_acquire().
+ * Remove a reference that was previously acquired with {@link ANativeWindow_acquire()}.
  */
 void ANativeWindow_release(ANativeWindow* window);
 
 /**
- * Return the current width in pixels of the window surface.  Returns a
- * negative value on error.
+ * Return the current width in pixels of the window surface.
+ *
+ * \return negative value on error.
  */
 int32_t ANativeWindow_getWidth(ANativeWindow* window);
 
 /**
- * Return the current height in pixels of the window surface.  Returns a
- * negative value on error.
+ * Return the current height in pixels of the window surface.
+ *
+ * \return a negative value on error.
  */
 int32_t ANativeWindow_getHeight(ANativeWindow* window);
 
 /**
- * Return the current pixel format (AHARDWAREBUFFER_FORMAT_*) of the window surface.  Returns a
- * negative value on error.
+ * Return the current pixel format (AHARDWAREBUFFER_FORMAT_*) of the window surface.
+ *
+ * \return a negative value on error.
  */
 int32_t ANativeWindow_getFormat(ANativeWindow* window);
 
 /**
  * Change the format and size of the window buffers.
  *
- * format: one of AHARDWAREBUFFER_FORMAT_ constants
- *
  * The width and height control the number of pixels in the buffers, not the
- * dimensions of the window on screen.  If these are different than the
- * window's physical size, then it buffer will be scaled to match that size
- * when compositing it to the screen.
+ * dimensions of the window on screen. If these are different than the
+ * window's physical size, then its buffer will be scaled to match that size
+ * when compositing it to the screen. The width and height must be either both zero
+ * or both non-zero.
  *
  * For all of these parameters, if 0 is supplied then the window's base
  * value will come back in force.
  *
- * width and height must be either both zero or both non-zero.
- *
+ * \param width width of the buffers in pixels.
+ * \param height height of the buffers in pixels.
+ * \param format one of AHARDWAREBUFFER_FORMAT_* constants.
+ * \return 0 for success, or a negative value on error.
  */
 int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
         int32_t width, int32_t height, int32_t format);
@@ -157,7 +162,9 @@
  * function, it contains the dirty region, that is, the region the caller
  * intends to redraw. When the function returns, inOutDirtyBounds is updated
  * with the actual area the caller needs to redraw -- this region is often
- * extended by ANativeWindow_lock.
+ * extended by {@link ANativeWindow_lock}.
+ *
+ * \return 0 for success, or a negative value on error.
  */
 int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
         ARect* inOutDirtyBounds);
@@ -165,6 +172,8 @@
 /**
  * Unlock the window's drawing surface after previously locking it,
  * posting the new buffer to the display.
+ *
+ * \return 0 for success, or a negative value on error.
  */
 int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
 
@@ -173,9 +182,8 @@
 /**
  * Set a transform that will be applied to future buffers posted to the window.
  *
- * @param transform combination of {@link ANativeWindowTransform} flags
- * @return 0 if successful
- * @return -EINVAL if @param transform is invalid
+ * \param transform combination of {@link ANativeWindowTransform} flags
+ * \return 0 for success, or -EINVAL if \p transform is invalid
  */
 int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform);
 
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 5ccf178..5edd664 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: [
@@ -61,6 +62,10 @@
         "UiConfig.cpp",
     ],
 
+    include_dirs: [
+        "frameworks/native/include",
+    ],
+
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
@@ -72,6 +77,7 @@
         "libhardware",
         "libhidlbase",
         "libhidltransport",
+        "libhwbinder",
         "libsync",
         "libutils",
         "liblog",
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/libs/ui/GraphicsEnv.cpp b/libs/ui/GraphicsEnv.cpp
index 1d20424..8182c07 100644
--- a/libs/ui/GraphicsEnv.cpp
+++ b/libs/ui/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/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 07c921f..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 {
 
@@ -53,44 +43,34 @@
 int BufferHubBuffer::ImportBuffer() {
   ATRACE_NAME("BufferHubBuffer::ImportBuffer");
 
-  Status<std::vector<NativeBufferHandle<LocalHandle>>> status =
-      InvokeRemoteMethod<BufferHubRPC::GetBuffers>();
+  Status<NativeBufferHandle<LocalHandle>> status =
+      InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
   if (!status) {
-    ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffers: %s",
+    ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
           status.GetErrorMessage().c_str());
     return -status.error();
-  } else if (status.get().empty()) {
-    ALOGE(
-        "BufferHubBuffer::ImportBuffer: Expected to receive at least one "
-        "buffer handle but got zero!");
+  } else if (status.get().id() < 0) {
+    ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!");
     return -EIO;
   }
 
-  auto buffer_handles = status.take();
+  auto buffer_handle = status.take();
 
-  // Stash the buffer id to replace the value in id_. All sub-buffers of a
-  // buffer hub buffer have the same id.
-  const int new_id = buffer_handles[0].id();
+  // Stash the buffer id to replace the value in id_.
+  const int new_id = buffer_handle.id();
 
-  // Import all of the buffers.
-  std::vector<IonBuffer> ion_buffers;
-  for (auto& handle : buffer_handles) {
-    const size_t i = &handle - buffer_handles.data();
-    ALOGD_IF(
-        TRACE,
-        "BufferHubBuffer::ImportBuffer: i=%zu id=%d FdCount=%zu IntCount=%zu",
-        i, handle.id(), handle.FdCount(), handle.IntCount());
+  // Import the buffer.
+  IonBuffer ion_buffer;
+  ALOGD_IF(
+      TRACE, "BufferHubBuffer::ImportBuffer: id=%d FdCount=%zu IntCount=%zu",
+      buffer_handle.id(), buffer_handle.FdCount(), buffer_handle.IntCount());
 
-    IonBuffer buffer;
-    const int ret = handle.Import(&buffer);
-    if (ret < 0)
-      return ret;
+  const int ret = buffer_handle.Import(&ion_buffer);
+  if (ret < 0)
+    return ret;
 
-    ion_buffers.emplace_back(std::move(buffer));
-  }
-
-  // If all imports succeed, replace the previous buffers and id.
-  slices_ = std::move(ion_buffers);
+  // If the import succeeds, replace the previous buffer and id.
+  buffer_ = std::move(ion_buffer);
   id_ = new_id;
   return 0;
 }
@@ -102,34 +82,23 @@
 }
 
 int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height,
-                          void** address, size_t index) {
-  return slices_[index].Lock(usage, x, y, width, height, address);
+                          void** address) {
+  return buffer_.Lock(usage, x, y, width, height, address);
 }
 
-int BufferHubBuffer::Unlock(size_t index) { return slices_[index].Unlock(); }
+int BufferHubBuffer::Unlock() { return buffer_.Unlock(); }
 
 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,
@@ -199,27 +168,24 @@
 }
 
 BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
-                               uint32_t usage, size_t metadata_size,
-                               size_t slice_count)
-    : BufferProducer(width, height, format, usage, usage, metadata_size,
-                     slice_count) {}
+                               uint32_t usage, size_t metadata_size)
+    : BufferProducer(width, height, format, usage, usage, metadata_size) {}
 
 BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
                                uint64_t producer_usage, uint64_t consumer_usage,
-                               size_t metadata_size, size_t slice_count)
+                               size_t metadata_size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
            "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
-           " metadata_size=%zu slice_count=%zu",
+           " metadata_size=%zu",
            event_fd(), width, height, format, producer_usage, consumer_usage,
-           metadata_size, slice_count);
+           metadata_size);
 
   // (b/37881101) Deprecate producer/consumer usage
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, (producer_usage | consumer_usage), metadata_size,
-      slice_count);
+      width, height, format, (producer_usage | consumer_usage), metadata_size);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -240,28 +206,27 @@
 BufferProducer::BufferProducer(const std::string& name, int user_id,
                                int group_id, uint32_t width, uint32_t height,
                                uint32_t format, uint32_t usage,
-                               size_t meta_size_bytes, size_t slice_count)
+                               size_t meta_size_bytes)
     : BufferProducer(name, user_id, group_id, width, height, format, usage,
-                     usage, meta_size_bytes, slice_count) {}
+                     usage, meta_size_bytes) {}
 
 BufferProducer::BufferProducer(const std::string& name, int user_id,
                                int group_id, uint32_t width, uint32_t height,
                                uint32_t format, uint64_t producer_usage,
-                               uint64_t consumer_usage, size_t meta_size_bytes,
-                               size_t slice_count)
+                               uint64_t consumer_usage, size_t meta_size_bytes)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
            "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
-           " consumer_usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
+           " consumer_usage=%" PRIx64 " meta_size_bytes=%zu",
            event_fd(), name.c_str(), user_id, group_id, width, height, format,
-           producer_usage, consumer_usage, meta_size_bytes, slice_count);
+           producer_usage, consumer_usage, meta_size_bytes);
 
   // (b/37881101) Deprecate producer/consumer usage
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
       name, user_id, group_id, width, height, format,
-      (producer_usage | consumer_usage), meta_size_bytes, slice_count);
+      (producer_usage | consumer_usage), meta_size_bytes);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -296,12 +261,11 @@
   const int height = 1;
   const int format = HAL_PIXEL_FORMAT_BLOB;
   const size_t meta_size_bytes = 0;
-  const size_t slice_count = 1;
 
   // (b/37881101) Deprecate producer/consumer usage
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, (producer_usage | consumer_usage), meta_size_bytes,
-      slice_count);
+      width, height, format, (producer_usage | consumer_usage),
+      meta_size_bytes);
   if (!status) {
     ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
           status.GetErrorMessage().c_str());
@@ -336,12 +300,11 @@
   const int height = 1;
   const int format = HAL_PIXEL_FORMAT_BLOB;
   const size_t meta_size_bytes = 0;
-  const size_t slice_count = 1;
 
   // (b/37881101) Deprecate producer/consumer usage
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
       name, user_id, group_id, width, height, format,
-      (producer_usage | consumer_usage), meta_size_bytes, slice_count);
+      (producer_usage | consumer_usage), meta_size_bytes);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create persistent "
@@ -445,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 dbd4110..be20e72 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -32,20 +32,11 @@
   // the usage is software then |addr| will be updated to point to the address
   // of the buffer in virtual memory. The caller should only access/modify the
   // pixels in the specified area. anything else is undefined behavior.
-  int Lock(int usage, int x, int y, int width, int height, void** addr,
-           size_t index);
+  int Lock(int usage, int x, int y, int width, int height, void** addr);
 
   // Must be called after Lock() when the caller has finished changing the
   // buffer.
-  int Unlock(size_t index);
-
-  // Helper for when index is 0.
-  int Lock(int usage, int x, int y, int width, int height, void** addr) {
-    return Lock(usage, x, y, width, height, addr, 0);
-  }
-
-  // Helper for when index is 0.
-  int Unlock() { return Unlock(0); }
+  int Unlock();
 
   // Gets a blob buffer that was created with BufferProducer::CreateBlob.
   // Locking and Unlocking is handled internally. There's no need to Unlock
@@ -85,38 +76,27 @@
   }
 
   native_handle_t* native_handle() const {
-    return const_cast<native_handle_t*>(slices_[0].handle());
-  }
-  // If index is greater than or equal to slice_count(), the result is
-  // undefined.
-  native_handle_t* native_handle(size_t index) const {
-    return const_cast<native_handle_t*>(slices_[index].handle());
+    return const_cast<native_handle_t*>(buffer_.handle());
   }
 
-  IonBuffer* buffer() { return &slices_[0]; }
-  const IonBuffer* buffer() const { return &slices_[0]; }
+  IonBuffer* buffer() { return &buffer_; }
+  const IonBuffer* buffer() const { return &buffer_; }
 
-  // If index is greater than or equal to slice_count(), the result is
-  // undefined.
-  IonBuffer* slice(size_t index) { return &slices_[index]; }
-  const IonBuffer* slice(size_t index) const { return &slices_[index]; }
-
-  int slice_count() const { return static_cast<int>(slices_.size()); }
   int id() const { return id_; }
 
   // The following methods return settings of the first buffer. Currently,
   // it is only possible to create multi-buffer BufferHubBuffers with the same
   // settings.
-  uint32_t width() const { return slices_[0].width(); }
-  uint32_t height() const { return slices_[0].height(); }
-  uint32_t stride() const { return slices_[0].stride(); }
-  uint32_t format() const { return slices_[0].format(); }
-  uint32_t usage() const { return slices_[0].usage(); }
-  uint32_t layer_count() const { return slices_[0].layer_count(); }
+  uint32_t width() const { return buffer_.width(); }
+  uint32_t height() const { return buffer_.height(); }
+  uint32_t stride() const { return buffer_.stride(); }
+  uint32_t format() const { return buffer_.format(); }
+  uint32_t usage() const { return buffer_.usage(); }
+  uint32_t layer_count() const { return buffer_.layer_count(); }
 
   // TODO(b/37881101) Clean up producer/consumer usage.
-  uint64_t producer_usage() const { return slices_[0].usage(); }
-  uint64_t consumer_usage() const { return slices_[0].usage(); }
+  uint64_t producer_usage() const { return buffer_.usage(); }
+  uint64_t consumer_usage() const { return buffer_.usage(); }
 
  protected:
   explicit BufferHubBuffer(LocalChannelHandle channel);
@@ -135,9 +115,7 @@
   // or any other functional purpose as a security precaution.
   int id_;
 
-  // A BufferHubBuffer may contain multiple slices of IonBuffers with same
-  // configurations.
-  std::vector<IonBuffer> slices_;
+  IonBuffer buffer_;
 };
 
 // This represents a writable buffer. Calling Post notifies all clients and
@@ -153,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(
@@ -224,11 +193,10 @@
 
   // Constructs a buffer with the given geometry and parameters.
   BufferProducer(uint32_t width, uint32_t height, uint32_t format,
-                 uint32_t usage, size_t metadata_size = 0,
-                 size_t slice_count = 1);
+                 uint32_t usage, size_t metadata_size = 0);
   BufferProducer(uint32_t width, uint32_t height, uint32_t format,
                  uint64_t producer_usage, uint64_t consumer_usage,
-                 size_t metadata_size, size_t slice_count);
+                 size_t metadata_size);
 
   // Constructs a persistent buffer with the given geometry and parameters and
   // binds it to |name| in one shot. If a persistent buffer with the same name
@@ -244,12 +212,11 @@
   // effective user or group id of the calling process.
   BufferProducer(const std::string& name, int user_id, int group_id,
                  uint32_t width, uint32_t height, uint32_t format,
-                 uint32_t usage, size_t metadata_size = 0,
-                 size_t slice_count = 1);
+                 uint32_t usage, size_t metadata_size = 0);
   BufferProducer(const std::string& name, int user_id, int group_id,
                  uint32_t width, uint32_t height, uint32_t format,
                  uint64_t producer_usage, uint64_t consumer_usage,
-                 size_t metadata_size, size_t slice_count);
+                 size_t meta_size_bytes);
 
   // Constructs a blob (flat) buffer with the given usage flags.
   BufferProducer(uint32_t usage, size_t size);
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index c6f0e1e..ffdc9e2 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -23,6 +23,7 @@
         stride_(buffer.stride()),
         width_(buffer.width()),
         height_(buffer.height()),
+        layer_count_(buffer.layer_count()),
         format_(buffer.format()),
         usage_(buffer.usage()) {
     // Populate the fd and int vectors: native_handle->data[] is an array of fds
@@ -47,9 +48,10 @@
     for (const auto& fd : fds_)
       fd_ints.push_back(fd.Get());
 
-    const int ret = buffer->Import(fd_ints.data(), fd_ints.size(),
-                                   opaque_ints_.data(), opaque_ints_.size(),
-                                   width_, height_, stride_, format_, usage_);
+    const int ret =
+        buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
+                       opaque_ints_.size(), width_, height_, layer_count_,
+                       stride_, format_, usage_);
     if (ret < 0)
       return ret;
 
@@ -72,6 +74,7 @@
   uint32_t stride_;
   uint32_t width_;
   uint32_t height_;
+  uint32_t layer_count_;
   uint32_t format_;
   uint64_t usage_;
   std::vector<int> opaque_ints_;
@@ -83,8 +86,8 @@
   }
 
   PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
-                           width_, height_, format_, usage_, opaque_ints_,
-                           fds_);
+                           width_, height_, layer_count_, format_, usage_,
+                           opaque_ints_, fds_);
 
   NativeBufferHandle(const NativeBufferHandle&) = delete;
   void operator=(const NativeBufferHandle&) = delete;
@@ -166,7 +169,6 @@
     kOpCreatePersistentBuffer,
     kOpGetPersistentBuffer,
     kOpGetBuffer,
-    kOpGetBuffers,
     kOpNewConsumer,
     kOpProducerMakePersistent,
     kOpProducerRemovePersistence,
@@ -192,19 +194,15 @@
   // Methods.
   PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
                     void(uint32_t width, uint32_t height, uint32_t format,
-                         uint64_t usage, size_t meta_size_bytes,
-                         size_t slice_count));
+                         uint64_t usage, size_t meta_size_bytes));
   PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
                     void(const std::string& name, int user_id, int group_id,
                          uint32_t width, uint32_t height, uint32_t format,
-                         uint64_t usage, size_t meta_size_bytes,
-                         size_t slice_count));
+                         uint64_t usage, size_t meta_size_bytes));
   PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
                     void(const std::string& name));
   PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
-                    NativeBufferHandle<LocalHandle>(unsigned index));
-  PDX_REMOTE_METHOD(GetBuffers, kOpGetBuffers,
-                    std::vector<NativeBufferHandle<LocalHandle>>(Void));
+                    NativeBufferHandle<LocalHandle>(Void));
   PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
                     void(const std::string& name, int user_id, int group_id));
@@ -229,9 +227,8 @@
   PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
                     kOpProducerQueueAllocateBuffers,
                     std::vector<std::pair<LocalChannelHandle, size_t>>(
-                        uint32_t width, uint32_t height, uint32_t format,
-                        uint64_t usage, size_t slice_count,
-                        size_t buffer_count));
+                        uint32_t width, uint32_t height, uint32_t layer_count,
+                        uint32_t format, uint64_t usage, size_t buffer_count));
   PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
                     void(size_t slot));
   PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers,
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index 72c8d81..0d337f7 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -16,8 +16,8 @@
   IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
             uint32_t stride, uint32_t format, uint64_t usage);
   IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
-            uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
-            uint32_t format, uint64_t usage);
+            uint32_t layer_count, uint32_t stride, uint32_t format,
+            uint64_t usage);
   ~IonBuffer();
 
   IonBuffer(IonBuffer&& other);
@@ -31,25 +31,29 @@
   // previous native handle if necessary. Returns 0 on success or a negative
   // errno code otherwise. If allocation fails the previous native handle is
   // left intact.
-  int Alloc(uint32_t width, uint32_t height, uint32_t format, uint64_t usage);
+  int Alloc(uint32_t width, uint32_t height, uint32_t layer_count,
+            uint32_t format, uint64_t usage);
 
   // Resets the underlying native handle and parameters, freeing the previous
   // native handle if necessary.
   void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
-             uint32_t stride, uint32_t format, uint64_t usage);
+             uint32_t layer_count, uint32_t stride, uint32_t format,
+             uint64_t usage);
 
   // Like Reset but also registers the native handle, which is necessary for
   // native handles received over IPC. Returns 0 on success or a negative errno
   // code otherwise. If import fails the previous native handle is left intact.
   int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
-             uint32_t stride, uint32_t format, uint64_t usage);
+             uint32_t layer_count, uint32_t stride, uint32_t format,
+             uint64_t usage);
 
   // Like Reset but imports a native handle from raw fd and int arrays. Returns
   // 0 on success or a negative errno code otherwise. If import fails the
   // previous native handle is left intact.
   int Import(const int* fd_array, int fd_count, const int* int_array,
-             int int_count, uint32_t width, uint32_t height, uint32_t stride,
-             uint32_t format, uint64_t usage);
+             int int_count, uint32_t width, uint32_t height,
+             uint32_t layer_count, uint32_t stride, uint32_t format,
+             uint64_t usage);
 
   // Duplicates the native handle underlying |other| and then imports it. This
   // is useful for creating multiple, independent views of the same Ion/Gralloc
@@ -72,7 +76,6 @@
     return buffer_.get() ? buffer_->getLayerCount() : 0;
   }
   uint32_t stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
-  uint32_t layer_stride() const { return 0; }
   uint32_t format() const {
     return buffer_.get() ? buffer_->getPixelFormat() : 0;
   }
diff --git a/libs/vr/libbufferhub/include/private/dvr/native_buffer.h b/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
index f9b6975..b4ef2f5 100644
--- a/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
@@ -52,40 +52,11 @@
   void operator=(NativeBuffer&) = delete;
 };
 
-// NativeBufferProducerSlice is an implementation of ANativeWindowBuffer backed
-// by a buffer slice of a BufferProducer.
-class NativeBufferProducerSlice
-    : public android::ANativeObjectBase<
-          ANativeWindowBuffer, NativeBufferProducerSlice,
-          android::LightRefBase<NativeBufferProducerSlice>> {
- public:
-  NativeBufferProducerSlice(const std::shared_ptr<BufferProducer>& buffer,
-                            int buffer_index)
-      : BASE(), buffer_(buffer) {
-    ANativeWindowBuffer::width = buffer_->width();
-    ANativeWindowBuffer::height = buffer_->height();
-    ANativeWindowBuffer::stride = buffer_->stride();
-    ANativeWindowBuffer::format = buffer_->format();
-    ANativeWindowBuffer::usage = buffer_->usage();
-    handle = buffer_->native_handle(buffer_index);
-  }
-
-  virtual ~NativeBufferProducerSlice() {}
-
- private:
-  friend class android::LightRefBase<NativeBufferProducerSlice>;
-
-  std::shared_ptr<BufferProducer> buffer_;
-
-  NativeBufferProducerSlice(const NativeBufferProducerSlice&) = delete;
-  void operator=(NativeBufferProducerSlice&) = delete;
-};
-
 // NativeBufferProducer is an implementation of ANativeWindowBuffer backed by a
 // BufferProducer.
 class NativeBufferProducer : public android::ANativeObjectBase<
-  ANativeWindowBuffer, NativeBufferProducer,
-  android::LightRefBase<NativeBufferProducer>> {
+                                 ANativeWindowBuffer, NativeBufferProducer,
+                                 android::LightRefBase<NativeBufferProducer>> {
  public:
   static constexpr int kEmptyFence = -1;
 
@@ -101,19 +72,6 @@
     ANativeWindowBuffer::format = buffer_->format();
     ANativeWindowBuffer::usage = buffer_->usage();
     handle = buffer_->native_handle();
-    for (int i = 0; i < buffer->slice_count(); ++i) {
-      // display == null means don't create an EGL image. This is used by our
-      // Vulkan code.
-      slices_.push_back(new NativeBufferProducerSlice(buffer, i));
-      if (display_ != nullptr) {
-        egl_images_.push_back(eglCreateImageKHR(
-            display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-            static_cast<ANativeWindowBuffer*>(slices_.back().get()), nullptr));
-        if (egl_images_.back() == EGL_NO_IMAGE_KHR) {
-          ALOGE("NativeBufferProducer: eglCreateImageKHR failed");
-        }
-      }
-    }
   }
 
   explicit NativeBufferProducer(const std::shared_ptr<BufferProducer>& buffer)
@@ -154,7 +112,6 @@
 
   std::shared_ptr<BufferProducer> buffer_;
   pdx::LocalHandle release_fence_;
-  std::vector<android::sp<NativeBufferProducerSlice>> slices_;
   std::vector<EGLImageKHR> egl_images_;
   uint32_t surface_buffer_index_;
   EGLDisplay display_;
@@ -171,21 +128,16 @@
  public:
   static constexpr int kEmptyFence = -1;
 
-  explicit NativeBufferConsumer(const std::shared_ptr<BufferConsumer>& buffer,
-                                int index)
+  explicit NativeBufferConsumer(const std::shared_ptr<BufferConsumer>& buffer)
       : BASE(), buffer_(buffer), acquire_fence_(kEmptyFence), sequence_(0) {
     ANativeWindowBuffer::width = buffer_->width();
     ANativeWindowBuffer::height = buffer_->height();
     ANativeWindowBuffer::stride = buffer_->stride();
     ANativeWindowBuffer::format = buffer_->format();
     ANativeWindowBuffer::usage = buffer_->usage();
-    LOG_ALWAYS_FATAL_IF(buffer_->slice_count() <= index);
-    handle = buffer_->slice(index)->handle();
+    handle = buffer_->native_handle();
   }
 
-  explicit NativeBufferConsumer(const std::shared_ptr<BufferConsumer>& buffer)
-      : NativeBufferConsumer(buffer, 0) {}
-
   virtual ~NativeBufferConsumer() {}
 
   std::shared_ptr<BufferConsumer> buffer() const { return buffer_; }
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index 716ab42..cbaa24a 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -15,36 +15,36 @@
 namespace android {
 namespace dvr {
 
-IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
+IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0) {}
 
 IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
                      uint64_t usage)
     : IonBuffer() {
-  Alloc(width, height, format, usage);
+  Alloc(width, height, kDefaultGraphicBufferLayerCount, format, usage);
 }
 
 IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
                      uint32_t stride, uint32_t format, uint64_t usage)
-    : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
+    : IonBuffer(handle, width, height, kDefaultGraphicBufferLayerCount, stride,
+                format, usage) {}
 
 IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
-                     uint32_t layer_count, uint32_t stride,
-                     uint32_t layer_stride, uint32_t format, uint64_t usage)
+                     uint32_t layer_count, uint32_t stride, uint32_t format,
+                     uint64_t usage)
     : buffer_(nullptr) {
   ALOGD_IF(TRACE,
            "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
-           "stride=%u layer stride=%u format=%u usage=%" PRIx64,
-           handle, width, height, layer_count, stride, layer_stride, format,
-           usage);
+           "stride=%u format=%u usage=%" PRIx64,
+           handle, width, height, layer_count, stride, format, usage);
   if (handle != 0) {
-    Import(handle, width, height, stride, format, usage);
+    Import(handle, width, height, layer_count, stride, format, usage);
   }
 }
 
 IonBuffer::~IonBuffer() {
   ALOGD_IF(TRACE,
            "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
-           "format=%u usage=%x",
+           "format=%u usage=%" PRIx64,
            handle(), width(), height(), stride(), format(), usage());
   FreeHandle();
 }
@@ -71,14 +71,14 @@
   }
 }
 
-int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
-                     uint64_t usage) {
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t layer_count,
+                     uint32_t format, uint64_t usage) {
   ALOGD_IF(TRACE,
-           "IonBuffer::Alloc: width=%u height=%u format=%u usage=%" PRIx64,
-           width, height, format, usage);
+           "IonBuffer::Alloc: width=%u height=%u layer_count=%u format=%u "
+           "usage=%" PRIx64, width, height, layer_count, format, usage);
 
-  sp<GraphicBuffer> buffer = new GraphicBuffer(
-      width, height, format, kDefaultGraphicBufferLayerCount, usage);
+  sp<GraphicBuffer> buffer =
+      new GraphicBuffer(width, height, format, layer_count, usage);
   if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
     return -EINVAL;
@@ -89,26 +89,27 @@
 }
 
 void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint64_t usage) {
+                      uint32_t layer_count, uint32_t stride, uint32_t format,
+                      uint64_t usage) {
   ALOGD_IF(TRACE,
-           "IonBuffer::Reset: handle=%p width=%u height=%u stride=%u format=%u "
-           "usage=%" PRIx64,
-           handle, width, height, stride, format, usage);
-  Import(handle, width, height, stride, format, usage);
+           "IonBuffer::Reset: handle=%p width=%u height=%u layer_count=%u "
+           "stride=%u format=%u usage=%" PRIx64,
+           handle, width, height, layer_count, stride, format, usage);
+  Import(handle, width, height, layer_count, stride, format, usage);
 }
 
 int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint64_t usage) {
+                      uint32_t layer_count, uint32_t stride, uint32_t format,
+                      uint64_t usage) {
   ATRACE_NAME("IonBuffer::Import1");
-  ALOGD_IF(
-      TRACE,
-      "IonBuffer::Import: handle=%p width=%u height=%u stride=%u format=%u "
-      "usage=%" PRIx64,
-      handle, width, height, stride, format, usage);
+  ALOGD_IF(TRACE,
+           "IonBuffer::Import: handle=%p width=%u height=%u layer_count=%u "
+           "stride=%u format=%u usage=%" PRIx64,
+           handle, width, height, layer_count, stride, format, usage);
   FreeHandle();
-  sp<GraphicBuffer> buffer = new GraphicBuffer(
-      handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
-      kDefaultGraphicBufferLayerCount, usage, stride);
+  sp<GraphicBuffer> buffer =
+      new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width,
+                        height, format, layer_count, usage, stride);
   if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Import: Failed to import buffer");
     return -EINVAL;
@@ -120,12 +121,14 @@
 
 int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
                       int int_count, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint64_t usage) {
+                      uint32_t layer_count, uint32_t stride, uint32_t format,
+                      uint64_t usage) {
   ATRACE_NAME("IonBuffer::Import2");
   ALOGD_IF(TRACE,
            "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
-           "stride=%u format=%u usage=%" PRIx64,
-           fd_count, int_count, width, height, stride, format, usage);
+           "layer_count=%u stride=%u format=%u usage=%" PRIx64,
+           fd_count, int_count, width, height, layer_count, stride, format,
+           usage);
 
   if (fd_count < 0 || int_count < 0) {
     ALOGE("IonBuffer::Import: invalid arguments.");
@@ -143,7 +146,8 @@
   memcpy(handle->data, fd_array, sizeof(int) * fd_count);
   memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
 
-  const int ret = Import(handle, width, height, stride, format, usage);
+  const int ret =
+      Import(handle, width, height, layer_count, stride, format, usage);
   if (ret < 0) {
     ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
           strerror(-ret));
@@ -179,8 +183,8 @@
          sizeof(int) * int_count);
 
   const int ret =
-      Import(handle, other->width(), other->height(), other->stride(),
-             other->format(), other->usage());
+      Import(handle, other->width(), other->height(), other->layer_count(),
+             other->stride(), other->format(), other->usage());
   if (ret < 0) {
     ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
           strerror(-ret));
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 fac6db0..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 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 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(layer_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 stride,
-             int format, int usage) {
-    return mock_->Import(handle, width, height, stride, format, usage);
-  }
-  int Import(const int* fd_array, int fd_count, const int* int_array,
-             int int_count, int width, int height, int stride, int format,
-             int usage) {
-    return mock_->Import(fd_array, fd_count, int_array, int_count, width,
-                         height, 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 layer_stride() const { return mock_->layer_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 0fa1f01..a587f95 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",
 ]
 
@@ -23,6 +21,10 @@
     "include",
 ]
 
+headerLibraries = [
+    "libdvr_headers",
+]
+
 staticLibraries = [
     "libbufferhub",
     "libdvrcommon",
@@ -49,6 +51,7 @@
     srcs: sourceFiles,
     export_include_dirs: includeFiles,
     export_static_lib_headers: staticLibraries,
+    header_libs: headerLibraries,
     static_libs: staticLibraries,
     shared_libs: sharedLibraries,
 }
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index b381d22..012a4e7 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -2,8 +2,8 @@
 
 #include <inttypes.h>
 #include <log/log.h>
-#include <sys/epoll.h>
 #include <poll.h>
+#include <sys/epoll.h>
 
 #include <array>
 
@@ -389,8 +389,8 @@
 }
 
 int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
-                                  uint32_t format, uint64_t usage,
-                                  size_t slice_count, size_t* out_slot) {
+                                  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;
@@ -405,7 +405,7 @@
   const size_t kBufferCount = 1U;
   Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
-          width, height, format, usage, slice_count, kBufferCount);
+          width, height, layer_count, format, usage, kBufferCount);
   if (!status) {
     ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
           status.GetErrorMessage().c_str());
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 00ff137..0000000
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
+++ /dev/null
@@ -1,75 +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,
-                                            PixelFormat format, uint32_t usage,
-                                            size_t slice_count) {
-  size_t slot;
-
-  // Allocate new buffer through BufferHub and add it into |producer_| queue for
-  // bookkeeping.
-  if (producer_->AllocateBuffer(width, height, format, usage, slice_count,
-                                &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 0a36156..8582bbf 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -1,22 +1,41 @@
 #include "include/private/dvr/buffer_hub_queue_producer.h"
 
+#include <dvr/dvr_api.h>
 #include <inttypes.h>
 #include <log/log.h>
 
 namespace android {
 namespace dvr {
 
-BufferHubQueueProducer::BufferHubQueueProducer(
-    const std::shared_ptr<BufferHubQueueCore>& core)
-    : core_(core) {}
+/* static */
+sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
+  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
+  producer->queue_ = ProducerQueue::Create<DvrNativeBufferMetadata>();
+  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;
   }
@@ -25,23 +44,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;
@@ -52,12 +71,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;
@@ -66,7 +85,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++;
     }
@@ -114,21 +133,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;
   }
 
-  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
+  const uint32_t kLayerCount = 1;
+  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, format, usage, 1);
+    ret = AllocateBuffer(width, height, kLayerCount, format, usage);
     if (ret < 0)
       return ret;
   }
@@ -138,12 +157,11 @@
 
   for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
     LocalHandle fence;
-    auto buffer_status  =
-        core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot, &fence);
-    if (!buffer_producer)
-      return NO_MEMORY;
+    auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
 
     buffer_producer = buffer_status.take();
+    if (!buffer_producer)
+      return NO_MEMORY;
 
     if (width == buffer_producer->width() &&
         height == buffer_producer->height() &&
@@ -162,34 +180,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, format, usage, 1);
+    // 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
@@ -198,9 +216,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;
@@ -265,9 +283,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;
   }
@@ -276,22 +294,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());
@@ -304,7 +322,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);
@@ -316,7 +334,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();
@@ -339,9 +357,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;
   }
@@ -350,19 +368,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;
@@ -371,7 +389,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");
@@ -384,19 +402,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
@@ -419,6 +437,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;
   }
@@ -440,9 +463,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;
   }
 
@@ -451,10 +474,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;
@@ -477,15 +500,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;
 }
 
@@ -519,8 +542,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;
 }
 
@@ -534,7 +557,8 @@
 
 status_t BufferHubQueueProducer::setSharedBufferMode(bool shared_buffer_mode) {
   if (shared_buffer_mode) {
-    ALOGE("BufferHubQueueProducer::setSharedBufferMode(true) is not supported.");
+    ALOGE(
+        "BufferHubQueueProducer::setSharedBufferMode(true) is not supported.");
     // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
     return INVALID_OPERATION;
   }
@@ -554,8 +578,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;
 }
 
@@ -574,15 +598,45 @@
 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;
+
+  if (queue_->AllocateBuffer(width, height, layer_count, format, usage, &slot) <
+      0) {
+    ALOGE("Failed to allocate new buffer in BufferHub.");
+    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) {
+  int ret = queue_->DetachBuffer(slot);
+  if (ret < 0) {
+    ALOGE("BufferHubQueueProducer::RemoveBuffer 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
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 c5dbbde..ed67f79 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
@@ -336,8 +336,8 @@
   // 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 format,
-                     uint64_t usage, size_t slice_count, size_t* out_slot);
+  int 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).
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 9a8a2c9..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, PixelFormat format,
-                     uint32_t usage, size_t slice_count);
-
-  // 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 b345498..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;
@@ -29,8 +42,7 @@
 
   // See |IGraphicBufferProducer::dequeueBuffer|
   status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
-                         uint32_t height, PixelFormat format,
-                         uint32_t usage,
+                         uint32_t height, PixelFormat format, uint32_t usage,
                          FrameEventHistoryDelta* outTimestamps) override;
 
   // See |IGraphicBufferProducer::detachBuffer|
@@ -41,7 +53,8 @@
                             sp<Fence>* out_fence) override;
 
   // See |IGraphicBufferProducer::attachBuffer|
-  status_t attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) override;
+  status_t attachBuffer(int* out_slot,
+                        const sp<GraphicBuffer>& buffer) override;
 
   // See |IGraphicBufferProducer::queueBuffer|
   status_t queueBuffer(int slot, const QueueBufferInput& input,
@@ -59,7 +72,8 @@
                    QueueBufferOutput* output) override;
 
   // See |IGraphicBufferProducer::disconnect|
-  status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) override;
+  status_t disconnect(int api,
+                      DisconnectMode mode = DisconnectMode::Api) override;
 
   // See |IGraphicBufferProducer::setSidebandStream|
   status_t setSidebandStream(const sp<NativeHandle>& stream) override;
@@ -97,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};
@@ -112,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 ba9c179..fe0b12a 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -15,9 +15,9 @@
 
 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 int kBufferSliceCount = 1;  // number of slices in each buffer
 
 class BufferHubQueueTest : public ::testing::Test {
  public:
@@ -55,8 +55,8 @@
     // Create producer buffer.
     size_t slot;
     int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                              kBufferFormat, kBufferUsage,
-                                              kBufferSliceCount, &slot);
+                                              kBufferLayerCount, kBufferFormat,
+                                              kBufferUsage, &slot);
     ASSERT_EQ(ret, 0);
   }
 
@@ -347,9 +347,9 @@
 
   // When allocation, leave out |set_mask| from usage bits on purpose.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage & ~set_mask,
-      kBufferSliceCount, &slot);
+  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                            kBufferFormat, kBufferLayerCount,
+                                            kBufferUsage & ~set_mask, &slot);
   ASSERT_EQ(0, ret);
 
   LocalHandle fence;
@@ -365,9 +365,9 @@
 
   // When allocation, add |clear_mask| into usage bits on purpose.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage | clear_mask,
-      kBufferSliceCount, &slot);
+  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                            kBufferLayerCount, kBufferFormat,
+                                            kBufferUsage | clear_mask, &slot);
   ASSERT_EQ(0, ret);
 
   LocalHandle fence;
@@ -385,14 +385,14 @@
   // be able to succeed.
   size_t slot;
   int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage & ~deny_set_mask,
-      kBufferSliceCount, &slot);
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage & ~deny_set_mask, &slot);
   ASSERT_EQ(ret, 0);
 
   // While allocation with those bits should fail.
-  ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage | deny_set_mask,
-      kBufferSliceCount, &slot);
+  ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                        kBufferLayerCount, kBufferFormat,
+                                        kBufferUsage | deny_set_mask, &slot);
   ASSERT_EQ(ret, -EINVAL);
 }
 
@@ -404,14 +404,14 @@
   // mandatory), allocation with those bits should be able to succeed.
   size_t slot;
   int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat,
-      kBufferUsage | deny_clear_mask, kBufferSliceCount, &slot);
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage | deny_clear_mask, &slot);
   ASSERT_EQ(ret, 0);
 
   // While allocation without those bits should fail.
-  ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat,
-      kBufferUsage & ~deny_clear_mask, kBufferSliceCount, &slot);
+  ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                        kBufferLayerCount, kBufferFormat,
+                                        kBufferUsage & ~deny_clear_mask, &slot);
   ASSERT_EQ(ret, -EINVAL);
 }
 
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..2b6239f 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);
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index 41baef8..d90521a 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -13,15 +13,9 @@
 // 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",
 ]
 
@@ -34,9 +28,6 @@
     "libcutils",
     "liblog",
     "libutils",
-    "libEGL",
-    "libGLESv2",
-    "libvulkan",
     "libui",
     "libgui",
     "libhardware",
@@ -45,10 +36,9 @@
 ]
 
 staticLibraries = [
-    "libbufferhub",
-    "libbufferhubqueue",
     "libdvrcommon",
-    "libdvrgraphics",
+    "libbufferhubqueue",
+    "libbufferhub",
     "libvrsensor",
     "libpdx_default_transport",
 ]
@@ -74,27 +64,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 dbee9f2..935ca2e 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;
@@ -123,15 +122,13 @@
   return {std::move(producer_queue)};
 }
 
-Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(uint32_t width,
-                                                            uint32_t height,
-                                                            uint32_t format,
-                                                            uint64_t usage,
-                                                            size_t capacity) {
+Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
+    uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
+    uint64_t usage, size_t capacity) {
   ALOGD_IF(TRACE,
-           "Surface::CreateQueue: width=%u height=%u format=%u usage=%" PRIx64
-           " capacity=%zu",
-           width, height, format, usage, capacity);
+           "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
+           "usage=%" PRIx64 " capacity=%zu",
+           width, height, layer_count, format, usage, capacity);
   auto status = CreateQueue();
   if (!status)
     return status.error_status();
@@ -141,9 +138,8 @@
   ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
   for (size_t i = 0; i < capacity; i++) {
     size_t slot;
-    const size_t kSliceCount = 1;
-    const int ret = producer_queue->AllocateBuffer(width, height, format, usage,
-                                                   kSliceCount, &slot);
+    const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
+                                                   format, usage, &slot);
     if (ret < 0) {
       ALOGE(
           "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
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 f0e37f8..0000000
--- a/libs/vr/libdisplay/graphics.cpp
+++ /dev/null
@@ -1,1609 +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 <android/native_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, 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 !=
-                        context->current_buffer->buffer()->slice_count());
-    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 =
-        graphics_context->current_buffer->surface_buffer_index();
-    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 668532d..7a7f670 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -42,6 +42,7 @@
   // parameters.
   pdx::Status<std::unique_ptr<ProducerQueue>> CreateQueue(uint32_t width,
                                                           uint32_t height,
+                                                          uint32_t layer_count,
                                                           uint32_t format,
                                                           uint64_t usage,
                                                           size_t capacity);
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 b03eeaa..0000000
--- a/libs/vr/libdisplay/include/private/dvr/dummy_native_window.h
+++ /dev/null
@@ -1,30 +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>
-
-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/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 762db32..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_, format_,
-                                                    usage_, 1, &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/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
new file mode 100644
index 0000000..fa78b1c
--- /dev/null
+++ b/libs/vr/libdvr/Android.bp
@@ -0,0 +1,89 @@
+// 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_headers {
+    name: "libdvr_headers",
+    owner: "google",
+    export_include_dirs: ["include"],
+}
+
+cflags = [
+    "-DLOG_TAG=\"libdvr\"",
+]
+
+srcs = [
+    "dvr_api.cpp",
+    "dvr_buffer.cpp",
+    "dvr_buffer_queue.cpp",
+    "dvr_display_manager.cpp",
+    "dvr_hardware_composer_client.cpp",
+    "dvr_surface.cpp",
+    "dvr_vsync.cpp",
+]
+
+static_libs = [
+    "libbufferhub",
+    "libbufferhubqueue",
+    "libdisplay",
+    "libvrsensor",
+    "libvirtualtouchpadclient",
+    "libvr_hwc-impl",
+    "libvr_hwc-binder",
+    "libgrallocusage",
+    "libpdx_default_transport",
+]
+
+shared_libs = [
+    "android.hardware.graphics.bufferqueue@1.0",
+    "android.hidl.token@1.0-utils",
+    "libbase",
+    "libbinder",
+    "liblog",
+    "libcutils",
+    "libutils",
+    "libnativewindow",
+    "libgui",
+    "libui",
+]
+
+cc_library_shared {
+    name: "libdvr",
+    owner: "google",
+    cflags: cflags,
+    header_libs: ["libdvr_headers"],
+    export_header_lib_headers: ["libdvr_headers"],
+    srcs: srcs,
+    static_libs: static_libs,
+    shared_libs: shared_libs,
+    version_script: "exported_apis.lds",
+}
+
+// Also build a static libdvr for linking into tests. The linker script
+// restricting function access in the shared lib makes it inconvenient to use in
+// test code.
+cc_library_static {
+    name: "libdvr_static",
+    owner: "google",
+    cflags: cflags,
+    header_libs: ["libdvr_headers"],
+    export_header_lib_headers: ["libdvr_headers"],
+    srcs: srcs,
+    static_libs: static_libs,
+    shared_libs: shared_libs,
+}
+
+subdirs = [
+    "tests",
+]
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
deleted file mode 100644
index 2375b5a..0000000
--- a/libs/vr/libdvr/Android.mk
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libdvr
-LOCAL_MODULE_OWNER := google
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-
-LOCAL_CFLAGS += \
-    -fvisibility=hidden \
-    -DLOG_TAG=\"libdvr\" \
-    -D DVR_EXPORT='__attribute__ ((visibility ("default")))'
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/include \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/include \
-
-LOCAL_SRC_FILES := \
-    dvr_api.cpp \
-    dvr_buffer.cpp \
-    dvr_buffer_queue.cpp \
-    dvr_display_manager.cpp \
-    dvr_hardware_composer_client.cpp \
-    dvr_surface.cpp \
-    dvr_vsync.cpp \
-
-LOCAL_STATIC_LIBRARIES := \
-    libbufferhub \
-    libbufferhubqueue \
-    libdisplay \
-    libvrsensor \
-    libvirtualtouchpadclient \
-    libvr_hwc-impl \
-    libvr_hwc-binder \
-    libgrallocusage \
-
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.graphics.bufferqueue@1.0 \
-    android.hidl.token@1.0-utils \
-    libbase \
-    libnativewindow \
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 4d7e1a6..2c95583 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -18,7 +18,7 @@
 
 extern "C" {
 
-DVR_EXPORT int dvrGetApi(void* api, size_t struct_size, int version) {
+int dvrGetApi(void* api, size_t struct_size, int version) {
   ALOGI("dvrGetApi: api=%p struct_size=%zu version=%d", api, struct_size,
         version);
   if (version == 1) {
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_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index b70f726..67e2ae8 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -133,7 +133,8 @@
 
 int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
                                      uint32_t height, uint32_t format,
-                                     uint64_t usage, size_t capacity,
+                                     uint32_t layer_count, uint64_t usage,
+                                     size_t capacity,
                                      DvrWriteBufferQueue** out_writer) {
   if (surface == nullptr || out_writer == nullptr) {
     ALOGE(
@@ -143,8 +144,8 @@
     return -EINVAL;
   }
 
-  auto status =
-      surface->surface->CreateQueue(width, height, format, usage, capacity);
+  auto status = surface->surface->CreateQueue(width, height, layer_count,
+                                              format, usage, capacity);
   if (!status) {
     ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
           status.GetErrorMessage().c_str());
diff --git a/libs/vr/libdvr/exported_apis.lds b/libs/vr/libdvr/exported_apis.lds
new file mode 100644
index 0000000..5ecb498
--- /dev/null
+++ b/libs/vr/libdvr/exported_apis.lds
@@ -0,0 +1,9 @@
+{
+  global:
+    # Whitelist the function to load the dvr api.
+    dvrGetApi;
+
+  local:
+    # Hide everything else.
+    *;
+};
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 7124bee..8a203e0 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -162,7 +162,8 @@
                                           size_t attribute_count);
 typedef int (*DvrSurfaceCreateWriteBufferQueuePtr)(
     DvrSurface* surface, uint32_t width, uint32_t height, uint32_t format,
-    uint64_t usage, size_t capacity, DvrWriteBufferQueue** queue_out);
+    uint32_t layer_count, uint64_t usage, size_t capacity,
+    DvrWriteBufferQueue** queue_out);
 
 // vsync_client_api.h
 typedef int (*DvrVSyncClientCreatePtr)(DvrVSyncClient** client_out);
@@ -261,13 +262,10 @@
 
 // The buffer metadata that an Android Surface (a.k.a. ANativeWindow)
 // will populate. A DvrWriteBufferQueue must be created with this metadata iff
-// ANativeWindow access is needed. Note that this struct must stay in sync with
-// BufferHubQueueCore::NativeBufferMetadata. 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|.
+// ANativeWindow access is needed. 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.
 struct DvrNativeBufferMetadata {
   // Timestamp of the frame.
   int64_t timestamp;
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 58f2a10..361488e 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -78,7 +78,8 @@
 // @return 0 on success. Otherwise returns a negative error value.
 int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
                                      uint32_t height, uint32_t format,
-                                     uint64_t usage, size_t capacity,
+                                     uint32_t layer_count, uint64_t usage,
+                                     size_t capacity,
                                      DvrWriteBufferQueue** queue_out);
 
 // Get a named buffer from the display service.
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
new file mode 100644
index 0000000..ef746e2
--- /dev/null
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -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.
+
+shared_libraries = [
+    "libbase",
+    "libbinder",
+    "libcutils",
+    "libgui",
+    "liblog",
+    "libhardware",
+    "libui",
+    "libutils",
+    "libnativewindow",
+]
+
+static_libraries = [
+    "libdvr_static",
+    "libbufferhubqueue",
+    "libbufferhub",
+    "libchrome",
+    "libdvrcommon",
+    "libdisplay",
+    "libpdx_default_transport",
+]
+
+cc_test {
+    srcs: [
+        "dvr_buffer_queue-test.cpp",
+        "dvr_display_manager-test.cpp",
+        "dvr_named_buffer-test.cpp",
+    ],
+
+    static_libs: static_libraries,
+    shared_libs: shared_libraries,
+    cflags: [
+        "-DLOG_TAG=\"dvr_api-test\"",
+        "-DTRACE=0",
+        "-O0",
+        "-g",
+    ],
+    name: "dvr_api-test",
+}
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
deleted file mode 100644
index d6ce99b..0000000
--- a/libs/vr/libdvr/tests/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-shared_libraries := \
-    libbase \
-    libbinder \
-    libcutils \
-    libgui \
-    liblog \
-    libhardware \
-    libui \
-    libutils \
-    libnativewindow \
-
-static_libraries := \
-    libdvr \
-    libbufferhubqueue \
-    libbufferhub \
-    libchrome \
-    libdvrcommon \
-    libdisplay \
-    libpdx_default_transport \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
-    dvr_buffer_queue-test.cpp \
-    dvr_display_manager-test.cpp \
-    dvr_named_buffer-test.cpp \
-
-LOCAL_STATIC_LIBRARIES := $(static_libraries)
-LOCAL_SHARED_LIBRARIES := $(shared_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-LOCAL_CFLAGS := -DLOG_TAG=\"dvr_api-test\" -DTRACE=0 -O0 -g
-LOCAL_MODULE := dvr_api-test
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index 5f7f1bf..474e968 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -15,9 +15,9 @@
 
 static constexpr int kBufferWidth = 100;
 static constexpr int kBufferHeight = 1;
+static constexpr int kLayerCount = 1;
 static constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
 static constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
-static constexpr int kBufferSliceCount = 1;  // number of slices in each buffer
 static constexpr size_t kQueueCapacity = 3;
 
 typedef uint64_t TestMeta;
@@ -40,10 +40,9 @@
   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, kBufferFormat,
-                               kBufferUsage, kBufferSliceCount, &out_slot);
+      int ret = GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
+                    ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
+                                     kBufferFormat, kBufferUsage, &out_slot);
       ASSERT_EQ(0, ret);
     }
   }
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
index 0150984..a2414d6 100644
--- a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -56,10 +56,11 @@
 
 Status<UniqueDvrWriteBufferQueue> CreateSurfaceQueue(
     const UniqueDvrSurface& surface, uint32_t width, uint32_t height,
-    uint32_t format, uint64_t usage, size_t capacity) {
+    uint32_t format, uint32_t layer_count, uint64_t usage, size_t capacity) {
   DvrWriteBufferQueue* queue;
-  const int ret = dvrSurfaceCreateWriteBufferQueue(
-      surface.get(), width, height, format, usage, capacity, &queue);
+  const int ret =
+      dvrSurfaceCreateWriteBufferQueue(surface.get(), width, height, format,
+                                       layer_count, usage, capacity, &queue);
   if (ret < 0)
     return ErrorStatus(-ret);
   else
@@ -484,7 +485,7 @@
 
   // Create a new queue in the surface.
   auto write_queue_status = CreateSurfaceQueue(
-      surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+      surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, 1,
       AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1);
   ASSERT_STATUS_OK(write_queue_status);
   UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
@@ -533,6 +534,45 @@
   ASSERT_EQ(0u, queue_ids.size());
 }
 
+TEST_F(DvrDisplayManagerTest, MultiLayerBufferQueue) {
+  // Create an application surface.
+  auto surface_status = CreateApplicationSurface();
+  ASSERT_STATUS_OK(surface_status);
+  UniqueDvrSurface surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  // Get surface state and verify there is one surface.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Create a new queue in the surface.
+  const uint32_t kLayerCount = 3;
+  auto write_queue_status = CreateSurfaceQueue(
+      surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kLayerCount,
+      AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1);
+  ASSERT_STATUS_OK(write_queue_status);
+  UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
+  ASSERT_NE(nullptr, write_queue.get());
+
+  DvrWriteBuffer* buffer = nullptr;
+  dvrWriteBufferCreateEmpty(&buffer);
+  int fence_fd = -1;
+  int error =
+      dvrWriteBufferQueueDequeue(write_queue.get(), 1000, buffer, &fence_fd);
+  ASSERT_EQ(0, error);
+
+  AHardwareBuffer* hardware_buffer = nullptr;
+  error = dvrWriteBufferGetAHardwareBuffer(buffer, &hardware_buffer);
+  ASSERT_EQ(0, error);
+
+  AHardwareBuffer_Desc desc = {};
+  AHardwareBuffer_describe(hardware_buffer, &desc);
+  ASSERT_EQ(kLayerCount, desc.layers);
+
+  AHardwareBuffer_release(hardware_buffer);
+  dvrWriteBufferDestroy(buffer);
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index eb78348..527cdbd 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",
 ]
@@ -40,7 +35,6 @@
 ]
 
 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/libeds/Android.bp b/libs/vr/libeds/Android.bp
deleted file mode 100644
index a149853..0000000
--- a/libs/vr/libeds/Android.bp
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (C) 2015 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 = [
-    "eds.cpp",
-    "eds_mesh.cpp",
-    "composite_hmd.cpp",
-    "display_metrics.cpp",
-    "distortion_renderer.cpp",
-    "device_metrics.cpp",
-    "polynomial_radial_distortion.cpp",
-]
-
-localIncludeFiles = [
-    "include",
-]
-
-sharedLibraries = [
-    "libbase",
-    "libcutils",
-    "liblog",
-    "libEGL",
-    "libGLESv1_CM",
-    "libGLESv2",
-    "libui",
-    "libutils",
-    "libvulkan",
-]
-
-staticLibraries = [
-    "libdisplay",
-    "libdvrcommon",
-    "libdvrgraphics",
-    "libvrsensor",
-    "libpdx_default_transport",
-]
-
-cc_library_static {
-    srcs: sourceFiles,
-    cflags: [
-        "-DGL_GLEXT_PROTOTYPES",
-        "-DEGL_EGLEXT_PROTOTYPES",
-        "-Wno-unused-parameter"],
-    // Enable debug options below to show GL errors and use gdb.
-    // + ["-UNDEBUG", "-DDEBUG", "-O0", "-g", ]
-    export_include_dirs: localIncludeFiles,
-    shared_libs: sharedLibraries,
-    static_libs: staticLibraries,
-    name: "libeds",
-}
-
-testFiles = ["tests/eds_app_tests.cpp"]
-
-cc_test {
-    name: "eds_app_tests",
-    tags: ["optional"],
-
-    srcs: testFiles,
-
-    shared_libs: [
-        "libhardware",
-        "libsync",
-    ] + sharedLibraries,
-
-    static_libs: [
-        "libgmock_main",
-        "libgmock",
-        "libeds",
-    ] + staticLibraries + [
-        "libbufferhub",
-        "libbufferhubqueue",
-    ],
-
-}
diff --git a/libs/vr/libeds/composite_hmd.cpp b/libs/vr/libeds/composite_hmd.cpp
deleted file mode 100644
index d6bf164..0000000
--- a/libs/vr/libeds/composite_hmd.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-#include "include/private/dvr/composite_hmd.h"
-
-#include <log/log.h>
-
-#include <private/dvr/numeric.h>
-
-namespace android {
-namespace dvr {
-
-CompositeHmd::CompositeHmd(const HeadMountMetrics& head_mount_metrics,
-                           const DisplayMetrics& display_metrics)
-    : head_mount_metrics_(head_mount_metrics),
-      display_metrics_(display_metrics) {
-  MetricsChanged();
-}
-
-float CompositeHmd::GetTargetFrameDuration() const {
-  return display_metrics_.GetFrameDurationSeconds();
-}
-
-vec2 CompositeHmd::ComputeDistortedPoint(EyeType eye, vec2 position,
-                                         RgbColorChannel channel) const {
-  position = TransformPoint(eye_tan_angle_from_norm_screen_matrix_[eye], position);
-  vec2 distorted =
-      head_mount_metrics_.GetColorChannelDistortion(channel).Distort(position);
-  return TransformPoint(eye_norm_texture_from_tan_angle_matrix_[eye], distorted);
-}
-
-vec2 CompositeHmd::ComputeInverseDistortedPoint(EyeType eye, vec2 position,
-                                                RgbColorChannel channel) const {
-  position = TransformPoint(eye_norm_texture_from_tan_angle_inv_matrix_[eye], position);
-  vec2 distorted =
-      head_mount_metrics_.GetColorChannelDistortion(channel).DistortInverse(
-          position);
-  return TransformPoint(eye_tan_angle_from_norm_screen_inv_matrix_[eye], distorted);
-}
-
-void CompositeHmd::ComputeDistortedVertex(EyeType eye, vec2 uv_in,
-                                          vec2* vertex_out,
-                                          vec2* uv_out) const {
-  // The mesh vertices holds the shape of the distortion.
-  vec2 vertex_position = ComputeInverseDistortedPoint(eye, uv_in, kRed);
-  *vertex_out = vec2(vertex_position.x() - 0.5f, vertex_position.y() - 0.5f);
-
-  if (uv_out) {
-    // Compute the texture coordinate for each vertex coordinate.
-    // Red's is the inverse of the inverse, skip the calculation and use uv_in.
-    uv_out[kRed] = uv_in;
-    uv_out[kGreen] = ComputeDistortedPoint(eye, vertex_position, kGreen);
-    uv_out[kBlue] = ComputeDistortedPoint(eye, vertex_position, kBlue);
-  }
-}
-
-vec2i CompositeHmd::GetRecommendedRenderTargetSize() const {
-  return recommended_render_target_size_;
-}
-
-Range2i CompositeHmd::GetDisplayRange() const { return display_range_; }
-
-mat4 CompositeHmd::GetEyeFromHeadMatrix(EyeType eye) const {
-  return eye_from_head_matrix_[eye];
-}
-
-FieldOfView CompositeHmd::GetEyeFov(EyeType eye) const { return eye_fov_[eye]; }
-
-Range2i CompositeHmd::GetEyeViewportBounds(EyeType eye) const {
-  return eye_viewport_range_[eye];
-}
-
-void CompositeHmd::SetHeadMountMetrics(
-    const HeadMountMetrics& head_mount_metrics) {
-  // Use the assignement operator to do memberwise copy.
-  head_mount_metrics_ = head_mount_metrics;
-  MetricsChanged();
-}
-
-const HeadMountMetrics& CompositeHmd::GetHeadMountMetrics() const {
-  return head_mount_metrics_;
-}
-
-void CompositeHmd::SetDisplayMetrics(const DisplayMetrics& display_metrics) {
-  // Use the assignment operator to do memberwise copy.
-  display_metrics_ = display_metrics;
-  MetricsChanged();
-}
-
-const DisplayMetrics& CompositeHmd::GetDisplayMetrics() const {
-  return display_metrics_;
-}
-
-void CompositeHmd::MetricsChanged() {
-  // Abbreviations in variable names:
-  //   "vp": viewport
-  //   "ta": tan-angle
-  const HeadMountMetrics& mount = head_mount_metrics_;
-  DisplayMetrics display = display_metrics_;
-
-  if (display.IsPortrait()) {
-    // If we're in portrait mode, toggle the orientation so that all
-    // calculations are done in landscape mode.
-    display.ToggleOrientation();
-  }
-
-  float display_width_meters = display.GetSizeMeters()[0];
-  float display_height_meters = display.GetSizeMeters()[1];
-
-  vec2 pixels_per_meter = vec2(1.0f / display.GetMetersPerPixel()[0],
-                               1.0f / display.GetMetersPerPixel()[1]);
-
-  // virtual_eye_to_screen_dist is the distance from the screen to the eye
-  // after it has been projected through the lens.  This would normally be
-  // slightly different from the distance to the actual eye.
-  float virtual_eye_to_screen_dist = mount.GetVirtualEyeToScreenDistance();
-  float meters_per_tan_angle = virtual_eye_to_screen_dist;
-  vec2 pixels_per_tan_angle = pixels_per_meter * meters_per_tan_angle;
-
-  LOG_ALWAYS_FATAL_IF(0.0f == display_width_meters);
-  LOG_ALWAYS_FATAL_IF(0.0f == display_height_meters);
-  LOG_ALWAYS_FATAL_IF(0.0f == virtual_eye_to_screen_dist);
-
-  // Height of lenses from the bottom of the screen.
-  float lens_y_center = 0;
-  float bottom_dist = 0;
-  float top_dist = 0;
-
-  // bottom_display_dist and top_display_dist represent the distance from the
-  // lens center to the edge of the display.
-  float bottom_display_dist = 0;
-  float top_display_dist = 0;
-  switch (mount.GetVerticalAlignment()) {
-    case HeadMountMetrics::kBottom:
-      lens_y_center =
-          mount.GetTrayToLensDistance() - display.GetBorderSizeMeters();
-      bottom_dist = lens_y_center;
-      top_dist = lens_y_center;
-      bottom_display_dist = lens_y_center;
-      top_display_dist = display_height_meters - lens_y_center;
-      break;
-    case HeadMountMetrics::kCenter:
-      // TODO(hendrikw): This should respect the border size, but since we
-      //                 currently hard code the border size, it would break
-      //                 the distortion on some devices.  Revisit when border
-      //                 size is fixed.
-      lens_y_center = display_height_meters * 0.5f;
-      bottom_dist = lens_y_center;
-      top_dist = lens_y_center;
-      bottom_display_dist = lens_y_center;
-      top_display_dist = lens_y_center;
-      break;
-    case HeadMountMetrics::kTop:
-      lens_y_center = display_height_meters - (mount.GetTrayToLensDistance() -
-                                               display.GetBorderSizeMeters());
-      bottom_dist =
-          mount.GetTrayToLensDistance() - display.GetBorderSizeMeters();
-      top_dist = bottom_dist;
-      bottom_display_dist = lens_y_center;
-      top_display_dist = display_height_meters - lens_y_center;
-      break;
-  }
-
-  float inner_dist = mount.GetScreenCenterToLensDistance();
-  float outer_dist = display_width_meters * 0.5f - inner_dist;
-
-  // We don't take chromatic aberration into account yet for computing FOV,
-  // viewport, etc, so we only use the green channel for now. Note the actual
-  // Distort function *does* implement chromatic aberration.
-  const ColorChannelDistortion& distortion =
-      mount.GetColorChannelDistortion(kGreen);
-
-  vec2 outer_point(outer_dist / virtual_eye_to_screen_dist, 0.0f);
-  vec2 inner_point(inner_dist / virtual_eye_to_screen_dist, 0.0f);
-  vec2 bottom_point(0.0f, bottom_dist / virtual_eye_to_screen_dist);
-  vec2 top_point(0.0f, top_dist / virtual_eye_to_screen_dist);
-
-  float outer_angle = atanf(distortion.Distort(outer_point)[0]);
-  float inner_angle = atanf(distortion.Distort(inner_point)[0]);
-  float bottom_angle = atanf(distortion.Distort(bottom_point)[1]);
-  float top_angle = atanf(distortion.Distort(top_point)[1]);
-
-  for (EyeType eye : {kLeftEye, kRightEye}) {
-    const FieldOfView max_fov = mount.GetEyeMaxFov(eye);
-    float left_angle = (eye == kLeftEye) ? outer_angle : inner_angle;
-    float right_angle = (eye == kLeftEye) ? inner_angle : outer_angle;
-
-    eye_fov_[eye] = FieldOfView(std::min(left_angle, max_fov.GetLeft()),
-                                std::min(right_angle, max_fov.GetRight()),
-                                std::min(bottom_angle, max_fov.GetBottom()),
-                                std::min(top_angle, max_fov.GetTop()));
-
-    vec2 texture_vp_ta_p1 =
-        vec2(-tanf(eye_fov_[eye].GetLeft()), -tanf(eye_fov_[eye].GetBottom()));
-    vec2 texture_vp_ta_p2 =
-        vec2(tanf(eye_fov_[eye].GetRight()), tanf(eye_fov_[eye].GetTop()));
-    vec2 texture_vp_size_ta = texture_vp_ta_p2 - texture_vp_ta_p1;
-
-    vec2 texture_vp_sizef_pixels =
-        texture_vp_size_ta.array() * pixels_per_tan_angle.array();
-
-    vec2i texture_vp_size_pixels =
-        vec2i(static_cast<int32_t>(roundf(texture_vp_sizef_pixels[0])),
-              static_cast<int32_t>(roundf(texture_vp_sizef_pixels[1])));
-    int vp_start_x =
-        (eye == kLeftEye) ? 0 : eye_viewport_range_[kLeftEye].p2[0];
-
-    eye_viewport_range_[eye] =
-        Range2i::FromSize(vec2i(vp_start_x, 0), texture_vp_size_pixels);
-    float left_dist = (eye == kLeftEye) ? outer_dist : inner_dist;
-    float right_dist = (eye == kLeftEye) ? inner_dist : outer_dist;
-    vec2 screen_ta_p1(-left_dist / virtual_eye_to_screen_dist,
-                      -bottom_display_dist / virtual_eye_to_screen_dist);
-    vec2 screen_ta_p2(right_dist / virtual_eye_to_screen_dist,
-                      top_display_dist / virtual_eye_to_screen_dist);
-    vec2 screen_ta_size = screen_ta_p2 - screen_ta_p1;
-
-    // Align the tan angle coordinates to the nearest pixel.  This will ensure
-    // that the optical center doesn't straddle multiple pixels.
-    // TODO(hendrikw): verify that this works correctly for Daydream View.
-    vec2 tan_angle_per_pixel(screen_ta_size.array() /
-                             texture_vp_size_pixels.cast<float>().array());
-    vec2 pixel_p1(screen_ta_p1.array() / tan_angle_per_pixel.array());
-    vec2 pixel_shift(roundf(pixel_p1.x()) - pixel_p1.x(),
-                     roundf(pixel_p1.y()) - pixel_p1.y());
-    screen_ta_p1 +=
-        (tan_angle_per_pixel.array() * pixel_shift.array()).matrix();
-    screen_ta_p2 +=
-        (tan_angle_per_pixel.array() * pixel_shift.array()).matrix();
-
-    // Calculate the transformations needed for the distortions.
-    eye_tan_angle_from_norm_screen_matrix_[eye] =
-        TranslationMatrix(vec2(screen_ta_p1)) *
-        ScaleMatrix(screen_ta_size);
-    eye_tan_angle_from_norm_screen_inv_matrix_[eye] =
-        eye_tan_angle_from_norm_screen_matrix_[eye].inverse();
-
-    eye_norm_texture_from_tan_angle_inv_matrix_[eye] =
-        TranslationMatrix(texture_vp_ta_p1) *
-        ScaleMatrix(texture_vp_size_ta);
-    eye_norm_texture_from_tan_angle_matrix_[eye] =
-        eye_norm_texture_from_tan_angle_inv_matrix_[eye].inverse();
-  }
-  vec2i left_vp_size = eye_viewport_range_[kLeftEye].GetSize();
-  vec2i right_vp_size = eye_viewport_range_[kRightEye].GetSize();
-
-  recommended_render_target_size_ =
-      vec2i(left_vp_size[0] + right_vp_size[0],
-            std::max(left_vp_size[1], right_vp_size[1]));
-
-  display_range_ = Range2i::FromSize(vec2i(0, 0), display.GetSizePixels());
-
-  eye_from_head_matrix_[kLeftEye] = Eigen::Translation3f(
-      vec3(mount.GetScreenCenterToLensDistance(), 0.0f, 0.0f));
-  eye_from_head_matrix_[kRightEye] = Eigen::Translation3f(
-      vec3(-mount.GetScreenCenterToLensDistance(), 0.0f, 0.0f));
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libeds/device_metrics.cpp b/libs/vr/libeds/device_metrics.cpp
deleted file mode 100644
index 68ee186..0000000
--- a/libs/vr/libeds/device_metrics.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-#include <private/dvr/device_metrics.h>
-
-#include <cutils/properties.h>
-#include <private/dvr/head_mount_metrics.h>
-#include <private/dvr/identity_distortion.h>
-#include <private/dvr/polynomial_radial_distortion.h>
-#include <private/dvr/types.h>
-#include "include/private/dvr/display_metrics.h"
-
-namespace {
-
-static constexpr char kRPolynomial[] = "persist.dvr.r_poly";
-static constexpr char kGPolynomial[] = "persist.dvr.g_poly";
-static constexpr char kBPolynomial[] = "persist.dvr.b_poly";
-static constexpr char kLensDistance[] = "persist.dvr.lens_distance";
-static constexpr char kDisplayGap[] = "persist.dvr.display_gap";
-static constexpr char kVEyeToDisplay[] = "persist.dvr.v_eye_to_display";
-static constexpr char kFovIOBT[] = "persist.dvr.fov_iobt";
-static constexpr char kScreenSize[] = "persist.dvr.screen_size";
-
-bool StringToFloat(const char* str, float* result) {
-  char* endptr = nullptr;
-  *result = std::strtof(str, &endptr);
-  return !(str == endptr || !endptr);
-}
-
-std::vector<std::string> SplitString(const std::string& string_to_split,
-                                     char deliminator) {
-  std::vector<std::string> result;
-  std::string sub_string;
-  std::stringstream ss(string_to_split);
-  while (std::getline(ss, sub_string, deliminator))
-    result.push_back(sub_string);
-  return result;
-}
-
-std::vector<float> GetProperty(const char* name,
-                               const std::vector<float>& default_values) {
-  char prop[PROPERTY_VALUE_MAX + 1] = {};
-  property_get(name, prop, "");
-  std::vector<std::string> values = SplitString(prop, ',');
-  std::vector<float> results;
-  for (const auto& value : values) {
-    float result = 0.0f;
-    if (StringToFloat(value.c_str(), &result)) {
-      results.push_back(static_cast<float>(result));
-    }
-  }
-  if (results.empty()) {
-    return default_values;
-  }
-  return results;
-}
-
-float GetProperty(const char* name, float default_value) {
-  char prop[PROPERTY_VALUE_MAX + 1] = {};
-  property_get(name, prop, "");
-  float result = 0.0f;
-  if (StringToFloat(prop, &result)) {
-    return static_cast<float>(result);
-  }
-  return default_value;
-}
-
-float GetInterLensDistance() { return GetProperty(kLensDistance, 0.064f); }
-
-float GetDisplayGap() { return GetProperty(kDisplayGap, 0.0f); }
-
-float GetTrayToLensDistance() { return 0.035f; }
-
-float GetVEyeToDisplay() { return GetProperty(kVEyeToDisplay, 0.042f); }
-
-android::dvr::vec2 GetDisplaySize() {
-  static const std::vector<float> default_size = {0.0742177f, 0.131943f};
-  std::vector<float> sizes = GetProperty(kScreenSize, default_size);
-  if (sizes.size() != 0)
-    sizes = default_size;
-  return android::dvr::vec2(sizes[0], sizes[1]);
-}
-
-std::vector<float> GetMaxFOVs() {
-  static const std::vector<float> defaults = {43.7f, 47.8f, 54.2f, 54.2f};
-  std::vector<float> fovs = GetProperty(kFovIOBT, defaults);
-  if (fovs.size() != 4)
-    fovs = defaults;
-  for (auto& value : fovs) {
-    value = value * M_PI / 180.0f;
-  }
-  return fovs;
-}
-
-static const android::dvr::HeadMountMetrics::VerticalAlignment
-    kDefaultVerticalAlignment = android::dvr::HeadMountMetrics::kCenter;
-
-// Default border size in meters.
-static const float kScreenBorderSize = 0.004f;
-
-// Refresh rate.
-static const float kScreenRefreshRate = 60.0f;
-
-// Default display orientation is portrait.
-static const android::dvr::DisplayOrientation kDisplayOrientation =
-    android::dvr::DisplayOrientation::kPortrait;
-
-}  // anonymous namespace
-
-namespace android {
-namespace dvr {
-
-HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov,
-                                        const FieldOfView& r_fov) {
-  static const std::vector<float> default_r = {
-      0.00103f, 2.63917f, -7.14427f, 8.98036f, -4.10586f, 0.83705f, 0.00130f};
-  static const std::vector<float> default_g = {
-      0.08944f, 2.26005f, -6.30924f, 7.94561f, -3.22788f, 0.45577f, 0.07300f};
-  static const std::vector<float> default_b = {
-      0.16364f, 1.94083f, -5.55033f, 6.89578f, -2.19053f, -0.04050f, 0.17380f};
-  std::vector<float> poly_r = GetProperty(kRPolynomial, default_r);
-  std::vector<float> poly_g = GetProperty(kGPolynomial, default_g);
-  std::vector<float> poly_b = GetProperty(kBPolynomial, default_b);
-
-  std::shared_ptr<ColorChannelDistortion> distortion_r(
-      new PolynomialRadialDistortion(poly_r));
-  std::shared_ptr<ColorChannelDistortion> distortion_g(
-      new PolynomialRadialDistortion(poly_g));
-  std::shared_ptr<ColorChannelDistortion> distortion_b(
-      new PolynomialRadialDistortion(poly_b));
-
-  return HeadMountMetrics(GetInterLensDistance(), GetTrayToLensDistance(),
-                          GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
-                          r_fov, distortion_r, distortion_g, distortion_b,
-                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
-                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
-                          (GetInterLensDistance() - GetDisplayGap()) / 2.0f);
-}
-
-HeadMountMetrics CreateHeadMountMetrics() {
-  std::vector<float> fovs = GetMaxFOVs();
-  FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]);
-  FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]);
-  return CreateHeadMountMetrics(l_fov, r_fov);
-}
-
-DisplayMetrics CreateDisplayMetrics(vec2i screen_size) {
-  android::dvr::vec2 size_in_meters = GetDisplaySize();
-  vec2 meters_per_pixel(size_in_meters[0] / static_cast<float>(screen_size[0]),
-                        size_in_meters[1] / static_cast<float>(screen_size[1]));
-  return DisplayMetrics(screen_size, meters_per_pixel, kScreenBorderSize,
-                        1000.0f / kScreenRefreshRate, kDisplayOrientation);
-}
-
-HeadMountMetrics CreateUndistortedHeadMountMetrics() {
-  std::vector<float> fovs = GetMaxFOVs();
-  FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]);
-  FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]);
-  return CreateUndistortedHeadMountMetrics(l_fov, r_fov);
-}
-
-HeadMountMetrics CreateUndistortedHeadMountMetrics(const FieldOfView& l_fov,
-                                                   const FieldOfView& r_fov) {
-  auto distortion_all = std::make_shared<IdentityDistortion>();
-
-  return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(),
-                          GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
-                          r_fov, distortion_all, distortion_all, distortion_all,
-                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
-                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
-                          (GetInterLensDistance() - GetDisplayGap()) / 2.0f);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libeds/display_metrics.cpp b/libs/vr/libeds/display_metrics.cpp
deleted file mode 100644
index e129395..0000000
--- a/libs/vr/libeds/display_metrics.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "include/private/dvr/display_metrics.h"
-
-namespace android {
-namespace dvr {
-
-DisplayMetrics::DisplayMetrics(vec2i size_pixels, vec2 meters_per_pixel,
-                               float border_size_meters,
-                               float frame_duration_seconds,
-                               DisplayOrientation orientation)
-    : size_pixels_(size_pixels),
-      meters_per_pixel_(meters_per_pixel),
-      border_size_meters_(border_size_meters),
-      frame_duration_seconds_(frame_duration_seconds),
-      orientation_(orientation) {}
-
-void DisplayMetrics::ToggleOrientation() {
-  std::swap(size_pixels_[0], size_pixels_[1]);
-  std::swap(meters_per_pixel_[0], meters_per_pixel_[1]);
-  if (orientation_ == DisplayOrientation::kPortrait)
-    orientation_ = DisplayOrientation::kLandscape;
-  else
-    orientation_ = DisplayOrientation::kPortrait;
-}
-
-DisplayMetrics::DisplayMetrics()
-    : DisplayMetrics(vec2i(0, 0), vec2(0.0f, 0.0f), 0.0f, 0.0f,
-                     DisplayOrientation::kLandscape) {}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libeds/distortion_renderer.cpp b/libs/vr/libeds/distortion_renderer.cpp
deleted file mode 100644
index 13090ca..0000000
--- a/libs/vr/libeds/distortion_renderer.cpp
+++ /dev/null
@@ -1,792 +0,0 @@
-#include "include/private/dvr/distortion_renderer.h"
-
-#include <float.h>
-
-#include <string>
-
-#include <utils/Log.h>
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Trace.h>
-
-#include <log/log.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/debug.h>
-#include <private/dvr/graphics/gpu_profiler.h>
-#include <private/dvr/ortho.h>
-#include <private/dvr/sensor_constants.h>
-
-#define STRINGIFY2(s) #s
-#define STRINGIFY(s) STRINGIFY2(s)
-
-#define POSITION_ATTR 0
-#define VIEWPORT_COORD_R_ATTR 1
-#define VIEWPORT_COORD_G_ATTR 2
-#define VIEWPORT_COORD_B_ATTR 3
-
-// Pose data uniform buffer bindings. Must be sequential.
-#define POSE_BINDING 0
-#define POSE_BINDING2 1
-
-// Texture unit bindings. Must be sequential.
-// Things break if we start at binding 0 (samples come back black).
-#define SAMPLER_BINDING 1
-#define SAMPLER_BINDING2 2
-
-#define GLSL_VIGNETTE_FUNC                                       \
-  "float vignette(vec2 texCoords) {\n"                           \
-  "  const float fadeDist = 0.01;\n"                             \
-  "  const float fadeDistInv = 1.0 / fadeDist;\n"                \
-  "  const float inset = 0.02;\n"                                \
-  "  vec2 lowEdge = vec2(inset - fadeDist);\n"                   \
-  "  vec2 highEdge = vec2(1.0 - inset + fadeDist);\n"            \
-  "  vec2 vignetteMin = "                                        \
-  "    clamp(-fadeDistInv * (lowEdge - texCoords), 0.0, 1.0);\n" \
-  "  vec2 vignetteMax = "                                        \
-  "    clamp(fadeDistInv * (highEdge - texCoords), 0.0, 1.0);\n" \
-  "  vec2 vignette = vignetteMin * vignetteMax;\n"               \
-  "  return vignette.x * vignette.y;\n"                          \
-  "}\n"
-
-namespace {
-
-// If enabled, the pixel shader will blend by reading back the current pixel
-// from the framebuffer.
-// TODO(jbates) With framebuffer read coherency disabled, this seems to perform
-//   well enough. That requires a GL extension, so for now we disable this path.
-constexpr bool kUseFramebufferReadback = false;
-
-static const char* kVertexShaderChromaticAberrationString =
-    "uniform mat4 uProjectionMatrix;\n"
-    "layout(binding = " STRINGIFY(POSE_BINDING) ", std140)\n"
-    "uniform LateLatchData {\n"
-    "  mat4 uTexFromRecommendedViewportMatrix;\n"
-    "};\n"
-    "#ifdef COMPOSITE_LAYER_2\n"
-    "layout(binding = " STRINGIFY(POSE_BINDING2) ", std140)\n"
-    "uniform LateLatchData2 {\n"
-    "  mat4 uTexFromRecommendedViewportMatrix2;\n"
-    "};\n"
-    "#endif\n"
-    "uniform vec4 uTexXMinMax;\n"
-    "layout(location = " STRINGIFY(POSITION_ATTR) ") in vec2 aPosition;\n"
-    "layout(location = " STRINGIFY(VIEWPORT_COORD_R_ATTR)
-           ") in vec2 aViewportCoordsR;\n"
-    "layout(location = " STRINGIFY(VIEWPORT_COORD_G_ATTR)
-           ") in vec2 aViewportCoordsG;\n"
-    "layout(location = " STRINGIFY(VIEWPORT_COORD_B_ATTR)
-           ") in vec2 aViewportCoordsB;\n"
-    "mediump out vec4 vTexCoordsRG;\n"
-    "mediump out vec2 vTexCoordsB;\n"
-    "#ifdef COMPOSITE_LAYER_2\n"
-    "mediump out vec4 vTexCoordsRG2;\n"
-    "mediump out vec2 vTexCoordsB2;\n"
-    "#endif\n"
-    "mediump out vec3 vVignette;\n"
-    "\n" GLSL_VIGNETTE_FUNC
-    "void main(void) {\n"
-    "  vVignette.r = vignette(aViewportCoordsR);\n"
-    "  vVignette.g = vignette(aViewportCoordsG);\n"
-    "  vVignette.b = vignette(aViewportCoordsB);\n"
-    "  vec4 redTexCoords = (uTexFromRecommendedViewportMatrix * \n"
-    "                       vec4(aViewportCoordsR, 0., 1.));\n"
-    "  vec4 greenTexCoords = (uTexFromRecommendedViewportMatrix * \n"
-    "                         vec4(aViewportCoordsG, 0., 1.));\n"
-    "  vec4 blueTexCoords = (uTexFromRecommendedViewportMatrix * \n"
-    "                        vec4(aViewportCoordsB, 0., 1.));\n"
-    "  vTexCoordsRG.xy = redTexCoords.xy / redTexCoords.w;\n"
-    "  vTexCoordsRG.zw = greenTexCoords.xy / greenTexCoords.w;\n"
-    "  vTexCoordsB = blueTexCoords.xy / blueTexCoords.w;\n"
-    "  vTexCoordsRG.x = clamp(vTexCoordsRG.x, uTexXMinMax.x, uTexXMinMax.y);\n"
-    "  vTexCoordsRG.z = clamp(vTexCoordsRG.z, uTexXMinMax.x, uTexXMinMax.y);\n"
-    "  vTexCoordsB.x = clamp(vTexCoordsB.x, uTexXMinMax.x, uTexXMinMax.y);\n"
-    "#ifdef COMPOSITE_LAYER_2\n"
-    "  redTexCoords = (uTexFromRecommendedViewportMatrix2 * \n"
-    "                  vec4(aViewportCoordsR, 0., 1.));\n"
-    "  greenTexCoords = (uTexFromRecommendedViewportMatrix2 * \n"
-    "                    vec4(aViewportCoordsG, 0., 1.));\n"
-    "  blueTexCoords = (uTexFromRecommendedViewportMatrix2 * \n"
-    "                   vec4(aViewportCoordsB, 0., 1.));\n"
-    "  vTexCoordsRG2.xy = redTexCoords.xy / redTexCoords.w;\n"
-    "  vTexCoordsRG2.zw = greenTexCoords.xy / greenTexCoords.w;\n"
-    "  vTexCoordsB2 = blueTexCoords.xy / blueTexCoords.w;\n"
-    "  vTexCoordsRG2.x = clamp(vTexCoordsRG2.x,\n"
-    "                          uTexXMinMax.z, uTexXMinMax.w);\n"
-    "  vTexCoordsRG2.z = clamp(vTexCoordsRG2.z, uTexXMinMax.z,\n"
-    "                          uTexXMinMax.w);\n"
-    "  vTexCoordsB2.x = clamp(vTexCoordsB2.x, uTexXMinMax.z, uTexXMinMax.w);\n"
-    "#endif\n"
-    "  gl_Position = uProjectionMatrix * vec4(aPosition, 0., 1.);\n"
-    "}\n";
-
-static const char* kFragmentShaderChromaticAberrationString =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
-    " \n"
-    "layout(binding = " STRINGIFY(SAMPLER_BINDING) ")\n"
-    "uniform sampler2D uDistortionTexture; \n"
-    "mediump in vec4 vTexCoordsRG;\n"
-    "mediump in vec2 vTexCoordsB;\n"
-    "#ifdef COMPOSITE_LAYER_2\n"
-    "layout(binding = " STRINGIFY(SAMPLER_BINDING2) ")\n"
-    "uniform sampler2D uDistortionTexture2; \n"
-    "mediump in vec4 vTexCoordsRG2;\n"
-    "mediump in vec2 vTexCoordsB2;\n"
-    "#endif\n"
-    "mediump in vec3 vVignette;\n"
-    "#ifdef BLEND_WITH_PREVIOUS_LAYER \n"
-    "inout vec4 fragColor; \n"
-    "#else \n"
-    "out vec4 fragColor; \n"
-    "#endif \n"
-    " \n"
-    "void main(void) { \n"
-    "  vec4 ra = texture(uDistortionTexture, vTexCoordsRG.xy); \n"
-    "  vec4 ga = texture(uDistortionTexture, vTexCoordsRG.zw); \n"
-    "  vec4 ba = texture(uDistortionTexture, vTexCoordsB); \n"
-    "#ifdef BLEND_WITH_PREVIOUS_LAYER \n"
-    "  vec3 alpha1 = vec3(ra.a, ga.a, ba.a); \n"
-    "  vec3 color = (vec3(1.0) - alpha1) * fragColor.rgb + \n"
-    "               alpha1 * vec3(ra.r, ga.g, ba.b); \n"
-    "#else // BLEND_WITH_PREVIOUS_LAYER \n"
-    "  vec3 color = vec3(ra.r, ga.g, ba.b); \n"
-    "#endif // BLEND_WITH_PREVIOUS_LAYER \n"
-    "#ifdef COMPOSITE_LAYER_2 \n"
-    "  // Alpha blend layer 2 onto layer 1. \n"
-    "  vec4 ra2 = texture(uDistortionTexture2, vTexCoordsRG2.xy); \n"
-    "  vec4 ga2 = texture(uDistortionTexture2, vTexCoordsRG2.zw); \n"
-    "  vec4 ba2 = texture(uDistortionTexture2, vTexCoordsB2); \n"
-    "  vec3 color2 = vec3(ra2.r, ga2.g, ba2.b); \n"
-    "  vec3 alpha2 = vec3(ra2.a, ga2.a, ba2.a); \n"
-    "  color = (vec3(1.0) - alpha2) * color + alpha2 * color2; \n"
-    "#endif \n"
-    "#ifdef ALPHA_VIGNETTE\n"
-    "  fragColor = vec4(color, vVignette.b * ga.a); \n"
-    "#else // ALPHA_VIGNETTE\n"
-    "  fragColor = vec4(vVignette.rgb * color, ga.a); \n"
-    "#endif // ALPHA_VIGNETTE\n"
-    "} \n";
-
-static const char* kVertexShaderNoChromaticAberrationString =
-    "uniform mat4 uProjectionMatrix;\n"
-    "layout(binding = " STRINGIFY(POSE_BINDING) ", std140)\n"
-    "uniform LateLatchData {\n"
-    "  mat4 uTexFromRecommendedViewportMatrix;\n"
-    "};\n"
-    "#ifdef COMPOSITE_LAYER_2\n"
-    "layout(binding = " STRINGIFY(POSE_BINDING2) ", std140)\n"
-    "uniform LateLatchData2 {\n"
-    "  mat4 uTexFromRecommendedViewportMatrix2;\n"
-    "};\n"
-    "#endif\n"
-    "uniform vec4 uTexXMinMax;\n"
-    "layout(location = " STRINGIFY(POSITION_ATTR) ") in vec2 aPosition;\n"
-    "layout(location = " STRINGIFY(VIEWPORT_COORD_G_ATTR)
-           ") in vec2 aViewportCoords;\n"
-    "mediump out vec2 vTexCoords;\n"
-    "#ifdef COMPOSITE_LAYER_2\n"
-    "mediump out vec2 vTexCoords2;\n"
-    "#endif\n"
-    "mediump out vec3 vVignette;\n"
-    "\n" GLSL_VIGNETTE_FUNC
-    "void main(void) {\n"
-    "  float fVignette = vignette(aViewportCoords);\n"
-    "  vVignette = vec3(fVignette, fVignette, fVignette);\n"
-    "  vec4 texCoords = (uTexFromRecommendedViewportMatrix * \n"
-    "                    vec4(aViewportCoords, 0., 1.));\n"
-    "  vTexCoords = texCoords.xy / texCoords.w;\n"
-    "  vTexCoords.x = clamp(vTexCoords.x, uTexXMinMax.x, uTexXMinMax.y);\n"
-    "#ifdef COMPOSITE_LAYER_2\n"
-    "  texCoords = (uTexFromRecommendedViewportMatrix2 * \n"
-    "               vec4(aViewportCoords, 0., 1.));\n"
-    "  vTexCoords2 = texCoords.xy / texCoords.w;\n"
-    "  vTexCoords2.x = clamp(vTexCoords2.x, uTexXMinMax.z, uTexXMinMax.w);\n"
-    "#endif\n"
-    "  gl_Position = uProjectionMatrix * vec4(aPosition, 0., 1.);\n"
-    "}\n";
-
-static const char* kFragmentShaderNoChromaticAberrationString =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
-    " \n"
-    "layout(binding = " STRINGIFY(SAMPLER_BINDING) ")\n"
-    "uniform sampler2D uDistortionTexture; \n"
-    "mediump in vec2 vTexCoords;\n"
-    "#ifdef COMPOSITE_LAYER_2\n"
-    "layout(binding = " STRINGIFY(SAMPLER_BINDING2) ")\n"
-    "uniform sampler2D uDistortionTexture2; \n"
-    "mediump in vec2 vTexCoords2;\n"
-    "#endif\n"
-    "mediump in vec3 vVignette;\n"
-    "out vec4 fragColor;\n"
-    " \n"
-    "void main(void) { \n"
-    "  vec4 color = texture(uDistortionTexture, vTexCoords); \n"
-    "#ifdef COMPOSITE_LAYER_2 \n"
-    "  // Alpha blend layer 2 onto layer 1. \n"
-    "  vec4 color2 = texture(uDistortionTexture2, vTexCoords2); \n"
-    "  float alpha2 = color2.a; \n"
-    "  color.rgb = (1.0 - alpha2) * color.rgb + alpha2 * color2.rgb; \n"
-    "#endif \n"
-    "  fragColor = vec4(vVignette * color.rgb, color.a); \n"
-    "} \n";
-
-static const char* kVertexShaderSimpleVideoQuadString =
-    "uniform mat4 uProjectionMatrix;\n"
-    "layout(binding = " STRINGIFY(POSE_BINDING) ", std140)\n"
-    "uniform LateLatchData {\n"
-    "  mat4 uEdsCorrection;\n"
-    "};\n"
-    "uniform mat4 uTexFromEyeMatrix;\n"
-    "uniform mat4 uEyeFromViewportMatrix;\n"
-    "layout(location = " STRINGIFY(POSITION_ATTR) ") in vec2 aPosition;\n"
-    "layout(location = " STRINGIFY(VIEWPORT_COORD_G_ATTR)
-           ") in vec2 aViewportCoords;\n"
-    "mediump out vec2 vTexCoords;\n"
-    "void main(void) {\n"
-    "  mat4 m = uTexFromEyeMatrix * inverse(uEdsCorrection) * uEyeFromViewportMatrix;\n"
-    "  mat3 uTexFromViewportMatrix = inverse(mat3(m[0].xyw, m[1].xyw, m[3].xyw)); \n"
-    "  vec3 texCoords = uTexFromViewportMatrix * vec3(aViewportCoords, 1.0);\n"
-    "  vTexCoords = texCoords.xy / texCoords.z;\n"
-    "  gl_Position = uProjectionMatrix * vec4(aPosition, 0.0, 1.0);\n"
-    "}\n";
-
-static const char* kFragmentShaderSimpleVideoQuadString =
-    "#extension GL_OES_EGL_image_external_essl3 : enable\n"
-    " \n"
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
-    " \n"
-    "layout(binding = " STRINGIFY(SAMPLER_BINDING) ")\n"
-    "uniform samplerExternalOES uDistortionTexture; \n"
-    "mediump in vec2 vTexCoords;\n"
-    "out vec4 fragColor;\n"
-    " \n"
-    "void main(void) { \n"
-    "  if (clamp(vTexCoords, 0.0, 1.0) != vTexCoords) { \n"
-    "    fragColor = vec4(0.0, 0.0, 0.0, 0.0); \n"
-    "  } else { \n"
-    "    fragColor = texture(uDistortionTexture, vTexCoords); \n"
-    "  } \n"
-    "} \n";
-
-}  // anonymous namespace
-
-namespace android {
-namespace dvr {
-
-// Note that converting from Clip Space ([-1,1]^3) to Viewport Space
-// for one eye ([0,1]x[0,1]) requires dividing by 2 in x and y.
-const mat4 DistortionRenderer::kViewportFromClipMatrix =
-    Eigen::Translation3f(vec3(0.5f, 0.5f, 0)) *
-    Eigen::DiagonalMatrix<float, 3>(vec3(0.5f, 0.5f, 1.0f));
-
-const mat4 DistortionRenderer::kClipFromViewportMatrix =
-    Eigen::DiagonalMatrix<float, 3>(vec3(2.0f, 2.0f, 1.0f)) *
-    Eigen::Translation3f(vec3(-0.5f, -0.5f, 0));
-
-void DistortionRenderer::EdsShader::load(const char* vertex,
-                                         const char* fragment, int num_layers,
-                                         bool use_alpha_vignette,
-                                         float rotation, bool flip_vertical,
-                                         bool blend_with_previous_layer) {
-  std::string vert_builder = "#version 310 es\n";
-  std::string frag_builder = "#version 310 es\n";
-  if (blend_with_previous_layer && kUseFramebufferReadback) {
-    frag_builder += "#extension GL_EXT_shader_framebuffer_fetch : require\n";
-  }
-
-  if (num_layers == 2) {
-    vert_builder += "#define COMPOSITE_LAYER_2\n";
-    frag_builder += "#define COMPOSITE_LAYER_2\n";
-  } else {
-    LOG_ALWAYS_FATAL_IF(num_layers != 1);
-  }
-  if (blend_with_previous_layer) {
-    // Check for unsupported shader combinations:
-    LOG_ALWAYS_FATAL_IF(num_layers != 1);
-    LOG_ALWAYS_FATAL_IF(use_alpha_vignette);
-    if (kUseFramebufferReadback)
-      frag_builder += "#define BLEND_WITH_PREVIOUS_LAYER\n";
-  }
-  if (use_alpha_vignette) {
-    vert_builder += "#define ALPHA_VIGNETTE\n";
-    frag_builder += "#define ALPHA_VIGNETTE\n";
-  }
-
-  vert_builder += vertex;
-  frag_builder += fragment;
-  pgm.Link(vert_builder, frag_builder);
-  LOG_ALWAYS_FATAL_IF(!pgm.IsUsable());
-
-  pgm.Use();
-
-  uProjectionMatrix =
-      glGetUniformLocation(pgm.GetProgram(), "uProjectionMatrix");
-  uTexFromEyeMatrix =
-      glGetUniformLocation(pgm.GetProgram(), "uTexFromEyeMatrix");
-  uEyeFromViewportMatrix =
-      glGetUniformLocation(pgm.GetProgram(), "uEyeFromViewportMatrix");
-  uTexXMinMax = glGetUniformLocation(pgm.GetProgram(), "uTexXMinMax");
-  CHECK_GL();
-
-  float vertical_multiply = flip_vertical ? -1.0 : 1.0;
-  mat4 projectionMatrix = OrthoMatrix(-0.5f, 0.5f, vertical_multiply * -0.5f,
-                                      vertical_multiply * 0.5f, -1.0f, 1.0f);
-
-  // Rotate the mesh into the screen's orientation.
-  // TODO(hendrikw): Once the display is finalized, and perhaps not portrait,
-  //                 look into removing this matrix altogether.
-  projectionMatrix =
-      projectionMatrix * Eigen::AngleAxisf(rotation, vec3::UnitZ());
-
-  LOG_ALWAYS_FATAL_IF(sizeof(mat4) != 4 * 4 * 4);
-  glUniformMatrix4fv(uProjectionMatrix, 1, false, projectionMatrix.data());
-}
-
-DistortionRenderer::DistortionRenderer(
-    const CompositeHmd& hmd, vec2i display_size, int distortion_mesh_resolution,
-    bool flip_texture_horizontally, bool flip_texture_vertically,
-    bool separated_eye_buffers, bool eds_enabled, bool late_latch_enabled)
-    : shader_type_(kChromaticAberrationCorrection),
-      eds_enabled_(eds_enabled),
-      chromatic_aberration_correction_enabled_(true),
-      use_alpha_vignette_(false),
-      distortion_mesh_resolution_(distortion_mesh_resolution),
-      last_distortion_texture_id_(0),
-      app_texture_target_(GL_TEXTURE_2D),
-      display_size_(display_size),
-      separated_eye_buffers_(separated_eye_buffers) {
-  ATRACE_NAME("DistortionRenderer::DistortionRenderer");
-
-  float device_rotation = 0.0;
-
-  if (eds_enabled_) {
-    // Late latch must be on if eds_enabled_ is true.
-    if (!late_latch_enabled) {
-      ALOGE("Cannot enable EDS without late latch. Force enabling late latch.");
-      late_latch_enabled = true;
-    }
-  }
-
-  // TODO(hendrikw): Look into moving this logic into DisplayMetrics.
-  if (hmd.GetDisplayMetrics().IsPortrait()) {
-    device_rotation = -M_PI / 2.0f;
-  }
-
-  // Create shader programs.
-  shaders_[kNoChromaticAberrationCorrection].load(
-      kVertexShaderNoChromaticAberrationString,
-      kFragmentShaderNoChromaticAberrationString, 1, false, device_rotation,
-      flip_texture_horizontally, false);
-  shaders_[kNoChromaticAberrationCorrectionTwoLayers].load(
-      kVertexShaderNoChromaticAberrationString,
-      kFragmentShaderNoChromaticAberrationString, 2, false, device_rotation,
-      flip_texture_horizontally, false);
-  shaders_[kChromaticAberrationCorrection].load(
-      kVertexShaderChromaticAberrationString,
-      kFragmentShaderChromaticAberrationString, 1, false, device_rotation,
-      flip_texture_horizontally, false);
-  shaders_[kChromaticAberrationCorrectionTwoLayers].load(
-      kVertexShaderChromaticAberrationString,
-      kFragmentShaderChromaticAberrationString, 2, false, device_rotation,
-      flip_texture_horizontally, false);
-  shaders_[kChromaticAberrationCorrectionAlphaVignette].load(
-      kVertexShaderChromaticAberrationString,
-      kFragmentShaderChromaticAberrationString, 1, true, device_rotation,
-      flip_texture_horizontally, false);
-  shaders_[kChromaticAberrationCorrectionAlphaVignetteTwoLayers].load(
-      kVertexShaderChromaticAberrationString,
-      kFragmentShaderChromaticAberrationString, 2, true, device_rotation,
-      flip_texture_horizontally, false);
-  shaders_[kChromaticAberrationCorrectionWithBlend].load(
-      kVertexShaderChromaticAberrationString,
-      kFragmentShaderChromaticAberrationString, 1, false, device_rotation,
-      flip_texture_horizontally, true);
-  shaders_[kSimpleVideoQuad].load(
-      kVertexShaderSimpleVideoQuadString,
-      kFragmentShaderSimpleVideoQuadString, 1, false, device_rotation,
-      flip_texture_horizontally, true);
-  CHECK_GL();
-
-  mat4 tex_from_recommended_viewport_matrix[2][2][2];
-  for (int eye = 0; eye < 2; ++eye) {
-    // Near and far plane don't actually matter for the clip_from_eye_matrix
-    // below since it is only used (for EDS) to transform coordinates for
-    // which the Z has been dropped.
-    static const float kNear = 0.1f, kFar = 100.0f;
-    const FieldOfView& fov =
-        (eye == kLeftEye ? hmd.GetEyeFov(kLeftEye) : hmd.GetEyeFov(kRightEye));
-    mat4 c_clip_from_eye_matrix = fov.GetProjectionMatrix(kNear, kFar);
-    mat4 c_eye_from_clip_matrix = c_clip_from_eye_matrix.inverse();
-
-    // Compute tex_from_recommended_viewport_matrix.
-
-    // flip_texture_vertically defines the default flip behavior.
-    // do_flip[0] should be the default, while do_flip[1] should be the
-    // inverse of the default.
-    int do_flip[2] = {flip_texture_vertically ? 1 : 0,
-                      flip_texture_vertically ? 0 : 1};
-    for (int flip = 0; flip < 2; ++flip) {
-      vec2 flip_scale(1.0f, do_flip[flip] ? -1.0f : 1.0f);
-      vec2 flip_offset(0.0f, do_flip[flip] ? 1.0f : 0.0f);
-
-      for (int separate_eye = 0; separate_eye < 2; ++separate_eye) {
-        vec2 viewport_corner_offset = (eye == kLeftEye || separate_eye)
-                                          ? vec2(0.0f, 0.0f)
-                                          : vec2(0.5f, 0.0f);
-        const vec2 txy = viewport_corner_offset + flip_offset;
-        const vec2 scalexy = vec2(separate_eye ? 1.0f : 0.5f, 1.0f);
-        tex_from_recommended_viewport_matrix[eye][flip][separate_eye] =
-            Eigen::Translation3f(vec3(txy.x(), txy.y(), 0.0f)) *
-            Eigen::DiagonalMatrix<float, 3>(vec3(flip_scale.x() * scalexy.x(),
-                                                 flip_scale.y(), scalexy.y()));
-
-        tex_from_eye_matrix_[eye][flip][separate_eye] =
-            tex_from_recommended_viewport_matrix[eye][flip][separate_eye] *
-            kViewportFromClipMatrix * c_clip_from_eye_matrix;
-      }
-    }
-
-    eye_from_viewport_matrix_[eye] =
-        c_eye_from_clip_matrix * kClipFromViewportMatrix;
-  }
-
-  // Create UBO for setting the EDS matrix to identity when EDS is disabled.
-  glGenBuffers(2 * 2 * 2, &uTexFromRecommendedViewportMatrix[0][0][0]);
-  for (int eye = 0; eye < 2; ++eye) {
-    for (int flip = 0; flip < 2; ++flip) {
-      for (int separate_eye = 0; separate_eye < 2; ++separate_eye) {
-        glBindBuffer(
-            GL_UNIFORM_BUFFER,
-            uTexFromRecommendedViewportMatrix[eye][flip][separate_eye]);
-        glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), 0, GL_STATIC_DRAW);
-        CHECK_GL();
-        mat4* mat = static_cast<mat4*>(glMapBufferRange(
-            GL_UNIFORM_BUFFER, 0, sizeof(mat4), GL_MAP_WRITE_BIT));
-        CHECK_GL();
-        *mat = tex_from_recommended_viewport_matrix[eye][flip][separate_eye];
-        glUnmapBuffer(GL_UNIFORM_BUFFER);
-      }
-    }
-  }
-  glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
-  // Create distortion meshes and associated GL resources.
-  glGenBuffers(2, mesh_vbo_);
-  glGenVertexArrays(2, mesh_vao_);
-  glGenBuffers(2, mesh_ibo_);
-  RecomputeDistortion(hmd);
-
-  SetDisplaySize(display_size);
-
-  if (hmd.GetDisplayMetrics().IsPortrait()) {
-    eye_viewport_origin_[0] =
-        vec2i(0, flip_texture_horizontally ? 0 : display_size_[1] / 2);
-    eye_viewport_origin_[1] =
-        vec2i(0, flip_texture_horizontally ? display_size_[1] / 2 : 0);
-    eye_viewport_size_ = vec2i(display_size_[0], display_size_[1] / 2);
-  } else {
-    eye_viewport_origin_[0] = vec2i(0, 0);
-    eye_viewport_origin_[1] = vec2i(display_size_[0] / 2, 0);
-    eye_viewport_size_ = vec2i(display_size_[0] / 2, display_size_[1]);
-  }
-
-  CHECK_GL();
-}
-
-DistortionRenderer::~DistortionRenderer() {
-  glDeleteBuffers(2 * 2 * 2, &uTexFromRecommendedViewportMatrix[0][0][0]);
-  glDeleteBuffers(2, mesh_vbo_);
-  glDeleteVertexArrays(2, mesh_vao_);
-  glDeleteBuffers(2, mesh_ibo_);
-}
-
-void DistortionRenderer::ApplyDistortionCorrectionToTexture(
-    EyeType eye, const GLuint* texture_ids, const bool* vertical_flip,
-    const bool* separate_eye, const int* late_latch_layer, int num_textures,
-    bool blend_with_previous_layer, bool do_gl_state_prep) {
-  ATRACE_NAME(__PRETTY_FUNCTION__);
-
-  bool use_gl_blend = use_alpha_vignette_ ||
-                      (blend_with_previous_layer && !kUseFramebufferReadback);
-  if (use_gl_blend) {
-    glEnable(GL_BLEND);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  }
-  DrawEye(eye, texture_ids, vertical_flip, separate_eye, late_latch_layer,
-          num_textures, blend_with_previous_layer, do_gl_state_prep);
-  if (use_gl_blend) {
-    glDisable(GL_BLEND);
-  }
-  CHECK_GL();
-}
-
-void DistortionRenderer::DrawVideoQuad(EyeType eye, int layer_i,
-                                       GLuint texture_id,
-                                       const mat4& transform) {
-  shaders_[kSimpleVideoQuad].use();
-
-  shaders_[kSimpleVideoQuad].SetTexFromEyeTransform(
-      tex_from_eye_matrix_[eye][0][1]);
-  shaders_[kSimpleVideoQuad].SetEyeFromViewportTransform(
-      transform * kClipFromViewportMatrix);
-
-  if (eds_enabled_) {
-    // Bind late latch view-projection UBO that is produced by AddEdsLateLatch.
-    late_latch_[layer_i]->BindUniformBuffer(
-        POSE_BINDING, LateLatch::kViewMatrix, eye);
-    CHECK_GL();
-  } else {
-    // When EDS is disabled we just set the matrix here with no pose offset.
-    glBindBufferBase(GL_UNIFORM_BUFFER, POSE_BINDING + layer_i,
-                     uTexFromRecommendedViewportMatrix[eye][0][1]);
-    CHECK_GL();
-  }
-
-  glActiveTexture(GL_TEXTURE0 + SAMPLER_BINDING);
-  glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id);
-  CHECK_GL();
-
-  glDrawElements(GL_TRIANGLE_STRIP, mesh_node_[eye].indices.size(),
-                 GL_UNSIGNED_SHORT, nullptr);
-
-  CHECK_GL();
-}
-
-void DistortionRenderer::DoLateLatch(uint32_t target_vsync_count,
-                                     const uint32_t* render_buffer_index,
-                                     const GLuint* render_pose_buffer_objects,
-                                     const bool* vertical_flip,
-                                     const bool* separate_eye,
-                                     int num_textures) {
-  if (eds_enabled_) {
-    LateLatchInput data;
-    memset(&data, 0, sizeof(data));
-    for (int ti = 0; ti < num_textures; ++ti) {
-      if (late_latch_[ti] == nullptr)
-        late_latch_[ti].reset(new LateLatch(false));
-
-      int flip_index = vertical_flip[ti] ? 1 : 0;
-      int separate_eye_i = separate_eye[ti] ? 1 : 0;
-      // Copy data into late latch input struct.
-      for (int eye = 0; eye < 2; ++eye) {
-        data.eds_mat1[eye] =
-            tex_from_eye_matrix_[eye][flip_index][separate_eye_i];
-        data.eds_mat2[eye] = eye_from_viewport_matrix_[eye];
-      }
-      data.pose_index = target_vsync_count & kPoseAsyncBufferIndexMask;
-      data.render_pose_index = render_buffer_index[ti];
-
-      late_latch_[ti]->AddEdsLateLatch(data, render_pose_buffer_objects[ti]);
-    }
-  }
-}
-
-void DistortionRenderer::PrepGlState(EyeType eye) {
-  glViewport(eye_viewport_origin_[eye].x(), eye_viewport_origin_[eye].y(),
-             eye_viewport_size_.x(), eye_viewport_size_.y());
-
-  glBindVertexArray(mesh_vao_[eye]);
-  CHECK_GL();
-
-  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_ibo_[eye]);
-  CHECK_GL();
-
-  if (!eds_enabled_) {
-    glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
-  }
-}
-
-void DistortionRenderer::ResetGlState(int num_textures) {
-  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-  glBindBuffer(GL_ARRAY_BUFFER, 0);
-  glBindVertexArray(0);
-  if (eds_enabled_) {
-    for (int ti = 0; ti < num_textures; ++ti)
-      glBindBufferBase(GL_UNIFORM_BUFFER, POSE_BINDING + ti, 0);
-  } else {
-    glBindBuffer(GL_UNIFORM_BUFFER, 0);
-  }
-
-  CHECK_GL();
-
-  // Unbind all texture inputs.
-  for (int ti = 0; ti < num_textures; ++ti) {
-    glActiveTexture(GL_TEXTURE0 + SAMPLER_BINDING + ti);
-    glBindTexture(app_texture_target_, 0);
-  }
-  glActiveTexture(GL_TEXTURE0);
-}
-
-void DistortionRenderer::DrawEye(EyeType eye, const GLuint* texture_ids,
-                                 const bool* vertical_flip,
-                                 const bool* separate_eye,
-                                 const int* late_latch_layer, int num_textures,
-                                 bool blend_with_previous_layer,
-                                 bool do_gl_state_prep) {
-  if (do_gl_state_prep)
-    PrepGlState(eye);
-
-  if (num_textures > kMaxLayers) {
-    ALOGE("Too many textures for DistortionRenderer");
-    num_textures = kMaxLayers;
-  }
-
-  LOG_ALWAYS_FATAL_IF(num_textures != 1 && num_textures != 2);
-
-  if (num_textures == 2) {
-    if (chromatic_aberration_correction_enabled_) {
-      if (use_alpha_vignette_) {
-        shader_type_ = kChromaticAberrationCorrectionAlphaVignetteTwoLayers;
-      } else {
-        shader_type_ = kChromaticAberrationCorrectionTwoLayers;
-      }
-    } else {
-      shader_type_ = kNoChromaticAberrationCorrectionTwoLayers;
-    }
-  } else {
-    if (chromatic_aberration_correction_enabled_) {
-      if (blend_with_previous_layer) {
-        shader_type_ = kChromaticAberrationCorrectionWithBlend;
-      } else if (use_alpha_vignette_) {
-        shader_type_ = kChromaticAberrationCorrectionAlphaVignette;
-      } else {
-        shader_type_ = kChromaticAberrationCorrection;
-      }
-    } else {
-      shader_type_ = kNoChromaticAberrationCorrection;
-    }
-  }
-  shaders_[shader_type_].use();
-
-  for (int ti = 0; ti < num_textures; ++ti) {
-    int flip_index = vertical_flip[ti] ? 1 : 0;
-    if (eds_enabled_) {
-      // Bind late latch view-projection UBO that is produced by
-      // AddEdsLateLatch.
-      late_latch_[late_latch_layer[ti]]->BindUniformBuffer(
-          POSE_BINDING + ti, LateLatch::kViewProjMatrix, eye);
-      CHECK_GL();
-    } else {
-      // When EDS is disabled we just set the matrix here with no pose offset.
-      // With app late-latching, we can't know the pose that the app used
-      // because it's in the app's framebuffer.
-      int separate_eye_i = separate_eye[ti] ? 1 : 0;
-      glBindBufferBase(
-          GL_UNIFORM_BUFFER, POSE_BINDING + ti,
-          uTexFromRecommendedViewportMatrix[eye][flip_index][separate_eye_i]);
-      CHECK_GL();
-    }
-
-    glActiveTexture(GL_TEXTURE0 + SAMPLER_BINDING + ti);
-    glBindTexture(app_texture_target_, texture_ids[ti]);
-    CHECK_GL();
-  }
-
-  // Prevents left eye data from bleeding into right eye and vice-versa.
-  vec2 layer_min_max[kMaxLayers];
-  for (int i = 0; i < kMaxLayers; ++i)
-    layer_min_max[i] = vec2(0.0f, 0.0f);
-  for (int ti = 0; ti < num_textures; ++ti) {
-    if (separate_eye[ti]) {
-      layer_min_max[ti] = vec2(0.0f, 1.0f);  // Use the whole texture.
-    } else if (eye == kLeftEye) {
-      layer_min_max[ti] = vec2(0.0f, 0.499f);
-    } else {
-      layer_min_max[ti] = vec2(0.501f, 1.0f);
-    }
-  }
-  // The second layer stores its x min and max in the z,w slots of the vec4.
-  vec4 xTexMinMax(layer_min_max[0].x(), layer_min_max[0].y(),
-                  layer_min_max[1].x(), layer_min_max[1].y());
-
-  glUniform4fv(shaders_[shader_type_].uTexXMinMax, 1, &xTexMinMax[0]);
-  CHECK_GL();
-
-  glDrawElements(GL_TRIANGLE_STRIP, mesh_node_[eye].indices.size(),
-                 GL_UNSIGNED_SHORT, nullptr);
-  CHECK_GL();
-  if (do_gl_state_prep)
-    ResetGlState(num_textures);
-}
-
-void DistortionRenderer::SetDisplaySize(vec2i display_size) {
-  display_size_ = display_size;
-}
-
-void DistortionRenderer::SetEdsEnabled(bool enabled) { eds_enabled_ = enabled; }
-
-void DistortionRenderer::RecomputeDistortion(const CompositeHmd& hmd) {
-  using std::placeholders::_1;
-  using std::placeholders::_2;
-  using std::placeholders::_3;
-  using std::placeholders::_4;
-  DistortionFunction distortion_function =
-      std::bind(&CompositeHmd::ComputeDistortedVertex, &hmd, _1, _2, _3, _4);
-
-  for (int i = 0; i < 2; ++i) {
-    mesh_node_[i] =
-        BuildDistortionMesh(static_cast<EyeType>(i),
-                            distortion_mesh_resolution_, distortion_function);
-
-    glBindVertexArray(mesh_vao_[i]);
-
-    glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo_[i]);
-    glBufferData(GL_ARRAY_BUFFER,
-                 sizeof(EdsVertex) * mesh_node_[i].vertices.size(),
-                 &mesh_node_[i].vertices.front(), GL_STATIC_DRAW);
-
-    glEnableVertexAttribArray(POSITION_ATTR);
-    glEnableVertexAttribArray(VIEWPORT_COORD_R_ATTR);
-    glEnableVertexAttribArray(VIEWPORT_COORD_G_ATTR);
-    glEnableVertexAttribArray(VIEWPORT_COORD_B_ATTR);
-
-    glVertexAttribPointer(
-        POSITION_ATTR, 2, GL_FLOAT, GL_FALSE, sizeof(EdsVertex),
-        reinterpret_cast<void*>(offsetof(EdsVertex, position)));
-
-    glVertexAttribPointer(
-        VIEWPORT_COORD_R_ATTR, 2, GL_FLOAT, GL_FALSE, sizeof(EdsVertex),
-        reinterpret_cast<void*>(offsetof(EdsVertex, red_viewport_coords)));
-
-    glVertexAttribPointer(
-        VIEWPORT_COORD_G_ATTR, 2, GL_FLOAT, GL_FALSE, sizeof(EdsVertex),
-        reinterpret_cast<void*>(offsetof(EdsVertex, green_viewport_coords)));
-
-    glVertexAttribPointer(
-        VIEWPORT_COORD_B_ATTR, 2, GL_FLOAT, GL_FALSE, sizeof(EdsVertex),
-        reinterpret_cast<void*>(offsetof(EdsVertex, blue_viewport_coords)));
-
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_ibo_[i]);
-    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
-                 sizeof(uint16_t) * mesh_node_[i].indices.size(),
-                 &mesh_node_[i].indices.front(), GL_STATIC_DRAW);
-    CHECK_GL();
-  }
-  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-  glBindBuffer(GL_ARRAY_BUFFER, 0);
-
-  glBindVertexArray(0);
-}
-
-bool DistortionRenderer::GetLastEdsPose(LateLatchOutput* out_data, int layer_id) const {
-  if (layer_id >= kMaxLayers) {
-    ALOGE("Accessing invalid layer %d", layer_id);
-    return false;
-  }
-
-  if (late_latch_[layer_id] != nullptr) {
-    late_latch_[layer_id]->CaptureOutputData(out_data);
-    return true;
-  } else {
-    ALOGE("Late latch shader not enabled.");
-    return false;
-  }
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libeds/eds.cpp b/libs/vr/libeds/eds.cpp
deleted file mode 100644
index 8af5b27..0000000
--- a/libs/vr/libeds/eds.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <dvr/eds.h>
-
-#include <private/dvr/graphics/vr_gl_extensions.h>
-#include <private/dvr/late_latch.h>
-#include <private/dvr/types.h>
-
-// TODO(jbates) delete this file and eds.h
-
-extern "C" int dvrEdsInit(bool with_late_latch) { return 0; }
-
-extern "C" void dvrEdsDeinit() {}
-
-extern "C" int dvrEdsCapturePoseAsync(int eye, uint32_t target_vsync_count,
-                                      const float* projection_matrix,
-                                      const float* eye_from_head_matrix,
-                                      const float* pose_offset_matrix) {
-  return 0;
-}
-
-extern "C" int dvrEdsBindPose(int eye, uint32_t ubo_binding, intptr_t offset,
-                              ssize_t size) {
-  return 0;
-}
-
-extern "C" int dvrEdsBlitPose(int eye, int viewport_width,
-                              int viewport_height) {
-  return 0;
-}
-
-extern "C" int dvrEdsBlitPoseFromCpu(int eye, int viewport_width,
-                                     int viewport_height,
-                                     const float* pose_quaternion,
-                                     const float* pose_position) {
-  return 0;
-}
diff --git a/libs/vr/libeds/eds_mesh.cpp b/libs/vr/libeds/eds_mesh.cpp
deleted file mode 100644
index 01a90cf..0000000
--- a/libs/vr/libeds/eds_mesh.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "include/private/dvr/eds_mesh.h"
-
-#include <log/log.h>
-#include <math.h>
-
-#include <private/dvr/types.h>
-
-namespace {
-
-using android::dvr::EdsVertex;
-using android::dvr::EyeType;
-using android::dvr::DistortionFunction;
-using android::dvr::vec2;
-
-// Computes the vertices for a distortion mesh with resolution |resolution| and
-// distortion provided by |hmd| and stores them in |vertices|.
-static void ComputeDistortionMeshVertices(
-    EdsVertex* vertices, int resolution,
-    const DistortionFunction& distortion_function, EyeType eye) {
-  for (int row = 0; row < resolution; row++) {
-    for (int col = 0; col < resolution; col++) {
-      const float x_norm =
-          static_cast<float>(col) / (static_cast<float>(resolution - 1U));
-      const float y_norm =
-          static_cast<float>(row) / (static_cast<float>(resolution - 1U));
-
-      const vec2 xy_norm(x_norm, y_norm);
-      const size_t index = col * resolution + row;
-
-      // Evaluate distortion function to get the new coordinates for each color
-      // channel. The distortion function returns the new coordinates relative
-      // to a full viewport with 0 <= x <= 1 for each eye.
-      vec2 coords[3];
-      distortion_function(eye, xy_norm, &vertices[index].position, coords);
-
-      // Store distortion mapping in texture coordinates.
-      vertices[index].red_viewport_coords = coords[0];
-      vertices[index].green_viewport_coords = coords[1];
-      vertices[index].blue_viewport_coords = coords[2];
-    }
-  }
-}
-
-// Computes the triangle strip indices for a distortion mesh with resolution
-// |resolution| and stores them in |indices|.
-static void ComputeDistortionMeshIndices(uint16_t* indices, int resolution) {
-  // The following strip method has been used in the Cardboard SDK
-  // (java/com/google/vrtoolkit/cardboard/DistortionRenderer.java) and has
-  // originally been described at:
-  //
-  // http://dan.lecocq.us/wordpress/2009/12/25/triangle-strip-for-grids-a-construction/
-  //
-  // For a grid with 4 rows and 4 columns of vertices, the strip would
-  // look like:
-  //                             ↻
-  //         0    -    4    -    8    -   12
-  //         ↓    ↗    ↓    ↗    ↓    ↗    ↓
-  //         1    -    5    -    9    -   13
-  //         ↓    ↖    ↓    ↖    ↓    ↖    ↓
-  //         2    -    6    -   10    -   14
-  //         ↓    ↗    ↓    ↗    ↓    ↗    ↓
-  //         3    -    7    -   11    -   15
-  //                   ↺
-  //
-  // Note the little circular arrows next to 7 and 8 that indicate
-  // repeating that vertex once so as to produce degenerate triangles.
-  //
-  // To facilitate scanline racing, the vertex order is left to right.
-
-  int16_t index_offset = 0;
-  int16_t vertex_offset = 0;
-  for (int row = 0; row < resolution - 1; ++row) {
-    if (row > 0) {
-      indices[index_offset] = indices[index_offset - 1];
-      ++index_offset;
-    }
-    for (int col = 0; col < resolution; ++col) {
-      if (col > 0) {
-        if (row % 2 == 0) {
-          // Move right on even rows.
-          ++vertex_offset;
-        } else {
-          --vertex_offset;
-        }
-      }
-      // A cast to uint16_t is safe here as |vertex_offset| will not drop below
-      // zero in this loop. As col is initially equal to zero |vertex_offset| is
-      // always incremented before being decremented, is initialized to zero and
-      // is only incremented outside of the loop.
-      indices[index_offset++] = static_cast<uint16_t>(vertex_offset);
-      indices[index_offset++] = static_cast<uint16_t>(
-          vertex_offset + static_cast<int16_t>(resolution));
-    }
-    vertex_offset =
-        static_cast<int16_t>(static_cast<int>(resolution) + vertex_offset);
-  }
-}
-
-}  // anonymous namespace
-
-namespace android {
-namespace dvr {
-
-// Builds a distortion mesh of resolution |resolution| using the distortion
-// provided by |hmd| for |eye|.
-EdsMesh BuildDistortionMesh(EyeType eye, int resolution,
-                            const DistortionFunction& distortion_function) {
-  LOG_ALWAYS_FATAL_IF(resolution <= 2);
-
-  // Number of indices produced by the strip method
-  // (see comment in ComputeDistortionMeshIndices):
-  //
-  //     1 vertex per triangle
-  //     2 triangles per quad, (rows - 1) * (cols - 1) quads
-  //     2 vertices at the start of each row for the first triangle
-  //     1 extra vertex per row (except first and last) for a
-  //       degenerate triangle
-  //
-  const uint16_t index_count =
-      static_cast<uint16_t>(resolution * (2 * resolution - 1U) - 2U);
-  const uint16_t vertex_count = static_cast<uint16_t>(resolution * resolution);
-
-  EdsMesh mesh;
-  mesh.vertices.resize(vertex_count);
-  mesh.indices.resize(index_count);
-
-  // Populate vertex and index buffer.
-  ComputeDistortionMeshVertices(&mesh.vertices[0], resolution,
-                                distortion_function, eye);
-  ComputeDistortionMeshIndices(&mesh.indices[0], resolution);
-
-  return mesh;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libeds/include/CPPLINT.cfg b/libs/vr/libeds/include/CPPLINT.cfg
deleted file mode 100644
index 2f8a3c0..0000000
--- a/libs/vr/libeds/include/CPPLINT.cfg
+++ /dev/null
@@ -1 +0,0 @@
-filter=-build/header_guard
diff --git a/libs/vr/libeds/include/dvr/eds.h b/libs/vr/libeds/include/dvr/eds.h
deleted file mode 100644
index 37b1297..0000000
--- a/libs/vr/libeds/include/dvr/eds.h
+++ /dev/null
@@ -1,150 +0,0 @@
-#ifndef ANDROID_DVR_EDS_H_
-#define ANDROID_DVR_EDS_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-__BEGIN_DECLS
-
-// This struct aligns with GLSL uniform blocks with std140 layout.
-// std140 allows padding between certain types, so padding must be explicitly
-// added as struct members.
-struct __attribute__((__packed__)) DvrLateLatchData {
-  // Column-major order.
-  float view_proj_matrix[16];
-  // Column-major order.
-  float view_matrix[16];
-  float pose_quaternion[4];
-  float pose_position[4];
-};
-
-//
-// These APIs are not thread safe and must be called on a single thread with an
-// actively bound GL context corresponding to a display surface.
-//
-
-// Prepares EDS and Late Latching system. Idempotent if called more than once.
-// The target GL context must be created and bound.
-//
-// If |with_late_latch| is true, a thread will be created that asynchronously
-// updates the pose in memory.
-//
-// The following GL states are modified as follows:
-// glBindBuffer(GL_ARRAY_BUFFER, 0);
-// glBindBuffer(GL_UNIFORM_BUFFER, 0);
-//
-// Returns 0 on success, negative error code on failure.
-// Check GL errors with glGetError for other error conditions.
-int dvrEdsInit(bool with_late_latch);
-
-// Stops and destroys the EDS Late Latching system.
-void dvrEdsDeinit();
-
-// Submits GL draw command that will capture the latest head pose into a uniform
-// buffer object. This should be called twice per frame, before the app begins
-// drawing for each eye.
-// For each eye, a later call to dvrEdsBlitPose will write this pose into
-// the application framebuffer corner so that the EDS service knows what pose
-// the frame was rendered with.
-//
-// |eye| is 0 for left eye and 1 for right eye.
-//
-// The following GL states are modified as follows:
-// glUseProgram(0);
-// glBindBuffer(GL_UNIFORM_BUFFER, 0);
-// glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, id);
-// glDisable(GL_RASTERIZER_DISCARD);
-//
-// Returns 0 on success, negative error code on failure:
-//   EPERM - dvrEdsInit(true) was not called.
-// Check GL errors with glGetError for other error conditions.
-int dvrEdsCapturePoseAsync(int eye, uint32_t target_vsync_count,
-                           const float* projection_matrix,
-                           const float* eye_from_head_matrix,
-                           const float* pose_offset_matrix);
-
-// Binds the late-latch output data as a GL_UNIFORM_BUFFER so that your vertex
-// shaders can use the latest head pose. For example, to bind just the
-// view_matrix from the output:
-//
-// dvrEdsBindPose(eye, BINDING,
-//                       offsetof(DvrLateLatchData, view_matrix),
-//                       sizeof(DvrLateLatchData::view_matrix));
-//
-// Or more commonly, bind the view projection matrix:
-//
-// dvrEdsBindPose(eye, BINDING,
-//                       offsetof(DvrLateLatchData, view_proj_matrix),
-//                       sizeof(DvrLateLatchData::view_proj_matrix));
-//
-// BINDING in the above examples is the binding location of the uniform
-// interface block in the GLSL shader.
-//
-// Shader example (3 would be the |ubo_binding| passed to this function):
-//  layout(binding = 3, std140) uniform LateLatchData {
-//    mat4 uViewProjection;
-//  };
-//
-// |eye| is 0 for left eye and 1 for right eye.
-//
-// The following GL states are modified as follows:
-// glBindBuffer(GL_UNIFORM_BUFFER, ...);
-// glBindBufferRange(GL_UNIFORM_BUFFER, ...);
-//
-// To clear the binding, call glBindBuffer(GL_UNIFORM_BUFFER, 0);
-//
-// Returns 0 on success, negative error code on failure:
-//   EPERM - dvrEdsInit(true) was not called.
-// Check GL errors with glGetError for other error conditions.
-int dvrEdsBindPose(int eye, uint32_t ubo_binding, intptr_t offset,
-                   ssize_t size);
-
-// DEPRECATED
-//
-// Blits the pose captured previously into the currently bound framebuffer.
-// The current framebuffer is assumed to be the default framebuffer 0, the
-// surface that will be sent to the display and have EDS and lens warp applied
-// to it.
-//
-// |eye| is 0 for left eye and 1 for right eye.
-// |viewport_width| is the width of the viewport for this eye, which is
-//                  usually half the width of the framebuffer.
-// |viewport_height| is the height of the viewport for this eye, which is
-//                   usually the height of the framebuffer.
-//
-// The following GL states are modified as follows:
-// glUseProgram(0);
-// glBindBuffer(GL_UNIFORM_BUFFER, 0);
-// glBindBufferRange(GL_UNIFORM_BUFFER, 23, ...);
-//
-// Returns 0 on success, negative error code on failure:
-//   EPERM - dvrEdsInit was not called.
-// Check GL errors with glGetError for other error conditions.
-int dvrEdsBlitPose(int eye, int viewport_width, int viewport_height);
-
-// DEPRECATED
-//
-// Same as dvrEdsBlitPose except that the pose is provided as an
-// parameter instead of getting it from dvrEdsBindPose. This is for
-// applications that want EDS but do not want late-latching.
-//
-// |pose_quaternion| should point to 4 floats that represent a quaternion.
-// |pose_position| should point to 3 floats that represent x,y,z position.
-//
-// GL states are modified as follows:
-// glUseProgram(0);
-// glBindBuffer(GL_UNIFORM_BUFFER, 0);
-// glBindBufferBase(GL_UNIFORM_BUFFER, 23, ...);
-//
-// Returns 0 on success, negative error code on failure:
-//   EPERM - dvrEdsInit was not called.
-// Check GL errors with glGetError for other error conditions.
-int dvrEdsBlitPoseFromCpu(int eye, int viewport_width, int viewport_height,
-                          const float* pose_quaternion,
-                          const float* pose_position);
-
-__END_DECLS
-
-#endif  // ANDROID_DVR_EDS_H_
diff --git a/libs/vr/libeds/include/private/dvr/color_channel_distortion.h b/libs/vr/libeds/include/private/dvr/color_channel_distortion.h
deleted file mode 100644
index 4e612cd..0000000
--- a/libs/vr/libeds/include/private/dvr/color_channel_distortion.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef ANDROID_DVR_COLOR_CHANNEL_DISTORTION_H_
-#define ANDROID_DVR_COLOR_CHANNEL_DISTORTION_H_
-
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-// ColorChannelDistortion encapsulates the way one color channel (wavelength)
-// is distorted optically when an image is viewed through a lens.
-class ColorChannelDistortion {
- public:
-  virtual ~ColorChannelDistortion() {}
-
-  // Given a 2d point p, returns the corresponding distorted point.
-  // The units of both the input and output points are tan-angle units,
-  // which can be computed as the distance on the screen divided by
-  // distance from the virtual eye to the screen.  For both the input
-  // and output points, the intersection of the optical axis of the lens
-  // with the screen defines the origin, the x axis points right, and
-  // the y axis points up.
-  virtual vec2 Distort(vec2 p) const = 0;
-
-  virtual vec2 DistortInverse(vec2 p) const = 0;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_COLOR_CHANNEL_DISTORTION_H_
diff --git a/libs/vr/libeds/include/private/dvr/composite_hmd.h b/libs/vr/libeds/include/private/dvr/composite_hmd.h
deleted file mode 100644
index 70727e0..0000000
--- a/libs/vr/libeds/include/private/dvr/composite_hmd.h
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef ANDROID_DVR_COMPOSITE_HMD_H_
-#define ANDROID_DVR_COMPOSITE_HMD_H_
-
-#include <private/dvr/display_metrics.h>
-#include <private/dvr/head_mount_metrics.h>
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-// An intermediate structure composed of a head mount (described by
-// HeadMountMetrics) and a display (described by DisplayMetrics).
-class CompositeHmd {
- public:
-  // Constructs a new CompositeHmd given a HeadMountMetrics and a
-  // DisplayMetrics.
-  CompositeHmd(const HeadMountMetrics& head_mount_metrics,
-               const DisplayMetrics& display_metrics);
-
-  CompositeHmd(CompositeHmd&& composite_hmd) = delete;
-  CompositeHmd(const CompositeHmd& composite_hmd) = delete;
-  CompositeHmd& operator=(CompositeHmd&& composite_hmd) = delete;
-  CompositeHmd& operator=(const CompositeHmd& composite_hmd) = delete;
-
-  // Headset metadata.
-  float GetTargetFrameDuration() const;
-  void ComputeDistortedVertex(EyeType eye, vec2 uv_in, vec2* vertex_out,
-                              vec2* uv_out) const;
-
-  // Eye-unspecific view accessors.
-  vec2i GetRecommendedRenderTargetSize() const;
-  Range2i GetDisplayRange() const;
-
-  // Eye-specific view accessors.
-  mat4 GetEyeFromHeadMatrix(EyeType eye) const;
-  FieldOfView GetEyeFov(EyeType eye) const;
-  Range2i GetEyeViewportBounds(EyeType eye) const;
-
-  // Set HeadMountMetrics and recompute everything that depends on
-  // HeadMountMetrics.
-  void SetHeadMountMetrics(const HeadMountMetrics& head_mount_metrics);
-
-  // Returns a reference to the |head_mount_metrics_| member.
-  const HeadMountMetrics& GetHeadMountMetrics() const;
-
-  // Set DisplayMetrics and recompute everything that depends on DisplayMetrics.
-  void SetDisplayMetrics(const DisplayMetrics& display_metrics);
-
-  // Returns a reference to the current display metrics.
-  const DisplayMetrics& GetDisplayMetrics() const;
-
-  // Compute the distorted point for a single channel.
-  vec2 ComputeDistortedPoint(EyeType eye, vec2 position,
-                             RgbColorChannel channel) const;
-
-  // Compute the inverse distorted point for a single channel.
-  vec2 ComputeInverseDistortedPoint(EyeType eye, vec2 position,
-                                    RgbColorChannel channel) const;
-
- private:
-  FieldOfView eye_fov_[2];
-  Range2i eye_viewport_range_[2];
-  mat4 eye_from_head_matrix_[2];
-  Range2i display_range_;
-  vec2i recommended_render_target_size_;
-
-  // Per-eye scale and translation to convert from normalized Screen Space
-  // ([0:1]x[0:1]) to tan-angle space.
-  mat3 eye_tan_angle_from_norm_screen_matrix_[2];
-  mat3 eye_tan_angle_from_norm_screen_inv_matrix_[2];
-
-  // Per-eye scale and translation to convert from tan-angle space to normalized
-  // Texture Space ([0:1]x[0:1]).
-  mat3 eye_norm_texture_from_tan_angle_matrix_[2];
-  mat3 eye_norm_texture_from_tan_angle_inv_matrix_[2];
-
-  HeadMountMetrics head_mount_metrics_;
-  DisplayMetrics display_metrics_;
-
-  // Called by SetHeadMountMetrics/SetDisplayMetrics after metrics get changed.
-  // This function will update head_mount_metrics_/display_metrics_ based on the
-  // metrics supplied in the above two methods.
-  void MetricsChanged();
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_COMPOSITE_HMD_H_
diff --git a/libs/vr/libeds/include/private/dvr/device_metrics.h b/libs/vr/libeds/include/private/dvr/device_metrics.h
deleted file mode 100644
index 7985f28..0000000
--- a/libs/vr/libeds/include/private/dvr/device_metrics.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef ANDROID_DVR_DEVICE_METRICS_H_
-#define ANDROID_DVR_DEVICE_METRICS_H_
-
-#include <private/dvr/display_metrics.h>
-#include <private/dvr/head_mount_metrics.h>
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-HeadMountMetrics CreateHeadMountMetrics();
-HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov,
-                                        const FieldOfView& r_fov);
-HeadMountMetrics CreateUndistortedHeadMountMetrics();
-HeadMountMetrics CreateUndistortedHeadMountMetrics(const FieldOfView& l_fov,
-                                                   const FieldOfView& r_fov);
-DisplayMetrics CreateDisplayMetrics(vec2i screen_size);
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_DEVICE_METRICS_H_
diff --git a/libs/vr/libeds/include/private/dvr/display_metrics.h b/libs/vr/libeds/include/private/dvr/display_metrics.h
deleted file mode 100644
index 87d9d04..0000000
--- a/libs/vr/libeds/include/private/dvr/display_metrics.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef ANDROID_DVR_DISPLAY_METRICS_H_
-#define ANDROID_DVR_DISPLAY_METRICS_H_
-
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-enum class DisplayOrientation { kPortrait, kLandscape };
-
-// DisplayMetrics encapsulates metrics describing a display to be used
-// with a head mount to create a head mounted display.
-class DisplayMetrics {
- public:
-  DisplayMetrics();
-  // Constructs a DisplayMetrics given a display size in pixels,
-  // meters per pixel, border size in meters, and frame duration in
-  // seconds.
-  //
-  // size_pixels The size of the display in pixels.
-  // meters_per_pixel The meters per pixel in each dimension.
-  // border_size_meters The size of the border around the display
-  //     in meters.  When the device sits on a surface in the proper
-  //     orientation this is the distance from the surface to the edge
-  //     of the display.
-  // frame_duration_seconds The duration in seconds of each frame
-  //     (i.e., 1 / framerate).
-  DisplayMetrics(vec2i size_pixels, vec2 meters_per_pixel,
-                 float border_size_meters, float frame_duration_seconds,
-                 DisplayOrientation orientation);
-
-  // Gets the size of the display in physical pixels (not logical pixels).
-  vec2i GetSizePixels() const { return size_pixels_; }
-
-  DisplayOrientation GetOrientation() const { return orientation_; }
-  bool IsPortrait() const {
-    return orientation_ == DisplayOrientation::kPortrait;
-  }
-
-  // Gets the size of the display in meters.
-  vec2 GetSizeMeters() const {
-    return vec2(static_cast<float>(size_pixels_[0]),
-                static_cast<float>(size_pixels_[1]))
-               .array() *
-           meters_per_pixel_.array();
-  }
-
-  // Gets the meters per pixel.
-  vec2 GetMetersPerPixel() const { return meters_per_pixel_; }
-
-  // Gets the size of the border around the display.
-  // For a phone in landscape position this would be the distance from
-  // the bottom the edge of the phone to the bottom of the screen.
-  float GetBorderSizeMeters() const { return border_size_meters_; }
-
-  // Gets the frame duration in seconds for the display.
-  float GetFrameDurationSeconds() const { return frame_duration_seconds_; }
-
-  // Toggles the orientation and swaps all of the settings such that the
-  // display is being held in the other orientation.
-  void ToggleOrientation();
-
-  // Override the meters per pixel.
-  void SetMetersPerPixel(const vec2& meters_per_pixel) {
-    meters_per_pixel_ = meters_per_pixel;
-  }
-
- private:
-  vec2i size_pixels_;
-  vec2 meters_per_pixel_;
-  float border_size_meters_;
-  float frame_duration_seconds_;
-  DisplayOrientation orientation_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_DISPLAY_METRICS_H_
diff --git a/libs/vr/libeds/include/private/dvr/distortion_renderer.h b/libs/vr/libeds/include/private/dvr/distortion_renderer.h
deleted file mode 100644
index 28fd48a..0000000
--- a/libs/vr/libeds/include/private/dvr/distortion_renderer.h
+++ /dev/null
@@ -1,232 +0,0 @@
-#ifndef ANDROID_DVR_DISTORTION_RENDERER_H_
-#define ANDROID_DVR_DISTORTION_RENDERER_H_
-
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <array>
-#include <functional>
-
-#include <private/dvr/eds_mesh.h>
-#include <private/dvr/graphics/shader_program.h>
-#include <private/dvr/late_latch.h>
-#include <private/dvr/render_texture_params.h>
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-class CompositeHmd;
-
-// Encapsulates the rendering operations to correct for the HMD's lens
-// distortion.
-class DistortionRenderer {
- public:
-  static constexpr int kMaxLayers = 2;
-  static constexpr int kMaxLatchedLayers = 4;
-
-  static const mat4 kViewportFromClipMatrix;
-  static const mat4 kClipFromViewportMatrix;
-
-  // Creates a distortion renderer for distortion function.
-  //
-  // distortion_function the black-box distortion function to apply.
-  // display_size the resolution of the output of the distortion renderer.
-  // distortion_mesh_resolution the amount of subdivision in the
-  //     distortion mesh.
-  DistortionRenderer(const CompositeHmd& hmd, vec2i display_size,
-                     int distortion_mesh_resolution,
-                     bool flip_texture_horizontally,
-                     bool flip_texture_vertically, bool separated_eye_buffers,
-                     bool eds_enabled, bool late_latch_enabled);
-  ~DistortionRenderer();
-
-  // Returns the distortion factor array for the distortion function that was
-  // passed in at creation time. The distortion factor array contains the
-  // magnification factor induced by the distortion mesh at every vertex. There
-  // is one entry per vertex, and entries are ordered in row-major major. The
-  // array contains the magnification for both eyes averaged.
-  const std::vector<float>& GetDistortionFactorArray();
-
-  // |render_pose_buffer_object| is the per-texture pose array buffer object.
-  // |render_buffer_index| is the per-texture index into the pose array buffer
-  //                       object. This selects which pose was rendered into the
-  //                       corresponding texture.
-  void DoLateLatch(uint32_t target_vsync_count,
-                   const uint32_t* render_buffer_index,
-                   const GLuint* render_pose_buffer_objects,
-                   const bool* vertical_flip, const bool* separate_eye,
-                   int num_textures);
-
-  // Convenience method that does no flipping.
-  void DoLateLatch(uint32_t target_vsync_count,
-                   const uint32_t* render_buffer_index,
-                   const GLuint* render_pose_buffer_objects, int num_textures) {
-    bool flip[kMaxLayers] = {false};
-    bool separate[kMaxLayers] = {separated_eye_buffers_};
-    DoLateLatch(target_vsync_count, render_buffer_index,
-                render_pose_buffer_objects, flip, separate, num_textures);
-  }
-
-  void PrepGlState(EyeType eye);
-  void ResetGlState(int num_textures);
-
-  // Applies distortion correction to the given textures by rendering into the
-  // current output target.
-  //
-  // eye Which eye is being corrected.
-  // texture_ids The OpenGL texture IDs of the texture layers.
-  // texture_sizes Dimensions of the corresponding textures.
-  // vertical_flip Whether to flip each input texture vertically.
-  // separate_eye Whether the correspending texture is a separate texture for
-  //              left and right eyes. If false, it is a shared texture with
-  //              the left view on the left half and right on the right half.
-  // late_latch_layer Which late latch layer index to use for each texture.
-  //     Typically this is just {0, 1} unless blend_with_previous_layer is used.
-  // num_textures Number of textures in texture_ids and texture_sizes.
-  // blend_with_previous_layer If enabled, blend this single layer with the
-  //     existing framebuffer contents.
-  void ApplyDistortionCorrectionToTexture(
-      EyeType eye, const GLuint* texture_ids, const bool* vertical_flip,
-      const bool* separate_eye, const int* late_latch_layer, int num_textures,
-      bool blend_with_previous_layer, bool do_gl_state_prep);
-
-  // Convenience method that does no flipping.
-  void ApplyDistortionCorrectionToTexture(EyeType eye,
-                                          const GLuint* texture_ids,
-                                          int num_textures) {
-    bool flip[kMaxLayers] = {false};
-    bool separate[kMaxLayers] = {separated_eye_buffers_,
-                                 separated_eye_buffers_};
-    int latch_layer[kMaxLayers] = {0, 1};
-    ApplyDistortionCorrectionToTexture(eye, texture_ids, flip, separate,
-                                       latch_layer, num_textures, false, true);
-  }
-
-  // Draw a video quad based on the given video texture by rendering into the
-  // current output target.
-  //
-  // eye Which eye is being corrected.
-  // layer_id Which compositor layer the video mesh should be drawn into.
-  // texture_ids The OpenGL texture IDs of the texture layers.
-  // transform The transformation matrix that transforms the video mesh to its
-  //           desired eye space position for the target eye.
-  void DrawVideoQuad(EyeType eye, int layer_id, GLuint texture_id,
-                     const mat4& transform);
-
-  // Modifies the size of the output display. This is the number of physical
-  // pixels per dimension covered by the display on the output device. Calling
-  // this method is cheap; it only updates the state table of the two
-  // eye-specific mesh nodes.
-  void SetDisplaySize(vec2i size);
-
-  void SetEdsEnabled(bool enabled);
-  void SetChromaticAberrationCorrectionEnabled(bool enabled) {
-    chromatic_aberration_correction_enabled_ = enabled;
-  }
-  void SetUseAlphaVignette(bool enabled) { use_alpha_vignette_ = enabled; }
-
-  bool GetLastEdsPose(LateLatchOutput* out_data, int layer_id = 0) const;
-
- private:
-  enum ShaderProgramType {
-    kNoChromaticAberrationCorrection,
-    kNoChromaticAberrationCorrectionTwoLayers,
-    kChromaticAberrationCorrection,
-    kChromaticAberrationCorrectionTwoLayers,
-    kChromaticAberrationCorrectionAlphaVignette,
-    kChromaticAberrationCorrectionAlphaVignetteTwoLayers,
-    kChromaticAberrationCorrectionWithBlend,
-    kSimpleVideoQuad,
-    kNumShaderPrograms,
-  };
-
-  struct EdsShader {
-    EdsShader() {}
-    ~EdsShader() {
-    }
-
-    void load(const char* vertex, const char* fragment, int num_layers,
-              bool use_alpha_vignette, float rotation, bool flip_vertical,
-              bool blend_with_previous_layer);
-    void use() { pgm.Use(); }
-
-    // Update uTexFromEyeMatrix and uEyeFromViewportMatrix by the distortion
-    // renderer with the transform matrix.
-    void SetTexFromEyeTransform(const mat4& transform) {
-      glUniformMatrix4fv(uTexFromEyeMatrix, 1, false, transform.data());
-    }
-
-    void SetEyeFromViewportTransform(const mat4& transform) {
-      glUniformMatrix4fv(uEyeFromViewportMatrix, 1, false, transform.data());
-    }
-
-    ShaderProgram pgm;
-
-    // Texture variables, named to match shader strings for convenience.
-    GLint uProjectionMatrix;
-    GLint uTexFromEyeMatrix;
-    GLint uEyeFromViewportMatrix;
-    GLint uTexXMinMax;
-  };
-
-  void DrawEye(EyeType eye, const GLuint* texture_ids,
-               const bool* vertical_flip, const bool* separate_eye,
-               const int* late_latch_layer, int num_textures,
-               bool blend_with_previous_layer, bool do_gl_state_prep);
-
-  // This function is called when there is an update on Hmd and distortion mesh
-  // vertices and factor array will be updated.
-  void RecomputeDistortion(const CompositeHmd& hmd);
-
-  // Per-eye, per flip, per separate eye mode buffers for setting EDS matrix
-  // when EDS is disabled.
-  GLuint uTexFromRecommendedViewportMatrix[2][2][2];
-
-  // Distortion mesh for the each eye.
-  EdsMesh mesh_node_[2];
-  // VBO (vertex buffer object) for distortion mesh vertices.
-  GLuint mesh_vbo_[2];
-  // VAO (vertex array object) for distortion mesh vertex array data.
-  GLuint mesh_vao_[2];
-  // IBO (index buffer object) for distortion mesh indices.
-  GLuint mesh_ibo_[2];
-
-  EdsShader shaders_[kNumShaderPrograms];
-
-  // Enum to indicate which shader program is being used.
-  ShaderProgramType shader_type_;
-
-  bool eds_enabled_;
-  bool chromatic_aberration_correction_enabled_;
-  bool use_alpha_vignette_;
-
-  // This keeps track of what distortion mesh resolution we are using currently.
-  // When there is an update on Hmd, the distortion mesh vertices/factor array
-  // will be re-computed with the old resolution that is stored here.
-  int distortion_mesh_resolution_;
-
-  // The OpenGL ID of the last texture passed to
-  // ApplyDistortionCorrectionToTexture().
-  GLuint last_distortion_texture_id_;
-
-  // GL texture 2D target for application texture.
-  GLint app_texture_target_;
-
-  // Precomputed matrices for EDS and viewport transforms.
-  mat4 tex_from_eye_matrix_[2][2][2];
-  mat4 eye_from_viewport_matrix_[2];
-
-  // Eye viewport locations.
-  vec2i eye_viewport_origin_[2];
-  vec2i eye_viewport_size_;
-
-  vec2i display_size_;
-
-  std::unique_ptr<LateLatch> late_latch_[kMaxLatchedLayers];
-  bool separated_eye_buffers_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_DISTORTION_RENDERER_H_
diff --git a/libs/vr/libeds/include/private/dvr/eds_mesh.h b/libs/vr/libeds/include/private/dvr/eds_mesh.h
deleted file mode 100644
index d2c901e..0000000
--- a/libs/vr/libeds/include/private/dvr/eds_mesh.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef ANDROID_DVR_EDS_MESH_H_
-#define ANDROID_DVR_EDS_MESH_H_
-
-#include <stdint.h>
-#include <functional>
-#include <vector>
-
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-struct EdsVertex {
-  vec2 position;
-  vec2 red_viewport_coords;
-  vec2 green_viewport_coords;
-  vec2 blue_viewport_coords;
-};
-
-struct EdsMesh {
-  std::vector<EdsVertex> vertices;
-  std::vector<uint16_t> indices;
-};
-
-// Distortion function takes in a point in the range [0..1, 0..1] and returns
-// the vertex position and the three distorted points for separate R, G and B
-// channels.
-typedef std::function<void(EyeType, vec2, vec2*, vec2*)> DistortionFunction;
-
-// Builds a distortion mesh of resolution |resolution| using
-// the distortion provided by |hmd| for |eye|.
-EdsMesh BuildDistortionMesh(EyeType eye, int resolution,
-                            const DistortionFunction& distortion_function);
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_EDS_MESH_H_
diff --git a/libs/vr/libeds/include/private/dvr/head_mount_metrics.h b/libs/vr/libeds/include/private/dvr/head_mount_metrics.h
deleted file mode 100644
index f3e63a6..0000000
--- a/libs/vr/libeds/include/private/dvr/head_mount_metrics.h
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef ANDROID_DVR_HEAD_MOUNT_METRICS_H_
-#define ANDROID_DVR_HEAD_MOUNT_METRICS_H_
-
-#include <array>
-
-#include <private/dvr/color_channel_distortion.h>
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-// HeadMountMetrics encapsulates metrics describing a head mount to be used
-// with a display to create a head mounted display.
-class HeadMountMetrics {
- public:
-  // The vertical point of the HMD where the lens distance is measured from.
-  enum VerticalAlignment { kBottom = 0, kCenter = 1, kTop = 2 };
-
-  enum EyeOrientation {
-    kCCW0Degrees = 0,
-    kCCW90Degrees = 1,
-    kCCW180Degrees = 2,
-    kCCW270Degrees = 3,
-    kCCW0DegreesMirrored = 4,
-    kCCW90DegreesMirrored = 5,
-    kCCW180DegreesMirrored = 6,
-    kCCW270DegreesMirrored = 7,
-
-    // Rotations that consist of an odd number of 90 degree rotations will swap
-    // the height and width of any bounding boxes/viewports. This bit informs
-    // any viewport manipulating code to perform the appropriate transformation.
-    kRightAngleBit = 0x01,
-    // Viewports are represented as four floating point values (four half
-    // angles). Rotating this structure can be done through a shift operation.
-    // This mask extracts the rotation portion of the orientation.
-    kRotationMask = 0x03,
-    // This mask specifies whether the output is mirrored.
-    kMirroredBit = 0x04
-  };
-
-  HeadMountMetrics(
-      float inter_lens_distance, float tray_to_lens_distance,
-      float virtual_eye_to_screen_distance,
-      VerticalAlignment vertical_alignment, const FieldOfView& left_eye_max_fov,
-      const FieldOfView& right_eye_max_fov,
-      const std::shared_ptr<ColorChannelDistortion>& red_distortion,
-      const std::shared_ptr<ColorChannelDistortion>& green_distortion,
-      const std::shared_ptr<ColorChannelDistortion>& blue_distortion,
-      EyeOrientation left_eye_orientation, EyeOrientation right_eye_orientation,
-      float screen_center_to_lens_distance)
-      : inter_lens_distance_(inter_lens_distance),
-        tray_to_lens_distance_(tray_to_lens_distance),
-        virtual_eye_to_screen_distance_(virtual_eye_to_screen_distance),
-        screen_center_to_lens_distance_(screen_center_to_lens_distance),
-        vertical_alignment_(vertical_alignment),
-        eye_max_fov_({{left_eye_max_fov, right_eye_max_fov}}),
-        color_channel_distortion_(
-            {{red_distortion, green_distortion, blue_distortion}}),
-        supports_chromatic_aberration_correction_(true),
-        eye_orientation_({{left_eye_orientation, right_eye_orientation}}) {
-    // If we're missing the green or blur distortions, assume that we don't
-    // correct for chromatic aberration.
-    if (!green_distortion || !blue_distortion) {
-      color_channel_distortion_[1] = red_distortion;
-      color_channel_distortion_[2] = red_distortion;
-      supports_chromatic_aberration_correction_ = false;
-    }
-  }
-
-  // Returns the distance in meters between the optical centers of the two
-  // lenses.
-  float GetInterLensDistance() const { return inter_lens_distance_; }
-
-  // Returns the distance in meters from the "tray" upon which the display
-  // rests to the optical center of a lens.
-  float GetTrayToLensDistance() const { return tray_to_lens_distance_; }
-
-  // Returns the distance in meters from the virtual eye to the screen.
-  // See http://go/vr-distortion-correction for an explanation of what
-  // this distance is.
-  float GetVirtualEyeToScreenDistance() const {
-    return virtual_eye_to_screen_distance_;
-  }
-
-  // Returns the horizontal distance from the center of the screen to the center
-  // of the lens, in meters.
-  float GetScreenCenterToLensDistance() const {
-    return screen_center_to_lens_distance_;
-  }
-
-  // Returns the vertical alignment of the HMD.  The tray-to-lens distance
-  // is relative to this position.  Exception: if the alignment is kCenter,
-  // then the offset has no meaning.
-  VerticalAlignment GetVerticalAlignment() const { return vertical_alignment_; }
-
-  // Returns the given eye's maximum field of view visible through the lens.
-  // The actual rendered field of view will be limited by this and also by
-  // the size of the screen.
-  const FieldOfView& GetEyeMaxFov(EyeType eye) const {
-    return eye_max_fov_[eye];
-  }
-
-  // Returns the ColorChannelDistortion object representing the distortion
-  // caused by the lenses for the given color channel.
-  const ColorChannelDistortion& GetColorChannelDistortion(
-      RgbColorChannel channel) const {
-    return *color_channel_distortion_[channel];
-  }
-
-  bool supports_chromatic_aberration_correction() const {
-    return supports_chromatic_aberration_correction_;
-  }
-
-  EyeOrientation GetEyeOrientation(EyeType eye) const {
-    return eye_orientation_[eye];
-  }
-
- private:
-  float inter_lens_distance_;
-  float tray_to_lens_distance_;
-  float virtual_eye_to_screen_distance_;
-  float screen_center_to_lens_distance_;
-  VerticalAlignment vertical_alignment_;
-  std::array<FieldOfView, 2> eye_max_fov_;
-  std::array<std::shared_ptr<ColorChannelDistortion>, 3>
-      color_channel_distortion_;
-  bool supports_chromatic_aberration_correction_;
-  std::array<EyeOrientation, 2> eye_orientation_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_HEAD_MOUNT_METRICS_H_
diff --git a/libs/vr/libeds/include/private/dvr/identity_distortion.h b/libs/vr/libeds/include/private/dvr/identity_distortion.h
deleted file mode 100644
index b9c5cf6..0000000
--- a/libs/vr/libeds/include/private/dvr/identity_distortion.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef ANDROID_DVR_IDENTITY_DISTORTION_H_
-#define ANDROID_DVR_IDENTITY_DISTORTION_H_
-
-#include <private/dvr/color_channel_distortion.h>
-
-namespace android {
-namespace dvr {
-
-// Provides an identity distortion operation if running the device without any
-// lenses.
-class IdentityDistortion : public ColorChannelDistortion {
- public:
-  IdentityDistortion() {}
-
-  vec2 Distort(vec2 p) const override { return p; }
-
-  vec2 DistortInverse(vec2 p) const override { return p; }
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_IDENTITY_DISTORTION_H_
diff --git a/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h b/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h
deleted file mode 100644
index 8f080aa..0000000
--- a/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef ANDROID_DVR_POLYNOMIAL_RADIAL_DISTORTION_H_
-#define ANDROID_DVR_POLYNOMIAL_RADIAL_DISTORTION_H_
-
-#include <vector>
-
-#include <private/dvr/color_channel_distortion.h>
-
-namespace android {
-namespace dvr {
-
-// PolynomialRadialDistortion implements a radial distortion based using
-// a set of coefficients describing a polynomial function.
-// See http://en.wikipedia.org/wiki/Distortion_(optics).
-//
-// Unless otherwise stated, the units used in this class are tan-angle units
-// which can be computed as distance on the screen divided by distance from the
-// virtual eye to the screen.
-class PolynomialRadialDistortion : public ColorChannelDistortion {
- public:
-  // Construct a PolynomialRadialDistortion with coefficients for
-  // the radial distortion equation:
-  //
-  //   p' = p (1 + K1 r^2 + K2 r^4 + ... + Kn r^(2n))
-  //
-  // where r is the distance in tan-angle units from the optical center,
-  // p the input point and p' the output point.
-  // The provided vector contains the coefficients for the even monomials
-  // in the distortion equation: coefficients[0] is K1, coefficients[1] is K2,
-  // etc.  Thus the polynomial used for distortion has degree
-  // (2 * coefficients.size()).
-  explicit PolynomialRadialDistortion(const std::vector<float>& coefficients);
-
-  // Given a radius (measuring distance from the optical axis of the lens),
-  // returns the distortion factor for that radius.
-  float DistortionFactor(float r_squared) const;
-
-  // Given a radius (measuring distance from the optical axis of the lens),
-  // returns the corresponding distorted radius.
-  float DistortRadius(float r) const;
-
-  // Given a 2d point p, returns the corresponding distorted point.
-  // distance from the virtual eye to the screen.  The optical axis
-  // of the lens defines the origin for both input and output points.
-  vec2 Distort(vec2 p) const override;
-
-  // Given a 2d point p, returns the point that would need to be passed to
-  // Distort to get point p (approximately).
-  vec2 DistortInverse(vec2 p) const override;
-
-  // Returns the distortion coefficients.
-  const std::vector<float>& GetCoefficients() const;
-
- private:
-  std::vector<float> coefficients_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_POLYNOMIAL_RADIAL_DISTORTION_H_
diff --git a/libs/vr/libeds/include/private/dvr/raw_pose.h b/libs/vr/libeds/include/private/dvr/raw_pose.h
deleted file mode 100644
index 7058f1a..0000000
--- a/libs/vr/libeds/include/private/dvr/raw_pose.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef ANDROID_DVR_RAW_POSE_H_
-#define ANDROID_DVR_RAW_POSE_H_
-
-#include <atomic>
-
-namespace android {
-namespace dvr {
-
-// POD raw data of a head pose with a count field for read consistency checking.
-// Warning: The layout of this struct and RawPosePair are specific to match the
-// corresponding buffer type in the shader in late_latch.cpp.
-struct RawPose {
-  void Reset(uint32_t new_count) volatile {
-    qx = qy = qz = 0.0f;
-    qw = 1.0f;
-    px = py = pz = 0.0f;
-    count = new_count;
-  }
-
-  float qx, qy, qz, qw;
-  float px, py, pz;
-  std::atomic<uint32_t> count;
-};
-
-// RawPosePair is used for lock-free writing at about 1khz by the CPU/DSP
-// and reading by the GPU. At creation time, pose1 is given count = 1 and
-// pose2 is given count = 2.
-//
-// The lock-free write pattern is:
-// - write to pose with least count.
-// - memory write barrier.
-// - write count = count + 2.
-//
-// For reads, there is an important assumption about the GPU: it generally
-// processes things contiguously, without arbitrary preemptions that save and
-// restore full cache states. In other words, if the GPU is preempted and then
-// later resumed, any data that was read from memory before the preemption will
-// be re-read from memory after resume. This allows the following read trick to
-// work:
-// - read the full RawPosePair into a shader.
-// - select the pose with the newest count.
-//
-// The older pose may be partially written by the async stores from CPU/DSP, but
-// because of the memory barrier and GPU characteristics, the highest count pose
-// should always be a fully consistent RawPose.
-struct RawPosePair {
-  RawPose pose1;
-  RawPose pose2;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_RAW_POSE_H_
diff --git a/libs/vr/libeds/include/private/dvr/render_texture_params.h b/libs/vr/libeds/include/private/dvr/render_texture_params.h
deleted file mode 100644
index 71aebef..0000000
--- a/libs/vr/libeds/include/private/dvr/render_texture_params.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef ANDROID_DVR_RENDER_TEXTURE_PARAMS_H_
-#define ANDROID_DVR_RENDER_TEXTURE_PARAMS_H_
-
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-// Encapsulates information about the render texture, includes the size
-// of the render texture, and the left/right viewport which define the
-// portion each eye is rendering onto. This struct will be passed to
-// PresentFrame every frame before the client actually drawing the scene.
-struct RenderTextureParams {
-  RenderTextureParams() {}
-
-  RenderTextureParams(vec2i target_texture_size,
-                      const Range2i& eye_viewport_bounds_left,
-                      const Range2i& eye_viewport_bounds_right,
-                      const FieldOfView& eye_fov_left,
-                      const FieldOfView& eye_fov_right)
-      : texture_size(target_texture_size) {
-    eye_viewport_bounds[kLeftEye] = eye_viewport_bounds_left;
-    eye_viewport_bounds[kRightEye] = eye_viewport_bounds_right;
-    eye_fov[kLeftEye] = eye_fov_left;
-    eye_fov[kRightEye] = eye_fov_right;
-  }
-
-  explicit RenderTextureParams(vec2i target_texture_size,
-                               const FieldOfView& eye_fov_left,
-                               const FieldOfView& eye_fov_right) {
-    texture_size = target_texture_size;
-    eye_viewport_bounds[0] = Range2i::FromSize(
-        vec2i(0, 0), vec2i(texture_size[0] / 2, texture_size[1]));
-    eye_viewport_bounds[1] =
-        Range2i::FromSize(vec2i(texture_size[0] / 2, 0),
-                          vec2i(texture_size[0] / 2, texture_size[1]));
-
-    eye_fov[kLeftEye] = eye_fov_left;
-    eye_fov[kRightEye] = eye_fov_right;
-  }
-
-  // The render texture size.
-  vec2i texture_size;
-
-  // The viewport bounds on the render texture for each eye.
-  Range2i eye_viewport_bounds[2];
-
-  // The field of view for each eye in degrees.
-  FieldOfView eye_fov[2];
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_RENDER_TEXTURE_PARAMS_H_
diff --git a/libs/vr/libeds/polynomial_radial_distortion.cpp b/libs/vr/libeds/polynomial_radial_distortion.cpp
deleted file mode 100644
index fa01bb4..0000000
--- a/libs/vr/libeds/polynomial_radial_distortion.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "include/private/dvr/polynomial_radial_distortion.h"
-
-namespace android {
-namespace dvr {
-
-PolynomialRadialDistortion::PolynomialRadialDistortion(
-    const std::vector<float>& coefficients)
-    : coefficients_(coefficients) {}
-
-float PolynomialRadialDistortion::DistortionFactor(float r_squared) const {
-  float r_factor = 1.0f;
-  float distortion_factor = 1.0f;
-
-  for (float ki : coefficients_) {
-    r_factor *= r_squared;
-    distortion_factor += ki * r_factor;
-  }
-
-  return distortion_factor;
-}
-
-float PolynomialRadialDistortion::DistortRadius(float r) const {
-  return r * DistortionFactor(r * r);
-}
-
-vec2 PolynomialRadialDistortion::Distort(vec2 p) const {
-  return p * DistortionFactor(p.squaredNorm());
-}
-
-vec2 PolynomialRadialDistortion::DistortInverse(vec2 p) const {
-  // Secant method.
-  const float radius = p.norm();
-  float r0 = radius / 0.9f;
-  float r1 = radius * 0.9f;
-  float r2;
-  float dr0 = radius - DistortRadius(r0);
-  float dr1;
-  while (fabsf(r1 - r0) > 0.0001f /** 0.1mm */) {
-    dr1 = radius - DistortRadius(r1);
-    r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0));
-    r0 = r1;
-    r1 = r2;
-    dr0 = dr1;
-  }
-  return (r1 / radius) * p;
-}
-
-const std::vector<float>& PolynomialRadialDistortion::GetCoefficients() const {
-  return coefficients_;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libeds/tests/eds_app_tests.cpp b/libs/vr/libeds/tests/eds_app_tests.cpp
deleted file mode 100644
index 549d864..0000000
--- a/libs/vr/libeds/tests/eds_app_tests.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-
-#include <dvr/graphics.h>
-#include <dvr/pose_client.h>
-#include <gtest/gtest.h>
-#include <private/dvr/graphics/shader_program.h>
-#include <private/dvr/types.h>
-
-namespace {
-
-#define POSE_BINDING 0
-
-#ifndef STRINGIFY
-#define STRINGIFY2(s) #s
-#define STRINGIFY(s) STRINGIFY2(s)
-#endif
-
-static const char g_vert_shader[] =
-    "layout(binding = " STRINGIFY(POSE_BINDING) ", std140)\n"
-    "uniform LateLatchData {\n"
-    "  mat4 uViewProjection;\n"
-    "};\n"
-    "void main() {\n"
-    "  vec2 verts[4];\n"
-    "  verts[0] = vec2(-1, -1);\n"
-    "  verts[1] = vec2(-1, 1);\n"
-    "  verts[2] = vec2(1, -1);\n"
-    "  verts[3] = vec2(1, 1);\n"
-    "  gl_Position = uViewProjection * vec4(verts[gl_VertexID], 0.0, 1.0);\n"
-    "}\n";
-
-static const char g_frag_shader[] =
-    "precision mediump float;\n"
-    "out vec4 outColor;\n"
-    "void main() {\n"
-    "  outColor = vec4(1.0);\n"
-    "}\n";
-
-DvrGraphicsContext* CreateContext(int* surface_width, int* surface_height) {
-  DvrGraphicsContext* context = nullptr;
-  int display_width = 0, display_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 enable_late_latch = 1;
-  DvrSurfaceParameter surface_params[] = {
-      DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, disable_warp),
-      DVR_SURFACE_PARAMETER_IN(ENABLE_LATE_LATCH, enable_late_latch),
-      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;
-}
-
-}  // namespace
-
-TEST(SensorAppTests, EdsWithLateLatch) {
-  int surface_width = 0, surface_height = 0;
-  DvrGraphicsContext* context = CreateContext(&surface_width, &surface_height);
-  ASSERT_NE(nullptr, context);
-
-  android::dvr::ShaderProgram shader(g_vert_shader, g_frag_shader);
-
-  for (int i = 0; i < 5; ++i) {
-    DvrFrameSchedule schedule;
-    dvrGraphicsWaitNextFrame(context, 0, &schedule);
-
-    const auto ident_mat = android::dvr::mat4::Identity();
-    const float* ident_mats[] = { ident_mat.data(), ident_mat.data() };
-    GLuint late_latch_buffer_id = 0;
-    int ret = dvrBeginRenderFrameLateLatch(context, 0, schedule.vsync_count, 2,
-                                           ident_mats, ident_mats, ident_mats,
-                                           &late_latch_buffer_id);
-    EXPECT_EQ(0, ret);
-    for (int eye = 0; eye < 2; ++eye) {
-      if (eye == 0)
-        glViewport(0, 0, surface_width / 2, surface_height);
-      else
-        glViewport(surface_width / 2, 0, surface_width / 2, surface_height);
-
-      glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-      shader.Use();
-
-      // Bind late latch pose matrix buffer.
-      glBindBufferRange(
-          GL_UNIFORM_BUFFER, POSE_BINDING, late_latch_buffer_id,
-          offsetof(DvrGraphicsLateLatchData, view_proj_matrix[eye]),
-          16 * sizeof(float));
-
-      // TODO(jbates): use transform feedback here to grab the vertex output
-      // and verify that it received late-latch pose data. Combine this with
-      // mocked pose data to verify that late-latching is working.
-      glDrawArrays(GL_POINTS, 0, 4);
-    }
-    dvrPresent(context);
-  }
-
-  glFinish();
-  dvrGraphicsContextDestroy(context);
-}
-
-TEST(SensorAppTests, EdsWithoutLateLatch) {
-  int surface_width = 0, surface_height = 0;
-  DvrGraphicsContext* context = CreateContext(&surface_width, &surface_height);
-  ASSERT_NE(nullptr, context);
-  DvrPose* client = dvrPoseCreate();
-  ASSERT_NE(nullptr, client);
-
-  for (int i = 0; i < 5; ++i) {
-    DvrFrameSchedule schedule;
-    dvrGraphicsWaitNextFrame(context, 0, &schedule);
-    DvrPoseAsync pose;
-    int ret = dvrPoseGet(client, schedule.vsync_count, &pose);
-    ASSERT_EQ(0, ret);
-
-    dvrBeginRenderFrameEds(context, pose.orientation, pose.translation);
-    for (int eye = 0; eye < 2; ++eye) {
-      if (eye == 0)
-        glViewport(0, 0, surface_width / 2, surface_height);
-      else
-        glViewport(surface_width / 2, 0, surface_width / 2, surface_height);
-
-      glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-      EXPECT_EQ(0, ret);
-    }
-    dvrPresent(context);
-  }
-
-  dvrPoseDestroy(client);
-  dvrGraphicsContextDestroy(context);
-}
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/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 69300d6..f55e994 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -37,6 +37,7 @@
         "libpdx",
         "liblog",
         "libutils",
+        "libvndksupport",
     ],
 }
 
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index cfc2022..82a5ea7 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -24,6 +24,9 @@
         "libbase",
         "libpdx",
     ],
+    whole_static_libs: [
+        "libselinux",
+    ],
 }
 
 cc_test {
diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp
index 850c6d3..433f459 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -60,7 +60,7 @@
 
   bool connected = socket_.IsValid();
   if (!connected) {
-    socket_.Reset(socket(AF_UNIX, SOCK_STREAM, 0));
+    socket_.Reset(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
     LOG_ALWAYS_FATAL_IF(
         endpoint_path_.empty(),
         "ClientChannelFactory::Connect: unspecified socket path");
@@ -123,6 +123,15 @@
       connected = true;
       ALOGD("ClientChannelFactory: Connected successfully to %s...",
             remote.sun_path);
+      ChannelConnectionInfo<LocalHandle> connection_info;
+      status = ReceiveData(socket_.Borrow(), &connection_info);
+      if (!status)
+        return status.error_status();
+      socket_ = std::move(connection_info.channel_fd);
+      if (!socket_) {
+        ALOGE("ClientChannelFactory::Connect: Failed to obtain channel socket");
+        return ErrorStatus(EIO);
+      }
     }
     if (use_timeout)
       now = steady_clock::now();
@@ -132,11 +141,11 @@
   InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false);
   status = SendData(socket_.Borrow(), request);
   if (!status)
-    return ErrorStatus(status.error());
+    return status.error_status();
   ResponseHeader<LocalHandle> response;
   status = ReceiveData(socket_.Borrow(), &response);
   if (!status)
-    return ErrorStatus(status.error());
+    return status.error_status();
   int ref = response.ret_code;
   if (ref < 0 || static_cast<size_t>(ref) > response.file_descriptors.size())
     return ErrorStatus(EIO);
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 5b7e5ff..bde16d3 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -116,6 +116,15 @@
 };
 
 template <typename FileHandleType>
+class ChannelConnectionInfo {
+ public:
+  FileHandleType channel_fd;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd);
+};
+
+template <typename FileHandleType>
 class RequestHeader {
  public:
   int32_t op{0};
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index eb87827..368891c 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -142,6 +142,8 @@
   BorrowedHandle GetChannelSocketFd(int32_t channel_id);
   BorrowedHandle GetChannelEventFd(int32_t channel_id);
   int32_t GetChannelId(const BorrowedHandle& channel_fd);
+  Status<void> CreateChannelSocketPair(LocalHandle* local_socket,
+                                       LocalHandle* remote_socket);
 
   std::string endpoint_path_;
   bool is_blocking_;
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 6c92259..27a56f9 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -11,6 +11,7 @@
 #include <android-base/strings.h>
 #include <cutils/sockets.h>
 #include <pdx/service.h>
+#include <selinux/selinux.h>
 #include <uds/channel_manager.h>
 #include <uds/client_channel_factory.h>
 #include <uds/ipc_helper.h>
@@ -214,30 +215,42 @@
 
   sockaddr_un remote;
   socklen_t addrlen = sizeof(remote);
-  LocalHandle channel_fd{accept4(socket_fd_.Get(),
-                                 reinterpret_cast<sockaddr*>(&remote), &addrlen,
-                                 SOCK_CLOEXEC)};
-  if (!channel_fd) {
+  LocalHandle connection_fd{accept4(socket_fd_.Get(),
+                                    reinterpret_cast<sockaddr*>(&remote),
+                                    &addrlen, SOCK_CLOEXEC)};
+  if (!connection_fd) {
     ALOGE("Endpoint::AcceptConnection: failed to accept connection: %s",
           strerror(errno));
     return ErrorStatus(errno);
   }
 
-  int optval = 1;
-  if (setsockopt(channel_fd.Get(), SOL_SOCKET, SO_PASSCRED, &optval,
-                 sizeof(optval)) == -1) {
-    ALOGE(
-        "Endpoint::AcceptConnection: Failed to enable the receiving of the "
-        "credentials for channel %d: %s",
-        channel_fd.Get(), strerror(errno));
-    return ErrorStatus(errno);
+  LocalHandle local_socket;
+  LocalHandle remote_socket;
+  auto status = CreateChannelSocketPair(&local_socket, &remote_socket);
+  if (!status)
+    return status;
+
+  // Borrow the local channel handle before we move it into OnNewChannel().
+  BorrowedHandle channel_handle = local_socket.Borrow();
+  status = OnNewChannel(std::move(local_socket));
+  if (!status)
+    return status;
+
+  // Send the channel socket fd to the client.
+  ChannelConnectionInfo<LocalHandle> connection_info;
+  connection_info.channel_fd = std::move(remote_socket);
+  status = SendData(connection_fd.Borrow(), connection_info);
+
+  if (status) {
+    // Get the CHANNEL_OPEN message from client over the channel socket.
+    status = ReceiveMessageForChannel(channel_handle, message);
+  } else {
+    CloseChannel(GetChannelId(channel_handle));
   }
 
-  // Borrow the channel handle before we pass (move) it into OnNewChannel().
-  BorrowedHandle borrowed_channel_handle = channel_fd.Borrow();
-  auto status = OnNewChannel(std::move(channel_fd));
-  if (status)
-    status = ReceiveMessageForChannel(borrowed_channel_handle, message);
+  // Don't need the connection socket anymore. Further communication should
+  // happen over the channel socket.
+  shutdown(connection_fd.Get(), SHUT_WR);
   return status;
 }
 
@@ -349,29 +362,73 @@
   return ErrorStatus{EINVAL};
 }
 
+Status<void> Endpoint::CreateChannelSocketPair(LocalHandle* local_socket,
+                                               LocalHandle* remote_socket) {
+  Status<void> status;
+  char* endpoint_context = nullptr;
+  // Make sure the channel socket has the correct SELinux label applied.
+  // Here we get the label from the endpoint file descriptor, which should be
+  // something like "u:object_r:pdx_service_endpoint_socket:s0" and replace
+  // "endpoint" with "channel" to produce the channel label such as this:
+  // "u:object_r:pdx_service_channel_socket:s0".
+  if (fgetfilecon_raw(socket_fd_.Get(), &endpoint_context) > 0) {
+    std::string channel_context = endpoint_context;
+    freecon(endpoint_context);
+    const std::string suffix = "_endpoint_socket";
+    auto pos = channel_context.find(suffix);
+    if (pos != std::string::npos) {
+      channel_context.replace(pos, suffix.size(), "_channel_socket");
+    } else {
+      ALOGW(
+          "Endpoint::CreateChannelSocketPair: Endpoint security context '%s' "
+          "does not contain expected substring '%s'",
+          channel_context.c_str(), suffix.c_str());
+    }
+    ALOGE_IF(setsockcreatecon_raw(channel_context.c_str()) == -1,
+             "Endpoint::CreateChannelSocketPair: Failed to set channel socket "
+             "security context: %s",
+             strerror(errno));
+  } else {
+    ALOGE(
+        "Endpoint::CreateChannelSocketPair: Failed to obtain the endpoint "
+        "socket's security context: %s",
+        strerror(errno));
+  }
+
+  int channel_pair[2] = {};
+  if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, channel_pair) == -1) {
+    ALOGE("Endpoint::CreateChannelSocketPair: Failed to create socket pair: %s",
+          strerror(errno));
+    status.SetError(errno);
+    return status;
+  }
+
+  setsockcreatecon_raw(nullptr);
+
+  local_socket->Reset(channel_pair[0]);
+  remote_socket->Reset(channel_pair[1]);
+
+  int optval = 1;
+  if (setsockopt(local_socket->Get(), SOL_SOCKET, SO_PASSCRED, &optval,
+                 sizeof(optval)) == -1) {
+    ALOGE(
+        "Endpoint::CreateChannelSocketPair: Failed to enable the receiving of "
+        "the credentials for channel %d: %s",
+        local_socket->Get(), strerror(errno));
+    status.SetError(errno);
+  }
+  return status;
+}
+
 Status<RemoteChannelHandle> Endpoint::PushChannel(Message* message,
                                                   int /*flags*/,
                                                   Channel* channel,
                                                   int* channel_id) {
-  int channel_pair[2] = {};
-  if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, channel_pair) == -1) {
-    ALOGE("Endpoint::PushChannel: Failed to create a socket pair: %s",
-          strerror(errno));
-    return ErrorStatus(errno);
-  }
-
-  LocalHandle local_socket{channel_pair[0]};
-  LocalHandle remote_socket{channel_pair[1]};
-
-  int optval = 1;
-  if (setsockopt(local_socket.Get(), SOL_SOCKET, SO_PASSCRED, &optval,
-                 sizeof(optval)) == -1) {
-    ALOGE(
-        "Endpoint::PushChannel: Failed to enable the receiving of the "
-        "credentials for channel %d: %s",
-        local_socket.Get(), strerror(errno));
-    return ErrorStatus(errno);
-  }
+  LocalHandle local_socket;
+  LocalHandle remote_socket;
+  auto status = CreateChannelSocketPair(&local_socket, &remote_socket);
+  if (!status)
+    return status.error_status();
 
   std::lock_guard<std::mutex> autolock(channel_mutex_);
   auto channel_data = OnNewChannelLocked(std::move(local_socket), channel);
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 dc81c60..de26a74 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -30,10 +30,8 @@
     "libhwcomposer-command-buffer",
     "libbufferhub",
     "libbufferhubqueue",
-    "libeds",
     "libdisplay",
     "libdvrcommon",
-    "libdvrgraphics",
     "libperformance",
     "libvrsensor",
     "libpdx_default_transport",
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index 5829788..fb2751b 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"
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 079d6fd..34474d9 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -25,7 +25,6 @@
 #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;
@@ -49,10 +48,6 @@
 // Offset before vsync to submit frames to hardware composer.
 constexpr int64_t kFramePostOffsetNs = 4000000;  // 4ms
 
-constexpr size_t kDefaultDisplayConfigCount = 32;
-
-constexpr float kMetersPerInch = 0.0254f;
-
 const char kBacklightBrightnessSysFile[] =
     "/sys/class/leds/lcd-backlight/brightness";
 
@@ -65,23 +60,6 @@
 
 const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
 
-// Returns our best guess for the time the compositor will spend rendering the
-// next frame.
-int64_t GuessFrameTime(int compositor_visible_layer_count) {
-  // The cost of asynchronous EDS and lens warp is currently measured at 2.5ms
-  // for one layer and 7ms for two layers, but guess a higher frame time to
-  // account for CPU overhead. This guess is only used before we've measured the
-  // actual time to render a frame for the current compositor configuration.
-  switch (compositor_visible_layer_count) {
-    case 0:
-      return 500000;  // .5ms
-    case 1:
-      return 5000000;  // 5ms
-    default:
-      return 10500000;  // 10.5ms
-  }
-}
-
 // Get time offset from a vsync to when the pose for that vsync should be
 // predicted out to. For example, if scanout gets halfway through the frame
 // at the halfway point between vsyncs, then this could be half the period.
@@ -241,14 +219,6 @@
 }
 
 void HardwareComposer::OnPostThreadResumed() {
-  constexpr int format = HAL_PIXEL_FORMAT_RGBA_8888;
-  constexpr int usage =
-      GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER;
-
-  framebuffer_target_ = std::make_shared<IonBuffer>(
-      native_display_metrics_.width, native_display_metrics_.height, format,
-      usage);
-
   hwc2_hidl_->resetCommands();
 
   // Connect to pose service.
@@ -275,7 +245,6 @@
 }
 
 void HardwareComposer::OnPostThreadPaused() {
-  framebuffer_target_.reset();
   retire_fence_fds_.clear();
   display_surfaces_.clear();
 
@@ -770,9 +739,6 @@
   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) {
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 5a75f42..8ba72ab 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -20,8 +20,6 @@
 #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 "acquired_buffer.h"
 #include "display_surface.h"
@@ -383,9 +381,6 @@
   // Transform required to get from native to logical display orientation.
   HWC::Transform display_transform_ = HWC::Transform::None;
 
-  // Buffer for the background layer required by hardware composer.
-  std::shared_ptr<IonBuffer> framebuffer_target_;
-
   // Pending surface list. Set by the display service when DirectSurfaces are
   // added, removed, or change visibility. Written by the message dispatch
   // thread and read by the post thread.
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index d59182e..abad78b 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -46,29 +46,3 @@
     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",
-        "libeds",
-        "libvrsensor",
-        "libdvrgraphics",
-    ] + staticLibraries,
-
-}
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/libs/Android.bp b/opengl/libs/Android.bp
index a895e63..d6bdc81 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -111,6 +111,7 @@
         "EGL/Loader.cpp",
         "EGL/BlobCache.cpp",
     ],
+    shared_libs: ["libvndksupport"],
     static_libs: ["libEGL_getProcAddress"],
     ldflags: ["-Wl,--exclude-libs=ALL"],
     export_include_dirs: ["EGL/include"],
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 7d20ba1..823b502 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -29,6 +29,7 @@
 #include <log/log.h>
 
 #include <ui/GraphicsEnv.h>
+#include <vndksupport/linker.h>
 
 #include "egl_trace.h"
 #include "egldefs.h"
@@ -115,6 +116,11 @@
     return android_dlopen_ext(path, mode, info);
 }
 
+static void* do_android_load_sphal_library(const char* path, int mode) {
+    ATRACE_CALL();
+    return android_load_sphal_library(path, mode);
+}
+
 // ----------------------------------------------------------------------------
 
 Loader::driver_t::driver_t(void* gles)
@@ -424,27 +430,11 @@
     const char* const driver_absolute_path = absolutePath.c_str();
 
     // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
-    // the original routine when the namespace does not exist or the load from
-    // the namespace fails.
+    // the original routine when the namespace does not exist.
     // See /system/core/rootdir/etc/ld.config.txt for the configuration of the
     // sphal namespace.
-    android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
-    if (sphal_namespace != NULL) {
-        const android_dlextinfo dlextinfo = {
-            .flags = ANDROID_DLEXT_USE_NAMESPACE,
-            .library_namespace = sphal_namespace,
-        };
-        void* dso = do_android_dlopen_ext(driver_absolute_path, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
-        if (dso) {
-            ALOGD("loaded %s from sphal namespace", driver_absolute_path);
-            return dso;
-        }
-        else {
-            ALOGW("failed to load %s from sphal namespace: %s", driver_absolute_path, dlerror());
-        }
-    }
-
-    void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
+    void* dso = do_android_load_sphal_library(driver_absolute_path,
+                                              RTLD_NOW | RTLD_LOCAL);
     if (dso == 0) {
         const char* err = dlerror();
         ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 9de15d0..ba3a5f9 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -829,6 +829,38 @@
             egl_tls_t::setContext(EGL_NO_CONTEXT);
         }
     } else {
+
+        if (cur_c != NULL) {
+            // Force return to current context for drivers that cannot handle errors
+            EGLBoolean restore_result = EGL_FALSE;
+            // get a reference to the old current objects
+            ContextRef _c2(dp.get(), cur_c);
+            SurfaceRef _d2(dp.get(), cur_c->draw);
+            SurfaceRef _r2(dp.get(), cur_c->read);
+
+            c = cur_c;
+            impl_ctx = c->context;
+            impl_draw = EGL_NO_SURFACE;
+            if (cur_c->draw != EGL_NO_SURFACE) {
+                d = get_surface(cur_c->draw);
+                impl_draw = d->surface;
+            }
+            impl_read = EGL_NO_SURFACE;
+            if (cur_c->read != EGL_NO_SURFACE) {
+                r = get_surface(cur_c->read);
+                impl_read = r->surface;
+            }
+            restore_result = dp->makeCurrent(c, cur_c,
+                    cur_c->draw, cur_c->read, cur_c->context,
+                    impl_draw, impl_read, impl_ctx);
+            if (restore_result == EGL_TRUE) {
+                _c2.acquire();
+                _r2.acquire();
+                _d2.acquire();
+            } else {
+                ALOGE("Could not restore original EGL context");
+            }
+        }
         // this will ALOGE the error
         egl_connection_t* const cnx = &gEGLImpl;
         result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 94de5af..24b1315 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -49,6 +49,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/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 2705e13..73255dd 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -227,18 +227,65 @@
 
 // --- InputReaderConfiguration ---
 
-bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const {
-    const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay;
-    if (viewport.displayId >= 0) {
-        *outViewport = viewport;
+bool InputReaderConfiguration::getDisplayViewport(ViewportType viewportType,
+        const String8* uniqueDisplayId, DisplayViewport* outViewport) const {
+    const DisplayViewport* viewport = NULL;
+    if (viewportType == ViewportType::VIEWPORT_VIRTUAL && uniqueDisplayId != NULL) {
+        for (DisplayViewport currentViewport : mVirtualDisplays) {
+            if (currentViewport.uniqueId == *uniqueDisplayId) {
+                viewport = &currentViewport;
+                break;
+            }
+        }
+    } else if (viewportType == ViewportType::VIEWPORT_EXTERNAL) {
+        viewport = &mExternalDisplay;
+    } else if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
+        viewport = &mInternalDisplay;
+    }
+
+    if (viewport != NULL && viewport->displayId >= 0) {
+        *outViewport = *viewport;
         return true;
     }
     return false;
 }
 
-void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) {
-    DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay;
-    v = viewport;
+void InputReaderConfiguration::setPhysicalDisplayViewport(ViewportType viewportType,
+        const DisplayViewport& viewport) {
+    if (viewportType == ViewportType::VIEWPORT_EXTERNAL) {
+        mExternalDisplay = viewport;
+    } else if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
+        mInternalDisplay = viewport;
+    }
+}
+
+void InputReaderConfiguration::setVirtualDisplayViewports(
+        const Vector<DisplayViewport>& viewports) {
+    mVirtualDisplays = viewports;
+}
+
+void InputReaderConfiguration::dump(String8& dump) const {
+    dump.append(INDENT4 "ViewportInternal:\n");
+    dumpViewport(dump, mInternalDisplay);
+    dump.append(INDENT4 "ViewportExternal:\n");
+    dumpViewport(dump, mExternalDisplay);
+    dump.append(INDENT4 "ViewportVirtual:\n");
+    for (const DisplayViewport& viewport : mVirtualDisplays) {
+        dumpViewport(dump, viewport);
+    }
+}
+
+void InputReaderConfiguration::dumpViewport(String8& dump, const DisplayViewport& viewport) const {
+    dump.appendFormat(INDENT5 "Viewport: displayId=%d, orientation=%d, uniqueId='%s', "
+            "logicalFrame=[%d, %d, %d, %d], "
+            "physicalFrame=[%d, %d, %d, %d], "
+            "deviceSize=[%d, %d]\n",
+            viewport.displayId, viewport.orientation, viewport.uniqueId.c_str(),
+            viewport.logicalLeft, viewport.logicalTop,
+            viewport.logicalRight, viewport.logicalBottom,
+            viewport.physicalLeft, viewport.physicalTop,
+            viewport.physicalRight, viewport.physicalBottom,
+            viewport.deviceWidth, viewport.deviceHeight);
 }
 
 
@@ -851,6 +898,9 @@
             mConfig.pointerGestureMovementSpeedRatio);
     dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
             mConfig.pointerGestureZoomSpeedRatio);
+
+    dump.append(INDENT3 "Viewports:\n");
+    mConfig.dump(dump);
 }
 
 void InputReader::monitor() {
@@ -2161,7 +2211,7 @@
     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
             DisplayViewport v;
-            if (config->getDisplayInfo(false /*external*/, &v)) {
+            if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) {
                 mOrientation = v.orientation;
             } else {
                 mOrientation = DISPLAY_ORIENTATION_0;
@@ -2534,7 +2584,7 @@
     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
             DisplayViewport v;
-            if (config->getDisplayInfo(false /*external*/, &v)) {
+            if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) {
                 mOrientation = v.orientation;
             } else {
                 mOrientation = DISPLAY_ORIENTATION_0;
@@ -2979,7 +3029,7 @@
 }
 
 void TouchInputMapper::dump(String8& dump) {
-    dump.append(INDENT2 "Touch Input Mapper:\n");
+    dump.appendFormat(INDENT2 "Touch Input Mapper (mode - %s):\n", modeToString(mDeviceMode));
     dumpParameters(dump);
     dumpVirtualKeys(dump);
     dumpRawPointerAxes(dump);
@@ -3071,6 +3121,22 @@
     }
 }
 
+const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
+    switch (deviceMode) {
+    case DEVICE_MODE_DISABLED:
+        return "disabled";
+    case DEVICE_MODE_DIRECT:
+        return "direct";
+    case DEVICE_MODE_UNSCALED:
+        return "unscaled";
+    case DEVICE_MODE_NAVIGATION:
+        return "navigation";
+    case DEVICE_MODE_POINTER:
+        return "pointer";
+    }
+    return "unknown";
+}
+
 void TouchInputMapper::configure(nsecs_t when,
         const InputReaderConfiguration* config, uint32_t changes) {
     InputMapper::configure(when, config, changes);
@@ -3196,9 +3262,11 @@
             || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
             || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
         mParameters.hasAssociatedDisplay = true;
-        mParameters.associatedDisplayIsExternal =
-                mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
-                        && getDevice()->isExternal();
+        if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
+            mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
+            getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
+                    mParameters.uniqueDisplayId);
+        }
     }
 
     // Initial downs on external touch devices should wake the device.
@@ -3240,9 +3308,11 @@
         ALOG_ASSERT(false);
     }
 
-    dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n",
+    dump.appendFormat(
+            INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, displayId='%s'\n",
             toString(mParameters.hasAssociatedDisplay),
-            toString(mParameters.associatedDisplayIsExternal));
+            toString(mParameters.associatedDisplayIsExternal),
+            mParameters.uniqueDisplayId.c_str());
     dump.appendFormat(INDENT4 "OrientationAware: %s\n",
             toString(mParameters.orientationAware));
 }
@@ -3318,7 +3388,21 @@
     // Get associated display dimensions.
     DisplayViewport newViewport;
     if (mParameters.hasAssociatedDisplay) {
-        if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) {
+        const String8* uniqueDisplayId = NULL;
+        ViewportType viewportTypeToUse;
+
+        if (mParameters.associatedDisplayIsExternal) {
+            viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
+        } else if (!mParameters.uniqueDisplayId.isEmpty()) {
+            // If the IDC file specified a unique display Id, then it expects to be linked to a
+            // virtual display with the same unique ID.
+            uniqueDisplayId = &mParameters.uniqueDisplayId;
+            viewportTypeToUse = ViewportType::VIEWPORT_VIRTUAL;
+        } else {
+            viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
+        }
+
+        if (!mConfig.getDisplayViewport(viewportTypeToUse, uniqueDisplayId, &newViewport)) {
             ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
                     "display.  The device will be inoperable until the display size "
                     "becomes available.",
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 3171526..edb6fcc 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -21,6 +21,7 @@
 #include "PointerControllerInterface.h"
 #include "InputListener.h"
 
+#include <input/DisplayViewport.h>
 #include <input/Input.h>
 #include <input/VelocityControl.h>
 #include <input/VelocityTracker.h>
@@ -49,70 +50,6 @@
 class InputMapper;
 
 /*
- * Describes how coordinates are mapped on a physical display.
- * See com.android.server.display.DisplayViewport.
- */
-struct DisplayViewport {
-    int32_t displayId; // -1 if invalid
-    int32_t orientation;
-    int32_t logicalLeft;
-    int32_t logicalTop;
-    int32_t logicalRight;
-    int32_t logicalBottom;
-    int32_t physicalLeft;
-    int32_t physicalTop;
-    int32_t physicalRight;
-    int32_t physicalBottom;
-    int32_t deviceWidth;
-    int32_t deviceHeight;
-
-    DisplayViewport() :
-            displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
-            logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
-            physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
-            deviceWidth(0), deviceHeight(0) {
-    }
-
-    bool operator==(const DisplayViewport& other) const {
-        return displayId == other.displayId
-                && orientation == other.orientation
-                && logicalLeft == other.logicalLeft
-                && logicalTop == other.logicalTop
-                && logicalRight == other.logicalRight
-                && logicalBottom == other.logicalBottom
-                && physicalLeft == other.physicalLeft
-                && physicalTop == other.physicalTop
-                && physicalRight == other.physicalRight
-                && physicalBottom == other.physicalBottom
-                && deviceWidth == other.deviceWidth
-                && deviceHeight == other.deviceHeight;
-    }
-
-    bool operator!=(const DisplayViewport& other) const {
-        return !(*this == other);
-    }
-
-    inline bool isValid() const {
-        return displayId >= 0;
-    }
-
-    void setNonDisplayViewport(int32_t width, int32_t height) {
-        displayId = ADISPLAY_ID_NONE;
-        orientation = DISPLAY_ORIENTATION_0;
-        logicalLeft = 0;
-        logicalTop = 0;
-        logicalRight = width;
-        logicalBottom = height;
-        physicalLeft = 0;
-        physicalTop = 0;
-        physicalRight = width;
-        physicalBottom = height;
-        deviceWidth = width;
-        deviceHeight = height;
-    }
-};
-
-/*
  * Input reader configuration.
  *
  * Specifies various options that modify the behavior of the input reader.
@@ -255,12 +192,19 @@
             pointerGestureZoomSpeedRatio(0.3f),
             showTouches(false) { }
 
-    bool getDisplayInfo(bool external, DisplayViewport* outViewport) const;
-    void setDisplayInfo(bool external, const DisplayViewport& viewport);
+    bool getDisplayViewport(ViewportType viewportType, const String8* displayId,
+            DisplayViewport* outViewport) const;
+    void setPhysicalDisplayViewport(ViewportType viewportType, const DisplayViewport& viewport);
+    void setVirtualDisplayViewports(const Vector<DisplayViewport>& viewports);
+
+
+    void dump(String8& dump) const;
+    void dumpViewport(String8& dump, const DisplayViewport& viewport) const;
 
 private:
     DisplayViewport mInternalDisplay;
     DisplayViewport mExternalDisplay;
+    Vector<DisplayViewport> mVirtualDisplays;
 };
 
 
@@ -1341,6 +1285,7 @@
         bool associatedDisplayIsExternal;
         bool orientationAware;
         bool hasButtonUnderPad;
+        String8 uniqueDisplayId;
 
         enum GestureMode {
             GESTURE_MODE_SINGLE_TOUCH,
@@ -1889,6 +1834,8 @@
     const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
 
     static void assignPointerIds(const RawState* last, RawState* current);
+
+    const char* modeToString(DeviceMode deviceMode);
 };
 
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 2e0bcd1..dcfe114 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -29,6 +29,10 @@
 static const int32_t DISPLAY_ID = 0;
 static const int32_t DISPLAY_WIDTH = 480;
 static const int32_t DISPLAY_HEIGHT = 800;
+static const int32_t VIRTUAL_DISPLAY_ID = 1;
+static const int32_t VIRTUAL_DISPLAY_WIDTH = 400;
+static const int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
+static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "Vr-display-unique-ID";
 
 // Error tolerance for floating point assertions.
 static const float EPSILON = 0.001f;
@@ -136,25 +140,19 @@
     FakeInputReaderPolicy() {
     }
 
-    void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
+    void setDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
+            const String8& uniqueId) {
+        DisplayViewport v = createDisplayViewport(displayId, width, height, orientation, uniqueId);
         // Set the size of both the internal and external display at the same time.
-        bool isRotated = (orientation == DISPLAY_ORIENTATION_90
-                || orientation == DISPLAY_ORIENTATION_270);
-        DisplayViewport v;
-        v.displayId = displayId;
-        v.orientation = orientation;
-        v.logicalLeft = 0;
-        v.logicalTop = 0;
-        v.logicalRight = isRotated ? height : width;
-        v.logicalBottom = isRotated ? width : height;
-        v.physicalLeft = 0;
-        v.physicalTop = 0;
-        v.physicalRight = isRotated ? height : width;
-        v.physicalBottom = isRotated ? width : height;
-        v.deviceWidth = isRotated ? height : width;
-        v.deviceHeight = isRotated ? width : height;
-        mConfig.setDisplayInfo(false /*external*/, v);
-        mConfig.setDisplayInfo(true /*external*/, v);
+        mConfig.setPhysicalDisplayViewport(ViewportType::VIEWPORT_INTERNAL, v);
+        mConfig.setPhysicalDisplayViewport(ViewportType::VIEWPORT_EXTERNAL, v);
+    }
+
+    void setVirtualDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
+            const String8& uniqueId) {
+        Vector<DisplayViewport> viewports;
+        viewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId));
+        mConfig.setVirtualDisplayViewports(viewports);
     }
 
     void addExcludedDeviceName(const String8& deviceName) {
@@ -187,6 +185,27 @@
     }
 
 private:
+    DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
+            int32_t orientation, const String8& uniqueId) {
+        bool isRotated = (orientation == DISPLAY_ORIENTATION_90
+                || orientation == DISPLAY_ORIENTATION_270);
+        DisplayViewport v;
+        v.displayId = displayId;
+        v.orientation = orientation;
+        v.logicalLeft = 0;
+        v.logicalTop = 0;
+        v.logicalRight = isRotated ? height : width;
+        v.logicalBottom = isRotated ? width : height;
+        v.physicalLeft = 0;
+        v.physicalTop = 0;
+        v.physicalRight = isRotated ? height : width;
+        v.physicalBottom = isRotated ? width : height;
+        v.deviceWidth = isRotated ? height : width;
+        v.deviceHeight = isRotated ? width : height;
+        v.uniqueId = uniqueId;
+        return v;
+    }
+
     virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) {
         *outConfig = mConfig;
     }
@@ -1445,7 +1464,13 @@
 
     void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
             int32_t orientation) {
-        mFakePolicy->setDisplayInfo(displayId, width, height, orientation);
+        mFakePolicy->setDisplayViewport(displayId, width, height, orientation, String8::empty());
+        configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+    }
+
+    void setVirtualDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
+            int32_t orientation, const String8& uniqueId) {
+        mFakePolicy->setVirtualDisplayViewport(displayId, width, height, orientation, uniqueId);
         configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     }
 
@@ -2751,6 +2776,8 @@
     static const int32_t RAW_SLOT_MAX;
     static const float X_PRECISION;
     static const float Y_PRECISION;
+    static const float X_PRECISION_VIRTUAL;
+    static const float Y_PRECISION_VIRTUAL;
 
     static const float GEOMETRIC_SCALE;
     static const TouchAffineTransformation AFFINE_TRANSFORM;
@@ -2772,6 +2799,7 @@
     };
 
     void prepareDisplay(int32_t orientation);
+    void prepareVirtualDisplay(int32_t orientation);
     void prepareVirtualKeys();
     void prepareLocationCalibration();
     int32_t toRawX(float displayX);
@@ -2779,7 +2807,10 @@
     float toCookedX(float rawX, float rawY);
     float toCookedY(float rawX, float rawY);
     float toDisplayX(int32_t rawX);
+    float toDisplayX(int32_t rawX, int32_t displayWidth);
     float toDisplayY(int32_t rawY);
+    float toDisplayY(int32_t rawY, int32_t displayHeight);
+
 };
 
 const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
@@ -2804,6 +2835,10 @@
 const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
 const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
 const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
+const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
+        float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
+const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
+        float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
 const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
         TouchAffineTransformation(1, -2, 3, -4, 5, -6);
 
@@ -2820,6 +2855,11 @@
     setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
 }
 
+void TouchInputMapperTest::prepareVirtualDisplay(int32_t orientation) {
+    setVirtualDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
+        VIRTUAL_DISPLAY_HEIGHT, orientation, String8(VIRTUAL_DISPLAY_UNIQUE_ID));
+}
+
 void TouchInputMapperTest::prepareVirtualKeys() {
     mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]);
     mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]);
@@ -2850,11 +2890,19 @@
 }
 
 float TouchInputMapperTest::toDisplayX(int32_t rawX) {
-    return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN + 1);
+    return toDisplayX(rawX, DISPLAY_WIDTH);
+}
+
+float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
+    return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
 }
 
 float TouchInputMapperTest::toDisplayY(int32_t rawY) {
-    return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN + 1);
+    return toDisplayY(rawY, DISPLAY_HEIGHT);
+}
+
+float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
+    return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
 }
 
 
@@ -3314,6 +3362,105 @@
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
 }
 
+TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    addConfigurationProperty("touch.deviceType", "touchScreen");
+    addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
+
+    prepareVirtualDisplay(DISPLAY_ORIENTATION_0);
+    prepareButtons();
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    NotifyMotionArgs motionArgs;
+
+    // Down.
+    int32_t x = 100;
+    int32_t y = 125;
+    processDown(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.buttonState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
+            1, 0, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Move.
+    x += 50;
+    y += 75;
+    processMove(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.buttonState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
+            1, 0, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Up.
+    processUp(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.buttonState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
+            1, 0, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Should not have sent any more keys or motions.
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+}
+
 TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index c5bbeee..d60768c 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1250,7 +1250,7 @@
     }
 
     // Check maximum delay for the sensor.
-    nsecs_t maxDelayNs = sensor->getSensor().getMaxDelay() * 1000;
+    nsecs_t maxDelayNs = sensor->getSensor().getMaxDelay() * 1000LL;
     if (maxDelayNs > 0 && (samplingPeriodNs > maxDelayNs)) {
         samplingPeriodNs = maxDelayNs;
     }
@@ -1511,4 +1511,3 @@
 }
 
 }; // namespace android
-
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 7bb20ba..95a522d 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -54,11 +54,7 @@
     LOCAL_SRC_FILES += \
         SurfaceFlinger.cpp \
         DisplayHardware/HWComposer.cpp
-    ifeq ($(TARGET_USES_HWC2ON1ADAPTER), true)
-        LOCAL_CFLAGS += -DBYPASS_IHWC
-    endif
 else
-    LOCAL_CFLAGS += -DBYPASS_IHWC
     LOCAL_SRC_FILES += \
         SurfaceFlinger_hwc1.cpp \
         DisplayHardware/HWComposer_hwc1.cpp
@@ -84,7 +80,6 @@
     libdl \
     libfmq \
     libhardware \
-    libhwc2on1adapter \
     libhidlbase \
     libhidltransport \
     libhwbinder \
@@ -133,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/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 8270c39..0366630 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -88,55 +88,8 @@
 
 // Device methods
 
-#ifdef BYPASS_IHWC
-Device::Device(hwc2_device_t* device)
-  : mHwcDevice(device),
-    mCreateVirtualDisplay(nullptr),
-    mDestroyVirtualDisplay(nullptr),
-    mDump(nullptr),
-    mGetMaxVirtualDisplayCount(nullptr),
-    mRegisterCallback(nullptr),
-    mAcceptDisplayChanges(nullptr),
-    mCreateLayer(nullptr),
-    mDestroyLayer(nullptr),
-    mGetActiveConfig(nullptr),
-    mGetChangedCompositionTypes(nullptr),
-    mGetColorModes(nullptr),
-    mGetDisplayAttribute(nullptr),
-    mGetDisplayConfigs(nullptr),
-    mGetDisplayName(nullptr),
-    mGetDisplayRequests(nullptr),
-    mGetDisplayType(nullptr),
-    mGetDozeSupport(nullptr),
-    mGetHdrCapabilities(nullptr),
-    mGetReleaseFences(nullptr),
-    mPresentDisplay(nullptr),
-    mSetActiveConfig(nullptr),
-    mSetClientTarget(nullptr),
-    mSetColorMode(nullptr),
-    mSetColorTransform(nullptr),
-    mSetOutputBuffer(nullptr),
-    mSetPowerMode(nullptr),
-    mSetVsyncEnabled(nullptr),
-    mValidateDisplay(nullptr),
-    mSetCursorPosition(nullptr),
-    mSetLayerBuffer(nullptr),
-    mSetLayerSurfaceDamage(nullptr),
-    mSetLayerBlendMode(nullptr),
-    mSetLayerColor(nullptr),
-    mSetLayerCompositionType(nullptr),
-    mSetLayerDataspace(nullptr),
-    mSetLayerDisplayFrame(nullptr),
-    mSetLayerPlaneAlpha(nullptr),
-    mSetLayerSidebandStream(nullptr),
-    mSetLayerSourceCrop(nullptr),
-    mSetLayerTransform(nullptr),
-    mSetLayerVisibleRegion(nullptr),
-    mSetLayerZOrder(nullptr),
-#else
 Device::Device(bool useVrComposer)
   : mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),
-#endif // BYPASS_IHWC
     mCapabilities(),
     mDisplays(),
     mHotplug(),
@@ -147,18 +100,11 @@
     mPendingVsyncs()
 {
     loadCapabilities();
-    loadFunctionPointers();
     registerCallbacks();
 }
 
 Device::~Device()
 {
-#ifdef BYPASS_IHWC
-    if (mHwcDevice == nullptr) {
-        return;
-    }
-#endif
-
     for (auto element : mDisplays) {
         auto display = element.second.lock();
         if (!display) {
@@ -185,36 +131,18 @@
             }
         }
     }
-
-#ifdef BYPASS_IHWC
-    hwc2_close(mHwcDevice);
-#endif
 }
 
 // Required by HWC2 device
 
 std::string Device::dump() const
 {
-#ifdef BYPASS_IHWC
-    uint32_t numBytes = 0;
-    mDump(mHwcDevice, &numBytes, nullptr);
-
-    std::vector<char> buffer(numBytes);
-    mDump(mHwcDevice, &numBytes, buffer.data());
-
-    return std::string(buffer.data(), buffer.size());
-#else
     return mComposer->dumpDebugInfo();
-#endif
 }
 
 uint32_t Device::getMaxVirtualDisplayCount() const
 {
-#ifdef BYPASS_IHWC
-    return mGetMaxVirtualDisplayCount(mHwcDevice);
-#else
     return mComposer->getMaxVirtualDisplayCount();
-#endif
 }
 
 Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
@@ -223,15 +151,9 @@
     ALOGI("Creating virtual display");
 
     hwc2_display_t displayId = 0;
-#ifdef BYPASS_IHWC
-    int32_t intFormat = static_cast<int32_t>(*format);
-    int32_t intError = mCreateVirtualDisplay(mHwcDevice, width, height,
-            &intFormat, &displayId);
-#else
     auto intFormat = static_cast<Hwc2::PixelFormat>(*format);
     auto intError = mComposer->createVirtualDisplay(width, height,
             &intFormat, &displayId);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -285,9 +207,7 @@
 {
     if (connected == Connection::Connected) {
         if (!display->isConnected()) {
-#ifndef BYPASS_IHWC
             mComposer->setClientTargetSlotCount(display->getId());
-#endif
             display->loadConfigs();
             display->setConnected(true);
         }
@@ -345,21 +265,10 @@
 {
     static_assert(sizeof(Capability) == sizeof(int32_t),
             "Capability size has changed");
-#ifdef BYPASS_IHWC
-    uint32_t numCapabilities = 0;
-    mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
-    std::vector<Capability> capabilities(numCapabilities);
-    auto asInt = reinterpret_cast<int32_t*>(capabilities.data());
-    mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
-    for (auto capability : capabilities) {
-        mCapabilities.emplace(capability);
-    }
-#else
     auto capabilities = mComposer->getCapabilities();
     for (auto capability : capabilities) {
         mCapabilities.emplace(static_cast<Capability>(capability));
     }
-#endif
 }
 
 bool Device::hasCapability(HWC2::Capability capability) const
@@ -368,105 +277,6 @@
             capability) != mCapabilities.cend();
 }
 
-void Device::loadFunctionPointers()
-{
-#ifdef BYPASS_IHWC
-    // For all of these early returns, we log an error message inside
-    // loadFunctionPointer specifying which function failed to load
-
-    // Display function pointers
-    if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
-            mCreateVirtualDisplay)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
-            mDestroyVirtualDisplay)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
-            mGetMaxVirtualDisplayCount)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
-            mRegisterCallback)) return;
-
-    // Device function pointers
-    if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
-            mAcceptDisplayChanges)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
-            mCreateLayer)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
-            mDestroyLayer)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
-            mGetActiveConfig)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
-            mGetChangedCompositionTypes)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetColorModes,
-            mGetColorModes)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
-            mGetDisplayAttribute)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
-            mGetDisplayConfigs)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
-            mGetDisplayName)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
-            mGetDisplayRequests)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
-            mGetDisplayType)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
-            mGetDozeSupport)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
-            mGetHdrCapabilities)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
-            mGetReleaseFences)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
-            mPresentDisplay)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
-            mSetActiveConfig)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
-            mSetClientTarget)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetColorMode,
-            mSetColorMode)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform,
-            mSetColorTransform)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
-            mSetOutputBuffer)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
-            mSetPowerMode)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
-            mSetVsyncEnabled)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
-            mValidateDisplay)) return;
-
-    // Layer function pointers
-    if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
-            mSetCursorPosition)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
-            mSetLayerBuffer)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
-            mSetLayerSurfaceDamage)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
-            mSetLayerBlendMode)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
-            mSetLayerColor)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
-            mSetLayerCompositionType)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerDataspace,
-            mSetLayerDataspace)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
-            mSetLayerDisplayFrame)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
-            mSetLayerPlaneAlpha)) return;
-    if (hasCapability(Capability::SidebandStream)) {
-        if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
-                mSetLayerSidebandStream)) return;
-    }
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
-            mSetLayerSourceCrop)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
-            mSetLayerTransform)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
-            mSetLayerVisibleRegion)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
-            mSetLayerZOrder)) return;
-#endif // BYPASS_IHWC
-}
-
 namespace {
 class ComposerCallback : public Hwc2::IComposerCallback {
 public:
@@ -498,14 +308,8 @@
 
 void Device::registerCallbacks()
 {
-#ifdef BYPASS_IHWC
-    registerCallback<HWC2_PFN_HOTPLUG>(Callback::Hotplug, hotplug_hook);
-    registerCallback<HWC2_PFN_REFRESH>(Callback::Refresh, refresh_hook);
-    registerCallback<HWC2_PFN_VSYNC>(Callback::Vsync, vsync_hook);
-#else
     sp<ComposerCallback> callback = new ComposerCallback(this);
     mComposer->registerCallback(callback);
-#endif
 }
 
 
@@ -514,11 +318,7 @@
 void Device::destroyVirtualDisplay(hwc2_display_t display)
 {
     ALOGI("Destroying virtual display");
-#ifdef BYPASS_IHWC
-    int32_t intError = mDestroyVirtualDisplay(mHwcDevice, display);
-#else
     auto intError = mComposer->destroyVirtualDisplay(display);
-#endif
     auto error = static_cast<Error>(intError);
     ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
             " %s (%d)", display, to_string(error).c_str(), intError);
@@ -535,13 +335,8 @@
 {
     ALOGV("Created display %" PRIu64, id);
 
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
-            reinterpret_cast<int32_t *>(&mType));
-#else
     auto intError = mDevice.mComposer->getDisplayType(mId,
             reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
@@ -588,22 +383,14 @@
 
 Error Display::acceptChanges()
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mAcceptDisplayChanges(mDevice.mHwcDevice, mId);
-#else
     auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
 {
     hwc2_layer_t layerId = 0;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
-#else
     auto intError = mDevice.mComposer->createLayer(mId, &layerId);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -620,12 +407,7 @@
 {
     ALOGV("[%" PRIu64 "] getActiveConfig", mId);
     hwc2_config_t configId = 0;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
-            &configId);
-#else
     auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
-#endif
     auto error = static_cast<Error>(intError);
 
     if (error != Error::None) {
@@ -650,27 +432,12 @@
 Error Display::getChangedCompositionTypes(
         std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
 {
-#ifdef BYPASS_IHWC
-    uint32_t numElements = 0;
-    int32_t intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice,
-            mId, &numElements, nullptr, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<hwc2_layer_t> layerIds(numElements);
-    std::vector<int32_t> types(numElements);
-    intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice, mId,
-            &numElements, layerIds.data(), types.data());
-#else
     std::vector<Hwc2::Layer> layerIds;
     std::vector<Hwc2::IComposerClient::Composition> types;
     auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
             &layerIds, &types);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
-#endif
     error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -696,25 +463,10 @@
 
 Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
 {
-#ifdef BYPASS_IHWC
-    uint32_t numModes = 0;
-    int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
-            &numModes, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None)  {
-        return error;
-    }
-
-    std::vector<int32_t> modes(numModes);
-    intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
-            modes.data());
-    error = static_cast<Error>(intError);
-#else
     std::vector<Hwc2::ColorMode> modes;
     auto intError = mDevice.mComposer->getColorModes(mId, &modes);
     uint32_t numModes = modes.size();
     auto error = static_cast<Error>(intError);
-#endif
     if (error != Error::None) {
         return error;
     }
@@ -737,52 +489,14 @@
 
 Error Display::getName(std::string* outName) const
 {
-#ifdef BYPASS_IHWC
-    uint32_t size;
-    int32_t intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
-            nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<char> rawName(size);
-    intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
-            rawName.data());
-    error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    *outName = std::string(rawName.cbegin(), rawName.cend());
-    return Error::None;
-#else
     auto intError = mDevice.mComposer->getDisplayName(mId, outName);
     return static_cast<Error>(intError);
-#endif
 }
 
 Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
         std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
                 outLayerRequests)
 {
-#ifdef BYPASS_IHWC
-    int32_t intDisplayRequests = 0;
-    uint32_t numElements = 0;
-    int32_t intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
-            &intDisplayRequests, &numElements, nullptr, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<hwc2_layer_t> layerIds(numElements);
-    std::vector<int32_t> layerRequests(numElements);
-    intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
-            &intDisplayRequests, &numElements, layerIds.data(),
-            layerRequests.data());
-    error = static_cast<Error>(intError);
-#else
     uint32_t intDisplayRequests;
     std::vector<Hwc2::Layer> layerIds;
     std::vector<uint32_t> layerRequests;
@@ -790,7 +504,6 @@
             &intDisplayRequests, &layerIds, &layerRequests);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
-#endif
     if (error != Error::None) {
         return error;
     }
@@ -821,14 +534,8 @@
 
 Error Display::supportsDoze(bool* outSupport) const
 {
-#ifdef BYPASS_IHWC
-    int32_t intSupport = 0;
-    int32_t intError = mDevice.mGetDozeSupport(mDevice.mHwcDevice, mId,
-            &intSupport);
-#else
     bool intSupport = false;
     auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -844,20 +551,6 @@
     float maxLuminance = -1.0f;
     float maxAverageLuminance = -1.0f;
     float minLuminance = -1.0f;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
-            &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
-            &minLuminance);
-    auto error = static_cast<HWC2::Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<int32_t> types(numTypes);
-    intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
-            types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
-    error = static_cast<HWC2::Error>(intError);
-#else
     std::vector<Hwc2::Hdr> intTypes;
     auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
             &maxLuminance, &maxAverageLuminance, &minLuminance);
@@ -868,7 +561,6 @@
         types.push_back(static_cast<int32_t>(type));
     }
     numTypes = types.size();
-#endif
     if (error != Error::None) {
         return error;
     }
@@ -881,28 +573,12 @@
 Error Display::getReleaseFences(
         std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
 {
-#ifdef BYPASS_IHWC
-    uint32_t numElements = 0;
-    int32_t intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId,
-            &numElements, nullptr, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<hwc2_layer_t> layerIds(numElements);
-    std::vector<int32_t> fenceFds(numElements);
-    intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId, &numElements,
-            layerIds.data(), fenceFds.data());
-    error = static_cast<Error>(intError);
-#else
     std::vector<Hwc2::Layer> layerIds;
     std::vector<int> fenceFds;
     auto intError = mDevice.mComposer->getReleaseFences(mId,
             &layerIds, &fenceFds);
     auto error = static_cast<Error>(intError);
     uint32_t numElements = layerIds.size();
-#endif
     if (error != Error::None) {
         return error;
     }
@@ -917,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;
         }
     }
@@ -928,12 +607,7 @@
 Error Display::present(sp<Fence>* outPresentFence)
 {
     int32_t presentFenceFd = -1;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
-            &presentFenceFd);
-#else
     auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -951,12 +625,7 @@
                 config->getDisplayId(), mId);
         return Error::BadConfig;
     }
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetActiveConfig(mDevice.mHwcDevice, mId,
-            config->getId());
-#else
     auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -965,44 +634,24 @@
 {
     // TODO: Properly encode client target surface damage
     int32_t fenceFd = acquireFence->dup();
-#ifdef BYPASS_IHWC
-    (void) slot;
-    buffer_handle_t handle = nullptr;
-    if (target.get() && target->getNativeBuffer()) {
-        handle = target->getNativeBuffer()->handle;
-    }
-
-    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
-            fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
-#else
     auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
             fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
             std::vector<Hwc2::IComposerClient::Rect>());
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setColorMode(android_color_mode_t mode)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
-#else
     auto intError = mDevice.mComposer->setColorMode(mId,
             static_cast<Hwc2::ColorMode>(mode));
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setColorTransform(const android::mat4& matrix,
         android_color_transform_t hint)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
-            matrix.asArray(), static_cast<int32_t>(hint));
-#else
     auto intError = mDevice.mComposer->setColorTransform(mId,
             matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1011,38 +660,22 @@
 {
     int32_t fenceFd = releaseFence->dup();
     auto handle = buffer->getNativeBuffer()->handle;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
-            fenceFd);
-#else
     auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
-#endif
     close(fenceFd);
     return static_cast<Error>(intError);
 }
 
 Error Display::setPowerMode(PowerMode mode)
 {
-#ifdef BYPASS_IHWC
-    auto intMode = static_cast<int32_t>(mode);
-    int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
-#else
     auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
     auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setVsyncEnabled(Vsync enabled)
 {
-#ifdef BYPASS_IHWC
-    auto intEnabled = static_cast<int32_t>(enabled);
-    int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
-            intEnabled);
-#else
     auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
     auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1050,13 +683,8 @@
 {
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mValidateDisplay(mDevice.mHwcDevice, mId,
-            &numTypes, &numRequests);
-#else
     auto intError = mDevice.mComposer->validateDisplay(mId,
             &numTypes, &numRequests);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None && error != Error::HasChanges) {
         return error;
@@ -1072,14 +700,9 @@
 int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
 {
     int32_t value = 0;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
-            configId, static_cast<int32_t>(attribute), &value);
-#else
     auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
             static_cast<Hwc2::IComposerClient::Attribute>(attribute),
             &value);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
@@ -1108,26 +731,9 @@
 {
     ALOGV("[%" PRIu64 "] loadConfigs", mId);
 
-#ifdef BYPASS_IHWC
-    uint32_t numConfigs = 0;
-    int32_t intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId,
-            &numConfigs, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        ALOGE("[%" PRIu64 "] getDisplayConfigs [1] failed: %s (%d)", mId,
-                to_string(error).c_str(), intError);
-        return;
-    }
-
-    std::vector<hwc2_config_t> configIds(numConfigs);
-    intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId, &numConfigs,
-            configIds.data());
-    error = static_cast<Error>(intError);
-#else
     std::vector<Hwc2::Config> configIds;
     auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
     auto error = static_cast<Error>(intError);
-#endif
     if (error != Error::None) {
         ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
                 to_string(error).c_str(), intError);
@@ -1143,11 +749,7 @@
 
 void Display::destroyLayer(hwc2_layer_t layerId)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mDestroyLayer(mDevice.mHwcDevice, mId, layerId);
-#else
     auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
-#endif
     auto error = static_cast<Error>(intError);
     ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
             " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
@@ -1189,13 +791,8 @@
 
 Error Layer::setCursorPosition(int32_t x, int32_t y)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetCursorPosition(mDevice.mHwcDevice,
-            mDisplayId, mId, x, y);
-#else
     auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
             mId, x, y);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1203,19 +800,8 @@
         const sp<Fence>& acquireFence)
 {
     int32_t fenceFd = acquireFence->dup();
-#ifdef BYPASS_IHWC
-    (void) slot;
-    buffer_handle_t handle = nullptr;
-    if (buffer.get() && buffer->getNativeBuffer()) {
-        handle = buffer->getNativeBuffer()->handle;
-    }
-
-    int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
-            mId, handle, fenceFd);
-#else
     auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
             mId, slot, buffer, fenceFd);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1223,44 +809,22 @@
 {
     // We encode default full-screen damage as INVALID_RECT upstream, but as 0
     // rects for HWC
-#ifdef BYPASS_IHWC
-    int32_t intError = 0;
-#else
     Hwc2::Error intError = Hwc2::Error::NONE;
-#endif
     if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
-#ifdef BYPASS_IHWC
-        intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
-                mDisplayId, mId, {0, nullptr});
-#else
         intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
                 mId, std::vector<Hwc2::IComposerClient::Rect>());
-#endif
     } else {
         size_t rectCount = 0;
         auto rectArray = damage.getArray(&rectCount);
 
-#ifdef BYPASS_IHWC
-        std::vector<hwc_rect_t> hwcRects;
-#else
         std::vector<Hwc2::IComposerClient::Rect> hwcRects;
-#endif
         for (size_t rect = 0; rect < rectCount; ++rect) {
             hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
                     rectArray[rect].right, rectArray[rect].bottom});
         }
 
-#ifdef BYPASS_IHWC
-        hwc_region_t hwcRegion = {};
-        hwcRegion.numRects = rectCount;
-        hwcRegion.rects = hwcRects.data();
-
-        intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
-                mDisplayId, mId, hwcRegion);
-#else
         intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
                 mId, hwcRects);
-#endif
     }
 
     return static_cast<Error>(intError);
@@ -1268,83 +832,49 @@
 
 Error Layer::setBlendMode(BlendMode mode)
 {
-#ifdef BYPASS_IHWC
-    auto intMode = static_cast<int32_t>(mode);
-    int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
-            mDisplayId, mId, intMode);
-#else
     auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
     auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
             mId, intMode);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setColor(hwc_color_t color)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
-            mId, color);
-#else
     Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
     auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
             mId, hwcColor);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setCompositionType(Composition type)
 {
-#ifdef BYPASS_IHWC
-    auto intType = static_cast<int32_t>(type);
-    int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
-            mDisplayId, mId, intType);
-#else
     auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
     auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
             mId, intType);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setDataspace(android_dataspace_t dataspace)
 {
-#ifdef BYPASS_IHWC
-    auto intDataspace = static_cast<int32_t>(dataspace);
-    int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
-            mDisplayId, mId, intDataspace);
-#else
     auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
     auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
             mId, intDataspace);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setDisplayFrame(const Rect& frame)
 {
-#ifdef BYPASS_IHWC
-    hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
-    int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
-            mDisplayId, mId, hwcRect);
-#else
     Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
         frame.right, frame.bottom};
     auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
             mId, hwcRect);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setPlaneAlpha(float alpha)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetLayerPlaneAlpha(mDevice.mHwcDevice,
-            mDisplayId, mId, alpha);
-#else
     auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
             mId, alpha);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1355,42 +885,25 @@
                 "device supports sideband streams");
         return Error::Unsupported;
     }
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
-            mDisplayId, mId, stream);
-#else
     auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
             mId, stream);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setSourceCrop(const FloatRect& crop)
 {
-#ifdef BYPASS_IHWC
-    hwc_frect_t hwcRect{crop.left, crop.top, crop.right, crop.bottom};
-    int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
-            mDisplayId, mId, hwcRect);
-#else
     Hwc2::IComposerClient::FRect hwcRect{
         crop.left, crop.top, crop.right, crop.bottom};
     auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
             mId, hwcRect);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setTransform(Transform transform)
 {
-#ifdef BYPASS_IHWC
-    auto intTransform = static_cast<int32_t>(transform);
-    int32_t intError = mDevice.mSetLayerTransform(mDevice.mHwcDevice,
-            mDisplayId, mId, intTransform);
-#else
     auto intTransform = static_cast<Hwc2::Transform>(transform);
     auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
             mId, intTransform);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1399,50 +912,26 @@
     size_t rectCount = 0;
     auto rectArray = region.getArray(&rectCount);
 
-#ifdef BYPASS_IHWC
-    std::vector<hwc_rect_t> hwcRects;
-#else
     std::vector<Hwc2::IComposerClient::Rect> hwcRects;
-#endif
     for (size_t rect = 0; rect < rectCount; ++rect) {
         hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
                 rectArray[rect].right, rectArray[rect].bottom});
     }
 
-#ifdef BYPASS_IHWC
-    hwc_region_t hwcRegion = {};
-    hwcRegion.numRects = rectCount;
-    hwcRegion.rects = hwcRects.data();
-
-    int32_t intError = mDevice.mSetLayerVisibleRegion(mDevice.mHwcDevice,
-            mDisplayId, mId, hwcRegion);
-#else
     auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
             mId, hwcRects);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setZOrder(uint32_t z)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetLayerZOrder(mDevice.mHwcDevice, mDisplayId,
-            mId, z);
-#else
     auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setInfo(uint32_t type, uint32_t appId)
 {
-#ifdef BYPASS_IHWC
-  (void)type;
-  (void)appId;
-  int32_t intError = 0;
-#else
   auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
-#endif
   return static_cast<Error>(intError);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 643b1e0..97582a7 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -62,14 +62,10 @@
 class Device
 {
 public:
-#ifdef BYPASS_IHWC
-    explicit Device(hwc2_device_t* device);
-#else
     // useVrComposer is passed to the composer HAL. When true, the composer HAL
     // will use the vr composer service, otherwise it uses the real hardware
     // composer.
     Device(bool useVrComposer);
-#endif
     ~Device();
 
     friend class HWC2::Display;
@@ -107,43 +103,12 @@
 
     bool hasCapability(HWC2::Capability capability) const;
 
-#ifdef BYPASS_IHWC
-    android::Hwc2::Composer* getComposer() { return nullptr; }
-#else
     android::Hwc2::Composer* getComposer() { return mComposer.get(); }
-#endif
 
 private:
     // Initialization methods
 
-#ifdef BYPASS_IHWC
-    template <typename PFN>
-    [[clang::warn_unused_result]] bool loadFunctionPointer(
-            FunctionDescriptor desc, PFN& outPFN) {
-        auto intDesc = static_cast<int32_t>(desc);
-        auto pfn = mHwcDevice->getFunction(mHwcDevice, intDesc);
-        if (pfn != nullptr) {
-            outPFN = reinterpret_cast<PFN>(pfn);
-            return true;
-        } else {
-            ALOGE("Failed to load function %s", to_string(desc).c_str());
-            return false;
-        }
-    }
-
-    template <typename PFN, typename HOOK>
-    void registerCallback(Callback callback, HOOK hook) {
-        static_assert(std::is_same<PFN, HOOK>::value,
-                "Incompatible function pointer");
-        auto intCallback = static_cast<int32_t>(callback);
-        auto callbackData = static_cast<hwc2_callback_data_t>(this);
-        auto pfn = reinterpret_cast<hwc2_function_pointer_t>(hook);
-        mRegisterCallback(mHwcDevice, intCallback, callbackData, pfn);
-    }
-#endif
-
     void loadCapabilities();
-    void loadFunctionPointers();
     void registerCallbacks();
 
     // For use by Display
@@ -151,60 +116,7 @@
     void destroyVirtualDisplay(hwc2_display_t display);
 
     // Member variables
-
-#ifdef BYPASS_IHWC
-    hwc2_device_t* mHwcDevice;
-
-    // Device function pointers
-    HWC2_PFN_CREATE_VIRTUAL_DISPLAY mCreateVirtualDisplay;
-    HWC2_PFN_DESTROY_VIRTUAL_DISPLAY mDestroyVirtualDisplay;
-    HWC2_PFN_DUMP mDump;
-    HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT mGetMaxVirtualDisplayCount;
-    HWC2_PFN_REGISTER_CALLBACK mRegisterCallback;
-
-    // Display function pointers
-    HWC2_PFN_ACCEPT_DISPLAY_CHANGES mAcceptDisplayChanges;
-    HWC2_PFN_CREATE_LAYER mCreateLayer;
-    HWC2_PFN_DESTROY_LAYER mDestroyLayer;
-    HWC2_PFN_GET_ACTIVE_CONFIG mGetActiveConfig;
-    HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES mGetChangedCompositionTypes;
-    HWC2_PFN_GET_COLOR_MODES mGetColorModes;
-    HWC2_PFN_GET_DISPLAY_ATTRIBUTE mGetDisplayAttribute;
-    HWC2_PFN_GET_DISPLAY_CONFIGS mGetDisplayConfigs;
-    HWC2_PFN_GET_DISPLAY_NAME mGetDisplayName;
-    HWC2_PFN_GET_DISPLAY_REQUESTS mGetDisplayRequests;
-    HWC2_PFN_GET_DISPLAY_TYPE mGetDisplayType;
-    HWC2_PFN_GET_DOZE_SUPPORT mGetDozeSupport;
-    HWC2_PFN_GET_HDR_CAPABILITIES mGetHdrCapabilities;
-    HWC2_PFN_GET_RELEASE_FENCES mGetReleaseFences;
-    HWC2_PFN_PRESENT_DISPLAY mPresentDisplay;
-    HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig;
-    HWC2_PFN_SET_CLIENT_TARGET mSetClientTarget;
-    HWC2_PFN_SET_COLOR_MODE mSetColorMode;
-    HWC2_PFN_SET_COLOR_TRANSFORM mSetColorTransform;
-    HWC2_PFN_SET_OUTPUT_BUFFER mSetOutputBuffer;
-    HWC2_PFN_SET_POWER_MODE mSetPowerMode;
-    HWC2_PFN_SET_VSYNC_ENABLED mSetVsyncEnabled;
-    HWC2_PFN_VALIDATE_DISPLAY mValidateDisplay;
-
-    // Layer function pointers
-    HWC2_PFN_SET_CURSOR_POSITION mSetCursorPosition;
-    HWC2_PFN_SET_LAYER_BUFFER mSetLayerBuffer;
-    HWC2_PFN_SET_LAYER_SURFACE_DAMAGE mSetLayerSurfaceDamage;
-    HWC2_PFN_SET_LAYER_BLEND_MODE mSetLayerBlendMode;
-    HWC2_PFN_SET_LAYER_COLOR mSetLayerColor;
-    HWC2_PFN_SET_LAYER_COMPOSITION_TYPE mSetLayerCompositionType;
-    HWC2_PFN_SET_LAYER_DATASPACE mSetLayerDataspace;
-    HWC2_PFN_SET_LAYER_DISPLAY_FRAME mSetLayerDisplayFrame;
-    HWC2_PFN_SET_LAYER_PLANE_ALPHA mSetLayerPlaneAlpha;
-    HWC2_PFN_SET_LAYER_SIDEBAND_STREAM mSetLayerSidebandStream;
-    HWC2_PFN_SET_LAYER_SOURCE_CROP mSetLayerSourceCrop;
-    HWC2_PFN_SET_LAYER_TRANSFORM mSetLayerTransform;
-    HWC2_PFN_SET_LAYER_VISIBLE_REGION mSetLayerVisibleRegion;
-    HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder;
-#else
     std::unique_ptr<android::Hwc2::Composer> mComposer;
-#endif // BYPASS_IHWC
 
     std::unordered_set<Capability> mCapabilities;
     std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 40979c9..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;
@@ -109,45 +106,7 @@
 void HWComposer::loadHwcModule(bool useVrComposer)
 {
     ALOGV("loadHwcModule");
-
-#ifdef BYPASS_IHWC
-    (void)useVrComposer; // Silence unused parameter warning.
-
-    hw_module_t const* module;
-
-    if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
-        ALOGE("%s module not found, aborting", HWC_HARDWARE_MODULE_ID);
-        abort();
-    }
-
-    hw_device_t* device = nullptr;
-    int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
-    if (error != 0) {
-        ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
-        abort();
-    }
-
-    uint32_t majorVersion = (device->version >> 24) & 0xF;
-    if (majorVersion == 2) {
-        mHwcDevice = std::make_unique<HWC2::Device>(
-                reinterpret_cast<hwc2_device_t*>(device));
-    } else {
-        mAdapter = std::make_unique<HWC2On1Adapter>(
-                reinterpret_cast<hwc_composer_device_1_t*>(device));
-        uint8_t minorVersion = mAdapter->getHwc1MinorVersion();
-        if (minorVersion < 1) {
-            ALOGE("Cannot adapt to HWC version %d.%d",
-                    static_cast<int32_t>((minorVersion >> 8) & 0xF),
-                    static_cast<int32_t>(minorVersion & 0xF));
-            abort();
-        }
-        mHwcDevice = std::make_unique<HWC2::Device>(
-                static_cast<hwc2_device_t*>(mAdapter.get()));
-    }
-#else
     mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);
-#endif
-
     mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
 }
 
@@ -494,8 +453,6 @@
         return NO_ERROR;
     }
 
-    mDumpMayLockUp = true;
-
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
     auto error = hwcDisplay->validate(&numTypes, &numRequests);
@@ -636,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));
@@ -876,19 +830,10 @@
 */
 
 bool HWComposer::isUsingVrComposer() const {
-#ifdef BYPASS_IHWC
-    return false;
-#else
     return getComposer()->isUsingVrComposer();
-#endif
 }
 
 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/DisplayHardware/HWComposerBufferCache.cpp b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
index 6b91224..a234b63 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
@@ -29,10 +29,6 @@
         const sp<GraphicBuffer>& buffer,
         uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
 {
-#ifdef BYPASS_IHWC
-    *outSlot = slot;
-    *outBuffer = buffer;
-#else
     if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
         // default to slot 0
         slot = 0;
@@ -53,7 +49,6 @@
         // update cache
         mBuffers[slot] = buffer;
     }
-#endif
 }
 
 } // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d33d370..6f430a3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -103,7 +103,7 @@
         mLastFrameNumberReceived(0),
         mUpdateTexImageFailed(false),
         mAutoRefresh(false),
-        mFreezePositionUpdates(false)
+        mFreezeGeometryUpdates(false)
 {
 #ifdef USE_HWC2
     ALOGV("Creating Layer %s", name.string());
@@ -131,6 +131,8 @@
     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;
@@ -296,6 +298,11 @@
     }
 
     mSurfaceFlingerConsumer->abandon();
+
+#ifdef USE_HWC2
+    clearHwcLayers();
+#endif
+
     for (const auto& child : mCurrentChildren) {
         child->onRemoved();
     }
@@ -392,6 +399,10 @@
     Transform t = getTransform();
     win = t.transform(win);
 
+    if (!s.finalCrop.isEmpty()) {
+        win.intersect(s.finalCrop, &win);
+    }
+
     const sp<Layer>& p = getParent();
     // Now we need to calculate the parent bounds, so we can clip ourselves to those.
     // When calculating the parent bounds for purposes of clipping,
@@ -697,7 +708,16 @@
             mName.string(), z, to_string(error).c_str(),
             static_cast<int32_t>(error));
 
-    error = hwcLayer->setInfo(s.type, s.appId);
+    int type = s.type;
+    int appId = s.appId;
+    sp<Layer> parent = mParent.promote();
+    if (parent.get()) {
+        auto& parentState = parent->getDrawingState();
+        type = parentState.type;
+        appId = parentState.appId;
+    }
+
+    error = hwcLayer->setInfo(type, appId);
     ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)",
              mName.string(), static_cast<int32_t>(error));
 #else
@@ -1627,12 +1647,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;
@@ -1693,10 +1726,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);
@@ -1819,26 +1856,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;
@@ -2128,7 +2169,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);
@@ -2506,7 +2547,25 @@
     }
 
     for (const sp<Layer>& child : mCurrentChildren) {
-        newParent->addChild(child);
+        // We don't call addChild as we need to delay updating the child's parent pointer until
+        // a transaction occurs. Remember a refresh could occur in between now and the next
+        // transaction, in which case the Layer's parent pointer would be updated, but changes
+        // made to the parent in the same transaction would not have applied.
+        // This means that the following kind of scenario wont work:
+        //
+        // 1. Existing and visible child and parent surface exist
+        // 2. Create new surface hidden
+        // 3. Open transaction
+        // 4. Show the new surface, and reparent the old surface's children to it.
+        // 5. Close transaction.
+        //
+        // If we were to update the parent pointer immediately, then the child surface
+        // could disappear for one frame as it pointed at the new parent which
+        // hasn't yet become visible as the transaction hasn't yet occurred.
+        //
+        // Instead we defer the reparenting to commitChildList which happens as part
+        // of the global transaction.
+        newParent->mCurrentChildren.add(child);
 
         sp<Client> client(child->mClientRef.promote());
         if (client != nullptr) {
@@ -2676,6 +2735,8 @@
 void Layer::commitChildList() {
     for (size_t i = 0; i < mCurrentChildren.size(); i++) {
         const auto& child = mCurrentChildren[i];
+        child->setParent(this);
+
         child->commitChildList();
     }
     mDrawingChildren = mCurrentChildren;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9f45435..05c367d 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);
@@ -754,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 0b302eb..6e37b45 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -37,7 +37,7 @@
     mStickyTransformSet(stickySet),
     mName(name),
     mOverrideScalingMode(overrideScalingMode),
-    mFreezePositionUpdates(freezePositionUpdates) {}
+    mFreezeGeometryUpdates(freezePositionUpdates) {}
 
 bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
     if (buf == NULL) {
@@ -73,6 +73,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,
@@ -100,6 +113,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;
 
@@ -115,18 +132,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 45cac6f..29a8292 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1116,9 +1116,14 @@
 
 void SurfaceFlinger::resyncWithRateLimit() {
     static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
-    if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+
+    // No explicit locking is needed here since EventThread holds a lock while calling this method
+    static nsecs_t sLastResyncAttempted = 0;
+    const nsecs_t now = systemTime();
+    if (now - sLastResyncAttempted > kIgnoreDelay) {
         resyncToHardwareVsync(false);
     }
+    sLastResyncAttempted = now;
 }
 
 void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type,
@@ -1262,7 +1267,6 @@
         }
     }
     mDisplays.clear();
-    initializeDisplays();
 }
 
 void SurfaceFlinger::updateVrFlinger() {
@@ -1309,6 +1313,12 @@
     // parts of this class rely on the primary display always being available.
     createDefaultDisplayDevice();
 
+    // Reset the timing values to account for the period of the swapped in HWC
+    const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+    const nsecs_t period = activeConfig->getVsyncPeriod();
+    mAnimFrameTracker.setDisplayRefreshPeriod(period);
+    setCompositorTimingSnapped(0, period, 0);
+
     android_atomic_or(1, &mRepaintEverything);
     setTransactionFlags(eDisplayTransactionNeeded);
 }
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/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index ff6be81..aea602b 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -4,6 +4,6 @@
     group graphics drmrpc readproc
     onrestart restart zygote
     writepid /dev/stune/foreground/tasks
-    socket pdx/system/vr/display/client stream 0666 system graphics
-    socket pdx/system/vr/display/manager stream 0666 system graphics
-    socket pdx/system/vr/display/vsync stream 0666 system graphics
+    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
+    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
+    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 1b17e55..b7792c7 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;
     {
@@ -762,6 +834,38 @@
     }
 }
 
+TEST_F(ChildLayerTest, ChildLayerCropping) {
+    SurfaceComposerClient::openGlobalTransaction();
+    mChild->show();
+    mChild->setPosition(0, 0);
+    mFGSurfaceControl->setPosition(0, 0);
+    mFGSurfaceControl->setCrop(Rect(0, 0, 5, 5));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectChildColor(0, 0);
+        mCapture->expectChildColor(4, 4);
+        mCapture->expectBGColor(5, 5);
+    }
+}
+
+TEST_F(ChildLayerTest, ChildLayerFinalCropping) {
+    SurfaceComposerClient::openGlobalTransaction();
+    mChild->show();
+    mChild->setPosition(0, 0);
+    mFGSurfaceControl->setPosition(0, 0);
+    mFGSurfaceControl->setFinalCrop(Rect(0, 0, 5, 5));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectChildColor(0, 0);
+        mCapture->expectChildColor(4, 4);
+        mCapture->expectBGColor(5, 5);
+    }
+}
+
 TEST_F(ChildLayerTest, ChildLayerConstraints) {
     SurfaceComposerClient::openGlobalTransaction();
     mChild->show();
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index debcc73..d27f274 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -73,7 +73,7 @@
       } else {
         std::string dimensions = std::to_string(info.width) + "x" +
                                  std::to_string(info.height) + "x" +
-                                 std::to_string(info.slice_count);
+                                 std::to_string(info.layer_count);
         stream << std::setw(14) << dimensions;
       }
       stream << " ";
@@ -120,7 +120,7 @@
       } else {
         std::string dimensions = std::to_string(info.width) + "x" +
                                  std::to_string(info.height) + "x" +
-                                 std::to_string(info.slice_count);
+                                 std::to_string(info.layer_count);
         stream << std::setw(14) << dimensions;
       }
       stream << " ";
@@ -242,15 +242,13 @@
 Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
                                               uint32_t height, uint32_t format,
                                               uint64_t usage,
-                                              size_t meta_size_bytes,
-                                              size_t slice_count) {
+                                              size_t meta_size_bytes) {
   // Use the producer channel id as the global buffer id.
   const int buffer_id = message.GetChannelId();
   ALOGD_IF(TRACE,
            "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
-           "format=%u usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
-           buffer_id, width, height, format, usage, meta_size_bytes,
-           slice_count);
+           "format=%u usage=%" PRIx64 " meta_size_bytes=%zu",
+           buffer_id, width, height, format, usage, meta_size_bytes);
 
   // See if this channel is already attached to a buffer.
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -258,9 +256,10 @@
           buffer_id);
     return ErrorStatus(EALREADY);
   }
-
-  auto status = ProducerChannel::Create(this, buffer_id, width, height, format,
-                                        usage, meta_size_bytes, slice_count);
+  const uint32_t kDefaultLayerCount = 1;
+  auto status = ProducerChannel::Create(this, buffer_id, width, height,
+                                        kDefaultLayerCount, format, usage,
+                                        meta_size_bytes);
   if (status) {
     message.SetChannel(status.take());
     return {};
@@ -274,14 +273,15 @@
 Status<void> BufferHubService::OnCreatePersistentBuffer(
     Message& message, const std::string& name, int user_id, int group_id,
     uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
-    size_t meta_size_bytes, size_t slice_count) {
+    size_t meta_size_bytes) {
+  const uint32_t kDefaultLayerCount = 1;
   const int channel_id = message.GetChannelId();
   ALOGD_IF(TRACE,
            "BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
            "user_id=%d group_id=%d width=%u height=%u format=%u "
-           "usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
+           "usage=%" PRIx64 " meta_size_bytes=%zu",
            channel_id, name.c_str(), user_id, group_id, width, height, format,
-           usage, meta_size_bytes, slice_count);
+           usage, meta_size_bytes);
 
   // See if this channel is already attached to a buffer.
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -302,8 +302,8 @@
           "not have permission to access named buffer: name=%s euid=%d egid=%d",
           name.c_str(), euid, euid);
       return ErrorStatus(EPERM);
-    } else if (!buffer->CheckParameters(width, height, format, usage,
-                                        meta_size_bytes, slice_count)) {
+    } else if (!buffer->CheckParameters(width, height, kDefaultLayerCount,
+                                        format, usage, meta_size_bytes)) {
       ALOGE(
           "BufferHubService::OnCreatePersistentBuffer: Requested an existing "
           "buffer with different parameters: name=%s",
@@ -321,9 +321,9 @@
       return {};
     }
   } else {
-    auto status =
-        ProducerChannel::Create(this, channel_id, width, height, format, usage,
-                                meta_size_bytes, slice_count);
+    auto status = ProducerChannel::Create(this, channel_id, width, height,
+                                          kDefaultLayerCount, format, usage,
+                                          meta_size_bytes);
     if (!status) {
       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 817b01e..3bc2635 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -50,9 +50,9 @@
     // Data field for buffer producer.
     uint32_t width = 0;
     uint32_t height = 0;
+    uint32_t layer_count = 0;
     uint32_t format = 0;
     uint64_t usage = 0;
-    size_t slice_count = 0;
     std::string name;
 
     // Data filed for producer queue.
@@ -60,16 +60,15 @@
     UsagePolicy usage_policy{0, 0, 0, 0};
 
     BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
-               uint32_t format, uint64_t usage, size_t slice_count,
-               const std::string& name)
+               uint32_t layer_count, uint32_t format, uint64_t usage, const std::string& name)
         : id(id),
           type(kProducerType),
           consumer_count(consumer_count),
           width(width),
           height(height),
+          layer_count(layer_count),
           format(format),
           usage(usage),
-          slice_count(slice_count),
           name(name) {}
 
     BufferInfo(int id, size_t consumer_count, size_t capacity,
@@ -158,12 +157,13 @@
 
   pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width,
                                    uint32_t height, uint32_t format,
-                                   uint64_t usage, size_t meta_size_bytes,
-                                   size_t slice_count);
-  pdx::Status<void> OnCreatePersistentBuffer(
-      pdx::Message& message, const std::string& name, int user_id, int group_id,
-      uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
-      size_t meta_size_bytes, size_t slice_count);
+                                   uint64_t usage, size_t meta_size_bytes);
+  pdx::Status<void> OnCreatePersistentBuffer(pdx::Message& message,
+                                             const std::string& name,
+                                             int user_id, int group_id,
+                                             uint32_t width, uint32_t height,
+                                             uint32_t format, uint64_t usage,
+                                             size_t meta_size_bytes);
   pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message,
                                           const std::string& name);
   pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
diff --git a/services/vr/bufferhubd/bufferhubd.rc b/services/vr/bufferhubd/bufferhubd.rc
index 8d57723..46fe5f9 100644
--- a/services/vr/bufferhubd/bufferhubd.rc
+++ b/services/vr/bufferhubd/bufferhubd.rc
@@ -3,4 +3,4 @@
   user system
   group system
   writepid /dev/cpuset/tasks
-  socket pdx/system/buffer_hub/client stream 0660 system system
+  socket pdx/system/buffer_hub/client stream 0660 system system u:object_r:pdx_bufferhub_client_endpoint_socket:s0
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 311f5c6..08b2790 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -75,11 +75,6 @@
           *producer, &ProducerChannel::OnGetBuffer, message);
       return true;
 
-    case BufferHubRPC::GetBuffers::Opcode:
-      DispatchRemoteMethod<BufferHubRPC::GetBuffers>(
-          *producer, &ProducerChannel::OnGetBuffers, message);
-      return true;
-
     case BufferHubRPC::NewConsumer::Opcode:
       DispatchRemoteMethod<BufferHubRPC::NewConsumer>(
           *producer, &ProducerChannel::OnNewConsumer, message);
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 398aa12..b9984a0 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -26,23 +26,20 @@
 
 ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
                                  uint32_t width, uint32_t height,
-                                 uint32_t format, uint64_t usage,
-                                 size_t meta_size_bytes, size_t slice_count,
+                                 uint32_t layer_count, uint32_t format,
+                                 uint64_t usage, size_t meta_size_bytes,
                                  int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerType),
       pending_consumers_(0),
-      slices_(std::max(static_cast<size_t>(1), slice_count)),
       producer_owns_(true),
       meta_size_bytes_(meta_size_bytes),
       meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) {
-  for (auto& ion_buffer : slices_) {
-    const int ret = ion_buffer.Alloc(width, height, format, usage);
-    if (ret < 0) {
-      ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
-            strerror(-ret));
-      *error = ret;
-      return;
-    }
+  const int ret = buffer_.Alloc(width, height, layer_count, format, usage);
+  if (ret < 0) {
+    ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
+          strerror(-ret));
+    *error = ret;
+    return;
   }
 
   // Success.
@@ -51,12 +48,12 @@
 
 Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
     BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
-    uint32_t format, uint64_t usage, size_t meta_size_bytes,
-    size_t slice_count) {
+    uint32_t layer_count, uint32_t format, uint64_t usage,
+    size_t meta_size_bytes) {
   int error;
   std::shared_ptr<ProducerChannel> producer(
-      new ProducerChannel(service, channel_id, width, height, format, usage,
-                          meta_size_bytes, slice_count, &error));
+      new ProducerChannel(service, channel_id, width, height, layer_count,
+                          format, usage, meta_size_bytes, &error));
   if (error < 0)
     return ErrorStatus(-error);
   else
@@ -72,9 +69,9 @@
 }
 
 BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
-  return BufferInfo(buffer_id(), consumer_channels_.size(), slices_[0].width(),
-                    slices_[0].height(), slices_[0].format(),
-                    slices_[0].usage(), slices_.size(), name_);
+  return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(),
+                    buffer_.height(), buffer_.layer_count(), buffer_.format(),
+                    buffer_.usage(), name_);
 }
 
 void ProducerChannel::HandleImpulse(Message& message) {
@@ -94,11 +91,6 @@
           *this, &ProducerChannel::OnGetBuffer, message);
       return true;
 
-    case BufferHubRPC::GetBuffers::Opcode:
-      DispatchRemoteMethod<BufferHubRPC::GetBuffers>(
-          *this, &ProducerChannel::OnGetBuffers, message);
-      return true;
-
     case BufferHubRPC::NewConsumer::Opcode:
       DispatchRemoteMethod<BufferHubRPC::NewConsumer>(
           *this, &ProducerChannel::OnNewConsumer, message);
@@ -130,24 +122,10 @@
 }
 
 Status<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffer(
-    Message& message, unsigned index) {
+    Message& message) {
   ATRACE_NAME("ProducerChannel::OnGetBuffer");
   ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d", buffer_id());
-  if (index < slices_.size()) {
-    return {NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id())};
-  } else {
-    return ErrorStatus(EINVAL);
-  }
-}
-
-Status<std::vector<NativeBufferHandle<BorrowedHandle>>>
-ProducerChannel::OnGetBuffers(Message&) {
-  ATRACE_NAME("ProducerChannel::OnGetBuffers");
-  ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffers: buffer_id=%d", buffer_id());
-  std::vector<NativeBufferHandle<BorrowedHandle>> buffer_handles;
-  for (const auto& buffer : slices_)
-    buffer_handles.emplace_back(buffer, buffer_id());
-  return {std::move(buffer_handles)};
+  return {NativeBufferHandle<BorrowedHandle>(buffer_, buffer_id())};
 }
 
 Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
@@ -371,12 +349,11 @@
 
 // Returns true if the given parameters match the underlying buffer parameters.
 bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
-                                      uint32_t format, uint64_t usage,
-                                      size_t meta_size_bytes,
-                                      size_t slice_count) {
-  return slices_.size() == slice_count && meta_size_bytes == meta_size_bytes_ &&
-         slices_[0].width() == width && slices_[0].height() == height &&
-         slices_[0].format() == format && slices_[0].usage() == usage;
+                                      uint32_t layer_count, uint32_t format,
+                                      uint64_t usage, size_t meta_size_bytes) {
+  return meta_size_bytes == meta_size_bytes_ && buffer_.width() == width &&
+         buffer_.height() == height && buffer_.layer_count() == layer_count &&
+         buffer_.format() == format && buffer_.usage() == usage;
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index 6de619d..5ada478 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -32,8 +32,8 @@
 
   static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
       BufferHubService* service, int channel_id, uint32_t width,
-      uint32_t height, uint32_t format, uint64_t usage, size_t meta_size_bytes,
-      size_t slice_count);
+      uint32_t height, uint32_t layer_count, uint32_t format, uint64_t usage,
+      size_t meta_size_bytes);
 
   ~ProducerChannel() override;
 
@@ -42,10 +42,7 @@
 
   BufferInfo GetBufferInfo() const override;
 
-  pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message,
-                                                              unsigned index);
-  pdx::Status<std::vector<NativeBufferHandle<BorrowedHandle>>> OnGetBuffers(
-      Message& message);
+  pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message);
 
   pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message);
   pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message);
@@ -61,9 +58,8 @@
   void RemoveConsumer(ConsumerChannel* channel);
 
   bool CheckAccess(int euid, int egid);
-  bool CheckParameters(uint32_t width, uint32_t height, uint32_t format,
-                       uint64_t usage, size_t meta_size_bytes,
-                       size_t slice_count);
+  bool CheckParameters(uint32_t width, uint32_t height, uint32_t layer_count,
+                       uint32_t format, uint64_t usage, size_t meta_size_bytes);
 
   pdx::Status<void> OnProducerMakePersistent(Message& message,
                                              const std::string& name,
@@ -76,7 +72,7 @@
   // zero then the producer can re-acquire ownership.
   int pending_consumers_;
 
-  std::vector<IonBuffer> slices_;
+  IonBuffer buffer_;
 
   bool producer_owns_;
   LocalFence post_fence_;
@@ -95,8 +91,8 @@
   std::string name_;
 
   ProducerChannel(BufferHubService* service, int channel, uint32_t width,
-                  uint32_t height, uint32_t format, uint64_t usage,
-                  size_t meta_size_bytes, size_t slice_count, int* error);
+                  uint32_t height, uint32_t layer_count, uint32_t format,
+                  uint64_t usage, size_t meta_size_bytes, int* error);
 
   pdx::Status<void> OnProducerPost(
       Message& message, LocalFence acquire_fence,
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 843277e..886e621 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -39,14 +39,12 @@
     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)) {
+  if ((usage_policy.usage_deny_set_mask & usage_policy.usage_deny_clear_mask)) {
     ALOGE(
         "BufferHubService::OnCreateProducerQueue: illegal usage mask "
         "configuration: usage_deny_set_mask=%" PRIx64
         " usage_deny_clear_mask=%" PRIx64,
-        usage_policy.usage_deny_set_mask,
-        usage_policy.usage_deny_clear_mask);
+        usage_policy.usage_deny_set_mask, usage_policy.usage_deny_clear_mask);
     return ErrorStatus(EINVAL);
   }
 
@@ -141,8 +139,8 @@
 
 Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
 ProducerQueueChannel::OnProducerQueueAllocateBuffers(
-    Message& message, uint32_t width, uint32_t height, uint32_t format,
-    uint64_t usage, size_t slice_count, size_t buffer_count) {
+    Message& message, uint32_t width, uint32_t height, uint32_t layer_count,
+    uint32_t format, uint64_t usage, size_t buffer_count) {
   ATRACE_NAME("ProducerQueueChannel::OnProducerQueueAllocateBuffers");
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::OnProducerQueueAllocateBuffers: "
@@ -176,8 +174,8 @@
       (usage & ~usage_policy_.usage_clear_mask) | usage_policy_.usage_set_mask;
 
   for (size_t i = 0; i < buffer_count; i++) {
-    auto status = AllocateBuffer(message, width, height, format,
-                                 effective_usage, slice_count);
+    auto status = AllocateBuffer(message, width, height, layer_count, format,
+                                 effective_usage);
     if (!status) {
       ALOGE(
           "ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to "
@@ -192,8 +190,8 @@
 
 Status<std::pair<RemoteChannelHandle, size_t>>
 ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width,
-                                     uint32_t height, uint32_t format,
-                                     uint64_t usage, size_t slice_count) {
+                                     uint32_t height, uint32_t layer_count,
+                                     uint32_t format, uint64_t usage) {
   ATRACE_NAME("ProducerQueueChannel::AllocateBuffer");
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::AllocateBuffer: producer_channel_id=%d",
@@ -218,13 +216,13 @@
 
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%u "
-           "height=%u format=%u usage=%" PRIx64 " slice_count=%zu",
-           buffer_id, width, height, format, usage, slice_count);
+           "height=%u layer_count=%u format=%u usage=%" PRIx64,
+           buffer_id, width, height, layer_count, format, usage);
   auto buffer_handle = status.take();
 
   auto producer_channel_status =
-      ProducerChannel::Create(service(), buffer_id, width, height, format,
-                              usage, meta_size_bytes_, slice_count);
+      ProducerChannel::Create(service(), buffer_id, width, height, layer_count,
+                              format, usage, 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 13c9ddc..28c74cd 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -34,8 +34,8 @@
   // handle this as if a new producer is created through kOpCreateBuffer.
   pdx::Status<std::vector<std::pair<pdx::RemoteChannelHandle, size_t>>>
   OnProducerQueueAllocateBuffers(pdx::Message& message, uint32_t width,
-                                 uint32_t height, uint32_t format,
-                                 uint64_t usage, size_t slice_count,
+                                 uint32_t height, uint32_t layer_count,
+                                 uint32_t format, uint64_t usage,
                                  size_t buffer_count);
 
   // Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
@@ -57,8 +57,8 @@
   // Returns the remote channel handle and the slot number for the newly
   // allocated buffer.
   pdx::Status<std::pair<pdx::RemoteChannelHandle, size_t>> AllocateBuffer(
-      pdx::Message& message, uint32_t width, uint32_t height, uint32_t format,
-      uint64_t usage, size_t slice_count);
+      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
diff --git a/services/vr/performanced/performanced.rc b/services/vr/performanced/performanced.rc
index 6283f37..2605a47 100644
--- a/services/vr/performanced/performanced.rc
+++ b/services/vr/performanced/performanced.rc
@@ -3,4 +3,4 @@
   user root
   group system readproc
   writepid /dev/cpuset/tasks
-  socket pdx/system/performance/client stream 0666 system system
+  socket pdx/system/performance/client stream 0666 system system u:object_r:pdx_performance_client_endpoint_socket:s0
diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk
deleted file mode 100644
index 638c9a8..0000000
--- a/services/vr/sensord/Android.mk
+++ /dev/null
@@ -1,76 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-SENSORD_EXTEND ?= libsensordextensionstub
-
-sourceFiles := \
-	pose_service.cpp \
-	sensord.cpp \
-	sensor_fusion.cpp \
-	sensor_hal_thread.cpp \
-	sensor_ndk_thread.cpp \
-	sensor_service.cpp \
-	sensor_thread.cpp \
-
-includeFiles += \
-	$(LOCAL_PATH)/include
-
-staticLibraries := \
-	libdvrcommon \
-	libvrsensor \
-	libperformance \
-	libbufferhub \
-	libpdx_default_transport \
-	libposepredictor \
-
-sharedLibraries := \
-	libandroid \
-	libbase \
-	libbinder \
-	libcutils \
-	liblog \
-	libhardware \
-	libutils \
-        libui \
-	$(SENSORD_EXTEND) \
-
-cFlags := -DLOG_TAG=\"sensord\" \
-          -DTRACE=0
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_CFLAGS := $(cFlags)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE := sensord
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_C_INCLUDES += \
-    $(call local-generated-sources-dir)/proto/frameworks/native/services/vr/sensord
-LOCAL_INIT_RC := sensord.rc
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_SRC_FILES := test/poselatencytest.cpp
-LOCAL_MODULE := poselatencytest
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libsensordextensionstub
-LOCAL_SRC_FILES := sensord_extension.cpp
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/vr/sensord/pose_service.cpp b/services/vr/sensord/pose_service.cpp
deleted file mode 100644
index 75423bb..0000000
--- a/services/vr/sensord/pose_service.cpp
+++ /dev/null
@@ -1,649 +0,0 @@
-#define ATRACE_TAG ATRACE_TAG_INPUT
-#include "pose_service.h"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <time.h>
-
-#include <array>
-#include <cmath>
-#include <cstdint>
-#include <sstream>
-#include <type_traits>
-
-#include <cutils/properties.h>
-#include <cutils/trace.h>
-#include <dvr/performance_client_api.h>
-#include <dvr/pose_client.h>
-#include <hardware/sensors.h>
-#include <log/log.h>
-#include <pdx/default_transport/service_endpoint.h>
-#include <private/dvr/benchmark.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/platform_defines.h>
-#include <private/dvr/pose-ipc.h>
-#include <private/dvr/sensor_constants.h>
-#include <utils/Trace.h>
-
-using android::pdx::LocalChannelHandle;
-using android::pdx::default_transport::Endpoint;
-using android::pdx::Status;
-
-namespace android {
-namespace dvr {
-
-using Vector3d = vec3d;
-using Rotationd = quatd;
-using AngleAxisd = Eigen::AngleAxis<double>;
-
-namespace {
-// Wait a few seconds before checking if we need to disable sensors.
-static constexpr int64_t kSensorTimeoutNs = 5000000000ll;
-
-static constexpr float kTwoPi = 2.0 * M_PI;
-static constexpr float kDegToRad = M_PI / 180.f;
-
-// Head model code data.
-static constexpr float kDefaultNeckHorizontalOffset = 0.080f;  // meters
-static constexpr float kDefaultNeckVerticalOffset = 0.075f;    // meters
-
-static constexpr char kDisablePosePredictionProp[] =
-    "persist.dvr.disable_predict";
-
-// Device type property for controlling classes of behavior that differ
-// between devices. If unset, defaults to kOrientationTypeSmartphone.
-static constexpr char kOrientationTypeProp[] = "ro.dvr.orientation_type";
-static constexpr char kEnableSensorRecordProp[] = "dvr.enable_6dof_recording";
-static constexpr char kEnableSensorPlayProp[] = "dvr.enable_6dof_playback";
-static constexpr char kEnableSensorPlayIdProp[] = "dvr.6dof_playback_id";
-static constexpr char kEnablePoseRecordProp[] = "dvr.enable_pose_recording";
-static constexpr char kPredictorTypeProp[] = "dvr.predictor_type";
-
-// Persistent buffer names.
-static constexpr char kPoseRingBufferName[] = "PoseService:RingBuffer";
-
-static constexpr int kDatasetIdLength = 36;
-static constexpr char kDatasetIdChars[] = "0123456789abcdef-";
-
-static constexpr int kLatencyWindowSize = 200;
-
-// These are the flags used by BufferProducer::CreatePersistentUncachedBlob,
-// plus PRIVATE_ADSP_HEAP to allow access from the DSP.
-static constexpr int kPoseRingBufferFlags =
-    GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY |
-    GRALLOC_USAGE_PRIVATE_UNCACHED | GRALLOC_USAGE_PRIVATE_ADSP_HEAP;
-
-std::string GetPoseModeString(DvrPoseMode mode) {
-  switch (mode) {
-    case DVR_POSE_MODE_6DOF:
-      return "DVR_POSE_MODE_6DOF";
-    case DVR_POSE_MODE_3DOF:
-      return "DVR_POSE_MODE_3DOF";
-    case DVR_POSE_MODE_MOCK_FROZEN:
-      return "DVR_POSE_MODE_MOCK_FROZEN";
-    case DVR_POSE_MODE_MOCK_HEAD_TURN_SLOW:
-      return "DVR_POSE_MODE_MOCK_HEAD_TURN_SLOW";
-    case DVR_POSE_MODE_MOCK_HEAD_TURN_FAST:
-      return "DVR_POSE_MODE_MOCK_HEAD_TURN_FAST";
-    case DVR_POSE_MODE_MOCK_ROTATE_SLOW:
-      return "DVR_POSE_MODE_MOCK_ROTATE_SLOW";
-    case DVR_POSE_MODE_MOCK_ROTATE_MEDIUM:
-      return "DVR_POSE_MODE_MOCK_ROTATE_MEDIUM";
-    case DVR_POSE_MODE_MOCK_ROTATE_FAST:
-      return "DVR_POSE_MODE_MOCK_ROTATE_FAST";
-    case DVR_POSE_MODE_MOCK_CIRCLE_STRAFE:
-      return "DVR_POSE_MODE_MOCK_CIRCLE_STRAFE";
-    default:
-      return "Unknown pose mode";
-  }
-}
-
-}  // namespace
-
-PoseService::PoseService(SensorThread* sensor_thread)
-    : BASE("PoseService", Endpoint::Create(DVR_POSE_SERVICE_CLIENT)),
-      sensor_thread_(sensor_thread),
-      last_sensor_usage_time_ns_(0),
-      watchdog_shutdown_(false),
-      sensors_on_(false),
-      accelerometer_index_(-1),
-      gyroscope_index_(-1),
-      pose_mode_(DVR_POSE_MODE_6DOF),
-      mapped_pose_buffer_(nullptr),
-      vsync_count_(0),
-      photon_timestamp_(0),
-      // Will be updated by external service, but start with a non-zero value:
-      display_period_ns_(16000000),
-      sensor_latency_(kLatencyWindowSize) {
-  last_known_pose_ = {
-      .orientation = {1.0f, 0.0f, 0.0f, 0.0f},
-      .translation = {0.0f, 0.0f, 0.0f, 0.0f},
-      .angular_velocity = {0.0f, 0.0f, 0.0f, 0.0f},
-      .velocity = {0.0f, 0.0f, 0.0f, 0.0f},
-      .timestamp_ns = 0,
-      .flags = DVR_POSE_FLAG_HEAD,
-      .pad = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
-  };
-
-  switch (property_get_int32(kOrientationTypeProp, kOrientationTypePortrait)) {
-    case kOrientationTypeLandscape:
-      device_orientation_type_ = kOrientationTypeLandscape;
-      break;
-    default:
-      device_orientation_type_ = kOrientationTypePortrait;
-      break;
-  }
-
-  ring_buffer_ =
-      BufferProducer::Create(kPoseRingBufferName, 0, 0, kPoseRingBufferFlags,
-                             sizeof(DvrPoseRingBuffer));
-  if (!ring_buffer_) {
-    ALOGE("PoseService::PoseService: Failed to create/get pose ring buffer!");
-    return;
-  }
-
-  void* addr = nullptr;
-  int ret =
-      ring_buffer_->GetBlobReadWritePointer(sizeof(DvrPoseRingBuffer), &addr);
-  if (ret < 0) {
-    ALOGE("PoseService::PoseService: Failed to map pose ring buffer: %s",
-          strerror(-ret));
-    return;
-  }
-  memset(addr, 0, sizeof(DvrPoseRingBuffer));
-  mapped_pose_buffer_ = static_cast<DvrPoseRingBuffer*>(addr);
-  addr = nullptr;
-
-  for (int i = 0; i < sensor_thread->GetSensorCount(); ++i) {
-    if (sensor_thread->GetSensorType(i) == SENSOR_TYPE_ACCELEROMETER)
-      accelerometer_index_ = i;
-    if (sensor_thread->GetSensorType(i) == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED)
-      gyroscope_index_ = i;
-  }
-  // If we failed to find the uncalibrated gyroscope, use the regular one.
-  if (gyroscope_index_ < 0) {
-    ALOGW("PoseService was unable to find uncalibrated gyroscope");
-    for (int i = 0; i < sensor_thread->GetSensorCount(); ++i) {
-      ALOGI("Type %d", sensor_thread->GetSensorType(i));
-      if (sensor_thread->GetSensorType(i) == SENSOR_TYPE_GYROSCOPE)
-        gyroscope_index_ = i;
-    }
-  }
-
-  if (accelerometer_index_ < 0) {
-    ALOGE("PoseService was unable to find accelerometer");
-  }
-  if (gyroscope_index_ < 0) {
-    ALOGE("PoseService was unable to find gyroscope");
-  }
-
-  {
-    std::lock_guard<std::mutex> lock(mutex_);
-    KickSensorWatchDogThread();
-  }
-
-  // Read the persistent dvr flags before using them in SetPoseMode.
-  enable_pose_prediction_ =
-      property_get_bool(kDisablePosePredictionProp, 0) == 0;
-
-  enable_sensor_recording_ = property_get_bool(kEnableSensorRecordProp, 0) == 1;
-
-  enable_sensor_playback_ = property_get_bool(kEnableSensorPlayProp, 0) == 1;
-
-  if (enable_sensor_playback_) {
-    char dataset_id[PROPERTY_VALUE_MAX];
-    property_get(kEnableSensorPlayIdProp, dataset_id, "");
-    sensor_playback_id_ = std::string(dataset_id);
-
-    if (sensor_playback_id_.length() != kDatasetIdLength ||
-        sensor_playback_id_.find_first_not_of(kDatasetIdChars) !=
-            std::string::npos) {
-      ALOGE("Error: invalid playback id %s", sensor_playback_id_.c_str());
-      sensor_playback_id_ = "";
-      enable_sensor_playback_ = false;
-    } else {
-      ALOGI("Playback id %s", sensor_playback_id_.c_str());
-    }
-  }
-
-  switch (property_get_int32(kPredictorTypeProp, 0)) {
-    case 1:
-      pose_predictor_ = posepredictor::Predictor::Create(
-          posepredictor::PredictorType::Quadric);
-    default:
-      pose_predictor_ = posepredictor::Predictor::Create(
-          posepredictor::PredictorType::Linear);
-  }
-
-  enable_pose_recording_ = property_get_bool(kEnablePoseRecordProp, 0) == 1;
-
-  SetPoseMode(DVR_POSE_MODE_6DOF);
-}
-
-PoseService::~PoseService() {
-  if (watchdog_thread_.get_id() != std::thread::id()) {
-    {
-      std::lock_guard<std::mutex> guard(mutex_);
-      watchdog_shutdown_ = true;
-      watchdog_condition_.notify_one();
-    }
-    watchdog_thread_.join();
-  }
-}
-
-void PoseService::KickSensorWatchDogThread() {
-  // This method is called every frame while rendering so we want to make sure
-  // it is very light weight with synchronization.
-  // TODO(jbates) For better performance, we can consider a lock-free atomic
-  // solution instead of locking this mutex.
-
-  // Update the usage time. The watchdog thread will poll this value to know
-  // when to disable sensors.
-  last_sensor_usage_time_ns_ = GetSystemClockNs();
-
-  // If sensors are still on, there's nothing else to do.
-  if (sensors_on_)
-    return;
-
-  // Enable sensors.
-  ALOGI("Start using sensors.");
-  sensors_on_ = true;
-  if (accelerometer_index_ >= 0) {
-    sensor_thread_->StartUsingSensor(accelerometer_index_);
-  }
-  if (gyroscope_index_ >= 0) {
-    sensor_thread_->StartUsingSensor(gyroscope_index_);
-  }
-
-  // Tell the thread to wake up to disable the sensors when no longer needed.
-  watchdog_condition_.notify_one();
-
-  if (watchdog_thread_.get_id() == std::thread::id()) {
-    // The sensor watchdog thread runs while sensors are in use. When no APIs
-    // have requested sensors beyond a threshold (5 seconds), sensors are
-    // disabled.
-    watchdog_thread_ = std::thread([this] {
-      std::unique_lock<std::mutex> lock(mutex_);
-      while (!watchdog_shutdown_) {
-        int64_t remaining_sensor_time_ns =
-            last_sensor_usage_time_ns_ + kSensorTimeoutNs - GetSystemClockNs();
-
-        if (remaining_sensor_time_ns > 0) {
-          // Wait for the remaining usage time before checking again.
-          watchdog_condition_.wait_for(
-              lock, std::chrono::nanoseconds(remaining_sensor_time_ns));
-          continue;
-        }
-
-        if (sensors_on_) {
-          // Disable sensors.
-          ALOGI("Stop using sensors.");
-          sensors_on_ = false;
-          if (accelerometer_index_ >= 0) {
-            sensor_thread_->StopUsingSensor(accelerometer_index_);
-          }
-          if (gyroscope_index_ >= 0) {
-            sensor_thread_->StopUsingSensor(gyroscope_index_);
-          }
-        }
-
-        // Wait for sensors to be enabled again.
-        watchdog_condition_.wait(lock);
-      }
-    });
-  }
-}
-
-bool PoseService::IsInitialized() const {
-  return BASE::IsInitialized() && ring_buffer_ && mapped_pose_buffer_;
-}
-
-void PoseService::WriteAsyncPoses(const Vector3d& start_t_head,
-                                  const Rotationd& start_q_head,
-                                  int64_t pose_timestamp) {
-  if (enable_external_pose_) {
-    return;
-  }
-
-  // If playing back data, the timestamps are different enough from the
-  // current time that prediction doesn't work. This hack pretends that
-  // there was one nanosecond of latency between the sensors and here.
-  if (enable_sensor_playback_)
-    pose_timestamp = GetSystemClockNs() - 1;
-
-  // Feed the sample to the predictor
-  AddPredictorPose(pose_predictor_.get(), start_t_head, start_q_head,
-                   pose_timestamp, &last_known_pose_);
-
-  // Store one extra value, because the application is working on the next
-  // frame and expects the minimum count from that frame on.
-  for (uint32_t i = 0; i < kPoseAsyncBufferMinFutureCount + 1; ++i) {
-    int64_t target_time = photon_timestamp_ + i * display_period_ns_;
-
-    // TODO(jbates, cwolfe) For the DSP code, we may still want poses even when
-    // the vsyncs are not ticking up. But it's important not to update the pose
-    // data that's in the past so that applications have the most accurate
-    // estimate of the last frame's *actual* pose, so that they can update
-    // simulations and calculate collisions, etc.
-    if (target_time < pose_timestamp) {
-      // Already in the past, do not update this head pose slot.
-      continue;
-    }
-
-    // Write to the actual shared memory ring buffer.
-    uint32_t index = ((vsync_count_ + i) & kPoseAsyncBufferIndexMask);
-
-    // Make a pose prediction
-    if (enable_pose_prediction_) {
-      PredictPose(pose_predictor_.get(), target_time,
-                  target_time + right_eye_photon_offset_ns_,
-                  mapped_pose_buffer_->ring + index);
-    } else {
-      mapped_pose_buffer_->ring[index] = last_known_pose_;
-    }
-  }
-}
-
-void PoseService::UpdatePoseMode() {
-  ALOGI_IF(TRACE, "UpdatePoseMode: %f %f %f", last_known_pose_.translation[0],
-           last_known_pose_.translation[1], last_known_pose_.translation[2]);
-
-  const int64_t current_time_ns = GetSystemClockNs();
-
-  const PoseState pose_state = sensor_fusion_.GetLatestPoseState();
-
-  switch (pose_mode_) {
-    case DVR_POSE_MODE_MOCK_HEAD_TURN_SLOW:
-    case DVR_POSE_MODE_MOCK_HEAD_TURN_FAST:
-    case DVR_POSE_MODE_MOCK_ROTATE_SLOW:
-    case DVR_POSE_MODE_MOCK_ROTATE_MEDIUM:
-    case DVR_POSE_MODE_MOCK_ROTATE_FAST:
-    case DVR_POSE_MODE_MOCK_CIRCLE_STRAFE: {
-      // Calculate a pose based on monotic system time.
-      const Vector3d y_axis(0., 1., 0.);
-      double time_s = current_time_ns / 1e9;
-
-      // Generate fake yaw data.
-      float yaw = 0.0f;
-      Vector3d head_trans(0.0, 0.0, 0.0);
-      switch (pose_mode_) {
-        default:
-        case DVR_POSE_MODE_MOCK_HEAD_TURN_SLOW:
-          // Pan across 120 degrees in 15 seconds.
-          yaw = std::cos(kTwoPi * time_s / 15.0) * 60.0 * kDegToRad;
-          break;
-        case DVR_POSE_MODE_MOCK_HEAD_TURN_FAST:
-          // Pan across 120 degrees in 4 seconds.
-          yaw = std::cos(kTwoPi * time_s / 4.0) * 60.0 * kDegToRad;
-          break;
-        case DVR_POSE_MODE_MOCK_ROTATE_SLOW:
-          // Rotate 5 degrees per second.
-          yaw = std::fmod(time_s * 5.0 * kDegToRad, kTwoPi);
-          break;
-        case DVR_POSE_MODE_MOCK_ROTATE_MEDIUM:
-          // Rotate 30 degrees per second.
-          yaw = std::fmod(time_s * 30.0 * kDegToRad, kTwoPi);
-          break;
-        case DVR_POSE_MODE_MOCK_ROTATE_FAST:
-          // Rotate 90 degrees per second.
-          yaw = std::fmod(time_s * 90.0 * kDegToRad, kTwoPi);
-          break;
-        case DVR_POSE_MODE_MOCK_CIRCLE_STRAFE:
-          // Circle strafe around origin at distance of 3 meters.
-          yaw = std::fmod(time_s * 30.0 * kDegToRad, kTwoPi);
-          head_trans += 3.0 * Vector3d(sin(yaw), 0.0, cos(yaw));
-          break;
-      }
-
-      // Calculate the simulated head rotation in an absolute "head" space.
-      // This space is not related to start space and doesn't need a
-      // reference.
-      Rotationd head_rotation_in_head_space(AngleAxisd(yaw, y_axis));
-
-      WriteAsyncPoses(head_trans, head_rotation_in_head_space, current_time_ns);
-      break;
-    }
-    case DVR_POSE_MODE_MOCK_FROZEN: {
-      // Even when frozen, we still provide a current timestamp, because
-      // consumers may rely on it being monotonic.
-
-      Rotationd start_from_head_rotation(
-          frozen_state_.head_from_start_rotation.w,
-          frozen_state_.head_from_start_rotation.x,
-          frozen_state_.head_from_start_rotation.y,
-          frozen_state_.head_from_start_rotation.z);
-      Vector3d head_from_start_translation(
-          frozen_state_.head_from_start_translation.x,
-          frozen_state_.head_from_start_translation.y,
-          frozen_state_.head_from_start_translation.z);
-
-      WriteAsyncPoses(head_from_start_translation, start_from_head_rotation,
-                      current_time_ns);
-      break;
-    }
-    case DVR_POSE_MODE_3DOF: {
-      // Sensor fusion provides IMU-space data, transform to world space.
-
-      // Constants to perform IMU orientation adjustments. Note that these
-      // calculations will be optimized out in a release build.
-      constexpr double k90DegInRad = 90.0 * M_PI / 180.0;
-      const Vector3d kVecAxisX(1.0, 0.0, 0.0);
-      const Vector3d kVecAxisY(0.0, 1.0, 0.0);
-      const Vector3d kVecAxisZ(0.0, 0.0, 1.0);
-      const Rotationd kRotX90(AngleAxisd(k90DegInRad, kVecAxisX));
-
-      Rotationd start_from_head_rotation;
-      if (device_orientation_type_ == kOrientationTypeLandscape) {
-        const Rotationd kPostRotation =
-            kRotX90 * Rotationd(AngleAxisd(-k90DegInRad, kVecAxisY));
-        start_from_head_rotation =
-            (pose_state.sensor_from_start_rotation * kPostRotation).inverse();
-      } else if (device_orientation_type_ == kOrientationTypeLandscape180) {
-        const Rotationd kPreRotation =
-            Rotationd(AngleAxisd(k90DegInRad * 2.0, kVecAxisY)) *
-            Rotationd(AngleAxisd(k90DegInRad * 2.0, kVecAxisZ));
-        const Rotationd kPostRotation = kRotX90;
-        start_from_head_rotation =
-            (kPreRotation *
-             pose_state.sensor_from_start_rotation * kPostRotation)
-                .inverse();
-      } else {
-        const Rotationd kPreRotation =
-            Rotationd(AngleAxisd(k90DegInRad, kVecAxisZ));
-        const Rotationd kPostRotation = kRotX90;
-        start_from_head_rotation =
-            (kPreRotation * pose_state.sensor_from_start_rotation *
-             kPostRotation)
-                .inverse();
-      }
-      start_from_head_rotation.normalize();
-
-      // Neck / head model code procedure for when no 6dof is available.
-      // To apply the neck model, first translate the head pose to the new
-      // center of eyes, then rotate around the origin (the original head
-      // pos).
-      Vector3d position =
-          start_from_head_rotation * Vector3d(0.0, kDefaultNeckVerticalOffset,
-                                              -kDefaultNeckHorizontalOffset);
-
-      // Update the current latency model.
-      if (pose_state.timestamp_ns != 0) {
-        sensor_latency_.AddLatency(GetSystemClockNs() -
-                                   pose_state.timestamp_ns);
-      }
-
-      // Update the timestamp with the expected latency.
-      WriteAsyncPoses(
-          position, start_from_head_rotation,
-          pose_state.timestamp_ns + sensor_latency_.CurrentLatencyEstimate());
-      break;
-    }
-    default:
-    case DVR_POSE_MODE_6DOF:
-      ALOGE("ERROR: invalid pose mode");
-      break;
-  }
-}
-
-pdx::Status<void> PoseService::HandleMessage(pdx::Message& msg) {
-  pdx::Status<void> ret;
-  const pdx::MessageInfo& info = msg.GetInfo();
-  switch (info.op) {
-    case DVR_POSE_NOTIFY_VSYNC: {
-      std::lock_guard<std::mutex> guard(mutex_);
-
-      // Kick the sensor thread, because we are still rendering.
-      KickSensorWatchDogThread();
-
-      const struct iovec data[] = {
-          {.iov_base = &vsync_count_, .iov_len = sizeof(vsync_count_)},
-          {.iov_base = &photon_timestamp_,
-           .iov_len = sizeof(photon_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_)},
-      };
-      ret = msg.ReadVectorAll(data);
-      if (ret && !enable_external_pose_) {
-        mapped_pose_buffer_->vsync_count = vsync_count_;
-      }
-
-      // TODO(jbates, eieio): make this async, no need to reply.
-      REPLY_MESSAGE(msg, ret, error);
-    }
-    case DVR_POSE_POLL: {
-      ATRACE_NAME("pose_poll");
-      std::lock_guard<std::mutex> guard(mutex_);
-
-      DvrPoseState client_state;
-      client_state = {
-          .head_from_start_rotation = {last_known_pose_.orientation[0],
-                                       last_known_pose_.orientation[1],
-                                       last_known_pose_.orientation[2],
-                                       last_known_pose_.orientation[3]},
-          .head_from_start_translation = {last_known_pose_.translation[0],
-                                          last_known_pose_.translation[1],
-                                          last_known_pose_.translation[2]},
-          .timestamp_ns = static_cast<uint64_t>(last_known_pose_.timestamp_ns),
-          .sensor_from_start_rotation_velocity = {
-              last_known_pose_.angular_velocity[0],
-              last_known_pose_.angular_velocity[1],
-              last_known_pose_.angular_velocity[2]}};
-
-      Btrace("Sensor data received",
-             static_cast<int64_t>(client_state.timestamp_ns));
-
-      Btrace("Pose polled");
-
-      ret = msg.WriteAll(&client_state, sizeof(client_state));
-      REPLY_MESSAGE(msg, ret, error);
-    }
-    case DVR_POSE_FREEZE: {
-      {
-        std::lock_guard<std::mutex> guard(mutex_);
-
-        DvrPoseState frozen_state;
-        ret = msg.ReadAll(&frozen_state, sizeof(frozen_state));
-        if (!ret) {
-          REPLY_ERROR(msg, ret.error(), error);
-        }
-        frozen_state_ = frozen_state;
-      }
-      SetPoseMode(DVR_POSE_MODE_MOCK_FROZEN);
-      REPLY_MESSAGE(msg, ret, error);
-    }
-    case DVR_POSE_SET_MODE: {
-      int mode;
-      {
-        std::lock_guard<std::mutex> guard(mutex_);
-        ret = msg.ReadAll(&mode, sizeof(mode));
-        if (!ret) {
-          REPLY_ERROR(msg, ret.error(), error);
-        }
-        if (mode < 0 || mode >= DVR_POSE_MODE_COUNT) {
-          REPLY_ERROR(msg, EINVAL, error);
-        }
-      }
-      SetPoseMode(DvrPoseMode(mode));
-      REPLY_MESSAGE(msg, ret, error);
-    }
-    case DVR_POSE_GET_MODE: {
-      std::lock_guard<std::mutex> guard(mutex_);
-      int mode = pose_mode_;
-      ret = msg.WriteAll(&mode, sizeof(mode));
-      REPLY_MESSAGE(msg, ret, error);
-    }
-    case DVR_POSE_GET_RING_BUFFER: {
-      std::lock_guard<std::mutex> guard(mutex_);
-
-      // Kick the sensor thread, because we have a new consumer.
-      KickSensorWatchDogThread();
-
-      Status<LocalChannelHandle> consumer_channel =
-          ring_buffer_->CreateConsumer();
-      REPLY_MESSAGE(msg, consumer_channel, error);
-    }
-    case DVR_POSE_GET_CONTROLLER_RING_BUFFER: {
-      std::lock_guard<std::mutex> guard(mutex_);
-      REPLY_ERROR(msg, EINVAL, error);
-    }
-    case DVR_POSE_LOG_CONTROLLER: {
-      std::lock_guard<std::mutex> guard(mutex_);
-      REPLY_ERROR(msg, EINVAL, error);
-    }
-    default:
-      // Do not lock mutex_ here, because this may call the on*() handlers,
-      // which will lock the mutex themselves.
-      ret = Service::HandleMessage(msg);
-      break;
-  }
-error:
-  return ret;
-}
-
-std::string PoseService::DumpState(size_t /*max_length*/) {
-  DvrPoseMode pose_mode;
-  {
-    std::lock_guard<std::mutex> guard(mutex_);
-    pose_mode = pose_mode_;
-  }
-
-  std::ostringstream stream;
-  stream << "Pose mode: " << GetPoseModeString(pose_mode);
-  return stream.str();
-}
-
-void PoseService::HandleEvents(const sensors_event_t* begin_events,
-                               const sensors_event_t* end_events) {
-  ATRACE_NAME("PoseService::HandleEvents");
-  std::lock_guard<std::mutex> guard(mutex_);
-
-  for (const sensors_event_t* event = begin_events; event != end_events;
-       ++event) {
-    if (event->type == SENSOR_TYPE_ACCELEROMETER) {
-      sensor_fusion_.ProcessAccelerometerSample(
-          event->acceleration.x, event->acceleration.y, event->acceleration.z,
-          event->timestamp);
-    } else if (event->type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
-      sensor_fusion_.ProcessGyroscopeSample(event->gyro.x, event->gyro.y,
-                                            event->gyro.z, event->timestamp);
-    }
-  }
-
-  UpdatePoseMode();
-}
-
-void PoseService::SetPoseMode(DvrPoseMode mode) {
-  if (mode == DVR_POSE_MODE_6DOF) {
-    // Only 3DoF is currently supported.
-    mode = DVR_POSE_MODE_3DOF;
-  }
-
-  pose_mode_ = mode;
-
-  sensor_thread_->SetPaused(false);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/sensord/pose_service.h b/services/vr/sensord/pose_service.h
deleted file mode 100644
index 7b7adec..0000000
--- a/services/vr/sensord/pose_service.h
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef ANDROID_DVR_SENSORD_POSE_SERVICE_H_
-#define ANDROID_DVR_SENSORD_POSE_SERVICE_H_
-
-#include <condition_variable>
-#include <forward_list>
-#include <mutex>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-#include <dvr/pose_client.h>
-#include <pdx/service.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/dvr_pose_predictor.h>
-#include <private/dvr/latency_model.h>
-#include <private/dvr/pose_client_internal.h>
-#include <private/dvr/ring_buffer.h>
-
-#include "sensor_fusion.h"
-#include "sensor_thread.h"
-
-namespace android {
-namespace dvr {
-
-// PoseService implements the HMD pose service over ServiceFS.
-class PoseService : public pdx::ServiceBase<PoseService> {
- public:
-  ~PoseService() override;
-
-  bool IsInitialized() const override;
-  pdx::Status<void> HandleMessage(pdx::Message& msg) override;
-  std::string DumpState(size_t max_length) override;
-
-  // Handle events from the sensor HAL.
-  // Safe to call concurrently with any other public member functions.
-  void HandleEvents(const sensors_event_t* begin_events,
-                    const sensors_event_t* end_events);
-
- private:
-  friend BASE;
-
-  enum OrientationType {
-    // Typical smartphone device (default).
-    kOrientationTypePortrait = 1,
-    // Landscape device.
-    kOrientationTypeLandscape = 2,
-    // 180 Landscape device.
-    kOrientationTypeLandscape180 = 3,
-  };
-
-  // Initializes the service. Keeps a reference to sensor_thread, which must be
-  // non-null.
-  explicit PoseService(SensorThread* sensor_thread);
-
-  // Kick the sensor watch dog thread which will robustly disable IMU usage
-  // when there are no sensor data consumers.
-  // The class mutex (mutex_) must be locked while calling this method.
-  void KickSensorWatchDogThread();
-
-  void UpdatePoseMode();
-
-  // Update the async pose ring buffer with new pose data.
-  // |start_t_head| Head position in start space.
-  // |start_q_head| Head orientation quaternion in start space.
-  // |pose_timestamp| System timestamp of pose data in seconds.
-  // |pose_delta_time| Elapsed time in seconds between this pose and the last.
-  void WriteAsyncPoses(const Eigen::Vector3<double>& start_t_head,
-                       const Eigen::Quaternion<double>& start_q_head,
-                       int64_t pose_timestamp);
-
-  // Set the pose mode.
-  void SetPoseMode(DvrPoseMode mode);
-
-  // The abstraction around the sensor data.
-  SensorThread* sensor_thread_;
-
-  // Protects access to all member variables.
-  std::mutex mutex_;
-
-  // Watchdog thread data. The watchdog thread will ensure that sensor access
-  // is disabled when nothing has been consuming it for a while.
-  int64_t last_sensor_usage_time_ns_;
-  std::thread watchdog_thread_;
-  std::condition_variable watchdog_condition_;
-  bool watchdog_shutdown_;
-  bool sensors_on_;
-
-  // Indices for the accelerometer and gyroscope sensors, or -1 if the sensor
-  // wasn't present on construction.
-  int accelerometer_index_;
-  int gyroscope_index_;
-
-  // The sensor fusion algorithm and its state.
-  SensorFusion sensor_fusion_;
-
-  // Current pose mode.
-  DvrPoseMode pose_mode_;
-
-  // State which is sent if pose_mode_ is DVR_POSE_MODE_MOCK_FROZEN.
-  DvrPoseState frozen_state_;
-
-  // Last known pose.
-  DvrPoseAsync last_known_pose_;
-
-  // If this flag is true, the pose published includes a small prediction of
-  // where it'll be when it's consumed.
-  bool enable_pose_prediction_;
-
-  // Flag to turn on recording of raw sensor data
-  bool enable_sensor_recording_;
-
-  // Flag to log pose to a file
-  bool enable_pose_recording_;
-
-  // Flag to turn on playback from a saved dataset instead of using live data.
-  bool enable_sensor_playback_;
-
-  std::string sensor_playback_id_;
-
-  // External pose generation.
-  bool enable_external_pose_ = false;
-
-  // The predictor to extrapolate pose samples.
-  std::unique_ptr<posepredictor::Predictor> pose_predictor_;
-
-  // Pose ring buffer.
-  std::shared_ptr<BufferProducer> ring_buffer_;
-  // Temporary mapped ring buffer.
-  DvrPoseRingBuffer* mapped_pose_buffer_;
-  // Current vsync info, updated by displayd.
-  uint32_t vsync_count_;
-  int64_t photon_timestamp_;
-  int64_t display_period_ns_;
-  int64_t right_eye_photon_offset_ns_ = 0;
-
-  // To model the measurement - arrival latency.
-  LatencyModel sensor_latency_;
-
-  // Type for controlling pose orientation calculation.
-  OrientationType device_orientation_type_;
-
-  PoseService(const PoseService&) = delete;
-  void operator=(const PoseService&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSORD_POSE_SERVICE_H_
diff --git a/services/vr/sensord/sensor_fusion.cpp b/services/vr/sensord/sensor_fusion.cpp
deleted file mode 100644
index 5663ae4..0000000
--- a/services/vr/sensord/sensor_fusion.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-#include "sensor_fusion.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include <private/dvr/eigen.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-// --- start of added bits for porting to eigen
-
-// In general, we prefer to add wrappers for things like Inverse() to minimize
-// the changes to the imported code, so that merging in upstream changes becomes
-// simpler.
-
-inline Matrix3d Inverse(const Matrix3d& matrix) { return matrix.inverse(); }
-inline Matrix3d Transpose(const Matrix3d& matrix) { return matrix.transpose(); }
-inline Matrix3d RotationMatrixNH(const Rotationd& rotation) {
-  return rotation.toRotationMatrix();
-}
-inline double Length(const Vector3d& vector) { return vector.norm(); }
-
-using uint64 = uint64_t;
-
-// --- end of added bits for porting to eigen
-
-static const double kFiniteDifferencingEpsilon = 1e-7;
-static const double kEpsilon = 1e-15;
-// Default gyroscope frequency. This corresponds to 200 Hz.
-static const double kDefaultGyroscopeTimestep_s = 0.005f;
-// Maximum time between gyroscope before we start limiting the integration.
-static const double kMaximumGyroscopeSampleDelay_s = 0.04f;
-// Compute a first-order exponential moving average of changes in accel norm per
-// frame.
-static const double kSmoothingFactor = 0.5;
-// Minimum and maximum values used for accelerometer noise covariance matrix.
-// The smaller the sigma value, the more weight is given to the accelerometer
-// signal.
-static const double kMinAccelNoiseSigma = 0.75;
-static const double kMaxAccelNoiseSigma = 7.0;
-// Initial value for the diagonal elements of the different covariance matrices.
-static const double kInitialStateCovarianceValue = 25.0;
-static const double kInitialProcessCovarianceValue = 1.0;
-// Maximum accelerometer norm change allowed before capping it covariance to a
-// large value.
-static const double kMaxAccelNormChange = 0.15;
-// Timestep IIR filtering coefficient.
-static const double kTimestepFilterCoeff = 0.95;
-// Minimum number of sample for timestep filtering.
-static const uint32_t kTimestepFilterMinSamples = 10;
-
-// Z direction in start space.
-static const Vector3d kCanonicalZDirection(0.0, 0.0, 1.0);
-
-// Computes a axis angle rotation from the input vector.
-// angle = norm(a)
-// axis = a.normalized()
-// If norm(a) == 0, it returns an identity rotation.
-static Rotationd RotationFromVector(const Vector3d& a) {
-  const double norm_a = Length(a);
-  if (norm_a < kEpsilon) {
-    return Rotationd::Identity();
-  }
-  return Rotationd(AngleAxisd(norm_a, a / norm_a));
-}
-
-// --- start of functions ported from pose_prediction.cc
-
-namespace pose_prediction {
-
-// Returns a rotation matrix based on the integration of the gyroscope_value
-// over the timestep_s in seconds.
-// TODO(pfg): Document the space better here.
-//
-// @param gyroscope_value gyroscope sensor values.
-// @param timestep_s integration period in seconds.
-// @return Integration of the gyroscope value the rotation is from Start to
-//         Sensor Space.
-Rotationd GetRotationFromGyroscope(const Vector3d& gyroscope_value,
-                                   double timestep_s) {
-  const double velocity = Length(gyroscope_value);
-
-  // When there is no rotation data return an identity rotation.
-  if (velocity < kEpsilon) {
-    return Rotationd::Identity();
-  }
-  // Since the gyroscope_value is a start from sensor transformation we need to
-  // invert it to have a sensor from start transformation, hence the minus sign.
-  // For more info:
-  // http://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-gyro
-  return Rotationd(AngleAxisd(-timestep_s * velocity,
-                              gyroscope_value / velocity));
-}
-
-}  // namespace pose_prediction
-
-// --- end of functions ported from pose_prediction.cc
-
-}  // namespace
-
-SensorFusion::SensorFusion()
-    : execute_reset_with_next_accelerometer_sample_(false) {
-  ResetState();
-}
-
-void SensorFusion::Reset() {
-  execute_reset_with_next_accelerometer_sample_ = true;
-}
-
-void SensorFusion::ResetState() {
-  current_state_.timestamp_ns = 0;
-  current_state_.sensor_from_start_rotation = Rotationd::Identity();
-  current_state_.sensor_from_start_rotation_velocity = Vector3d::Zero();
-
-  current_accelerometer_timestamp_ns_ = 0;
-
-  state_covariance_ = Matrix3d::Identity() * kInitialStateCovarianceValue;
-  process_covariance_ = Matrix3d::Identity() * kInitialProcessCovarianceValue;
-  accelerometer_measurement_covariance_ =
-      Matrix3d::Identity() * kMinAccelNoiseSigma * kMinAccelNoiseSigma;
-  innovation_covariance_.setIdentity();
-
-  accelerometer_measurement_jacobian_ = Matrix3d::Zero();
-  kalman_gain_ = Matrix3d::Zero();
-  innovation_ = Vector3d::Zero();
-  accelerometer_measurement_ = Vector3d::Zero();
-  prediction_ = Vector3d::Zero();
-  control_input_ = Vector3d::Zero();
-  state_update_ = Vector3d::Zero();
-
-  moving_average_accelerometer_norm_change_ = 0.0;
-
-  is_timestep_filter_initialized_ = false;
-  is_gyroscope_filter_valid_ = false;
-  is_aligned_with_gravity_ = false;
-}
-
-// Here I am doing something wrong relative to time stamps. The state timestamps
-// always correspond to the gyrostamps because it would require additional
-// extrapolation if I wanted to do otherwise.
-// TODO(pfg): investigate about published an updated pose after accelerometer
-// data was used for filtering.
-PoseState SensorFusion::GetLatestPoseState() const {
-  std::unique_lock<std::mutex> lock(mutex_);
-  return current_state_;
-}
-
-void SensorFusion::ProcessGyroscopeSample(float v_x, float v_y, float v_z,
-                                          uint64 timestamp_ns) {
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  // Don't accept gyroscope sample when waiting for a reset.
-  if (execute_reset_with_next_accelerometer_sample_) {
-    return;
-  }
-
-  // Discard outdated samples.
-  if (current_state_.timestamp_ns >= timestamp_ns) {
-    // TODO(pfg): Investigate why this happens.
-    return;
-  }
-
-  // Checks that we received at least one gyroscope sample in the past.
-  if (current_state_.timestamp_ns != 0) {
-    // TODO(pfg): roll this in filter gyroscope timestep function.
-    double current_timestep_s =
-        static_cast<double>(timestamp_ns - current_state_.timestamp_ns) * 1e-9;
-    if (current_timestep_s > kMaximumGyroscopeSampleDelay_s) {
-      if (is_gyroscope_filter_valid_) {
-        // Replaces the delta timestamp by the filtered estimates of the delta
-        // time.
-        current_timestep_s = filtered_gyroscope_timestep_s_;
-      } else {
-        current_timestep_s = kDefaultGyroscopeTimestep_s;
-      }
-    } else {
-      FilterGyroscopeTimestep(current_timestep_s);
-    }
-
-    // Only integrate after receiving a accelerometer sample.
-    if (is_aligned_with_gravity_) {
-      const Rotationd rotation_from_gyroscope =
-          pose_prediction::GetRotationFromGyroscope(Vector3d(v_x, v_y, v_z),
-                                                    current_timestep_s);
-      current_state_.sensor_from_start_rotation =
-          rotation_from_gyroscope * current_state_.sensor_from_start_rotation;
-      current_state_.sensor_from_start_rotation.normalize();
-      UpdateStateCovariance(RotationMatrixNH(rotation_from_gyroscope));
-      state_covariance_ =
-          state_covariance_ +
-          (process_covariance_ * (current_timestep_s * current_timestep_s));
-    }
-  }
-
-  // Saves gyroscope event for future prediction.
-  current_state_.timestamp_ns = timestamp_ns;
-  current_state_.sensor_from_start_rotation_velocity = Vector3d(v_x, v_y, v_z);
-}
-
-// TODO(pfg): move to rotation object for the input.
-Vector3d SensorFusion::ComputeInnovation(const Rotationd& pose) {
-  const Vector3d predicted_down_direction =
-      RotationMatrixNH(pose) * kCanonicalZDirection;
-
-  const Rotationd rotation = Rotationd::FromTwoVectors(
-      predicted_down_direction, accelerometer_measurement_);
-  AngleAxisd angle_axis(rotation);
-  return angle_axis.axis() * angle_axis.angle();
-}
-
-void SensorFusion::ComputeMeasurementJacobian() {
-  for (int dof = 0; dof < 3; dof++) {
-    // TODO(pfg): Create this delta rotation in the constructor and used unitX..
-    Vector3d delta = Vector3d::Zero();
-    delta[dof] = kFiniteDifferencingEpsilon;
-
-    const Rotationd epsilon_rotation = RotationFromVector(delta);
-    const Vector3d delta_rotation = ComputeInnovation(
-        epsilon_rotation * current_state_.sensor_from_start_rotation);
-
-    const Vector3d col =
-        (innovation_ - delta_rotation) / kFiniteDifferencingEpsilon;
-    accelerometer_measurement_jacobian_(0, dof) = col[0];
-    accelerometer_measurement_jacobian_(1, dof) = col[1];
-    accelerometer_measurement_jacobian_(2, dof) = col[2];
-  }
-}
-
-void SensorFusion::ProcessAccelerometerSample(float acc_x, float acc_y,
-                                              float acc_z,
-                                              uint64 timestamp_ns) {
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  // Discard outdated samples.
-  if (current_accelerometer_timestamp_ns_ >= timestamp_ns) {
-    // TODO(pfg): Investigate why this happens.
-    return;
-  }
-
-  // Call reset state if required.
-  if (execute_reset_with_next_accelerometer_sample_.exchange(false)) {
-    ResetState();
-  }
-
-  accelerometer_measurement_ = Vector3d(acc_x, acc_y, acc_z);
-  current_accelerometer_timestamp_ns_ = timestamp_ns;
-
-  if (!is_aligned_with_gravity_) {
-    // This is the first accelerometer measurement so it initializes the
-    // orientation estimate.
-    current_state_.sensor_from_start_rotation = Rotationd::FromTwoVectors(
-        kCanonicalZDirection, accelerometer_measurement_);
-    is_aligned_with_gravity_ = true;
-
-    previous_accelerometer_norm_ = Length(accelerometer_measurement_);
-    return;
-  }
-
-  UpdateMeasurementCovariance();
-
-  innovation_ = ComputeInnovation(current_state_.sensor_from_start_rotation);
-  ComputeMeasurementJacobian();
-
-  // S = H * P * H' + R
-  innovation_covariance_ = accelerometer_measurement_jacobian_ *
-                               state_covariance_ *
-                               Transpose(accelerometer_measurement_jacobian_) +
-                           accelerometer_measurement_covariance_;
-
-  // K = P * H' * S^-1
-  kalman_gain_ = state_covariance_ *
-                 Transpose(accelerometer_measurement_jacobian_) *
-                 Inverse(innovation_covariance_);
-
-  // x_update = K*nu
-  state_update_ = kalman_gain_ * innovation_;
-
-  // P = (I - K * H) * P;
-  state_covariance_ = (Matrix3d::Identity() -
-                       kalman_gain_ * accelerometer_measurement_jacobian_) *
-                      state_covariance_;
-
-  // Updates pose and associate covariance matrix.
-  const Rotationd rotation_from_state_update =
-      RotationFromVector(state_update_);
-
-  current_state_.sensor_from_start_rotation =
-      rotation_from_state_update * current_state_.sensor_from_start_rotation;
-  UpdateStateCovariance(RotationMatrixNH(rotation_from_state_update));
-}
-
-void SensorFusion::UpdateStateCovariance(const Matrix3d& motion_update) {
-  state_covariance_ =
-      motion_update * state_covariance_ * Transpose(motion_update);
-}
-
-void SensorFusion::FilterGyroscopeTimestep(double gyroscope_timestep_s) {
-  if (!is_timestep_filter_initialized_) {
-    // Initializes the filter.
-    filtered_gyroscope_timestep_s_ = gyroscope_timestep_s;
-    num_gyroscope_timestep_samples_ = 1;
-    is_timestep_filter_initialized_ = true;
-    return;
-  }
-
-  // Computes the IIR filter response.
-  filtered_gyroscope_timestep_s_ =
-      kTimestepFilterCoeff * filtered_gyroscope_timestep_s_ +
-      (1 - kTimestepFilterCoeff) * gyroscope_timestep_s;
-  ++num_gyroscope_timestep_samples_;
-
-  if (num_gyroscope_timestep_samples_ > kTimestepFilterMinSamples) {
-    is_gyroscope_filter_valid_ = true;
-  }
-}
-
-void SensorFusion::UpdateMeasurementCovariance() {
-  const double current_accelerometer_norm = Length(accelerometer_measurement_);
-  // Norm change between current and previous accel readings.
-  const double current_accelerometer_norm_change =
-      std::abs(current_accelerometer_norm - previous_accelerometer_norm_);
-  previous_accelerometer_norm_ = current_accelerometer_norm;
-
-  moving_average_accelerometer_norm_change_ =
-      kSmoothingFactor * current_accelerometer_norm_change +
-      (1. - kSmoothingFactor) * moving_average_accelerometer_norm_change_;
-
-  // If we hit the accel norm change threshold, we use the maximum noise sigma
-  // for the accel covariance. For anything below that, we use a linear
-  // combination between min and max sigma values.
-  const double norm_change_ratio =
-      moving_average_accelerometer_norm_change_ / kMaxAccelNormChange;
-  const double accelerometer_noise_sigma = std::min(
-      kMaxAccelNoiseSigma,
-      kMinAccelNoiseSigma +
-          norm_change_ratio * (kMaxAccelNoiseSigma - kMinAccelNoiseSigma));
-
-  // Updates the accel covariance matrix with the new sigma value.
-  accelerometer_measurement_covariance_ = Matrix3d::Identity() *
-                                          accelerometer_noise_sigma *
-                                          accelerometer_noise_sigma;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/sensord/sensor_fusion.h b/services/vr/sensord/sensor_fusion.h
deleted file mode 100644
index 0ceae21..0000000
--- a/services/vr/sensord/sensor_fusion.h
+++ /dev/null
@@ -1,181 +0,0 @@
-#ifndef ANDROID_DVR_SENSORD_SENSOR_FUSION_H_
-#define ANDROID_DVR_SENSORD_SENSOR_FUSION_H_
-
-#include <atomic>
-#include <cstdlib>
-#include <mutex>
-
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-using Matrix3d = Eigen::Matrix<double, 3, 3>;
-using Rotationd = quatd;
-using Vector3d = vec3d;
-using AngleAxisd = Eigen::AngleAxisd;
-
-// Ported from GVR's pose_state.h.
-// Stores a 3dof pose plus derivatives. This can be used for prediction.
-struct PoseState {
-  // Time in nanoseconds for the current pose.
-  uint64_t timestamp_ns;
-
-  // Rotation from Sensor Space to Start Space.
-  Rotationd sensor_from_start_rotation;
-
-  // First derivative of the rotation.
-  // TODO(pfg): currently storing gyro data, switch to first derivative instead.
-  Vector3d sensor_from_start_rotation_velocity;
-};
-
-// Sensor fusion class that implements an Extended Kalman Filter (EKF) to
-// estimate a 3D rotation from a gyroscope and and accelerometer.
-// This system only has one state, the pose. It does not estimate any velocity
-// or acceleration.
-//
-// To learn more about Kalman filtering one can read this article which is a
-// good introduction: http://en.wikipedia.org/wiki/Kalman_filter
-//
-// Start Space is :
-// z is up.
-// y is forward based on the first sensor data.
-// x = y \times z
-// Sensor Space follows the android specification {@link
-// http://developer.android.com/guide/topics/sensors/sensors_overview.html#sensors-coords}
-// See http://go/vr-coords for definitions of Start Space and Sensor Space.
-//
-// This is a port from GVR's SensorFusion code (See
-// https://cs/vr/gvr/sensors/sensor_fusion.h)
-// which in turn is a port from java of OrientationEKF (See
-// https://cs/java/com/google/vr/cardboard/vrtoolkit/vrtoolkit/src/main/java/com/google/vrtoolkit/cardboard/sensors/internal/OrientationEKF.java)
-class SensorFusion {
- public:
-  SensorFusion();
-  SensorFusion(const SensorFusion&) = delete;
-  void operator=(const SensorFusion&) = delete;
-
-  // Resets the state of the sensor fusion. It sets the velocity for
-  // prediction to zero. The reset will happen with the next
-  // accelerometer sample. Gyroscope sample will be discarded until a new
-  // accelerometer sample arrives.
-  void Reset();
-
-  // Gets the PoseState representing the latest pose and  derivatives at a
-  // particular timestamp as estimated by SensorFusion.
-  PoseState GetLatestPoseState() const;
-
-  // Processes one gyroscope sample event. This updates the pose of the system
-  // and the prediction model. The gyroscope data is assumed to be in axis angle
-  // form. Angle = ||v|| and Axis = v / ||v||, with v = [v_x, v_y, v_z]^T.
-  //
-  // @param v_x velocity in x.
-  // @param v_y velocity in y.
-  // @param v_z velocity in z.
-  // @param timestamp_ns gyroscope event timestamp in nanosecond.
-  void ProcessGyroscopeSample(float v_x, float v_y, float v_z,
-                              uint64_t timestamp_ns);
-
-  // Processes one accelerometer sample event. This updates the pose of the
-  // system. If the Accelerometer norm changes too much between sample it is not
-  // trusted as much.
-  //
-  // @param acc_x accelerometer data in x.
-  // @param acc_y accelerometer data in y.
-  // @param acc_z accelerometer data in z.
-  // @param timestamp_ns accelerometer event timestamp in nanosecond.
-  void ProcessAccelerometerSample(float acc_x, float acc_y, float acc_z,
-                                  uint64_t timestamp_ns);
-
- private:
-  // Estimates the average timestep between gyroscope event.
-  void FilterGyroscopeTimestep(double gyroscope_timestep);
-
-  // Updates the state covariance with an incremental motion. It changes the
-  // space of the quadric.
-  void UpdateStateCovariance(const Matrix3d& motion_update);
-
-  // Computes the innovation vector of the Kalman based on the input pose.
-  // It uses the latest measurement vector (i.e. accelerometer data), which must
-  // be set prior to calling this function.
-  Vector3d ComputeInnovation(const Rotationd& pose);
-
-  // This computes the measurement_jacobian_ via numerical differentiation based
-  // on the current value of sensor_from_start_rotation_.
-  void ComputeMeasurementJacobian();
-
-  // Updates the accelerometer covariance matrix.
-  //
-  // This looks at the norm of recent accelerometer readings. If it has changed
-  // significantly, it means the phone receives additional acceleration than
-  // just gravity, and so the down vector information gravity signal is noisier.
-  //
-  // TODO(dcoz,pfg): this function is very simple, we probably need something
-  // more elaborated here once we have proper regression testing.
-  void UpdateMeasurementCovariance();
-
-  // Reset all internal states. This is not thread safe. Lock should be acquired
-  // outside of it. This function is called in ProcessAccelerometerSample.
-  void ResetState();
-
-  // Current transformation from Sensor Space to Start Space.
-  // x_sensor = sensor_from_start_rotation_ * x_start;
-  PoseState current_state_;
-
-  // Filtering of the gyroscope timestep started?
-  bool is_timestep_filter_initialized_;
-  // Filtered gyroscope timestep valid?
-  bool is_gyroscope_filter_valid_;
-  // Sensor fusion currently aligned with gravity? After initialization
-  // it will requires a couple of accelerometer data for the system to get
-  // aligned.
-  bool is_aligned_with_gravity_;
-
-  // Covariance of Kalman filter state (P in common formulation).
-  Matrix3d state_covariance_;
-  // Covariance of the process noise (Q in common formulation).
-  Matrix3d process_covariance_;
-  // Covariance of the accelerometer measurement (R in common formulation).
-  Matrix3d accelerometer_measurement_covariance_;
-  // Covariance of innovation (S in common formulation).
-  Matrix3d innovation_covariance_;
-  // Jacobian of the measurements (H in common formulation).
-  Matrix3d accelerometer_measurement_jacobian_;
-  // Gain of the Kalman filter (K in common formulation).
-  Matrix3d kalman_gain_;
-  // Parameter update a.k.a. innovation vector. (\nu in common formulation).
-  Vector3d innovation_;
-  // Measurement vector (z in common formulation).
-  Vector3d accelerometer_measurement_;
-  // Current prediction vector (g in common formulation).
-  Vector3d prediction_;
-  // Control input, currently this is only the gyroscope data (\mu in common
-  // formulation).
-  Vector3d control_input_;
-  // Update of the state vector. (x in common formulation).
-  Vector3d state_update_;
-
-  // Time of the last accelerometer processed event.
-  uint64_t current_accelerometer_timestamp_ns_;
-
-  // Estimates of the timestep between gyroscope event in seconds.
-  double filtered_gyroscope_timestep_s_;
-  // Number of timestep samples processed so far by the filter.
-  uint32_t num_gyroscope_timestep_samples_;
-  // Norm of the accelerometer for the previous measurement.
-  double previous_accelerometer_norm_;
-  // Moving average of the accelerometer norm changes. It is computed for every
-  // sensor datum.
-  double moving_average_accelerometer_norm_change_;
-
-  // Flag indicating if a state reset should be executed with the next
-  // accelerometer sample.
-  std::atomic<bool> execute_reset_with_next_accelerometer_sample_;
-
-  mutable std::mutex mutex_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSORD_SENSOR_FUSION_H_
diff --git a/services/vr/sensord/sensor_hal_thread.cpp b/services/vr/sensord/sensor_hal_thread.cpp
deleted file mode 100644
index c321d4f..0000000
--- a/services/vr/sensord/sensor_hal_thread.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-#include "sensor_hal_thread.h"
-
-#include <dvr/performance_client_api.h>
-#include <log/log.h>
-
-namespace android {
-namespace dvr {
-
-SensorHalThread::SensorHalThread(bool* out_success)
-    : shutting_down_(false),
-      paused_(false),
-      sensor_module_(nullptr),
-      sensor_device_(nullptr),
-      sensor_list_(nullptr) {
-  // Assume failure; we will change this to true on success.
-  *out_success = false;
-
-  // TODO(segal): module & device should be singletons.
-  int32_t err = hw_get_module_by_class(SENSORS_HARDWARE_MODULE_ID, "platform",
-                                       (hw_module_t const**)&sensor_module_);
-
-  if (err) {
-    ALOGE("couldn't load %s module (%s)", SENSORS_HARDWARE_MODULE_ID,
-          strerror(-err));
-    return;
-  }
-
-  err = sensors_open_1(&sensor_module_->common, &sensor_device_);
-  if (err) {
-    ALOGE("couldn't open device for module %s (%s)", SENSORS_HARDWARE_MODULE_ID,
-          strerror(-err));
-    return;
-  }
-
-  const int sensor_count =
-      sensor_module_->get_sensors_list(sensor_module_, &sensor_list_);
-
-  // Deactivate all of the sensors initially.
-  sensor_user_count_.resize(sensor_count, 0);
-  for (int i = 0; i < sensor_count; ++i) {
-    err = sensor_device_->activate(
-        reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
-        sensor_list_[i].handle, 0);
-
-    if (err) {
-      ALOGE("failed to deactivate sensor %d (%s)", i, strerror(-err));
-      return;
-    }
-  }
-
-  // At this point, we've successfully initialized everything.
-  *out_success = true;
-}
-
-SensorHalThread::~SensorHalThread() {
-  {
-    std::unique_lock<std::mutex> lock(mutex_);
-    shutting_down_ = true;
-    condition_.notify_one();
-  }
-
-  // Implicitly joins *thread_ if it's running.
-}
-
-void SensorHalThread::StartPolling(const EventConsumer& consumer) {
-  if (thread_) {
-    ALOGE("SensorHalThread::Start() called but thread is already running!");
-    return;
-  }
-
-  thread_.reset(new std::thread([this, consumer] {
-    const int priority_error = dvrSetSchedulerClass(0, "sensors:high");
-    LOG_ALWAYS_FATAL_IF(
-        priority_error < 0,
-        "SensorHalTread::StartPolling: Failed to set scheduler class: %s",
-        strerror(-priority_error));
-
-    for (;;) {
-      for (;;) {
-        std::unique_lock<std::mutex> lock(mutex_);
-        if (shutting_down_)
-          return;
-        if (!paused_)
-          break;
-        condition_.wait(lock);
-      }
-      const int kMaxEvents = 100;
-      sensors_event_t events[kMaxEvents];
-      ssize_t event_count = 0;
-      do {
-        if (sensor_device_) {
-          event_count = sensor_device_->poll(
-              reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
-              events, kMaxEvents);
-        } else {
-          // When there is no sensor_device_, we still call the consumer at
-          // regular intervals in case mock poses are in use. Note that this
-          // will never be the case for production devices, but this helps
-          // during bringup.
-          usleep(5000);
-        }
-      } while (event_count == -EINTR);
-      if (event_count == kMaxEvents)
-        ALOGI("max events (%d) reached", kMaxEvents);
-
-      if (event_count >= 0) {
-        consumer(events, events + event_count);
-      } else {
-        ALOGE(
-            "SensorHalThread::StartPolling: Error while polling sensor: %s "
-            "(%zd)",
-            strerror(-event_count), -event_count);
-      }
-    }
-  }));
-}
-
-void SensorHalThread::SetPaused(bool is_paused) {
-  std::unique_lock<std::mutex> lock(mutex_);
-  paused_ = is_paused;
-  condition_.notify_one();
-}
-
-void SensorHalThread::StartUsingSensor(const int sensor_index) {
-  if (sensor_index < 0 || sensor_index >= GetSensorCount()) {
-    ALOGE("StartUsingSensor(): sensor index %d out of range [0, %d)",
-          sensor_index, GetSensorCount());
-    return;
-  }
-
-  std::lock_guard<std::mutex> guard(user_count_mutex_);
-  if (sensor_user_count_[sensor_index]++ == 0) {
-    sensor_device_->activate(
-        reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
-        sensor_list_[sensor_index].handle, 1);
-    sensor_device_->setDelay(
-        reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
-        sensor_list_[sensor_index].handle, 0);
-  }
-}
-
-void SensorHalThread::StopUsingSensor(const int sensor_index) {
-  if (sensor_index < 0 || sensor_index >= GetSensorCount()) {
-    ALOGE("StopUsingSensor(): sensor index %d out of range [0, %d)",
-          sensor_index, GetSensorCount());
-    return;
-  }
-
-  std::lock_guard<std::mutex> guard(user_count_mutex_);
-  if (--sensor_user_count_[sensor_index] == 0) {
-    sensor_device_->activate(
-        reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
-        sensor_list_[sensor_index].handle, 0);
-  }
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/sensord/sensor_hal_thread.h b/services/vr/sensord/sensor_hal_thread.h
deleted file mode 100644
index 9220757..0000000
--- a/services/vr/sensord/sensor_hal_thread.h
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef ANDROID_DVR_SENSORD_SENSOR_HAL_THREAD_H_
-#define ANDROID_DVR_SENSORD_SENSOR_HAL_THREAD_H_
-
-#include <hardware/sensors.h>
-
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-#include "sensor_thread.h"
-
-namespace android {
-namespace dvr {
-
-// Manages initialization and polling of the sensor HAL. Polling is performed
-// continuously on a thread that passes events along to an arbitrary consumer.
-// All const member functions are thread-safe; otherwise, thread safety is noted
-// for each function.
-class SensorHalThread : public SensorThread {
- public:
-  // Initializes the sensor HAL, but does not yet start polling (see Start()
-  // below). Sets *out_success to true on success; otherwise, sets *out_success
-  // to false and logs an error.
-  explicit SensorHalThread(bool* out_success);
-
-  // Tells the polling thread to shut down if it's running, and waits for it to
-  // complete its polling loop.
-  ~SensorHalThread() override;
-
-  // Begins polling on the thread. The provided consumer will be notified of
-  // events. Event notification occurs on the polling thread.
-  // Calling Start() more than once on an instance of SensorHalThread is
-  // invalid.
-  void StartPolling(const EventConsumer& consumer) override;
-
-  // Set whether the sensor polling thread is paused or not. This is useful
-  // while we need to support both 3DoF and 6DoF codepaths. This 3DoF codepath
-  // must be paused while the 6DoF codepath is using the IMU event stream.
-  void SetPaused(bool is_paused) override;
-
-  // Increase the number of users of the given sensor by one. Activates the
-  // sensor if it wasn't already active.
-  // Safe to call concurrently with any other functions in this class.
-  void StartUsingSensor(int sensor_index) override;
-
-  // Decrease the number of users of the given sensor by one. Deactivates the
-  // sensor if its usage count has dropped to zero.
-  // Safe to call concurrently with any other functions in this class.
-  void StopUsingSensor(int sensor_index) override;
-
-  // The number of sensors that are available. Returns a negative number if
-  // initialization failed.
-  int GetSensorCount() const override {
-    return static_cast<int>(sensor_user_count_.size());
-  }
-
-  // The underlying sensor HAL data structure for the sensor at the given index.
-  int GetSensorType(int index) const override {
-    return sensor_list_[index].type;
-  }
-
- private:
-  // The actual thread on which we consume events.
-  std::unique_ptr<std::thread> thread_;
-
-  // Mutex for access to shutting_down_ and paused_ members.
-  std::mutex mutex_;
-
-  // Condition for signaling pause/unpause to the thread.
-  std::condition_variable condition_;
-
-  // If this member is set to true, the thread will stop running at its next
-  // iteration. Only set with the mutex held and signal condition_ when changed.
-  bool shutting_down_;
-
-  // If this member is set to true, the thread will pause at its next
-  // iteration. Only set with the mutex held and signal condition_ when changed.
-  bool paused_;
-
-  // HAL access
-  struct sensors_module_t* sensor_module_;
-  sensors_poll_device_1_t* sensor_device_;
-
-  // Contiguous array of available sensors, owned by the sensor HAL.
-  const sensor_t* sensor_list_;
-
-  // Mutex that protects access to sensor_user_count_.data().
-  std::mutex user_count_mutex_;
-
-  // A count of how many users each sensor has. Protected by user_count_mutex.
-  std::vector<int> sensor_user_count_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSORD_SENSOR_HAL_THREAD_H_
diff --git a/services/vr/sensord/sensor_ndk_thread.cpp b/services/vr/sensord/sensor_ndk_thread.cpp
deleted file mode 100644
index 9c3abbc..0000000
--- a/services/vr/sensord/sensor_ndk_thread.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-#include "sensor_ndk_thread.h"
-
-#include <dvr/performance_client_api.h>
-#include <log/log.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-static constexpr int kLooperIdUser = 5;
-}  // namespace
-
-SensorNdkThread::SensorNdkThread(bool* out_success)
-    : shutting_down_(false),
-      paused_(true),
-      thread_started_(false),
-      initialization_result_(false),
-      looper_(nullptr),
-      sensor_manager_(nullptr),
-      event_queue_(nullptr),
-      sensor_list_(nullptr),
-      sensor_count_(0) {
-  // Assume failure; we will change this to true on success.
-  *out_success = false;
-
-  // These structs are the same, but sanity check the sizes.
-  static_assert(sizeof(sensors_event_t) == sizeof(ASensorEvent),
-                "Error: sizeof(sensors_event_t) != sizeof(ASensorEvent)");
-
-  thread_.reset(new std::thread([this] {
-    const int priority_error = dvrSetSchedulerClass(0, "sensors:high");
-    LOG_ALWAYS_FATAL_IF(
-        priority_error < 0,
-        "SensorHalTread::StartPolling: Failed to set scheduler class: %s",
-        strerror(-priority_error));
-
-    // Start ALooper and initialize sensor access.
-    {
-      std::unique_lock<std::mutex> lock(mutex_);
-      InitializeSensors();
-      thread_started_ = true;
-      init_condition_.notify_one();
-      // Continue on failure - the loop below will periodically retry.
-    }
-
-    EventConsumer consumer;
-    for (;;) {
-      for (;;) {
-        std::unique_lock<std::mutex> lock(mutex_);
-        UpdateSensorUse();
-        if (!consumer)
-          consumer = consumer_;
-        if (shutting_down_)
-          return;
-        if (!paused_)
-          break;
-        condition_.wait(lock);
-      }
-
-      constexpr int kMaxEvents = 100;
-      sensors_event_t events[kMaxEvents];
-      ssize_t event_count = 0;
-      if (initialization_result_) {
-        int poll_fd, poll_events;
-        void* poll_source;
-        // Poll for events.
-        int ident = ALooper_pollAll(-1, &poll_fd, &poll_events, &poll_source);
-
-        if (ident != kLooperIdUser)
-          continue;
-
-        ASensorEvent* event = reinterpret_cast<ASensorEvent*>(&events[0]);
-        event_count =
-            ASensorEventQueue_getEvents(event_queue_, event, kMaxEvents);
-
-        if (event_count == 0) {
-          ALOGE("Detected sensor service failure, restarting sensors");
-          // This happens when sensorservice has died and restarted. To avoid
-          // spinning we need to restart the sensor access.
-          DestroySensors();
-        }
-      } else {
-        // When there is no sensor_device_, we still call the consumer at
-        // regular intervals in case mock poses are in use. Note that this
-        // will never be the case for production devices, but this helps
-        // during bringup.
-        usleep(5000);
-      }
-      if (event_count == kMaxEvents)
-        ALOGI("max events (%d) reached", kMaxEvents);
-
-      if (event_count >= 0) {
-        consumer(events, events + event_count);
-      } else {
-        ALOGE(
-            "SensorNdkThread::StartPolling: Error while polling sensor: %s "
-            "(%zd)",
-            strerror(-event_count), -event_count);
-      }
-    }
-
-    // About to exit sensor thread, destroy sensor objects.
-    DestroySensors();
-  }));
-
-  // Wait for thread to startup and initialize sensors so that we know whether
-  // it succeeded.
-  {
-    std::unique_lock<std::mutex> lock(mutex_);
-    while (!thread_started_)
-      init_condition_.wait(lock);
-  }
-
-  // At this point, we've successfully initialized everything.
-  // The NDK sensor thread will continue to retry on error, so assume success here.
-  *out_success = true;
-}
-
-SensorNdkThread::~SensorNdkThread() {
-  {
-    if (looper_)
-      ALooper_wake(looper_);
-    std::unique_lock<std::mutex> lock(mutex_);
-    shutting_down_ = true;
-    condition_.notify_one();
-  }
-
-  thread_->join();
-}
-
-bool SensorNdkThread::InitializeSensors() {
-  looper_ = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
-  if (!looper_) {
-    ALOGE("Failed to create ALooper.");
-    return false;
-  }
-
-  // Prepare to monitor accelerometer
-  sensor_manager_ = ASensorManager_getInstanceForPackage(nullptr);
-  if (!sensor_manager_) {
-    ALOGE("Failed to create ASensorManager.");
-    return false;
-  }
-
-  event_queue_ = ASensorManager_createEventQueue(
-      sensor_manager_, looper_, kLooperIdUser, nullptr, nullptr);
-  if (!event_queue_) {
-    ALOGE("Failed to create sensor EventQueue.");
-    return false;
-  }
-
-  sensor_count_ = ASensorManager_getSensorList(sensor_manager_, &sensor_list_);
-  ALOGI("Sensor count %d", sensor_count_);
-
-  sensor_user_count_.resize(sensor_count_, 0);
-
-  // To recover from sensorservice restart, enable the sensors that are already
-  // requested.
-  for (size_t sensor_index = 0; sensor_index < sensor_user_count_.size();
-       ++sensor_index) {
-    if (sensor_user_count_[sensor_index] > 0) {
-      int result = ASensorEventQueue_registerSensor(
-          event_queue_, sensor_list_[sensor_index], 0, 0);
-      ALOGE_IF(result < 0, "ASensorEventQueue_registerSensor failed: %d",
-               result);
-    }
-  }
-
-  initialization_result_ = true;
-  return true;
-}
-
-void SensorNdkThread::DestroySensors() {
-  if (!event_queue_)
-    return;
-  for (size_t sensor_index = 0; sensor_index < sensor_user_count_.size();
-       ++sensor_index) {
-    if (sensor_user_count_[sensor_index] > 0) {
-      ASensorEventQueue_disableSensor(event_queue_, sensor_list_[sensor_index]);
-    }
-  }
-  ASensorManager_destroyEventQueue(sensor_manager_, event_queue_);
-  event_queue_ = nullptr;
-  initialization_result_ = false;
-}
-
-void SensorNdkThread::UpdateSensorUse() {
-  if (!initialization_result_) {
-    // Sleep for 1 second to avoid spinning during system instability.
-    usleep(1000 * 1000);
-    InitializeSensors();
-    if (!initialization_result_)
-      return;
-  }
-
-  if (!enable_sensors_.empty()) {
-    for (int sensor_index : enable_sensors_) {
-      if (sensor_user_count_[sensor_index]++ == 0) {
-        int result = ASensorEventQueue_registerSensor(
-            event_queue_, sensor_list_[sensor_index], 0, 0);
-        ALOGE_IF(result < 0, "ASensorEventQueue_registerSensor failed: %d",
-                 result);
-      }
-    }
-    enable_sensors_.clear();
-  }
-
-  if (!disable_sensors_.empty()) {
-    for (int sensor_index : disable_sensors_) {
-      if (--sensor_user_count_[sensor_index] == 0) {
-        int result = ASensorEventQueue_disableSensor(
-            event_queue_, sensor_list_[sensor_index]);
-        ALOGE_IF(result < 0, "ASensorEventQueue_disableSensor failed: %d",
-                 result);
-      }
-    }
-    disable_sensors_.clear();
-  }
-}
-
-void SensorNdkThread::StartPolling(const EventConsumer& consumer) {
-  {
-    std::unique_lock<std::mutex> lock(mutex_);
-    if (consumer_) {
-      ALOGE("Already started sensor thread.");
-      return;
-    }
-    consumer_ = consumer;
-  }
-  SetPaused(false);
-}
-
-void SensorNdkThread::SetPaused(bool is_paused) {
-  std::unique_lock<std::mutex> lock(mutex_);
-  // SetPaused may be called before we have StartPolling, make sure we have
-  // an event consumer. Otherwise we defer until StartPolling is called.
-  if (!consumer_)
-    return;
-  paused_ = is_paused;
-  condition_.notify_one();
-  ALooper_wake(looper_);
-}
-
-void SensorNdkThread::StartUsingSensor(const int sensor_index) {
-  std::unique_lock<std::mutex> lock(mutex_);
-  if (sensor_index < 0 || sensor_index >= sensor_count_) {
-    ALOGE("StartUsingSensor(): sensor index %d out of range [0, %d)",
-          sensor_index, sensor_count_);
-    return;
-  }
-
-  enable_sensors_.push_back(sensor_index);
-  ALooper_wake(looper_);
-}
-
-void SensorNdkThread::StopUsingSensor(const int sensor_index) {
-  std::unique_lock<std::mutex> lock(mutex_);
-  if (sensor_index < 0 || sensor_index >= sensor_count_) {
-    ALOGE("StopUsingSensor(): sensor index %d out of range [0, %d)",
-          sensor_index, sensor_count_);
-    return;
-  }
-
-  disable_sensors_.push_back(sensor_index);
-  ALooper_wake(looper_);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/sensord/sensor_ndk_thread.h b/services/vr/sensord/sensor_ndk_thread.h
deleted file mode 100644
index eb3cf9d..0000000
--- a/services/vr/sensord/sensor_ndk_thread.h
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef ANDROID_DVR_SENSORD_SENSOR_NDK_THREAD_H_
-#define ANDROID_DVR_SENSORD_SENSOR_NDK_THREAD_H_
-
-#include <android/sensor.h>
-#include <hardware/sensors.h>
-
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-#include "sensor_thread.h"
-
-namespace android {
-namespace dvr {
-
-// Manages initialization and polling of the sensor data. Polling is performed
-// continuously on a thread that passes events along to an arbitrary consumer.
-// All const member functions are thread-safe; otherwise, thread safety is noted
-// for each function.
-class SensorNdkThread : public SensorThread {
- public:
-  // Initializes the sensor access, but does not yet start polling (see Start()
-  // below). Sets *out_success to true on success; otherwise, sets *out_success
-  // to false and logs an error.
-  explicit SensorNdkThread(bool* out_success);
-
-  // Tells the polling thread to shut down if it's running, and waits for it to
-  // complete its polling loop.
-  ~SensorNdkThread() override;
-
-  // Begins polling on the thread. The provided consumer will be notified of
-  // events. Event notification occurs on the polling thread.
-  // Calling Start() more than once on an instance of SensorNdkThread is
-  // invalid.
-  void StartPolling(const EventConsumer& consumer) override;
-
-  // Set whether the sensor polling thread is paused or not. This is useful
-  // while we need to support both 3DoF and 6DoF codepaths. This 3DoF codepath
-  // must be paused while the 6DoF codepath is using the IMU event stream.
-  void SetPaused(bool is_paused) override;
-
-  // Increase the number of users of the given sensor by one. Activates the
-  // sensor if it wasn't already active.
-  // Safe to call concurrently with any other functions in this class.
-  void StartUsingSensor(int sensor_index) override;
-
-  // Decrease the number of users of the given sensor by one. Deactivates the
-  // sensor if its usage count has dropped to zero.
-  // Safe to call concurrently with any other functions in this class.
-  void StopUsingSensor(int sensor_index) override;
-
-  // The number of sensors that are available. Returns a negative number if
-  // initialization failed.
-  int GetSensorCount() const override { return sensor_count_; }
-
-  // The underlying sensor HAL data structure for the sensor at the given index.
-  int GetSensorType(int index) const override {
-    return ASensor_getType(sensor_list_[index]);
-  }
-
- private:
-  // Initialize ALooper and sensor access on the thread.
-  // Returns true on success, false on failure.
-  bool InitializeSensors();
-
-  // Destroy sensor access.
-  void DestroySensors();
-
-  // Start or stop requested sensors from the thread. Class mutex must already
-  // be locked.
-  void UpdateSensorUse();
-
-  // The actual thread on which we consume events.
-  std::unique_ptr<std::thread> thread_;
-
-  // Mutex for access to shutting_down_ and paused_ members.
-  std::mutex mutex_;
-
-  // Condition for signaling pause/unpause to the thread.
-  std::condition_variable condition_;
-
-  // Condition for signaling thread initialization.
-  std::condition_variable init_condition_;
-
-  // If this member is set to true, the thread will stop running at its next
-  // iteration. Only set with the mutex held and signal condition_ when changed.
-  bool shutting_down_;
-
-  // If this member is set to true, the thread will pause at its next
-  // iteration. Only set with the mutex held and signal condition_ when changed.
-  bool paused_;
-
-  // Thread start hand shake to verify that sensor initialization succeeded.
-  bool thread_started_;
-
-  // Initialization result (true for success).
-  bool initialization_result_;
-
-  // The callback.
-  EventConsumer consumer_;
-
-  // Sensor access
-  ALooper* looper_;
-  ASensorManager* sensor_manager_;
-  ASensorEventQueue* event_queue_;
-
-  // Sensor list from NDK.
-  ASensorList sensor_list_;
-  int sensor_count_;
-
-  // Requests to the sensor thread to enable or disable given sensors.
-  std::vector<int> enable_sensors_;
-  std::vector<int> disable_sensors_;
-
-  // A count of how many users each sensor has. Protected by user_count_mutex.
-  std::vector<int> sensor_user_count_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSORD_SENSOR_NDK_THREAD_H_
diff --git a/services/vr/sensord/sensor_service.cpp b/services/vr/sensord/sensor_service.cpp
deleted file mode 100644
index a182a26..0000000
--- a/services/vr/sensord/sensor_service.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-#include "sensor_service.h"
-
-#include <hardware/sensors.h>
-#include <log/log.h>
-#include <pdx/default_transport/service_endpoint.h>
-#include <poll.h>
-#include <private/dvr/sensor-ipc.h>
-#include <time.h>
-
-using android::pdx::default_transport::Endpoint;
-
-namespace android {
-namespace dvr {
-
-SensorService::SensorService(SensorThread* sensor_thread)
-    : BASE("SensorService", Endpoint::Create(DVR_SENSOR_SERVICE_CLIENT)),
-      sensor_thread_(sensor_thread) {
-  sensor_clients_.resize(sensor_thread_->GetSensorCount());
-
-  for (int i = 0; i < sensor_thread_->GetSensorCount(); ++i)
-    type_to_sensor_[sensor_thread_->GetSensorType(i)] = i;
-}
-
-std::shared_ptr<pdx::Channel> SensorService::OnChannelOpen(pdx::Message& msg) {
-  std::lock_guard<std::mutex> guard(mutex_);
-
-  const pdx::MessageInfo& info = msg.GetInfo();
-
-  std::shared_ptr<SensorClient> client(
-      new SensorClient(*this, info.pid, info.cid));
-  AddClient(client);
-  return client;
-}
-
-void SensorService::OnChannelClose(pdx::Message& /*msg*/,
-                                   const std::shared_ptr<pdx::Channel>& chan) {
-  std::lock_guard<std::mutex> guard(mutex_);
-
-  auto client = std::static_pointer_cast<SensorClient>(chan);
-  if (!client) {
-    ALOGW("WARNING: SensorClient was NULL!\n");
-    return;
-  }
-  RemoveClient(client);
-}
-
-void SensorService::AddClient(const std::shared_ptr<SensorClient>& client) {
-  clients_.push_front(client);
-}
-
-void SensorService::RemoveClient(const std::shared_ptr<SensorClient>& client) {
-  // First remove it from the clients associated with its sensor, if any.
-  RemoveSensorClient(client.get());
-
-  // Finally, remove it from the list of clients we're aware of, and decrease
-  // its reference count.
-  clients_.remove(client);
-}
-
-void SensorService::RemoveSensorClient(SensorClient* client) {
-  if (!client->has_sensor())
-    return;
-
-  std::forward_list<SensorClient*>& sensor_clients =
-      sensor_clients_[client->sensor()];
-  sensor_clients.remove(client);
-  sensor_thread_->StopUsingSensor(client->sensor());
-
-  client->unset_sensor();
-}
-
-pdx::Status<void> SensorService::HandleMessage(pdx::Message& msg) {
-  pdx::Status<void> ret;
-  const pdx::MessageInfo& info = msg.GetInfo();
-  switch (info.op) {
-    case DVR_SENSOR_START: {
-      std::lock_guard<std::mutex> guard(mutex_);
-      // Associate this channel with the indicated sensor,
-      // unless it already has an association. In that case,
-      // fail.
-      auto client = std::static_pointer_cast<SensorClient>(msg.GetChannel());
-      if (client->has_sensor())
-        REPLY_ERROR(msg, EINVAL, error);
-      int sensor_type;
-      if (!msg.ReadAll(&sensor_type, sizeof(sensor_type)))
-        REPLY_ERROR(msg, EIO, error);
-
-      // Find the sensor of the requested type.
-      if (type_to_sensor_.find(sensor_type) == type_to_sensor_.end())
-        REPLY_ERROR(msg, EINVAL, error);
-      const int sensor_index = type_to_sensor_[sensor_type];
-
-      sensor_clients_[sensor_index].push_front(client.get());
-      client->set_sensor(sensor_index);
-      sensor_thread_->StartUsingSensor(sensor_index);
-
-      REPLY_SUCCESS(msg, 0, error);
-    }
-    case DVR_SENSOR_STOP: {
-      std::lock_guard<std::mutex> guard(mutex_);
-      auto client = std::static_pointer_cast<SensorClient>(msg.GetChannel());
-      if (!client->has_sensor())
-        REPLY_ERROR(msg, EINVAL, error);
-      RemoveSensorClient(client.get());
-      REPLY_SUCCESS(msg, 0, error);
-    }
-    case DVR_SENSOR_POLL: {
-      std::lock_guard<std::mutex> guard(mutex_);
-      auto client = std::static_pointer_cast<SensorClient>(msg.GetChannel());
-
-      // Package up the events we've got for this client. Number of
-      // events, followed by 0 or more sensor events, popped from
-      // this client's queue until it's empty.
-      int num_events = client->EventCount();
-      sensors_event_t out_buffer[num_events];
-      client->WriteEvents(out_buffer);
-      struct iovec svec[] = {
-          {.iov_base = &num_events, .iov_len = sizeof(num_events)},
-          {.iov_base = out_buffer,
-           .iov_len = num_events * sizeof(sensors_event_t)},
-      };
-      ret = msg.WriteVectorAll(svec, 2);
-      if (!ret) {
-        REPLY_ERROR(msg, EIO, error);
-      }
-      REPLY_SUCCESS(msg, 0, error);
-    }
-    default:
-      // Do not lock mutex_ here, because this may call the on*() handlers,
-      // which will lock the mutex themselves.
-      ret = Service::HandleMessage(msg);
-      break;
-  }
-error:
-  return ret;
-}
-
-void SensorService::EnqueueEvents(const sensors_event_t* begin_events,
-                                  const sensors_event_t* end_events) {
-  std::lock_guard<std::mutex> guard(mutex_);
-
-  // Put the sensor values we got in the circular queue for each client that
-  // cares about the given event.
-  for (const sensors_event_t* event = begin_events; event != end_events;
-       ++event) {
-    const int sensor_index = type_to_sensor_[event->type];
-    for (const auto& client : sensor_clients_[sensor_index]) {
-      client->EnqueueEvent(*event);
-    }
-  }
-}
-
-void SensorClient::WriteEvents(sensors_event_t* buffer) {
-  while (!event_queue_.Empty()) {
-    *buffer = *(event_queue_.Top());
-    event_queue_.Pop();
-    ++buffer;
-  }
-}
-
-void SensorClient::CircularQ::Push(const sensors_event_t& event) {
-  if (count_ != 0 && head_ == tail_) {
-    Pop();  // If we're full, throw away the oldest event.
-  }
-  events_[head_] = event;
-  head_ = (head_ + 1) % kCqSize;
-  ++count_;
-}
-
-const sensors_event_t* SensorClient::CircularQ::Top() const {
-  if (count_ == 0)
-    return nullptr;
-  return &events_[tail_];
-}
-
-void SensorClient::CircularQ::Pop() {
-  if (count_ == 0)
-    return;
-  tail_ = (tail_ + 1) % kCqSize;
-  --count_;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/sensord/sensor_service.h b/services/vr/sensord/sensor_service.h
deleted file mode 100644
index 6ea470b..0000000
--- a/services/vr/sensord/sensor_service.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef ANDROID_DVR_SENSORD_SENSOR_SERVICE_H_
-#define ANDROID_DVR_SENSORD_SENSOR_SERVICE_H_
-
-#include <forward_list>
-#include <unordered_map>
-#include <vector>
-
-#include <pdx/service.h>
-#include <pthread.h>
-
-#include "sensor_thread.h"
-
-namespace android {
-namespace dvr {
-
-class SensorClient;
-
-/*
- * SensorService implements the sensor service over ServiceFS.
- * The sensor service provides an interface to one sensor over
- * each channel.
- */
-class SensorService : public pdx::ServiceBase<SensorService> {
- public:
-  pdx::Status<void> HandleMessage(pdx::Message& msg) override;
-  std::shared_ptr<pdx::Channel> OnChannelOpen(pdx::Message& msg) override;
-  void OnChannelClose(pdx::Message& msg,
-                      const std::shared_ptr<pdx::Channel>& chan) override;
-
-  // Enqueue the events in [begin_events, end_events) onto any clients that care
-  // about them.
-  // Safe to call concurrently with any other public member functions.
-  void EnqueueEvents(const sensors_event_t* begin_events,
-                     const sensors_event_t* end_events);
-
- private:
-  friend BASE;
-
-  // Initializes the service. Keeps a reference to sensor_thread, which must be
-  // non-null.
-  explicit SensorService(SensorThread* sensor_thread);
-
-  // The abstraction around the sensor HAL.
-  SensorThread* sensor_thread_;
-
-  // All of the clients we are connected to. This is the one place in this class
-  // where we keep the SensorClient instances alive using shared_ptr instances.
-  std::forward_list<std::shared_ptr<SensorClient>> clients_;
-
-  // Map types back to sensor indexes.
-  std::unordered_map<int, int> type_to_sensor_;
-  // For each sensor, the list of clients that are connected to it.
-  // Every entry in here must also be in clients_, so that its reference count
-  // remains positive.
-  std::vector<std::forward_list<SensorClient*>> sensor_clients_;
-
-  // Protects access to all member variables.
-  std::mutex mutex_;
-
-  // None of the following functions is thread-safe; callers must lock mutex_
-  // before calling one.
-  void AddClient(const std::shared_ptr<SensorClient>& client);
-  void RemoveClient(const std::shared_ptr<SensorClient>& client);
-  // Dissociate the indicated client from its sensor, if it has one; otherwise
-  // do nothing.
-  void RemoveSensorClient(SensorClient* client);
-
-  SensorService(const SensorService&) = delete;
-  void operator=(const SensorService&) = delete;
-};
-
-/*
- * SensorClient manages the service-side per-client context for each client
- * using the service.
- */
-class SensorClient : public pdx::Channel {
- public:
-  SensorClient(SensorService& /*service*/, int /*pid*/, int /*cid*/)
-      : sensor_index_(-1), has_sensor_index_(false) {}
-
-  bool has_sensor() const { return has_sensor_index_; }
-  int sensor() const { return sensor_index_; }
-  void set_sensor(int sensor) {
-    sensor_index_ = sensor;
-    has_sensor_index_ = true;
-  }
-  void unset_sensor() {
-    sensor_index_ = -1;
-    has_sensor_index_ = false;
-  }
-
-  int EventCount() const { return event_queue_.Count(); }
-
-  // Push an event onto our queue.
-  void EnqueueEvent(const sensors_event_t& event) { event_queue_.Push(event); }
-
-  // Write all the events in our queue (and clear it) to the supplied
-  // buffer. Buffer must be large enough.
-  void WriteEvents(sensors_event_t* buffer);
-
- private:
-  SensorClient(const SensorClient&) = delete;
-  SensorClient& operator=(const SensorClient&) = delete;
-
-  int sensor_index_ = -1;
-  bool has_sensor_index_ = false;
-  // Circular queue holds as-yet-unasked-for events for the sensor associated
-  // with this client.
-  class CircularQ {
-   public:
-    static const int kCqSize = 10;
-    CircularQ() : head_(0), tail_(0), count_(0) {}
-    ~CircularQ() {}
-    void Push(const sensors_event_t& event);
-    const sensors_event_t* Top() const;
-    void Pop();
-    bool Empty() const { return count_ == 0; }
-    int Count() const { return count_; }
-
-   private:
-    sensors_event_t events_[kCqSize];
-    int head_ = 0;
-    int tail_ = 0;
-    int count_ = 0;
-  };
-  CircularQ event_queue_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSORD_SENSOR_SERVICE_H_
diff --git a/services/vr/sensord/sensor_thread.cpp b/services/vr/sensord/sensor_thread.cpp
deleted file mode 100644
index 01e4e7e..0000000
--- a/services/vr/sensord/sensor_thread.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "sensor_thread.h"
-
-namespace android {
-namespace dvr {
-
-SensorThread::~SensorThread() {}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/sensord/sensor_thread.h b/services/vr/sensord/sensor_thread.h
deleted file mode 100644
index 46aba17..0000000
--- a/services/vr/sensord/sensor_thread.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef ANDROID_DVR_SENSORD_SENSOR_THREAD_H_
-#define ANDROID_DVR_SENSORD_SENSOR_THREAD_H_
-
-#include <hardware/sensors.h>
-
-#include <functional>
-
-namespace android {
-namespace dvr {
-
-// Manages initialization and polling of the sensor data. Polling is performed
-// continuously on a thread that passes events along to an arbitrary consumer.
-// All const member functions are thread-safe; otherwise, thread safety is noted
-// for each function.
-class SensorThread {
- public:
-  // A function type that can be called to provide it with new events.
-  // [events_begin, events_end) forms a contiguous array of events.
-  using EventConsumer = std::function<void(const sensors_event_t* events_begin,
-                                           const sensors_event_t* events_end)>;
-
-  // Tells the polling thread to shut down if it's running, and waits for it to
-  // complete its polling loop.
-  virtual ~SensorThread();
-
-  // Begins polling on the thread. The provided consumer will be notified of
-  // events. Event notification occurs on the polling thread.
-  // Calling Start() more than once on an instance of SensorThread is
-  // invalid.
-  virtual void StartPolling(const EventConsumer& consumer) = 0;
-
-  // Set whether the sensor polling thread is paused or not. This is useful
-  // while we need to support both 3DoF and 6DoF codepaths. This 3DoF codepath
-  // must be paused while the 6DoF codepath is using the IMU event stream.
-  virtual void SetPaused(bool is_paused) = 0;
-
-  // Increase the number of users of the given sensor by one. Activates the
-  // sensor if it wasn't already active.
-  // Safe to call concurrently with any other functions in this class.
-  virtual void StartUsingSensor(int sensor_index) = 0;
-
-  // Decrease the number of users of the given sensor by one. Deactivates the
-  // sensor if its usage count has dropped to zero.
-  // Safe to call concurrently with any other functions in this class.
-  virtual void StopUsingSensor(int sensor_index) = 0;
-
-  // The number of sensors that are available. Returns a negative number if
-  // initialization failed.
-  virtual int GetSensorCount() const = 0;
-
-  // Get the sensor type for the sensor at the given index.
-  virtual int GetSensorType(int index) const = 0;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSORD_SENSOR_THREAD_H_
diff --git a/services/vr/sensord/sensord.cpp b/services/vr/sensord/sensord.cpp
deleted file mode 100644
index db39152..0000000
--- a/services/vr/sensord/sensord.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#define LOG_TAG "sensord"
-
-#include <string.h>
-
-#include <binder/ProcessState.h>
-
-#include <dvr/performance_client_api.h>
-#include <pdx/default_transport/service_dispatcher.h>
-#include <private/dvr/pose-ipc.h>
-#include <private/dvr/sensor-ipc.h>
-
-#include "pose_service.h"
-#include "sensor_hal_thread.h"
-#include "sensor_ndk_thread.h"
-#include "sensor_service.h"
-#include "sensor_thread.h"
-#include "sensord_extension.h"
-
-using android::dvr::PoseService;
-using android::dvr::SensorHalThread;
-using android::dvr::SensorNdkThread;
-using android::dvr::SensorService;
-using android::dvr::SensorThread;
-using android::pdx::Service;
-using android::pdx::ServiceDispatcher;
-using android::dvr::SensordExtension;
-
-int main(int, char**) {
-  ALOGI("Starting up...");
-
-  SensordExtension::run();
-
-  // We need to be able to create endpoints with full perms.
-  umask(0000);
-
-  android::ProcessState::self()->startThreadPool();
-
-  bool sensor_thread_succeeded = false;
-#ifdef SENSORD_USES_HAL
-  std::unique_ptr<SensorThread> sensor_thread(
-      new SensorHalThread(&sensor_thread_succeeded));
-#else
-  std::unique_ptr<SensorThread> sensor_thread(
-      new SensorNdkThread(&sensor_thread_succeeded));
-#endif
-
-  if (!sensor_thread_succeeded) {
-    ALOGE("ERROR: Failed to initialize SensorThread! No 3DoF!\n");
-  }
-
-  if (sensor_thread->GetSensorCount() == 0)
-    ALOGW("No sensors found\n");
-
-  auto sensor_service = SensorService::Create(sensor_thread.get());
-  if (!sensor_service) {
-    ALOGE("TERMINATING: failed to create SensorService!!!\n");
-    return -1;
-  }
-
-  auto pose_service = PoseService::Create(sensor_thread.get());
-  if (!pose_service) {
-    ALOGE("TERMINATING: failed to create PoseService!!!\n");
-    return -1;
-  }
-
-  std::unique_ptr<ServiceDispatcher> dispatcher =
-      android::pdx::default_transport::ServiceDispatcher::Create();
-  if (!dispatcher) {
-    ALOGE("TERMINATING: failed to create ServiceDispatcher!!!\n");
-    return -1;
-  }
-
-  dispatcher->AddService(sensor_service);
-  dispatcher->AddService(pose_service);
-
-  sensor_thread->StartPolling([sensor_service, pose_service](
-      const sensors_event_t* events_begin, const sensors_event_t* events_end) {
-    sensor_service->EnqueueEvents(events_begin, events_end);
-    pose_service->HandleEvents(events_begin, events_end);
-  });
-
-  const int priority_error = dvrSetSchedulerClass(0, "sensors:low");
-  LOG_ALWAYS_FATAL_IF(priority_error < 0,
-                      "SensorService: Failed to set scheduler class: %s",
-                      strerror(-priority_error));
-
-  int ret = dispatcher->EnterDispatchLoop();
-  ALOGI("Dispatch loop exited because: %s\n", strerror(-ret));
-
-  return ret;
-}
diff --git a/services/vr/sensord/sensord.rc b/services/vr/sensord/sensord.rc
deleted file mode 100644
index 36cd377..0000000
--- a/services/vr/sensord/sensord.rc
+++ /dev/null
@@ -1,11 +0,0 @@
-on init
-  mkdir /dev/socket/pdx/system/vr/pose 0775 system system
-  mkdir /dev/socket/pdx/system/vr/sensors 0775 system system
-
-service sensord /system/bin/sensord
-  class core
-  user system
-  group system camera sdcard_rw
-  writepid /dev/cpuset/system/tasks
-  socket pdx/system/vr/sensors/client stream 0666 system system
-  socket pdx/system/vr/pose/client stream 0666 system system
diff --git a/services/vr/sensord/sensord_extension.cpp b/services/vr/sensord/sensord_extension.cpp
deleted file mode 100644
index 6cd7db3..0000000
--- a/services/vr/sensord/sensord_extension.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "sensord_extension.h"
-
-void android::dvr::SensordExtension::run() {
-}
diff --git a/services/vr/sensord/sensord_extension.h b/services/vr/sensord/sensord_extension.h
deleted file mode 100644
index e553eed..0000000
--- a/services/vr/sensord/sensord_extension.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef ANDROID_DVR_SENSORD_EXTENSION_H_
-#define ANDROID_DVR_SENSORD_EXTENSION_H_
-
-namespace android {
-namespace dvr {
-
-// Allows sensord to be extended with additional code.
-class SensordExtension {
- public:
-  static void run();
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SENSORD_EXTENSION_H_
diff --git a/services/vr/sensord/test/poselatencytest.cpp b/services/vr/sensord/test/poselatencytest.cpp
deleted file mode 100644
index 615fc75..0000000
--- a/services/vr/sensord/test/poselatencytest.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include <dvr/pose_client.h>
-#include <inttypes.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <vector>
-
-// Creates a pose client and polls 30x for new data. Prints timestamp and
-// latency.  Latency is calculated based on the difference between the
-// current clock and the timestamp from the Myriad, which has been synced
-// to QC time. Note that there is some clock drift and clocks are only sycned
-// when the FW is loaded.
-int main(int /*argc*/, char** /*argv*/) {
-  DvrPose* pose_client = dvrPoseCreate();
-  if (pose_client == nullptr) {
-    printf("Unable to create pose client\n");
-    return -1;
-  }
-
-  DvrPoseAsync last_state;
-  DvrPoseAsync current_state;
-  last_state.timestamp_ns = 0;
-  current_state.timestamp_ns = 0;
-
-  double avg_latency = 0;
-  double min_latency = (float)UINT64_MAX;
-  double max_latency = 0;
-  double std = 0;
-  std::vector<uint64_t> latency;
-
-  int num_samples = 100;
-  for (int i = 0; i < num_samples; ++i) {
-    while (last_state.timestamp_ns == current_state.timestamp_ns) {
-      uint32_t vsync_count = dvrPoseGetVsyncCount(pose_client);
-      int err = dvrPoseGet(pose_client, vsync_count, &current_state);
-      if (err) {
-        printf("Error polling pose: %d\n", err);
-        dvrPoseDestroy(pose_client);
-        return err;
-      }
-    }
-    struct timespec timespec;
-    uint64_t timestamp, diff;
-    clock_gettime(CLOCK_MONOTONIC, &timespec);
-    timestamp =
-        ((uint64_t)timespec.tv_sec * 1000000000) + (uint64_t)timespec.tv_nsec;
-    if (timestamp < current_state.timestamp_ns) {
-      printf("ERROR: excessive clock drift detected, reload FW to resync\n");
-      return -1;
-    }
-    diff = timestamp - current_state.timestamp_ns;
-    printf("%02d) ts = %" PRIu64 " time = %" PRIu64 "\n", i + 1,
-           current_state.timestamp_ns, timestamp);
-    printf("\tlatency: %" PRIu64 " ns (%" PRIu64 " us) (%" PRIu64 " ms)\n",
-           diff, diff / 1000, diff / 1000000);
-
-    avg_latency += diff;
-    if (diff < min_latency) {
-      min_latency = diff;
-    }
-    if (diff > max_latency) {
-      max_latency = diff;
-    }
-    latency.push_back(diff);
-
-    last_state = current_state;
-  }
-  avg_latency /= num_samples;
-  for (unsigned int i = 0; i < latency.size(); i++) {
-    std += pow(latency[i] - avg_latency, 2);
-  }
-  std /= latency.size();
-  std = sqrt(std);
-
-  printf("\n************************\n");
-  printf("Avg latency =  %lf ns (%lf us) (%lf ms)\n", avg_latency,
-         avg_latency / 1000, avg_latency / 1000000);
-  printf("Max latency =  %lf ns (%lf us) (%lf ms)\n", max_latency,
-         max_latency / 1000, max_latency / 1000000);
-  printf("Min latency =  %lf ns (%lf us) (%lf ms)\n", min_latency,
-         min_latency / 1000, min_latency / 1000000);
-  printf("Standard dev = %lf ns (%lf us) (%lf ms)\n", std, std / 1000,
-         std / 1000000);
-  printf("\n************************\n");
-  return 0;
-}
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index ee09d48..f0bdcd9 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -18,7 +18,7 @@
 // use it to look up device configuration, so it must be unique. Vendor and
 // product values must be 0 to indicate an internal device and prevent a
 // similar lookup that could conflict with a physical device.
-static const char* const kDeviceNameFormat = "vr virtual touchpad %d";
+static const char* const kDeviceNameFormat = "vr-virtual-touchpad-%d";
 static constexpr int16_t kDeviceBusType = BUS_VIRTUAL;
 static constexpr int16_t kDeviceVendor = 0;
 static constexpr int16_t kDeviceProduct = 0;
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index 24cfdf8..564bcd7 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -139,7 +139,7 @@
     SCOPED_TRACE(t);
     uidev = touchpad->injector[t].GetUiDev();
     String8 name;
-    name.appendFormat("vr virtual touchpad %d", t);
+    name.appendFormat("vr-virtual-touchpad-%d", t);
     EXPECT_EQ(name, uidev->name);
     for (int i = 0; i < ABS_CNT; ++i) {
       EXPECT_EQ(0, uidev->absmin[i]);
diff --git a/services/vr/vr_window_manager/Android.bp b/services/vr/vr_window_manager/Android.bp
deleted file mode 100644
index d7ddba1..0000000
--- a/services/vr/vr_window_manager/Android.bp
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-native_src = [
-    "application.cpp",
-    "controller_mesh.cpp",
-    "elbow_model.cpp",
-    "hwc_callback.cpp",
-    "reticle.cpp",
-    "shell_view.cpp",
-    "surface_flinger_view.cpp",
-    "texture.cpp",
-    "vr_window_manager.cpp",
-    "vr_window_manager_binder.cpp",
-    "aidl/android/service/vr/IVrWindowManager.aidl",
-    "display_view.cpp",
-]
-
-static_libs = [
-    "libdisplay",
-    "libbufferhub",
-    "libbufferhubqueue",
-    "libeds",
-    "libdvrgraphics",
-    "libdvrcommon",
-    "libhwcomposer-client",
-    "libvrsensor",
-    "libperformance",
-    "libpdx_default_transport",
-    "libcutils",
-    "libvr_hwc-binder",
-    "libvr_manager",
-    "libvirtualtouchpadclient",
-]
-
-shared_libs = [
-    "android.frameworks.vr.composer@1.0",
-    "android.hardware.graphics.composer@2.1",
-    "libbase",
-    "libbinder",
-    "libinput",
-    "libhardware",
-    "libhwbinder",
-    "libsync",
-    "libutils",
-    "libgui",
-    "libEGL",
-    "libGLESv2",
-    "libvulkan",
-    "libsync",
-    "libui",
-    "libhidlbase",
-    "libhidltransport",
-    "liblog",
-    "libvr_hwc-hal",
-]
-
-cc_binary {
-    srcs: native_src,
-    static_libs: static_libs,
-    shared_libs: shared_libs,
-    cflags: ["-DGL_GLEXT_PROTOTYPES", "-DEGL_EGLEXT_PROTOTYPES", "-DLOG_TAG=\"VrWindowManager\""],
-    host_ldlibs: ["-llog"],
-    name: "vr_wm",
-    tags: ["optional"],
-    init_rc: ["vr_wm.rc"],
-}
-
-cmd_src = [
-    "vr_wm_ctl.cpp",
-    "aidl/android/service/vr/IVrWindowManager.aidl",
-]
-
-staticLibs = ["libcutils"]
-
-sharedLibs = [
-    "libbase",
-    "libbinder",
-    "libutils",
-]
-
-cc_binary {
-    srcs: cmd_src,
-    static_libs: staticLibs,
-    shared_libs: sharedLibs,
-    cppflags: ["-std=c++11"],
-    cflags: ["-DLOG_TAG=\"vrwmctl\""],
-    host_ldlibs: ["-llog"],
-    name: "vr_wm_ctl",
-    tags: ["optional"],
-}
diff --git a/services/vr/vr_window_manager/aidl/android/service/vr/IVrWindowManager.aidl b/services/vr/vr_window_manager/aidl/android/service/vr/IVrWindowManager.aidl
deleted file mode 100644
index b16049f..0000000
--- a/services/vr/vr_window_manager/aidl/android/service/vr/IVrWindowManager.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * 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.
- */
-
-package android.service.vr;
-
-/** @hide */
-interface IVrWindowManager {
-    const String SERVICE_NAME = "vr_window_manager";
-    void connectController(in FileDescriptor fd) = 0;
-    void disconnectController() = 1;
-    void enterVrMode() = 2;
-    void exitVrMode() = 3;
-    void setDebugMode(int mode) = 4;
-    void set2DMode(int mode) = 5;
-    void setRotation(int angle) = 6;
-}
-
diff --git a/services/vr/vr_window_manager/application.cpp b/services/vr/vr_window_manager/application.cpp
deleted file mode 100644
index 8b4460a..0000000
--- a/services/vr/vr_window_manager/application.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-#include "application.h"
-
-#include <inttypes.h>
-#include <EGL/egl.h>
-#include <GLES3/gl3.h>
-#include <binder/IServiceManager.h>
-#include <dvr/graphics.h>
-#include <dvr/performance_client_api.h>
-#include <dvr/pose_client.h>
-#include <gui/ISurfaceComposer.h>
-#include <hardware/hwcomposer_defs.h>
-#include <log/log.h>
-#include <private/dvr/graphics/vr_gl_extensions.h>
-
-#include <vector>
-
-namespace android {
-namespace dvr {
-
-Application::Application() {
-  vr_mode_listener_ = new VrModeListener(this);
-}
-
-Application::~Application() {
-  sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
-      defaultServiceManager()->getService(String16("vrmanager")));
-  if (vrManagerService.get()) {
-    vrManagerService->unregisterPersistentVrStateListener(vr_mode_listener_);
-  }
-}
-
-int Application::Initialize() {
-  dvrSetCpuPartition(0, "/application/performance");
-
-  bool is_right_handed = true;  // TODO: retrieve setting from system
-  elbow_model_.Enable(ElbowModel::kDefaultNeckPosition, is_right_handed);
-  last_frame_time_ = std::chrono::system_clock::now();
-
-  sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
-      defaultServiceManager()->getService(String16("vrmanager")));
-  if (vrManagerService.get()) {
-    vrManagerService->registerPersistentVrStateListener(vr_mode_listener_);
-  }
-  return 0;
-}
-
-int Application::AllocateResources() {
-  int surface_width = 0, surface_height = 0;
-  DvrLensInfo lens_info = {};
-  GLuint texture_id = 0;
-  GLenum texture_target = 0;
-  std::vector<DvrSurfaceParameter> surface_params = {
-    DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &surface_width),
-    DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &surface_height),
-    DVR_SURFACE_PARAMETER_OUT(INTER_LENS_METERS, &lens_info.inter_lens_meters),
-    DVR_SURFACE_PARAMETER_OUT(LEFT_FOV_LRBT, &lens_info.left_fov),
-    DVR_SURFACE_PARAMETER_OUT(RIGHT_FOV_LRBT, &lens_info.right_fov),
-    DVR_SURFACE_PARAMETER_OUT(SURFACE_TEXTURE_TARGET_TYPE, &texture_target),
-    DVR_SURFACE_PARAMETER_OUT(SURFACE_TEXTURE_TARGET_ID, &texture_id),
-    DVR_SURFACE_PARAMETER_IN(VISIBLE, 0),
-    DVR_SURFACE_PARAMETER_IN(Z_ORDER, 1),
-    DVR_SURFACE_PARAMETER_IN(GEOMETRY, DVR_SURFACE_GEOMETRY_SINGLE),
-    DVR_SURFACE_PARAMETER_IN(ENABLE_LATE_LATCH, 0),
-    DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, 0),
-    DVR_SURFACE_PARAMETER_LIST_END,
-  };
-
-  int ret = dvrGraphicsContextCreate(surface_params.data(), &graphics_context_);
-  if (ret)
-    return ret;
-
-  GLuint fbo = 0;
-  GLuint depth_stencil_buffer = 0;
-  GLuint samples = 1;
-  glGenFramebuffers(1, &fbo);
-  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-  glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                       texture_target, texture_id, 0, samples);
-
-  glGenRenderbuffers(1, &depth_stencil_buffer);
-  glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_buffer);
-  glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
-                                   GL_DEPTH_COMPONENT24, surface_width,
-                                   surface_height);
-
-  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                            GL_RENDERBUFFER, depth_stencil_buffer);
-
-  ALOGI("Surface size=%dx%d", surface_width, surface_height);
-  pose_client_ = dvrPoseCreate();
-  if (!pose_client_)
-    return 1;
-
-  vec2i eye_size(surface_width / 2, surface_height);
-
-  eye_viewport_[0] = Range2i::FromSize(vec2i(0, 0), eye_size);
-  eye_viewport_[1] = Range2i::FromSize(vec2i(surface_width / 2, 0), eye_size);
-
-  eye_from_head_[0] = Eigen::Translation3f(
-      vec3(lens_info.inter_lens_meters * 0.5f, 0.0f, 0.0f));
-  eye_from_head_[1] = Eigen::Translation3f(
-      vec3(-lens_info.inter_lens_meters * 0.5f, 0.0f, 0.0f));
-
-  fov_[0] = FieldOfView(lens_info.left_fov[0], lens_info.left_fov[1],
-                        lens_info.left_fov[2], lens_info.left_fov[3]);
-  fov_[1] = FieldOfView(lens_info.right_fov[0], lens_info.right_fov[1],
-                        lens_info.right_fov[2], lens_info.right_fov[3]);
-
-  return 0;
-}
-
-void Application::DeallocateResources() {
-  if (graphics_context_)
-    dvrGraphicsContextDestroy(graphics_context_);
-  graphics_context_ = nullptr;
-
-  if (pose_client_)
-    dvrPoseDestroy(pose_client_);
-
-  initialized_ = false;
-}
-
-void Application::ProcessTasks(const std::vector<MainThreadTask>& tasks) {
-  for (auto task : tasks) {
-    switch (task) {
-      case MainThreadTask::EnableDebugMode:
-        if (!debug_mode_) {
-          debug_mode_ = true;
-          SetVisibility(debug_mode_);
-        }
-        break;
-      case MainThreadTask::DisableDebugMode:
-        if (debug_mode_) {
-          debug_mode_ = false;
-          SetVisibility(debug_mode_);
-        }
-        break;
-      case MainThreadTask::EnteringVrMode:
-        if (!initialized_) {
-          LOG_ALWAYS_FATAL_IF(AllocateResources(),
-                              "Failed to allocate resources");
-        }
-        break;
-      case MainThreadTask::ExitingVrMode:
-        if (initialized_)
-          DeallocateResources();
-        break;
-      case MainThreadTask::Show:
-        if (!is_visible_)
-          SetVisibility(true);
-        break;
-    }
-  }
-}
-
-void Application::DrawFrame() {
-  // Thread should block if we are invisible or not fully initialized.
-  std::unique_lock<std::mutex> lock(mutex_);
-  wake_up_init_and_render_.wait(lock, [this]() {
-    return (is_visible_ && initialized_) || !main_thread_tasks_.empty();
-  });
-
-  // Process main thread tasks if there are any.
-  std::vector<MainThreadTask> tasks;
-  tasks.swap(main_thread_tasks_);
-  lock.unlock();
-
-  if (!tasks.empty())
-    ProcessTasks(tasks);
-
-  if (!initialized_)
-    return;
-
-  // TODO(steventhomas): If we're not visible, block until we are. For now we
-  // throttle by calling dvrGraphicsWaitNextFrame.
-  DvrFrameSchedule schedule;
-  int status = dvrGraphicsWaitNextFrame(graphics_context_, 0, &schedule);
-  if (status < 0) {
-    ALOGE("Context lost, deallocating graphics resources");
-    SetVisibility(false);
-    DeallocateResources();
-  }
-
-  OnDrawFrame();
-
-  if (is_visible_) {
-    ProcessControllerInput();
-
-    DvrPoseAsync pose;
-    dvrPoseGet(pose_client_, schedule.vsync_count, &pose);
-    last_pose_ = Posef(
-        quat(pose.orientation[3], pose.orientation[0], pose.orientation[1],
-             pose.orientation[2]),
-        vec3(pose.translation[0], pose.translation[1], pose.translation[2]));
-
-    std::chrono::time_point<std::chrono::system_clock> now =
-        std::chrono::system_clock::now();
-    double delta =
-        std::chrono::duration<double>(now - last_frame_time_).count();
-    last_frame_time_ = now;
-
-    if (delta > 1.0f)
-      delta = 0.05f;
-
-    fade_value_ += delta / 0.25f;
-    if (fade_value_ > 1.0f)
-      fade_value_ = 1.0f;
-
-    controller_position_ =
-        elbow_model_.Update(delta, last_pose_.GetRotation(),
-                            controller_orientation_, should_recenter_);
-
-    dvrBeginRenderFrameEds(graphics_context_, pose.orientation,
-                           pose.translation);
-
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-    mat4 head_matrix = last_pose_.GetObjectFromReferenceMatrix();
-    glViewport(eye_viewport_[kLeftEye].GetMinPoint()[0],
-               eye_viewport_[kLeftEye].GetMinPoint()[1],
-               eye_viewport_[kLeftEye].GetSize()[0],
-               eye_viewport_[kLeftEye].GetSize()[1]);
-    DrawEye(kLeftEye, fov_[kLeftEye].GetProjectionMatrix(0.1f, 500.0f),
-            eye_from_head_[kLeftEye], head_matrix);
-
-    glViewport(eye_viewport_[kRightEye].GetMinPoint()[0],
-               eye_viewport_[kRightEye].GetMinPoint()[1],
-               eye_viewport_[kRightEye].GetSize()[0],
-               eye_viewport_[kRightEye].GetSize()[1]);
-    DrawEye(kRightEye, fov_[kRightEye].GetProjectionMatrix(0.1f, 500.0f),
-            eye_from_head_[kRightEye], head_matrix);
-
-    OnEndFrame();
-
-    dvrPresent(graphics_context_);
-    should_recenter_ = false;
-  }
-}
-
-void Application::ProcessControllerInput() {
-  if (controller_data_provider_) {
-    shmem_controller_active_ = false;
-    const void* data = controller_data_provider_->LockControllerData();
-    // TODO(kpschoedel): define wire format.
-    if (data) {
-      struct wire_format {
-        uint32_t version;
-        uint32_t timestamph;
-        uint32_t timestampl;
-        uint32_t quat_count;
-        float q[4];
-        uint32_t buttonsh;
-        uint32_t buttonsl;
-      } __attribute__((__aligned__(32)));
-      const wire_format* wire_data = static_cast<const wire_format*>(data);
-      static uint64_t last_timestamp = 0;
-      if (wire_data->version == 1) {
-        shmem_controller_active_ = true;
-        uint64_t timestamp =
-            (((uint64_t)wire_data->timestamph) << 32) | wire_data->timestampl;
-        if (timestamp == last_timestamp) {
-          static uint64_t last_logged_timestamp = 0;
-          if (last_logged_timestamp != last_timestamp) {
-            last_logged_timestamp = last_timestamp;
-            ALOGI("Controller shmem stale T=0x%" PRIX64, last_timestamp);
-          }
-        } else {
-          last_timestamp = timestamp;
-          controller_orientation_ = quat(wire_data->q[3], wire_data->q[0],
-                                         wire_data->q[1], wire_data->q[2]);
-          shmem_controller_buttons_ =
-              (((uint64_t)wire_data->buttonsh) << 32) | wire_data->buttonsl;
-        }
-      } else if (wire_data->version == 0xFEEDFACE) {
-        static bool logged_init = false;
-        if (!logged_init) {
-          logged_init = true;
-          ALOGI("Controller shmem waiting for data");
-        }
-      }
-    }
-    controller_data_provider_->UnlockControllerData();
-    if (shmem_controller_active_) {
-      ALOGV("Controller shmem orientation: %f %f %f %f",
-            controller_orientation_.x(), controller_orientation_.y(),
-            controller_orientation_.z(), controller_orientation_.w());
-      if (shmem_controller_buttons_) {
-        ALOGV("Controller shmem buttons: %017" PRIX64,
-            shmem_controller_buttons_);
-      }
-    }
-  }
-}
-
-void Application::SetVisibility(bool visible) {
-  if (visible && !initialized_) {
-    if (AllocateResources())
-      ALOGE("Failed to allocate resources");
-  }
-
-  bool changed = is_visible_ != visible;
-  if (changed) {
-    is_visible_ = visible;
-    dvrGraphicsSurfaceSetVisible(graphics_context_, is_visible_);
-    OnVisibilityChanged(is_visible_);
-  }
-}
-
-void Application::OnVisibilityChanged(bool visible) {
-  if (visible) {
-    fade_value_ = 0;
-    // We have been sleeping so to ensure correct deltas, reset the time.
-    last_frame_time_ = std::chrono::system_clock::now();
-  }
-}
-
-void Application::QueueTask(MainThreadTask task) {
-  std::unique_lock<std::mutex> lock(mutex_);
-  main_thread_tasks_.push_back(task);
-  wake_up_init_and_render_.notify_one();
-}
-
-void Application::VrModeListener::onPersistentVrStateChanged(bool enabled) {
-  if (!enabled)
-    app_->QueueTask(MainThreadTask::ExitingVrMode);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/application.h b/services/vr/vr_window_manager/application.h
deleted file mode 100644
index ed99157..0000000
--- a/services/vr/vr_window_manager/application.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_APPLICATION_H_
-#define VR_WINDOW_MANAGER_APPLICATION_H_
-
-#include <memory>
-#include <private/dvr/types.h>
-#include <stdint.h>
-#include <vr/vr_manager/vr_manager.h>
-
-#include <chrono>
-#include <mutex>
-#include <vector>
-
-#include "controller_data_provider.h"
-#include "elbow_model.h"
-
-struct DvrGraphicsContext;
-struct DvrPose;
-
-namespace android {
-namespace dvr {
-
-class Application {
- public:
-  Application();
-  virtual ~Application();
-
-  virtual int Initialize();
-
-  virtual int AllocateResources();
-  virtual void DeallocateResources();
-
-  void DrawFrame();
-
-  void SetControllerDataProvider(ControllerDataProvider* provider) {
-    controller_data_provider_ = provider;
-  }
-
- protected:
-  enum class MainThreadTask {
-    EnteringVrMode,
-    ExitingVrMode,
-    EnableDebugMode,
-    DisableDebugMode,
-    Show,
-  };
-
-  class VrModeListener : public BnPersistentVrStateCallbacks {
-   public:
-    VrModeListener(Application *app) : app_(app) {}
-    void onPersistentVrStateChanged(bool enabled) override;
-
-   private:
-    Application *app_;
-  };
-
-  sp<VrModeListener> vr_mode_listener_;
-  virtual void OnDrawFrame() = 0;
-  virtual void DrawEye(EyeType eye, const mat4& perspective,
-                       const mat4& eye_matrix, const mat4& head_matrix) = 0;
-  virtual void OnEndFrame() = 0;
-
-  void SetVisibility(bool visible);
-  virtual void OnVisibilityChanged(bool visible);
-
-  void ProcessControllerInput();
-
-  void ProcessTasks(const std::vector<MainThreadTask>& tasks);
-
-  void QueueTask(MainThreadTask task);
-
-  DvrGraphicsContext* graphics_context_ = nullptr;
-  DvrPose* pose_client_ = nullptr;
-
-  Range2i eye_viewport_[2];
-  mat4 eye_from_head_[2];
-  FieldOfView fov_[2];
-  Posef last_pose_;
-
-  quat controller_orientation_;
-  bool shmem_controller_active_ = false;
-  uint64_t shmem_controller_buttons_;
-
-  // Used to center the scene when the shell becomes visible.
-  bool should_recenter_ = true;
-
-  bool is_visible_ = false;
-  std::chrono::time_point<std::chrono::system_clock> visibility_button_press_;
-  bool debug_mode_ = false;
-
-  std::chrono::time_point<std::chrono::system_clock> last_frame_time_;
-  vec3 controller_position_;
-  ElbowModel elbow_model_;
-
-  float fade_value_ = 0;
-
-  std::mutex mutex_;
-  std::condition_variable wake_up_init_and_render_;
-  bool initialized_ = false;
-  std::vector<MainThreadTask> main_thread_tasks_;
-
-  // Controller data provider from shared memory buffer.
-  ControllerDataProvider* controller_data_provider_ = nullptr;
-
-  Application(const Application&) = delete;
-  void operator=(const Application&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_APPLICATION_H_
diff --git a/services/vr/vr_window_manager/controller_data_provider.h b/services/vr/vr_window_manager/controller_data_provider.h
deleted file mode 100644
index bc1450c..0000000
--- a/services/vr/vr_window_manager/controller_data_provider.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_CONTROLLER_DATA_PROVIDER_H_
-#define VR_WINDOW_MANAGER_CONTROLLER_DATA_PROVIDER_H_
-
-namespace android {
-namespace dvr {
-
-class ControllerDataProvider {
- public:
-  virtual ~ControllerDataProvider() {}
-  // Returns data pointer or nullptr. If pointer is valid, call to
-  // UnlockControllerData is required.
-  virtual const void* LockControllerData() = 0;
-  virtual void UnlockControllerData() = 0;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_CONTROLLER_DATA_PROVIDER_H_
\ No newline at end of file
diff --git a/services/vr/vr_window_manager/controller_mesh.cpp b/services/vr/vr_window_manager/controller_mesh.cpp
deleted file mode 100644
index c6095b1..0000000
--- a/services/vr/vr_window_manager/controller_mesh.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "controller_mesh.h"
-
-namespace android {
-namespace dvr {
-
-const int kNumControllerMeshVertices = 60;
-
-// Vertices in position.xyz, normal.xyz, uv.xy oder.
-// Generated from an .obj mesh.
-const float kControllerMeshVertices[] = {
-    0.002023,  0.001469,  -0.5, 0.809016,  0.587787,  0, 0,   0,
-    0.000773,  0.002378,  -0.5, 0.309004,  0.951061,  0, 0.1, 0,
-    0.000773,  0.002378,  0,    0.309004,  0.951061,  0, 0.1, 1,
-    0.002023,  0.001469,  -0.5, 0.809016,  0.587787,  0, 0,   0,
-    0.000773,  0.002378,  0,    0.309004,  0.951061,  0, 0.1, 1,
-    0.002023,  0.001469,  0,    0.809016,  0.587787,  0, 0,   1,
-    0.000773,  0.002378,  -0.5, 0.309004,  0.951061,  0, 0.1, 0,
-    -0.000773, 0.002378,  -0.5, -0.309004, 0.951061,  0, 0.2, 0,
-    -0.000773, 0.002378,  0,    -0.309004, 0.951061,  0, 0.2, 1,
-    0.000773,  0.002378,  -0.5, 0.309004,  0.951061,  0, 0.1, 0,
-    -0.000773, 0.002378,  0,    -0.309004, 0.951061,  0, 0.2, 1,
-    0.000773,  0.002378,  0,    0.309004,  0.951061,  0, 0.1, 1,
-    -0.000773, 0.002378,  -0.5, -0.309004, 0.951061,  0, 0.2, 0,
-    -0.002023, 0.001469,  -0.5, -0.809016, 0.587787,  0, 0.3, 0,
-    -0.002023, 0.001469,  0,    -0.809016, 0.587787,  0, 0.3, 1,
-    -0.000773, 0.002378,  -0.5, -0.309004, 0.951061,  0, 0.2, 0,
-    -0.002023, 0.001469,  0,    -0.809016, 0.587787,  0, 0.3, 1,
-    -0.000773, 0.002378,  0,    -0.309004, 0.951061,  0, 0.2, 1,
-    -0.002023, 0.001469,  -0.5, -0.809016, 0.587787,  0, 0.3, 0,
-    -0.0025,   0,         -0.5, -1,        -0,        0, 0.4, 0,
-    -0.0025,   0,         0,    -1,        -0,        0, 0.4, 1,
-    -0.002023, 0.001469,  -0.5, -0.809016, 0.587787,  0, 0.3, 0,
-    -0.0025,   0,         0,    -1,        -0,        0, 0.4, 1,
-    -0.002023, 0.001469,  0,    -0.809016, 0.587787,  0, 0.3, 1,
-    -0.0025,   0,         -0.5, -1,        -0,        0, 0.4, 0,
-    -0.002023, -0.001469, -0.5, -0.809016, -0.587787, 0, 0.5, 0,
-    -0.002023, -0.001469, 0,    -0.809016, -0.587787, 0, 0.5, 1,
-    -0.0025,   0,         -0.5, -1,        -0,        0, 0.4, 0,
-    -0.002023, -0.001469, 0,    -0.809016, -0.587787, 0, 0.5, 1,
-    -0.0025,   0,         0,    -1,        -0,        0, 0.4, 1,
-    -0.002023, -0.001469, -0.5, -0.809016, -0.587787, 0, 0.5, 0,
-    -0.000773, -0.002378, -0.5, -0.309004, -0.951061, 0, 0.6, 0,
-    -0.000773, -0.002378, 0,    -0.309004, -0.951061, 0, 0.6, 1,
-    -0.002023, -0.001469, -0.5, -0.809016, -0.587787, 0, 0.5, 0,
-    -0.000773, -0.002378, 0,    -0.309004, -0.951061, 0, 0.6, 1,
-    -0.002023, -0.001469, 0,    -0.809016, -0.587787, 0, 0.5, 1,
-    -0.000773, -0.002378, -0.5, -0.309004, -0.951061, 0, 0.6, 0,
-    0.000773,  -0.002378, -0.5, 0.309004,  -0.951061, 0, 0.7, 0,
-    0.000773,  -0.002378, 0,    0.309004,  -0.951061, 0, 0.7, 1,
-    -0.000773, -0.002378, -0.5, -0.309004, -0.951061, 0, 0.6, 0,
-    0.000773,  -0.002378, 0,    0.309004,  -0.951061, 0, 0.7, 1,
-    -0.000773, -0.002378, 0,    -0.309004, -0.951061, 0, 0.6, 1,
-    0.000773,  -0.002378, -0.5, 0.309004,  -0.951061, 0, 0.7, 0,
-    0.002023,  -0.001469, -0.5, 0.809016,  -0.587787, 0, 0.8, 0,
-    0.002023,  -0.001469, 0,    0.809016,  -0.587787, 0, 0.8, 1,
-    0.000773,  -0.002378, -0.5, 0.309004,  -0.951061, 0, 0.7, 0,
-    0.002023,  -0.001469, 0,    0.809016,  -0.587787, 0, 0.8, 1,
-    0.000773,  -0.002378, 0,    0.309004,  -0.951061, 0, 0.7, 1,
-    0.002023,  -0.001469, -0.5, 0.809016,  -0.587787, 0, 0.8, 0,
-    0.0025,    0,         -0.5, 1,         0,         0, 0.9, 0,
-    0.0025,    0,         0,    1,         0,         0, 0.9, 1,
-    0.002023,  -0.001469, -0.5, 0.809016,  -0.587787, 0, 0.8, 0,
-    0.0025,    0,         0,    1,         0,         0, 0.9, 1,
-    0.002023,  -0.001469, 0,    0.809016,  -0.587787, 0, 0.8, 1,
-    0.0025,    0,         -0.5, 1,         0,         0, 0.9, 0,
-    0.002023,  0.001469,  -0.5, 0.809016,  0.587787,  0, 1,   0,
-    0.002023,  0.001469,  0,    0.809016,  0.587787,  0, 1,   1,
-    0.0025,    0,         -0.5, 1,         0,         0, 0.9, 0,
-    0.002023,  0.001469,  0,    0.809016,  0.587787,  0, 1,   1,
-    0.0025,    0,         0,    1,         0,         0, 0.9, 1,
-
-};
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/controller_mesh.h b/services/vr/vr_window_manager/controller_mesh.h
deleted file mode 100644
index 88872c7..0000000
--- a/services/vr/vr_window_manager/controller_mesh.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_CONTROLLER_MESH_H_
-#define VR_WINDOW_MANAGER_CONTROLLER_MESH_H_
-
-namespace android {
-namespace dvr {
-
-extern const int kNumControllerMeshVertices;
-extern const float kControllerMeshVertices[];
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_CONTROLLER_MESH_H_
diff --git a/services/vr/vr_window_manager/display_view.cpp b/services/vr/vr_window_manager/display_view.cpp
deleted file mode 100644
index 88768a0..0000000
--- a/services/vr/vr_window_manager/display_view.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
-#include "display_view.h"
-
-#include "texture.h"
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-constexpr float kLayerScaleFactor = 3.0f;
-constexpr unsigned int kMaximumPendingFrames = 8;
-constexpr uint32_t kSystemId = 1000;
-
-// clang-format off
-const GLfloat kVertices[] = {
-  -1, -1, 0,
-   1, -1, 0,
-  -1, 1, 0,
-   1, 1, 0,
-};
-
-const GLfloat kTextureVertices[] = {
-  0, 1,
-  1, 1,
-  0, 0,
-  1, 0,
-};
-// clang-format on
-
-// Returns true if the given point is inside the given rect.
-bool IsInside(const vec2& pt, const vec2& tl, const vec2& br) {
-  return pt.x() >= tl.x() && pt.x() <= br.x() && pt.y() >= tl.y() &&
-         pt.y() <= br.y();
-}
-
-mat4 GetScalingMatrix(float width, float height) {
-  float xscale = 1, yscale = 1;
-  float ar = width / height;
-  if (ar > 1)
-    yscale = 1.0 / ar;
-  else
-    xscale = ar;
-
-  xscale *= kLayerScaleFactor;
-  yscale *= kLayerScaleFactor;
-
-  return mat4(Eigen::Scaling<float>(xscale, yscale, 1.0));
-}
-
-// Helper function that applies the crop transform to the texture layer and
-// positions (and scales) the texture layer in the appropriate location in the
-// display space.
-mat4 GetLayerTransform(const TextureLayer& texture_layer, float display_width,
-                       float display_height) {
-  // Map from vertex coordinates to [0, 1] coordinates:
-  //  1) Flip y since in vertex coordinates (-1, -1) is at the bottom left and
-  //     in texture coordinates (0, 0) is at the top left.
-  //  2) Translate by (1, 1) to map vertex coordinates to [0, 2] on x and y.
-  //  3) Scale by 1 / 2 to map coordinates to [0, 1] on x  and y.
-  mat4 unit_space(Eigen::AlignedScaling3f(0.5f, 0.5f, 1.0f) *
-                  Eigen::Translation3f(1.0f, 1.0f, 0.0f) *
-                  Eigen::AlignedScaling3f(1.0f, -1.0f, 1.0f));
-
-  mat4 texture_space(Eigen::AlignedScaling3f(
-      texture_layer.texture->width(), texture_layer.texture->height(), 1.0f));
-
-  // 1) Translate the layer to crop the left and top edge.
-  // 2) Scale the layer such that the cropped right and bottom edges map outside
-  //    the exture region.
-  float crop_width = texture_layer.crop.right - texture_layer.crop.left;
-  float crop_height = texture_layer.crop.bottom - texture_layer.crop.top;
-  mat4 texture_crop(Eigen::AlignedScaling3f(
-                        texture_layer.texture->width() / crop_width,
-                        texture_layer.texture->height() / crop_height, 1.0f) *
-                    Eigen::Translation3f(-texture_layer.crop.left,
-                                         -texture_layer.crop.top, 0.0f));
-
-  mat4 display_space(
-      Eigen::AlignedScaling3f(display_width, display_height, 1.0f));
-
-  // 1) Scale the texture to fit the display frame.
-  // 2) Translate the texture in the display frame location.
-  float display_frame_width =
-      texture_layer.display_frame.right - texture_layer.display_frame.left;
-  float display_frame_height =
-      texture_layer.display_frame.bottom - texture_layer.display_frame.top;
-  mat4 display_frame(
-      Eigen::Translation3f(texture_layer.display_frame.left,
-                           texture_layer.display_frame.top, 0.0f) *
-      Eigen::AlignedScaling3f(display_frame_width / display_width,
-                              display_frame_height / display_height, 1.0f));
-
-  mat4 layer_transform = unit_space.inverse() * display_space.inverse() *
-                         display_frame * display_space *
-                         texture_space.inverse() * texture_crop *
-                         texture_space * unit_space;
-  return layer_transform;
-}
-
-// Determine if ths frame should be shown or hidden.
-ViewMode CalculateVisibilityFromLayerConfig(const HwcCallback::Frame& frame,
-                                            uint32_t* appid) {
-  auto& layers = frame.layers();
-
-  size_t index;
-  // Skip all layers that we don't know about.
-  for (index = 0; index < layers.size(); index++) {
-    if (layers[index].type != 0xFFFFFFFF && layers[index].type != 0)
-      break;
-  }
-
-  if (index == layers.size())
-    return ViewMode::Hidden;
-
-  if (layers[index].type != 1) {
-    // We don't have a VR app layer? Abort.
-    return ViewMode::Hidden;
-  }
-
-  if (layers[index].appid != *appid) {
-    *appid = layers[index].appid;
-    return ViewMode::App;
-  }
-
-  // This is the VR app, ignore it.
-  index++;
-
-  // Now, find a dim layer if it exists.
-  // If it does, ignore any layers behind it for visibility determination.
-  for (size_t i = index; i < layers.size(); i++) {
-    if (layers[i].appid == HwcCallback::HwcLayer::kSurfaceFlingerLayer) {
-      index = i + 1;
-    }
-  }
-
-  // If any non-skipped layers exist now then we show, otherwise hide.
-  for (size_t i = index; i < layers.size(); i++) {
-    if (!layers[i].should_skip_layer())
-      return ViewMode::VR;
-  }
-
-  return ViewMode::Hidden;
-}
-
-}  // namespace
-
-DisplayView::DisplayView(uint32_t id, int touchpad_id)
-    : id_(id), touchpad_id_(touchpad_id) {
-  translate_ = Eigen::Translation3f(0, 0, -5.0f);
-  ime_translate_ = mat4(Eigen::Translation3f(0.0f, -0.5f, 0.25f));
-  ime_top_left_ = vec2(0, 0);
-  ime_size_ = vec2(0, 0);
-  rotation_ = mat4::Identity();
-}
-
-DisplayView::~DisplayView() {}
-
-void DisplayView::Recenter(const mat4& initial) {
-  initial_head_matrix_ =
-      initial * Eigen::AngleAxisf(M_PI * 0.5f, vec3::UnitZ());
-}
-
-void DisplayView::SetPrograms(ShaderProgram* program,
-                              ShaderProgram* overlay_program) {
-  program_ = program;
-  overlay_program_ = overlay_program;
-}
-
-void DisplayView::DrawEye(EyeType /* eye */, const mat4& perspective,
-                          const mat4& eye_matrix, const mat4& head_matrix,
-                          float fade_value) {
-  scale_ = GetScalingMatrix(size_.x(), size_.y());
-
-  DrawOverlays(perspective, eye_matrix, head_matrix, fade_value);
-}
-
-void DisplayView::AdvanceFrame() {
-  if (!pending_frames_.empty()) {
-    // Check if we should advance the frame.
-    auto& frame = pending_frames_.front();
-    if (frame.visibility == ViewMode::Hidden ||
-        frame.frame->Finish() == HwcCallback::FrameStatus::kFinished) {
-      current_frame_ = std::move(frame);
-      pending_frames_.pop_front();
-    }
-  }
-}
-
-void DisplayView::OnDrawFrame(SurfaceFlingerView* surface_flinger_view,
-                              bool debug_mode) {
-  textures_.clear();
-  has_ime_ = false;
-
-  if (!visible())
-    return;
-
-  surface_flinger_view->GetTextures(*current_frame_.frame.get(), &textures_,
-                                    &ime_texture_, debug_mode,
-                                    current_frame_.visibility == ViewMode::VR);
-  has_ime_ = ime_texture_.texture != nullptr;
-}
-
-base::unique_fd DisplayView::OnFrame(std::unique_ptr<HwcCallback::Frame> frame,
-                                     bool debug_mode, bool is_vr_active,
-                                     bool* showing) {
-  size_ = vec2(frame->display_width(), frame->display_height());
-  uint32_t app = current_vr_app_;
-  ViewMode visibility = CalculateVisibilityFromLayerConfig(*frame.get(), &app);
-
-  if (visibility == ViewMode::Hidden && debug_mode)
-    visibility = ViewMode::VR;
-
-  if (frame->layers().empty()) {
-    current_vr_app_ = 0;
-  } else if (visibility == ViewMode::App) {
-    // This is either a VR app switch or a 2D app launching.
-    // If we can have VR apps, update if it's 0.
-    if (!always_2d_ && is_vr_active && !use_2dmode_ && app != kSystemId) {
-      visibility = ViewMode::Hidden;
-      current_vr_app_ = app;
-    }
-  } else if ((use_2dmode_ || !is_vr_active) && app != 0 &&
-             visibility == ViewMode::Hidden) {
-    // This is the case for the VR app launching a 2D intent of itself on some
-    // display.
-    visibility = ViewMode::App;
-  } else if (!current_vr_app_) {
-    // The VR app is running.
-    current_vr_app_ = app;
-  }
-
-  pending_frames_.emplace_back(std::move(frame), visibility);
-
-  if (pending_frames_.size() > kMaximumPendingFrames) {
-    pending_frames_.pop_front();
-  }
-
-  if (visibility == ViewMode::Hidden &&
-      current_frame_.visibility == ViewMode::Hidden) {
-    // Consume all frames while hidden.
-    while (!pending_frames_.empty())
-      AdvanceFrame();
-  }
-
-  // If we are showing ourselves the main thread is not processing anything,
-  // so give it a kick.
-  if (visibility != ViewMode::Hidden &&
-      current_frame_.visibility == ViewMode::Hidden) {
-    *showing = true;
-  }
-
-  return base::unique_fd(dup(release_fence_.get()));
-}
-
-bool DisplayView::IsHit(const vec3& view_location, const vec3& view_direction,
-                        vec3* hit_location, vec2* hit_location_in_window_coord,
-                        bool test_ime) {
-  mat4 m = GetStandardTransform();
-  if (test_ime)
-    m = m * ime_translate_;
-  mat4 inverse = (m * scale_).inverse();
-  vec4 transformed_loc =
-      inverse * vec4(view_location[0], view_location[1], view_location[2], 1);
-  vec4 transformed_dir = inverse * vec4(view_direction[0], view_direction[1],
-                                        view_direction[2], 0);
-
-  if (transformed_dir.z() >= 0 || transformed_loc.z() <= 0)
-    return false;
-
-  float distance = -transformed_loc.z() / transformed_dir.z();
-  vec4 transformed_hit_loc = transformed_loc + transformed_dir * distance;
-  if (transformed_hit_loc.x() < -1 || transformed_hit_loc.x() > 1)
-    return false;
-  if (transformed_hit_loc.y() < -1 || transformed_hit_loc.y() > 1)
-    return false;
-
-  hit_location_in_window_coord->x() =
-      (1 + transformed_hit_loc.x()) / 2 * size_.x();
-  hit_location_in_window_coord->y() =
-      (1 - transformed_hit_loc.y()) / 2 * size_.y();
-
-  *hit_location = view_location + view_direction * distance;
-  return true;
-}
-
-void DisplayView::DrawOverlays(const mat4& perspective, const mat4& eye_matrix,
-                               const mat4& head_matrix, float fade_value) {
-  if (textures_.empty())
-    return;
-
-  program_->Use();
-  mat4 mvp = perspective * eye_matrix * head_matrix;
-  GLint view_projection_location =
-      glGetUniformLocation(program_->GetProgram(), "uViewProjection");
-  glUniformMatrix4fv(view_projection_location, 1, 0, mvp.data());
-
-  GLint alpha_location = glGetUniformLocation(program_->GetProgram(), "uAlpha");
-
-  GLint tex_location = glGetUniformLocation(program_->GetProgram(), "tex");
-  glUniform1i(tex_location, 0);
-  glActiveTexture(GL_TEXTURE0);
-
-  for (const auto& texture_layer : textures_) {
-    switch (texture_layer.blending) {
-      case HWC2_BLEND_MODE_PREMULTIPLIED:
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-        break;
-      case HWC2_BLEND_MODE_COVERAGE:
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-        break;
-      default:
-        break;
-    }
-
-    glUniform1f(alpha_location, fade_value * texture_layer.alpha);
-
-    glBindTexture(GL_TEXTURE_2D, texture_layer.texture->id());
-
-    mat4 layer_transform =
-        GetLayerTransform(texture_layer, size_.x(), size_.y());
-
-    mat4 transform = GetStandardTransform() * scale_ * layer_transform;
-    DrawWithTransform(transform, *program_);
-
-    glDisable(GL_BLEND);
-  }
-
-  if (has_ime_) {
-    ime_top_left_ = vec2(static_cast<float>(ime_texture_.display_frame.left),
-                         static_cast<float>(ime_texture_.display_frame.top));
-    ime_size_ = vec2(static_cast<float>(ime_texture_.display_frame.right -
-                                        ime_texture_.display_frame.left),
-                     static_cast<float>(ime_texture_.display_frame.bottom -
-                                        ime_texture_.display_frame.top));
-
-    DrawDimOverlay(mvp, textures_[0], ime_top_left_, ime_top_left_ + ime_size_);
-
-    DrawIme();
-  }
-}
-
-void DisplayView::UpdateReleaseFence() {
-  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  EGLSyncKHR sync =
-      eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
-  if (sync != EGL_NO_SYNC_KHR) {
-    // Need to flush in order to get the fence FD.
-    glFlush();
-    base::unique_fd fence(eglDupNativeFenceFDANDROID(display, sync));
-    eglDestroySyncKHR(display, sync);
-    release_fence_ = std::move(fence);
-  } else {
-    ALOGE("Failed to create sync fence");
-    release_fence_ = base::unique_fd();
-  }
-}
-
-mat4 DisplayView::GetStandardTransform() {
-  mat4 m = initial_head_matrix_ * rotation_ * translate_;
-  if (current_frame_.visibility == ViewMode::App)
-    m *= Eigen::AngleAxisf(M_PI * -0.5f, vec3::UnitZ());
-  return m;
-}
-
-void DisplayView::DrawIme() {
-  program_->Use();
-  glBindTexture(GL_TEXTURE_2D, ime_texture_.texture->id());
-
-  mat4 layer_transform = GetLayerTransform(ime_texture_, size_.x(), size_.y());
-
-  mat4 transform =
-      GetStandardTransform() * ime_translate_ * scale_ * layer_transform;
-
-  DrawWithTransform(transform, *program_);
-}
-
-void DisplayView::DrawDimOverlay(const mat4& mvp, const TextureLayer& layer,
-                                 const vec2& top_left,
-                                 const vec2& bottom_right) {
-  overlay_program_->Use();
-  glUniformMatrix4fv(
-      glGetUniformLocation(overlay_program_->GetProgram(), "uViewProjection"),
-      1, 0, mvp.data());
-  glUniform4f(glGetUniformLocation(overlay_program_->GetProgram(), "uCoords"),
-              top_left.x() / size_.x(), top_left.y() / size_.y(),
-              bottom_right.x() / size_.x(), bottom_right.y() / size_.y());
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  mat4 layer_transform = GetLayerTransform(layer, size_.x(), size_.y());
-
-  mat4 transform = GetStandardTransform() * scale_ * layer_transform;
-  DrawWithTransform(transform, *overlay_program_);
-  glDisable(GL_BLEND);
-}
-
-void DisplayView::DrawWithTransform(const mat4& transform,
-                                    const ShaderProgram& program) {
-  GLint transform_location =
-      glGetUniformLocation(program.GetProgram(), "uTransform");
-  glUniformMatrix4fv(transform_location, 1, 0, transform.data());
-
-  glEnableVertexAttribArray(0);
-  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, kVertices);
-  glEnableVertexAttribArray(1);
-  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, kTextureVertices);
-  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-}
-
-bool DisplayView::UpdateHitInfo(const vec3& view_location,
-                                const vec3& view_direction,
-                                vec3* hit_location) {
-  bool is_hit = false;
-  if (has_ime_) {
-    // This will set allow_input_ and hit_location_in_window_coord_.
-    is_hit = IsImeHit(view_location, view_direction, hit_location);
-  } else {
-    is_hit = IsHit(view_location, view_direction, hit_location,
-                   &hit_location_in_window_coord_, false);
-    allow_input_ = is_hit;
-  }
-  return is_hit;
-}
-
-bool DisplayView::IsImeHit(const vec3& view_location,
-                           const vec3& view_direction, vec3* hit_location) {
-  // First, check if the IME window is hit.
-  bool is_hit = IsHit(view_location, view_direction, hit_location,
-                      &hit_location_in_window_coord_, true);
-  if (is_hit) {
-    // If it is, check if the window coordinate is in the IME region;
-    // if so then we are done.
-    if (IsInside(hit_location_in_window_coord_, ime_top_left_,
-                 ime_top_left_ + ime_size_)) {
-      allow_input_ = true;
-      return true;
-    }
-  }
-
-  allow_input_ = false;
-  // Check if we have hit the main window.
-  is_hit = IsHit(view_location, view_direction, hit_location,
-                 &hit_location_in_window_coord_, false);
-  if (is_hit) {
-    // Only allow input if we are not hitting the region hidden by the IME.
-    // Allowing input here would cause clicks on the main window to actually
-    // be clicks on the IME.
-    if (!IsInside(hit_location_in_window_coord_, ime_top_left_,
-                  ime_top_left_ + ime_size_)) {
-      allow_input_ = true;
-    }
-  }
-  return is_hit;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/display_view.h b/services/vr/vr_window_manager/display_view.h
deleted file mode 100644
index ad624c6..0000000
--- a/services/vr/vr_window_manager/display_view.h
+++ /dev/null
@@ -1,119 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_DISPLAY_VIEW_H_
-#define VR_WINDOW_MANAGER_DISPLAY_VIEW_H_
-
-#include <private/dvr/graphics/mesh.h>
-#include <private/dvr/graphics/shader_program.h>
-
-#include "hwc_callback.h"
-#include "surface_flinger_view.h"
-
-namespace android {
-namespace dvr {
-
-enum class ViewMode {
-  Hidden,
-  VR,
-  App,
-};
-
-class DisplayView {
- public:
-  DisplayView(uint32_t id, int touchpad_id);
-  ~DisplayView();
-
-  // Calls to these 3 functions must be synchronized.
-  base::unique_fd OnFrame(std::unique_ptr<HwcCallback::Frame> frame,
-                          bool debug_mode, bool is_vr_active, bool* showing);
-  void AdvanceFrame();
-  void UpdateReleaseFence();
-
-  void OnDrawFrame(SurfaceFlingerView* surface_flinger_view, bool debug_mode);
-  void DrawEye(EyeType eye, const mat4& perspective, const mat4& eye_matrix,
-               const mat4& head_matrix, float fade_value);
-
-  void Recenter(const mat4& initial);
-
-  bool UpdateHitInfo(const vec3& view_location, const vec3& view_direction,
-                     vec3* hit_location);
-
-  void SetPrograms(ShaderProgram* program, ShaderProgram* overlay_program);
-
-  bool visible() const { return current_frame_.visibility != ViewMode::Hidden; }
-  bool allow_input() const { return allow_input_; }
-  const vec2& hit_location() const { return hit_location_in_window_coord_; }
-  uint32_t id() const { return id_; }
-  int touchpad_id() const { return touchpad_id_; }
-  vec2 size() const { return size_; }
-
-  void set_2dmode(bool mode) { use_2dmode_ = mode; }
-  void set_always_2d(bool mode) { always_2d_ = mode; }
-
-  void set_rotation(const mat4& rotation) { rotation_ = rotation; }
-
- private:
-  bool IsHit(const vec3& view_location, const vec3& view_direction,
-             vec3* hit_location, vec2* hit_location_in_window_coord,
-             bool test_ime);
-  bool IsImeHit(const vec3& view_location, const vec3& view_direction,
-                vec3* hit_location);
-  void DrawOverlays(const mat4& perspective, const mat4& eye_matrix,
-                    const mat4& head_matrix, float fade_value);
-  void DrawIme();
-  void DrawDimOverlay(const mat4& mvp, const TextureLayer& layer,
-                      const vec2& top_left, const vec2& bottom_right);
-  void DrawWithTransform(const mat4& transform, const ShaderProgram& program);
-
-  // This is the rotated, translated but unscaled transform to apply everywhere.
-  mat4 GetStandardTransform();
-
-  uint32_t id_;
-  int touchpad_id_;
-
-  uint32_t current_vr_app_;
-
-  ShaderProgram* program_;
-  ShaderProgram* overlay_program_;
-
-  mat4 initial_head_matrix_;
-  mat4 scale_;
-  mat4 translate_;
-  mat4 ime_translate_;
-  mat4 rotation_;
-  vec2 size_;
-
-  std::vector<TextureLayer> textures_;
-  TextureLayer ime_texture_;
-
-  bool allow_input_ = false;
-  vec2 hit_location_in_window_coord_;
-  vec2 ime_top_left_;
-  vec2 ime_size_;
-  bool has_ime_ = false;
-  bool use_2dmode_ = false;
-  bool always_2d_ = false;
-
-  struct PendingFrame {
-    PendingFrame() = default;
-    PendingFrame(std::unique_ptr<HwcCallback::Frame>&& frame,
-                 ViewMode visibility)
-        : frame(std::move(frame)), visibility(visibility) {}
-    PendingFrame(PendingFrame&& r)
-        : frame(std::move(r.frame)), visibility(r.visibility) {}
-
-    void operator=(PendingFrame&& r) {
-      frame.reset(r.frame.release());
-      visibility = r.visibility;
-    }
-
-    std::unique_ptr<HwcCallback::Frame> frame;
-    ViewMode visibility = ViewMode::Hidden;
-  };
-  std::deque<PendingFrame> pending_frames_;
-  PendingFrame current_frame_;
-  base::unique_fd release_fence_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_DISPLAY_VIEW_H_
diff --git a/services/vr/vr_window_manager/elbow_model.cpp b/services/vr/vr_window_manager/elbow_model.cpp
deleted file mode 100644
index 9543f17..0000000
--- a/services/vr/vr_window_manager/elbow_model.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#include "elbow_model.h"
-
-#include <log/log.h>
-
-namespace android {
-namespace dvr {
-namespace {
-
-const vec3 kControllerForearm(0.0f, 0.0f, -0.25f);
-const vec3 kControllerPosition(0.0f, 0.0f, -0.05f);
-const vec3 kLeftElbowPosition(-0.195f, -0.5f, 0.075f);
-const vec3 kLeftArmExtension(0.13f, 0.14f, -0.08f);
-const vec3 kRightElbowPosition(0.195f, -0.5f, 0.075f);
-const vec3 kRightArmExtension(-0.13f, 0.14f, -0.08f);
-constexpr float kElbowBendRatio = 0.4f;
-constexpr float kCosMaxExtensionAngle =
-    0.87f;  // Cos of 30 degrees (90-30 = 60)
-constexpr float kCosMinExtensionAngle = 0.12f;  // Cos of 83 degrees (90-83 = 7)
-constexpr float kYAxisExtensionFraction = 0.4f;
-constexpr float kMinRotationSpeed = 0.61f;  // 35 degrees in radians
-constexpr float kMinAngleDelta = 0.175f;    // 10 degrees in radians
-
-float clamp(float v, float min, float max) {
-  if (v < min)
-    return min;
-  if (v > max)
-    return max;
-  return v;
-}
-
-float NormalizeAngle(float angle) {
-  if (angle > M_PI)
-    angle = 2.0f * M_PI - angle;
-  return angle;
-}
-
-}  // namespace
-
-const vec3 ElbowModel::kDefaultNeckPosition = vec3(0, -0.075f, -0.080f);
-
-ElbowModel::ElbowModel() {}
-ElbowModel::~ElbowModel() {}
-
-void ElbowModel::Enable(const vec3& neck_position, bool right_handed) {
-  enabled_ = true;
-  neck_position_ = neck_position;
-
-  if (right_handed) {
-    elbow_position_ = kRightElbowPosition;
-    arm_extension_ = kRightArmExtension;
-  } else {
-    elbow_position_ = kLeftElbowPosition;
-    arm_extension_ = kLeftArmExtension;
-  }
-
-  ResetRoot();
-}
-
-void ElbowModel::Disable() { enabled_ = false; }
-
-vec3 ElbowModel::Update(float delta_t, const quat& hmd_orientation,
-                        const quat& controller_orientation, bool recenter) {
-  if (!enabled_)
-    return vec3::Zero();
-
-  float heading_rad = GetHeading(hmd_orientation);
-
-  quat y_rotation;
-  y_rotation = Eigen::AngleAxis<float>(heading_rad, vec3::UnitY());
-
-  // If the controller's angular velocity is above a certain amount, we can
-  // assume torso rotation and move the elbow joint relative to the
-  // camera orientation.
-  float angle_delta = last_controller_.angularDistance(controller_orientation);
-  float rot_speed = angle_delta / delta_t;
-
-  if (recenter) {
-    root_rot_ = y_rotation;
-  } else if (rot_speed > kMinRotationSpeed) {
-    root_rot_.slerp(angle_delta / kMinAngleDelta, y_rotation);
-  }
-
-  // Calculate angle (or really, cos thereof) between controller forward vector
-  // and Y axis to determine extension amount.
-  vec3 controller_forward_rotated = controller_orientation * -vec3::UnitZ();
-  float dot_y = controller_forward_rotated.y();
-  float amt_extension = clamp(dot_y - kCosMinExtensionAngle, 0, 1);
-
-  // Remove the root rotation from the orientation reading--we'll add it back in
-  // later.
-  quat controller_rot = root_rot_.inverse() * controller_orientation;
-  controller_forward_rotated = controller_rot * -vec3::UnitZ();
-  quat rot_xy;
-  rot_xy.setFromTwoVectors(-vec3::UnitZ(), controller_forward_rotated);
-
-  // Fixing polar singularity
-  float total_angle = NormalizeAngle(atan2f(rot_xy.norm(), rot_xy.w()) * 2.0f);
-  float lerp_amount = (1.0f - powf(total_angle / M_PI, 6.0f)) *
-                      (1.0f - (kElbowBendRatio +
-                               (1.0f - kElbowBendRatio) *
-                                   (amt_extension + kYAxisExtensionFraction)));
-
-  // Calculate the relative rotations of the elbow and wrist joints.
-  quat wrist_rot = quat::Identity();
-  wrist_rot.slerp(lerp_amount, rot_xy);
-  quat elbow_rot = wrist_rot.inverse() * rot_xy;
-
-  last_controller_ = controller_orientation;
-
-  vec3 position =
-      root_rot_ *
-      ((controller_root_offset_ + arm_extension_ * amt_extension) +
-       elbow_rot * (kControllerForearm + wrist_rot * kControllerPosition));
-
-  return position;
-}
-
-float ElbowModel::GetHeading(const quat& orientation) {
-  vec3 gaze = orientation * -vec3::UnitZ();
-
-  if (gaze.y() > 0.99)
-    gaze = orientation * -vec3::UnitY();
-  else if (gaze.y() < -0.99)
-    gaze = orientation * vec3::UnitY();
-
-  return atan2f(-gaze.x(), -gaze.z());
-}
-
-void ElbowModel::ResetRoot() {
-  controller_root_offset_ = elbow_position_ + neck_position_;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/elbow_model.h b/services/vr/vr_window_manager/elbow_model.h
deleted file mode 100644
index a6d5ca9..0000000
--- a/services/vr/vr_window_manager/elbow_model.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_ELBOW_MODEL_H_
-#define VR_WINDOW_MANAGER_ELBOW_MODEL_H_
-
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-class ElbowModel {
- public:
-  ElbowModel();
-  ~ElbowModel();
-
-  void Enable(const vec3& neck_position, bool right_handed);
-  void Disable();
-
-  vec3 Update(float delta_t, const quat& hmd_orientation,
-              const quat& controller_orientation, bool recenter);
-
-  static const vec3 kDefaultNeckPosition;
-
- private:
-  ElbowModel(const ElbowModel&) = delete;
-  void operator=(const ElbowModel&) = delete;
-
-  void ResetRoot();
-
-  float GetHeading(const quat& orientation);
-
-  bool enabled_ = false;
-
-  quat last_controller_ = quat::Identity();
-
-  quat root_rot_ = quat::Identity();
-
-  vec3 controller_root_offset_ = vec3::Zero();
-  vec3 elbow_position_ = vec3::Zero();
-  vec3 arm_extension_ = vec3::Zero();
-  vec3 neck_position_ = vec3::Zero();
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_ELBOW_MODEL_H_
diff --git a/services/vr/vr_window_manager/hwc_callback.cpp b/services/vr/vr_window_manager/hwc_callback.cpp
deleted file mode 100644
index 28e97ff..0000000
--- a/services/vr/vr_window_manager/hwc_callback.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "hwc_callback.h"
-
-#include <android-base/unique_fd.h>
-#include <log/log.h>
-#include <private/dvr/native_buffer.h>
-#include <sync/sync.h>
-#include <ui/GraphicBufferMapper.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-HwcCallback::FrameStatus GetFrameStatus(const HwcCallback::Frame& frame) {
-  for (const auto& layer : frame.layers()) {
-    // If there is no fence it means the buffer is already finished.
-    if (layer.fence->isValid()) {
-      status_t result = layer.fence->wait(0);
-      if (result != OK) {
-        if (result != -ETIME) {
-          ALOGE("fence wait on buffer fence failed. status=%d (%s).",
-                result, strerror(-result));
-          return HwcCallback::FrameStatus::kError;
-        }
-        return HwcCallback::FrameStatus::kUnfinished;
-      }
-    }
-  }
-
-  return HwcCallback::FrameStatus::kFinished;
-}
-
-}  // namespace
-
-void HwcCallback::HwcLayer::PrintLayer() {
-  ALOGI("appid=%d, type=%d, alpha=%.2f, cursor=%dx%d, color=%02X%02X%02X%02X, "
-      "crop=%.1f,%.1f,%.1f,%.1f, display=%d,%d,%d,%d, dataspace=%d, "
-      "transform=%d", appid, type, alpha, cursor_x, cursor_y, color.r, color.g,
-      color.b, color.a, crop.left, crop.top, crop.right, crop.bottom,
-      display_frame.left, display_frame.right, display_frame.top,
-      display_frame.bottom, dataspace, transform);
-}
-
-HwcCallback::HwcCallback(Client* client) : client_(client) {
-}
-
-HwcCallback::~HwcCallback() {
-}
-
-binder::Status HwcCallback::onNewFrame(
-    const ParcelableComposerFrame& parcelable_frame,
-    ParcelableUniqueFd* fence) {
-  ComposerView::Frame frame = parcelable_frame.frame();
-  std::vector<HwcLayer> hwc_frame(frame.layers.size());
-  for (size_t i = 0; i < frame.layers.size(); ++i) {
-    const ComposerView::ComposerLayer& layer = frame.layers[i];
-    hwc_frame[i] = HwcLayer{
-      .fence = layer.fence,
-      .buffer = layer.buffer,
-      .crop = layer.crop,
-      .display_frame = layer.display_frame,
-      .blending = static_cast<int32_t>(layer.blend_mode),
-      .appid = layer.app_id,
-      .type = static_cast<HwcLayer::LayerType>(layer.type),
-      .alpha = layer.alpha,
-      .cursor_x = layer.cursor_x,
-      .cursor_y = layer.cursor_y,
-      .color = layer.color,
-      .dataspace = layer.dataspace,
-      .transform = layer.transform,
-    };
-  }
-
-  fence->set_fence(client_->OnFrame(std::make_unique<Frame>(
-      std::move(hwc_frame), frame.display_id, frame.removed,
-      frame.display_width, frame.display_height)));
-  return binder::Status::ok();
-}
-
-HwcCallback::Frame::Frame(std::vector<HwcLayer>&& layers, uint32_t display_id,
-                          bool removed, int32_t display_width,
-                          int32_t display_height)
-    : display_id_(display_id),
-      removed_(removed),
-      display_width_(display_width),
-      display_height_(display_height),
-      layers_(std::move(layers)) {}
-
-HwcCallback::FrameStatus HwcCallback::Frame::Finish() {
-  if (status_ == FrameStatus::kUnfinished)
-    status_ = GetFrameStatus(*this);
-  return status_;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/hwc_callback.h b/services/vr/vr_window_manager/hwc_callback.h
deleted file mode 100644
index 259c4ac..0000000
--- a/services/vr/vr_window_manager/hwc_callback.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_HWC_CALLBACK_H_
-#define VR_WINDOW_MANAGER_HWC_CALLBACK_H_
-
-#include <android/dvr/BnVrComposerCallback.h>
-#include <android-base/unique_fd.h>
-#include <impl/vr_hwc.h>
-
-#include <deque>
-#include <functional>
-#include <mutex>
-#include <vector>
-
-namespace android {
-
-class Fence;
-class GraphicBuffer;
-
-namespace dvr {
-
-using Recti = ComposerView::ComposerLayer::Recti;
-using Rectf = ComposerView::ComposerLayer::Rectf;
-
-class HwcCallback : public BnVrComposerCallback {
- public:
-  struct HwcLayer {
-    enum LayerType : uint32_t {
-      // These are from frameworks/base/core/java/android/view/WindowManager.java
-      kSurfaceFlingerLayer = 0,
-      kUndefinedWindow = ~0U,
-      kFirstApplicationWindow = 1,
-      kLastApplicationWindow = 99,
-      kFirstSubWindow = 1000,
-      kLastSubWindow = 1999,
-      kFirstSystemWindow = 2000,
-      kStatusBar = kFirstSystemWindow,
-      kInputMethod = kFirstSystemWindow + 11,
-      kNavigationBar = kFirstSystemWindow + 19,
-      kLastSystemWindow = 2999,
-    };
-
-    bool should_skip_layer() const {
-      switch (type) {
-        // Always skip the following layer types
-      case kNavigationBar:
-      case kStatusBar:
-      case kSurfaceFlingerLayer:
-      case kUndefinedWindow:
-        return true;
-      default:
-        return false;
-      }
-    }
-
-    // This is a layer that provides some other functionality, eg dim layer.
-    // We use this to determine the point at which layers are "on top".
-    bool is_extra_layer() const {
-      switch(type) {
-      case kSurfaceFlingerLayer:
-      case kUndefinedWindow:
-        return true;
-      default:
-        return false;
-      }
-    }
-
-    void PrintLayer();
-
-    sp<Fence> fence;
-    sp<GraphicBuffer> buffer;
-    Rectf crop;
-    Recti display_frame;
-    int32_t blending;
-    uint32_t appid;
-    LayerType type;
-    float alpha;
-    int32_t cursor_x;
-    int32_t cursor_y;
-    IComposerClient::Color color;
-    int32_t dataspace;
-    int32_t transform;
-  };
-
-  enum class FrameStatus {
-    kUnfinished,
-    kFinished,
-    kError
-  };
-
-  class Frame {
-  public:
-    Frame(std::vector<HwcLayer>&& layers, uint32_t display_id, bool removed,
-          int32_t display_width, int32_t display_height);
-
-    FrameStatus Finish();
-    const std::vector<HwcLayer>& layers() const { return layers_; }
-    uint32_t display_id() const { return display_id_; }
-    bool removed() const { return removed_; }
-    int32_t display_width() const { return display_width_; }
-    int32_t display_height() const { return display_height_; }
-
-  private:
-    uint32_t display_id_;
-    bool removed_;
-    int32_t display_width_;
-    int32_t display_height_;
-    std::vector<HwcLayer> layers_;
-    FrameStatus status_ = FrameStatus::kUnfinished;
-  };
-
-  class Client {
-   public:
-    virtual ~Client() {}
-    virtual base::unique_fd OnFrame(std::unique_ptr<Frame>) = 0;
-  };
-
-  explicit HwcCallback(Client* client);
-  ~HwcCallback() override;
-
- private:
-  binder::Status onNewFrame(const ParcelableComposerFrame& frame,
-                            ParcelableUniqueFd* fence) override;
-
-  Client *client_;
-
-  HwcCallback(const HwcCallback&) = delete;
-  void operator=(const HwcCallback&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_HWC_CALLBACK_H_
diff --git a/services/vr/vr_window_manager/proguard.flags b/services/vr/vr_window_manager/proguard.flags
deleted file mode 100644
index 7683d6e..0000000
--- a/services/vr/vr_window_manager/proguard.flags
+++ /dev/null
@@ -1,22 +0,0 @@
-# Don't obfuscate any NDK/SDK code. This makes the debugging of stack traces in
-# in release builds easier.
--keepnames class com.google.vr.ndk.** { *; }
--keepnames class com.google.vr.sdk.** { *; }
-
-# These are part of the SDK <-> VrCore interfaces for GVR.
--keepnames class com.google.vr.vrcore.library.api.** { *; }
-
-# These are part of the Java <-> native interfaces for GVR.
--keep class com.google.vr.** { native <methods>; }
-
--keep class com.google.vr.cardboard.annotations.UsedByNative
--keep @com.google.vr.cardboard.annotations.UsedByNative class *
--keepclassmembers class * {
-    @com.google.vr.cardboard.annotations.UsedByNative *;
-}
-
--keep class com.google.vr.cardboard.UsedByNative
--keep @com.google.vr.cardboard.UsedByNative class *
--keepclassmembers class * {
-    @com.google.vr.cardboard.UsedByNative *;
-}
diff --git a/services/vr/vr_window_manager/reticle.cpp b/services/vr/vr_window_manager/reticle.cpp
deleted file mode 100644
index cbd0caf..0000000
--- a/services/vr/vr_window_manager/reticle.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "reticle.h"
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-const std::string kVertexShader = SHADER0([]() {
-  layout(location = 0) in vec4 aPosition;
-  layout(location = 1) in vec4 aTexCoord;
-  uniform mat4 uViewProjection;
-  uniform mat4 uTransform;
-
-  out vec2 vTexCoord;
-  void main() {
-    gl_Position = uViewProjection * uTransform * aPosition;
-    vTexCoord = aTexCoord.xy;
-  }
-});
-
-const std::string kFragmentShader = SHADER0([]() {
-  precision mediump float;
-
-  in vec2 vTexCoord;
-  uniform vec3 uColor;
-
-  out vec4 fragColor;
-  void main() {
-    float alpha = smoothstep(1.0, 0.0, length(vTexCoord));
-    fragColor = vec4(uColor, alpha);
-  }
-});
-
-}  // namespace
-
-Reticle::Reticle() {}
-
-Reticle::~Reticle() {}
-
-bool Reticle::Initialize() {
-  program_.Link(kVertexShader, kFragmentShader);
-  if (!program_)
-    return false;
-
-  return true;
-}
-
-void Reticle::ShowAt(const mat4& hit_transform, const vec3& color) {
-  transform_ = hit_transform;
-  shown_ = true;
-
-  GLint view_projection_location =
-      glGetUniformLocation(program_.GetProgram(), "uColor");
-  glProgramUniform3f(program_.GetProgram(), view_projection_location, color.x(),
-                     color.y(), color.z());
-}
-
-void Reticle::Draw(const mat4& perspective, const mat4& eye_matrix,
-                   const mat4& head_matrix) {
-  if (!shown_)
-    return;
-
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-  program_.Use();
-
-  const float kRadius = 0.015;
-  GLfloat vertices[] = {
-      -kRadius, -kRadius, 0, kRadius, -kRadius, 0,
-      -kRadius, kRadius,  0, kRadius, kRadius,  0,
-  };
-  GLfloat texture_vertices[] = {
-      -1, 1, 1, 1, -1, -1, 1, -1,
-  };
-
-  mat4 mvp = perspective * eye_matrix * head_matrix;
-  GLint view_projection_location =
-      glGetUniformLocation(program_.GetProgram(), "uViewProjection");
-  glUniformMatrix4fv(view_projection_location, 1, 0, mvp.data());
-
-  GLint transform_location =
-      glGetUniformLocation(program_.GetProgram(), "uTransform");
-  glUniformMatrix4fv(transform_location, 1, 0, transform_.data());
-
-  glEnableVertexAttribArray(0);
-  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
-  glEnableVertexAttribArray(1);
-  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texture_vertices);
-
-  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
-  glDisable(GL_BLEND);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/reticle.h b/services/vr/vr_window_manager/reticle.h
deleted file mode 100644
index d8522aa..0000000
--- a/services/vr/vr_window_manager/reticle.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_SHELL_RETICLE_H_
-#define VR_WINDOW_MANAGER_SHELL_RETICLE_H_
-
-#include <private/dvr/graphics/shader_program.h>
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-class Reticle {
- public:
-  Reticle();
-  ~Reticle();
-
-  bool Initialize();
-
-  void ShowAt(const mat4& hit_transform, const vec3& color);
-  void Hide() { shown_ = false; }
-
-  void Draw(const mat4& perspective, const mat4& eye_matrix,
-            const mat4& head_matrix);
-
- private:
-  bool shown_ = false;
-  ShaderProgram program_;
-  mat4 transform_;
-
-  Reticle(const Reticle&) = delete;
-  void operator=(const Reticle&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_SHELL_RETICLE_H_
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
deleted file mode 100644
index abd0651..0000000
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ /dev/null
@@ -1,535 +0,0 @@
-#include "shell_view.h"
-
-#include <EGL/eglext.h>
-#include <GLES3/gl3.h>
-#include <android/input.h>
-#include <binder/IServiceManager.h>
-#include <dvr/graphics.h>
-#include <hardware/hwcomposer2.h>
-#include <inttypes.h>
-#include <log/log.h>
-
-#include "controller_mesh.h"
-#include "texture.h"
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-constexpr uint32_t kPrimaryDisplayId = 1;
-
-const std::string kVertexShader = SHADER0([]() {
-  layout(location = 0) in vec4 aPosition;
-  layout(location = 1) in vec4 aTexCoord;
-  uniform mat4 uViewProjection;
-  uniform mat4 uTransform;
-
-  out vec2 vTexCoord;
-  void main() {
-    gl_Position = uViewProjection * uTransform * aPosition;
-    vTexCoord = aTexCoord.xy;
-  }
-});
-
-const std::string kFragmentShader = SHADER0([]() {
-  precision mediump float;
-
-  in vec2 vTexCoord;
-  uniform sampler2D tex;
-  uniform float uAlpha;
-
-  out vec4 fragColor;
-  void main() {
-    fragColor = texture(tex, vTexCoord);
-    fragColor.a *= uAlpha;
-  }
-});
-
-// This shader provides a dim layer in a given rect. This is intended
-// to indicate the non-interactive region.
-// Texture coordinates between [uCoords.xy, uCoords.zw] are dim, otherwise
-// transparent.
-const std::string kOverlayFragmentShader = SHADER0([]() {
-  precision highp float;
-
-  in vec2 vTexCoord;
-  uniform sampler2D tex;
-  uniform vec4 uCoords;
-
-  out vec4 fragColor;
-  void main() {
-    vec4 color = vec4(0, 0, 0, 0);
-    if (all(greaterThan(vTexCoord, uCoords.xy)) &&
-        all(lessThan(vTexCoord, uCoords.zw))) {
-      color = vec4(0, 0, 0, 0.5);
-    }
-    fragColor = color;
-  }
-});
-
-const std::string kControllerFragmentShader = SHADER0([]() {
-  precision mediump float;
-
-  in vec2 vTexCoord;
-
-  out vec4 fragColor;
-  void main() { fragColor = vec4(0.8, 0.2, 0.2, 1.0); }
-});
-
-mat4 GetHorizontallyAlignedMatrixFromPose(const Posef& pose) {
-  vec3 position = pose.GetPosition();
-  quat view_quaternion = pose.GetRotation();
-
-  vec3 z = vec3(view_quaternion * vec3(0.0f, 0.0f, 1.0f));
-  vec3 y(0.0f, 1.0f, 0.0f);
-  vec3 x = y.cross(z);
-  x.normalize();
-  y = z.cross(x);
-
-  mat4 m;
-  // clang-format off
-  m(0, 0) = x[0]; m(0, 1) = y[0]; m(0, 2) = z[0]; m(0, 3) = position[0];
-  m(1, 0) = x[1]; m(1, 1) = y[1]; m(1, 2) = z[1]; m(1, 3) = position[1];
-  m(2, 0) = x[2]; m(2, 1) = y[2]; m(2, 2) = z[2]; m(2, 3) = position[2];
-  m(3, 0) = 0.0f; m(3, 1) = 0.0f; m(3, 2) = 0.0f; m(3, 3) = 1.0f;
-  // clang-format on
-
-  return m;
-}
-
-int GetTouchIdForDisplay(uint32_t display) {
-  return display == kPrimaryDisplayId ? DVR_VIRTUAL_TOUCHPAD_PRIMARY
-                                      : DVR_VIRTUAL_TOUCHPAD_VIRTUAL;
-}
-
-}  // namespace
-
-ShellView::ShellView() {}
-
-ShellView::~ShellView() {}
-
-int ShellView::Initialize() {
-  int ret = Application::Initialize();
-  if (ret)
-    return ret;
-
-  virtual_touchpad_.reset(dvrVirtualTouchpadCreate());
-  const status_t touchpad_status =
-      dvrVirtualTouchpadAttach(virtual_touchpad_.get());
-  if (touchpad_status != OK) {
-    ALOGE("Failed to connect to virtual touchpad");
-    return touchpad_status;
-  }
-
-  surface_flinger_view_.reset(new SurfaceFlingerView);
-  if (!surface_flinger_view_->Initialize(this))
-    return 1;
-
-  return 0;
-}
-
-int ShellView::AllocateResources() {
-  int ret = Application::AllocateResources();
-  if (ret)
-    return ret;
-
-  program_.reset(new ShaderProgram);
-  program_->Link(kVertexShader, kFragmentShader);
-  overlay_program_.reset(new ShaderProgram);
-  overlay_program_->Link(kVertexShader, kOverlayFragmentShader);
-  controller_program_.reset(new ShaderProgram);
-  controller_program_->Link(kVertexShader, kControllerFragmentShader);
-  if (!program_ || !overlay_program_ || !controller_program_)
-    return 1;
-
-  reticle_.reset(new Reticle());
-  if (!reticle_->Initialize())
-    return 1;
-
-  controller_mesh_.reset(new Mesh<vec3, vec3, vec2>());
-  controller_mesh_->SetVertices(kNumControllerMeshVertices,
-                                kControllerMeshVertices);
-
-  for (auto& display : displays_)
-    display->SetPrograms(program_.get(), overlay_program_.get());
-
-  initialized_ = true;
-
-  return 0;
-}
-
-void ShellView::DeallocateResources() {
-  {
-    std::unique_lock<std::mutex> l(display_frame_mutex_);
-    removed_displays_.clear();
-    new_displays_.clear();
-    displays_.clear();
-  }
-
-  display_client_.reset();
-  reticle_.reset();
-  controller_mesh_.reset();
-  program_.reset(new ShaderProgram);
-  overlay_program_.reset(new ShaderProgram);
-  controller_program_.reset(new ShaderProgram);
-  Application::DeallocateResources();
-}
-
-void ShellView::EnableDebug(bool debug) {
-  QueueTask(debug ? MainThreadTask::EnableDebugMode
-                  : MainThreadTask::DisableDebugMode);
-}
-
-void ShellView::VrMode(bool mode) {
-  QueueTask(mode ? MainThreadTask::EnteringVrMode
-                 : MainThreadTask::ExitingVrMode);
-}
-
-void ShellView::dumpInternal(String8& result) {
-  result.append("[shell]\n");
-  result.appendFormat("initialized = %s\n", initialized_ ? "true" : "false");
-  result.appendFormat("is_visible = %s\n", is_visible_ ? "true" : "false");
-  result.appendFormat("debug_mode = %s\n\n", debug_mode_ ? "true" : "false");
-
-  result.append("[displays]\n");
-  result.appendFormat("count = %zu\n", displays_.size());
-  for (size_t i = 0; i < displays_.size(); ++i) {
-    result.appendFormat("  display_id = %" PRId32 "\n", displays_[i]->id());
-    result.appendFormat("    size=%fx%f\n", displays_[i]->size().x(),
-                        displays_[i]->size().y());
-  }
-
-  result.append("\n");
-}
-
-void ShellView::Set2DMode(bool mode) {
-  if (!displays_.empty())
-    displays_[0]->set_2dmode(mode);
-}
-
-void ShellView::SetRotation(int angle) {
-  mat4 m(Eigen::AngleAxisf(M_PI * -0.5f * angle, vec3::UnitZ()));
-  for (auto& d : displays_)
-    d->set_rotation(m);
-}
-
-void ShellView::OnDrawFrame() {
-  bool visible = false;
-
-  {
-    std::unique_lock<std::mutex> l(display_frame_mutex_);
-
-    // Move any new displays into the list.
-    if (!new_displays_.empty()) {
-      for (auto& display : new_displays_) {
-        display->Recenter(GetHorizontallyAlignedMatrixFromPose(last_pose_));
-        display->SetPrograms(program_.get(), overlay_program_.get());
-        displays_.emplace_back(display.release());
-      }
-      new_displays_.clear();
-    }
-
-    // Remove any old displays from the list now.
-    if (!removed_displays_.empty()) {
-      for (auto& display : removed_displays_) {
-        displays_.erase(std::find_if(
-            displays_.begin(), displays_.end(),
-            [display](auto& ptr) { return display == ptr.get(); }));
-      }
-      removed_displays_.clear();
-    }
-
-    for (auto& display : displays_) {
-      display->AdvanceFrame();
-      visible = visible || display->visible();
-    }
-  }
-
-  if (!debug_mode_ && visible != is_visible_) {
-    SetVisibility(visible);
-  }
-
-  for (auto& display : displays_) {
-    display->OnDrawFrame(surface_flinger_view_.get(), debug_mode_);
-  }
-}
-
-void ShellView::OnEndFrame() {
-  std::unique_lock<std::mutex> l(display_frame_mutex_);
-  for (auto& display : displays_) {
-    display->UpdateReleaseFence();
-  }
-}
-
-DisplayView* ShellView::FindOrCreateDisplay(uint32_t id) {
-  for (auto& display : displays_) {
-    if (display->id() == id) {
-      return display.get();
-    }
-  }
-
-  // It might be pending addition.
-  for (auto& display : new_displays_) {
-    if (display->id() == id) {
-      return display.get();
-    }
-  }
-
-  auto display = new DisplayView(id, GetTouchIdForDisplay(id));
-  // Virtual displays only ever have 2D apps so force it.
-  if (id != kPrimaryDisplayId)
-    display->set_always_2d(true);
-  new_displays_.emplace_back(display);
-  return display;
-}
-
-base::unique_fd ShellView::OnFrame(std::unique_ptr<HwcCallback::Frame> frame) {
-  std::unique_lock<std::mutex> l(display_frame_mutex_);
-  DisplayView* display = FindOrCreateDisplay(frame->display_id());
-
-  if (frame->removed()) {
-    removed_displays_.push_back(display);
-    return base::unique_fd();
-  }
-
-  bool showing = false;
-
-  // This is a temporary fix for now. These APIs will be changed when everything
-  // is moved into vrcore.
-  // Do this on demand in case vr_flinger crashed and we are reconnecting.
-  if (!display_client_.get()) {
-    int error = 0;
-    display_client_ = display::DisplayClient::Create(&error);
-
-    if (error) {
-      ALOGE("Could not connect to display service : %s(%d)", strerror(error),
-            error);
-      return base::unique_fd();
-    }
-  }
-
-  // TODO(achaulk): change when moved into vrcore.
-  auto status = display_client_->IsVrAppRunning();
-  if (!status) {
-    ALOGE("Failed to check VR running status: %s",
-          status.GetErrorMessage().c_str());
-    return base::unique_fd();
-  }
-  const bool vr_running = status.get();
-
-  base::unique_fd fd(
-      display->OnFrame(std::move(frame), debug_mode_, vr_running, &showing));
-
-  if (showing)
-    QueueTask(MainThreadTask::Show);
-
-  return fd;
-}
-
-void ShellView::DrawEye(EyeType eye, const mat4& perspective,
-                        const mat4& eye_matrix, const mat4& head_matrix) {
-  if (should_recenter_ && !displays_.empty()) {
-    // Position the quad horizontally aligned in the direction the user
-    // is facing, effectively taking out head roll.
-    displays_[0]->Recenter(GetHorizontallyAlignedMatrixFromPose(last_pose_));
-  }
-
-  for (auto& display : displays_) {
-    if (display->visible()) {
-      display->DrawEye(eye, perspective, eye_matrix, head_matrix, fade_value_);
-    }
-  }
-
-  // TODO(alexst): Replicate controller rendering from VR Home.
-  // Current approach in the function below is a quick visualization.
-  DrawController(perspective, eye_matrix, head_matrix);
-
-  DrawReticle(perspective, eye_matrix, head_matrix);
-}
-
-void ShellView::OnVisibilityChanged(bool visible) {
-  should_recenter_ = visible;
-  Application::OnVisibilityChanged(visible);
-}
-
-bool ShellView::OnClick(bool down) {
-  if (down) {
-    if (!is_touching_ && active_display_ && active_display_->allow_input()) {
-      is_touching_ = true;
-    }
-  } else {
-    is_touching_ = false;
-  }
-  Touch();
-  return true;
-}
-
-void ShellView::DrawReticle(const mat4& perspective, const mat4& eye_matrix,
-                            const mat4& head_matrix) {
-  reticle_->Hide();
-
-  vec3 pointer_location = last_pose_.GetPosition();
-  quat view_quaternion = last_pose_.GetRotation();
-
-  if (shmem_controller_active_) {
-    view_quaternion = controller_orientation_;
-    vec4 controller_location = controller_translate_ * vec4(0, 0, 0, 1);
-    pointer_location = vec3(controller_location.x(), controller_location.y(),
-                            controller_location.z());
-
-    if (shmem_controller_active_) {
-      uint64_t buttons = shmem_controller_buttons_;
-      shmem_controller_buttons_ = 0;
-      while (buttons) {
-        switch (buttons & 0xF) {
-          case 0x1:
-            OnClick(false);
-            break;
-          case 0x3:
-            OnTouchpadButton(false, AMOTION_EVENT_BUTTON_BACK);
-            break;
-          case 0x4:
-            should_recenter_ = true;
-            break;
-          case 0x9:
-            OnClick(true);
-            break;
-          case 0xB:
-            OnTouchpadButton(true, AMOTION_EVENT_BUTTON_BACK);
-            break;
-          default:
-            break;
-        }
-        buttons >>= 4;
-      }
-    }
-  }
-
-  vec3 hit_location;
-  active_display_ =
-      FindActiveDisplay(pointer_location, view_quaternion, &hit_location);
-
-  if (active_display_) {
-    reticle_->ShowAt(
-        Eigen::Translation3f(hit_location) * view_quaternion.matrix(),
-        active_display_->allow_input() ? vec3(1, 0, 0) : vec3(0, 0, 0));
-    Touch();
-  }
-
-  reticle_->Draw(perspective, eye_matrix, head_matrix);
-}
-
-DisplayView* ShellView::FindActiveDisplay(const vec3& position,
-                                          const quat& quaternion,
-                                          vec3* hit_location) {
-  vec3 direction = vec3(quaternion * vec3(0, 0, -1));
-  vec3 temp_hit;
-
-  DisplayView* best_display = nullptr;
-  vec3 best_hit;
-
-  auto is_better = [&best_hit, &position](DisplayView*, const vec3& hit) {
-    return (hit - position).squaredNorm() < (best_hit - position).squaredNorm();
-  };
-
-  for (auto& display : displays_) {
-    if (display->UpdateHitInfo(position, direction, &temp_hit)) {
-      if (!best_display || is_better(display.get(), temp_hit)) {
-        best_display = display.get();
-        best_hit = temp_hit;
-      }
-    }
-  }
-
-  if (best_display)
-    *hit_location = best_hit;
-  return best_display;
-}
-
-void ShellView::DrawController(const mat4& perspective, const mat4& eye_matrix,
-                               const mat4& head_matrix) {
-  if (!shmem_controller_active_)
-    return;
-
-  controller_program_->Use();
-  mat4 mvp = perspective * eye_matrix * head_matrix;
-
-  GLint view_projection_location = glGetUniformLocation(
-      controller_program_->GetProgram(), "uViewProjection");
-  glUniformMatrix4fv(view_projection_location, 1, 0, mvp.data());
-
-  quat view_quaternion = controller_orientation_;
-  view_quaternion.toRotationMatrix();
-
-  vec3 world_pos = last_pose_.GetPosition() + controller_position_;
-
-  controller_translate_ =
-      Eigen::Translation3f(world_pos.x(), world_pos.y(), world_pos.z());
-
-  mat4 transform = controller_translate_ * view_quaternion *
-                   mat4(Eigen::Scaling<float>(1, 1, 3.0));
-  GLint transform_location =
-      glGetUniformLocation(controller_program_->GetProgram(), "uTransform");
-  glUniformMatrix4fv(transform_location, 1, 0, transform.data());
-
-  controller_mesh_->Draw();
-}
-
-void ShellView::Touch() {
-  if (!virtual_touchpad_) {
-    ALOGE("missing virtual touchpad");
-    return;
-  }
-
-  if (!active_display_)
-    return;
-
-  const vec2& hit_location = active_display_->hit_location();
-  const vec2 size = active_display_->size();
-
-  float x = hit_location.x() / size.x();
-  float y = hit_location.y() / size.y();
-
-  // Device is portrait, but in landscape when in VR.
-  // Rotate touch input appropriately.
-  const android::status_t status = dvrVirtualTouchpadTouch(
-      virtual_touchpad_.get(), active_display_->touchpad_id(), x, y,
-      is_touching_ ? 1.0f : 0.0f);
-  if (status != OK) {
-    ALOGE("touch failed: %d", status);
-  }
-}
-
-bool ShellView::OnTouchpadButton(bool down, int button) {
-  int buttons = touchpad_buttons_;
-  if (down) {
-    if (active_display_ && active_display_->allow_input()) {
-      buttons |= button;
-    }
-  } else {
-    buttons &= ~button;
-  }
-  if (buttons == touchpad_buttons_) {
-    return true;
-  }
-  touchpad_buttons_ = buttons;
-  if (!virtual_touchpad_) {
-    ALOGE("missing virtual touchpad");
-    return false;
-  }
-
-  if (!active_display_)
-    return true;
-
-  const android::status_t status = dvrVirtualTouchpadButtonState(
-      virtual_touchpad_.get(), active_display_->touchpad_id(),
-      touchpad_buttons_);
-  if (status != OK) {
-    ALOGE("touchpad button failed: %d %d", touchpad_buttons_, status);
-  }
-  return true;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
deleted file mode 100644
index 9b51600..0000000
--- a/services/vr/vr_window_manager/shell_view.h
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_SHELL_VIEW_H_
-#define VR_WINDOW_MANAGER_SHELL_VIEW_H_
-
-#include <dvr/virtual_touchpad_client.h>
-#include <private/dvr/display_client.h>
-#include <private/dvr/graphics/mesh.h>
-#include <private/dvr/graphics/shader_program.h>
-
-#include <deque>
-
-#include "application.h"
-#include "display_view.h"
-#include "reticle.h"
-#include "shell_view_binder_interface.h"
-#include "surface_flinger_view.h"
-
-namespace android {
-namespace dvr {
-
-class ShellView : public Application,
-                  public android::dvr::ShellViewBinderInterface,
-                  public HwcCallback::Client {
- public:
-  ShellView();
-  virtual ~ShellView();
-
-  int Initialize() override;
-
-  int AllocateResources() override;
-  void DeallocateResources() override;
-
-  // ShellViewBinderInterface:
-  void EnableDebug(bool debug) override;
-  void VrMode(bool mode) override;
-  void dumpInternal(String8& result) override;
-  void Set2DMode(bool mode) override;
-  void SetRotation(int angle) override;
-
-
- protected:
-  void DrawEye(EyeType eye, const mat4& perspective, const mat4& eye_matrix,
-               const mat4& head_matrix) override;
-  void OnDrawFrame() override;
-  void OnEndFrame() override;
-  void OnVisibilityChanged(bool visible) override;
-
-  void DrawReticle(const mat4& perspective, const mat4& eye_matrix,
-                   const mat4& head_matrix);
-  void DrawController(const mat4& perspective, const mat4& eye_matrix,
-                      const mat4& head_matrix);
-
-  void Touch();
-  bool OnTouchpadButton(bool down, int button);
-
-  bool OnClick(bool down);
-
-  DisplayView* FindActiveDisplay(const vec3& position, const quat& quaternion,
-                                 vec3* hit_location);
-
-  // HwcCallback::Client:
-  base::unique_fd OnFrame(std::unique_ptr<HwcCallback::Frame> frame) override;
-  DisplayView* FindOrCreateDisplay(uint32_t id);
-
-  std::unique_ptr<ShaderProgram> program_;
-  std::unique_ptr<ShaderProgram> overlay_program_;
-  std::unique_ptr<ShaderProgram> controller_program_;
-
-  std::unique_ptr<SurfaceFlingerView> surface_flinger_view_;
-  std::unique_ptr<Reticle> reticle_;
-
-  std::unique_ptr<display::DisplayClient> display_client_;
-
-  struct DvrVirtualTouchpadDeleter {
-    void operator()(DvrVirtualTouchpad* p) {
-      dvrVirtualTouchpadDetach(p);
-      dvrVirtualTouchpadDestroy(p);
-    }
-  };
-  std::unique_ptr<DvrVirtualTouchpad, DvrVirtualTouchpadDeleter>
-      virtual_touchpad_;
-
-  std::unique_ptr<Mesh<vec3, vec3, vec2>> controller_mesh_;
-
-  bool is_touching_ = false;
-  int touchpad_buttons_ = 0;
-
-  std::mutex display_frame_mutex_;
-
-  std::vector<std::unique_ptr<DisplayView>> displays_;
-  std::vector<std::unique_ptr<DisplayView>> new_displays_;
-  std::vector<DisplayView*> removed_displays_;
-  DisplayView* active_display_ = nullptr;
-
-  mat4 controller_translate_;
-
-  ShellView(const ShellView&) = delete;
-  void operator=(const ShellView&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_SHELL_VIEW_H_
diff --git a/services/vr/vr_window_manager/shell_view_binder_interface.h b/services/vr/vr_window_manager/shell_view_binder_interface.h
deleted file mode 100644
index c66e4a1..0000000
--- a/services/vr/vr_window_manager/shell_view_binder_interface.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_SHELL_VIEWBINDER_INTERFACE_H_
-#define VR_WINDOW_MANAGER_SHELL_VIEWBINDER_INTERFACE_H_
-
-namespace android {
-namespace dvr {
-
-class ShellViewBinderInterface {
- public:
-  ShellViewBinderInterface() {};
-  virtual ~ShellViewBinderInterface() {};
-
-  virtual void EnableDebug(bool debug) = 0;
-  virtual void VrMode(bool mode) = 0;
-  virtual void dumpInternal(String8& result) = 0;
-  virtual void Set2DMode(bool mode) = 0;
-  virtual void SetRotation(int angle) = 0;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_SHELL_VIEWBINDER_INTERFACE_H_
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
deleted file mode 100644
index b41de03..0000000
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "surface_flinger_view.h"
-
-#include <android/dvr/IVrComposer.h>
-#include <binder/IServiceManager.h>
-#include <private/dvr/native_buffer.h>
-
-#include "hwc_callback.h"
-#include "texture.h"
-
-namespace android {
-namespace dvr {
-
-SurfaceFlingerView::SurfaceFlingerView() {}
-
-SurfaceFlingerView::~SurfaceFlingerView() {}
-
-bool SurfaceFlingerView::Initialize(HwcCallback::Client *client) {
-  sp<IServiceManager> sm(defaultServiceManager());
-  vr_composer_ = interface_cast<IVrComposer>(
-      sm->getService(IVrComposer::SERVICE_NAME()));
-
-  String8 service_name(IVrComposer::SERVICE_NAME().string());
-  if (!vr_composer_.get()) {
-    ALOGE("Faild to connect to %s", service_name.c_str());
-    return false;
-  }
-
-  composer_callback_ = new HwcCallback(client);
-  binder::Status status = vr_composer_->registerObserver(composer_callback_);
-  if (!status.isOk()) {
-    ALOGE("Failed to register observer with %s", service_name.c_str());
-    return false;
-  }
-
-  return true;
-}
-
-bool SurfaceFlingerView::GetTextures(const HwcCallback::Frame& frame,
-                                     std::vector<TextureLayer>* texture_layers,
-                                     TextureLayer* ime_layer,
-                                     bool debug, bool skip_first_layer) const {
-  auto& layers = frame.layers();
-  texture_layers->clear();
-
-  size_t start = 0;
-  // Skip the second layer if it is from the VR app.
-  if (!debug && skip_first_layer) {
-    start = 2;
-  }
-
-  for (size_t i = start; i < layers.size(); ++i) {
-    if (!debug && layers[i].should_skip_layer())
-      continue;
-
-    std::unique_ptr<Texture> texture(new Texture());
-    if (!texture->Initialize(layers[i].buffer->getNativeBuffer())) {
-      ALOGE("Failed to create texture");
-      texture_layers->clear();
-      return false;
-    }
-
-    TextureLayer texture_layer = {
-        std::move(texture), layers[i].crop, layers[i].display_frame,
-        layers[i].blending, layers[i].alpha,
-    };
-    if (debug && layers[i].type == HwcCallback::HwcLayer::kInputMethod) {
-      *ime_layer = std::move(texture_layer);
-    } else {
-      texture_layers->emplace_back(std::move(texture_layer));
-    }
-  }
-
-  return true;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/surface_flinger_view.h b/services/vr/vr_window_manager/surface_flinger_view.h
deleted file mode 100644
index 1bea38d..0000000
--- a/services/vr/vr_window_manager/surface_flinger_view.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef APPLICATIONS_EXPERIMENTS_SURFACE_FLINGER_DEMO_SURFACE_FLINGER_VIEW_H_
-#define APPLICATIONS_EXPERIMENTS_SURFACE_FLINGER_DEMO_SURFACE_FLINGER_VIEW_H_
-
-#include <memory>
-
-#include "hwc_callback.h"
-
-namespace android {
-namespace dvr {
-
-class IDisplay;
-class IVrComposer;
-class Texture;
-
-struct TextureLayer {
-  std::unique_ptr<Texture> texture;
-  Rectf crop;
-  Recti display_frame;
-  int32_t blending;
-  float alpha;
-};
-
-class SurfaceFlingerView {
- public:
-  SurfaceFlingerView();
-  ~SurfaceFlingerView();
-
-  bool Initialize(HwcCallback::Client *client);
-
-  bool GetTextures(const HwcCallback::Frame& layers,
-                   std::vector<TextureLayer>* texture_layers,
-                   TextureLayer* ime_layer, bool debug,
-                   bool skip_first_layer) const;
-
- private:
-  sp<IVrComposer> vr_composer_;
-  sp<HwcCallback> composer_callback_;
-
-  SurfaceFlingerView(const SurfaceFlingerView&) = delete;
-  void operator=(const SurfaceFlingerView&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // APPLICATIONS_EXPERIMENTS_SURFACE_FLINGER_DEMO_SURFACE_FLINGER_VIEW_H_
diff --git a/services/vr/vr_window_manager/texture.cpp b/services/vr/vr_window_manager/texture.cpp
deleted file mode 100644
index 2229efa..0000000
--- a/services/vr/vr_window_manager/texture.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include "texture.h"
-
-#include <GLES/glext.h>
-#include <log/log.h>
-#include <system/window.h>
-
-namespace android {
-namespace dvr {
-
-Texture::Texture() {}
-
-Texture::~Texture() {
-  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  if (id_)
-    glDeleteTextures(1, &id_);
-  if (image_)
-    eglDestroyImageKHR(display, image_);
-}
-
-bool Texture::Initialize(ANativeWindowBuffer* buffer) {
-  width_ = buffer->width;
-  height_ = buffer->height;
-
-  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  image_ = eglCreateImageKHR(display, EGL_NO_CONTEXT,
-                             EGL_NATIVE_BUFFER_ANDROID, buffer, nullptr);
-  if (!image_) {
-    ALOGE("Failed to create eglImage");
-    return false;
-  }
-
-  glGenTextures(1, &id_);
-  glActiveTexture(GL_TEXTURE0);
-  glBindTexture(GL_TEXTURE_2D, id_);
-  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
-
-  return true;
-}
-
-}  // namespace android
-}  // namespace dvr
diff --git a/services/vr/vr_window_manager/texture.h b/services/vr/vr_window_manager/texture.h
deleted file mode 100644
index 9840f19..0000000
--- a/services/vr/vr_window_manager/texture.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_TEXTURE_H_
-#define VR_WINDOW_MANAGER_TEXTURE_H_
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-
-struct ANativeWindowBuffer;
-
-namespace android {
-namespace dvr {
-
-class Texture {
- public:
-  explicit Texture();
-  ~Texture();
-
-  bool Initialize(ANativeWindowBuffer* buffer);
-
-  GLuint id() const { return id_; }
-  int width() const { return width_; }
-  int height() const { return height_; }
-
- private:
-  EGLImageKHR image_ = nullptr;
-  GLuint id_ = 0;
-  int width_ = 0;
-  int height_ = 0;
-
-  Texture(const Texture&) = delete;
-  void operator=(const Texture&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_TEXTURE_H_
diff --git a/services/vr/vr_window_manager/vr_window_manager.cpp b/services/vr/vr_window_manager/vr_window_manager.cpp
deleted file mode 100644
index dd2cba7..0000000
--- a/services/vr/vr_window_manager/vr_window_manager.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <hwbinder/IPCThreadState.h>
-#include <impl/vr_hwc.h>
-
-#include "shell_view.h"
-#include "vr_window_manager_binder.h"
-
-using namespace android;
-using namespace android::dvr;
-
-int main(int /* argc */, char** /* argv */) {
-  android::ProcessState::self()->startThreadPool();
-
-  // ShellView needs to be created after vr_hwcomposer.
-  android::dvr::ShellView app;
-  const int app_status = app.Initialize();
-  LOG_ALWAYS_FATAL_IF(app_status != 0, "failed to initialize: %d", app_status);
-
-  // Create vr_wm_binder.
-  android::sp<android::service::vr::VrWindowManagerBinder> vr_wm_binder =
-      new android::service::vr::VrWindowManagerBinder(app);
-  const int status = vr_wm_binder->Initialize();
-  LOG_ALWAYS_FATAL_IF(status != 0, "initialization failed: %d", status);
-
-  android::sp<android::IServiceManager> sm(android::defaultServiceManager());
-  const android::status_t vr_wm_binder_status = sm->addService(
-      android::service::vr::VrWindowManagerBinder::SERVICE_NAME(),
-      vr_wm_binder, false /*allowIsolated*/);
-  LOG_ALWAYS_FATAL_IF(vr_wm_binder_status != android::OK,
-                      "vr_wm_binder service not added: %d",
-                      static_cast<int>(vr_wm_binder_status));
-
-  app.SetControllerDataProvider(vr_wm_binder.get());
-
-  android::hardware::ProcessState::self()->startThreadPool();
-
-  while (true) {
-    app.DrawFrame();
-  }
-
-  android::hardware::IPCThreadState::self()->joinThreadPool();
-  android::IPCThreadState::self()->joinThreadPool();
-
-  return 0;
-}
diff --git a/services/vr/vr_window_manager/vr_window_manager_binder.cpp b/services/vr/vr_window_manager/vr_window_manager_binder.cpp
deleted file mode 100644
index fdcb8b2..0000000
--- a/services/vr/vr_window_manager/vr_window_manager_binder.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-#include "vr_window_manager_binder.h"
-
-#include <inttypes.h>
-#include <sys/mman.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/PermissionCache.h>
-#include <binder/Status.h>
-#include <cutils/log.h>
-#include <private/android_filesystem_config.h>
-#include <utils/Errors.h>
-
-namespace android {
-namespace service {
-namespace vr {
-
-namespace {
-const String16 kDumpPermission("android.permission.DUMP");
-const String16 kSendMeControllerInputPermission(
-    "android.permission.RESTRICTED_VR_ACCESS");
-}  // anonymous namespace
-
-constexpr size_t AshmemControllerDataProvider::kRegionLength;
-
-status_t AshmemControllerDataProvider::Connect(const int in_fd) {
-  if (in_fd < 0) {
-    return BAD_VALUE;
-  }
-  if (fd_.get() >= 0) {
-    // The VrCore is dead. Long live the VrCore.
-    Disconnect();
-  }
-  void* const shared_region =
-      ::mmap(nullptr, kRegionLength, PROT_READ, MAP_SHARED, in_fd, 0);
-  if (shared_region == MAP_FAILED) {
-    shared_region_ = nullptr;
-    return NO_MEMORY;
-  }
-
-  errno = 0;
-  const int fd = ::fcntl(in_fd, F_DUPFD_CLOEXEC, 0);
-  if (fd < 0) {
-    ::munmap(shared_region, kRegionLength);
-    return -errno;
-  }
-  fd_.reset(fd);
-  ALOGI("controller connected %d -> %d @ %p", in_fd, fd, shared_region);
-
-  std::lock_guard<std::mutex> guard(mutex_);
-  shared_region_ = shared_region;
-  return OK;
-}
-
-status_t AshmemControllerDataProvider::Disconnect() {
-  if (shared_region_ == nullptr || fd_.get() < 0) {
-    return INVALID_OPERATION;
-  }
-  std::lock_guard<std::mutex> guard(mutex_);
-  ::munmap(shared_region_, kRegionLength);
-  shared_region_ = nullptr;
-  fd_.reset();
-  ALOGI("controller disconnected");
-  return OK;
-}
-
-const void* AshmemControllerDataProvider::LockControllerData() {
-  mutex_.lock();
-  if (!shared_region_) {
-    mutex_.unlock();
-    return nullptr;
-  }
-  return shared_region_;
-}
-
-void AshmemControllerDataProvider::UnlockControllerData() { mutex_.unlock(); }
-
-void AshmemControllerDataProvider::dumpInternal(String8& result) {
-  result.appendFormat("[controller]\nfd = %d\n", fd_.get());
-  if (shared_region_) {
-    int32_t* p = reinterpret_cast<int32_t*>(shared_region_);
-    result.appendFormat("header = ");
-    for (int i = 0; i < 8; ++i) {
-      result.appendFormat("%c 0x%08" PRIX32, i ? ',' : '[', p[i]);
-    }
-    result.appendFormat(" ]\n\n");
-  }
-}
-
-int VrWindowManagerBinder::Initialize() { return 0; }
-
-binder::Status VrWindowManagerBinder::connectController(
-    const ::android::base::unique_fd& in_fd) {
-  // TODO(kpschoedel): check permission
-#if 0
-  int32_t pid, uid;
-  if (!PermissionCache::checkCallingPermission(kSendMeControllerInputPermission,
-                                               &pid, &uid)) {
-    ALOGE("permission denied to pid=%" PRId32 " uid=%" PRId32, pid, uid);
-    return binder::Status::fromStatusT(PERMISSION_DENIED);
-  }
-#endif
-  return binder::Status::fromStatusT(Connect(in_fd.get()));
-}
-
-binder::Status VrWindowManagerBinder::disconnectController() {
-  // TODO(kpschoedel): check permission
-#if 0
-  int32_t pid, uid;
-  if (!PermissionCache::checkCallingPermission(kSendMeControllerInputPermission,
-                                               &pid, &uid)) {
-    ALOGE("permission denied to pid=%" PRId32 " uid=%" PRId32, pid, uid);
-    return binder::Status::fromStatusT(PERMISSION_DENIED);
-  }
-#endif
-  return binder::Status::fromStatusT(Disconnect());
-}
-
-binder::Status VrWindowManagerBinder::enterVrMode() {
-  // TODO(kpschoedel): check permission
-  app_.VrMode(true);
-  return binder::Status::ok();
-}
-
-binder::Status VrWindowManagerBinder::exitVrMode() {
-  // TODO(kpschoedel): check permission
-  app_.VrMode(false);
-  return binder::Status::ok();
-}
-
-binder::Status VrWindowManagerBinder::setDebugMode(int32_t mode) {
-  // TODO(kpschoedel): check permission
-  app_.EnableDebug(static_cast<bool>(mode));
-  return binder::Status::ok();
-}
-
-binder::Status VrWindowManagerBinder::set2DMode(int32_t mode) {
-  app_.Set2DMode(static_cast<bool>(mode));
-  return binder::Status::ok();
-}
-
-binder::Status VrWindowManagerBinder::setRotation(int32_t angle) {
-  app_.SetRotation(angle);
-  return binder::Status::ok();
-}
-
-status_t VrWindowManagerBinder::dump(
-    int fd, const Vector<String16>& args [[gnu::unused]]) {
-  String8 result;
-  const android::IPCThreadState* ipc = android::IPCThreadState::self();
-  const pid_t pid = ipc->getCallingPid();
-  const uid_t uid = ipc->getCallingUid();
-  if ((uid != AID_SHELL) &&
-      !PermissionCache::checkPermission(kDumpPermission, pid, uid)) {
-    result.appendFormat("Permission denial: can't dump " LOG_TAG
-                        " from pid=%d, uid=%d\n",
-                        pid, uid);
-  } else {
-    app_.dumpInternal(result);
-    AshmemControllerDataProvider::dumpInternal(result);
-  }
-  write(fd, result.string(), result.size());
-  return OK;
-}
-
-}  // namespace vr
-}  // namespace service
-}  // namespace android
diff --git a/services/vr/vr_window_manager/vr_window_manager_binder.h b/services/vr/vr_window_manager/vr_window_manager_binder.h
deleted file mode 100644
index 9d0f0b2..0000000
--- a/services/vr/vr_window_manager/vr_window_manager_binder.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_VR_WINDOW_MANAGER_BINDER_H_
-#define VR_WINDOW_MANAGER_VR_WINDOW_MANAGER_BINDER_H_
-
-#include <android/service/vr/BnVrWindowManager.h>
-
-#include <mutex>
-
-#include "controller_data_provider.h"
-#include "shell_view_binder_interface.h"
-
-namespace android {
-namespace service {
-namespace vr {
-
-class AshmemControllerDataProvider : public dvr::ControllerDataProvider {
- public:
-  AshmemControllerDataProvider() {}
-  virtual ~AshmemControllerDataProvider() {}
-
-  status_t Connect(int fd);
-  status_t Disconnect();
-
-  // ControllerDataProvider:
-  const void* LockControllerData() override;
-  void UnlockControllerData() override;
-
- protected:
-  void dumpInternal(String8& result);
-
- private:
-  static constexpr size_t kRegionLength = 8192;  // TODO(kpschoedel)
-  ::android::base::unique_fd fd_;
-
-  // Mutex for guarding shared_region_.
-  std::mutex mutex_;
-  void* shared_region_ = nullptr;
-
-  AshmemControllerDataProvider(const AshmemControllerDataProvider&) = delete;
-  void operator=(const AshmemControllerDataProvider&) = delete;
-};
-
-class VrWindowManagerBinder : public BnVrWindowManager,
-                              public AshmemControllerDataProvider {
- public:
-  VrWindowManagerBinder(android::dvr::ShellViewBinderInterface& app)
-      : app_(app) {}
-  virtual ~VrWindowManagerBinder() {}
-
-  // Must be called before clients can connect.
-  // Returns 0 if initialization is successful.
-  int Initialize();
-  static char const* getServiceName() { return "vr_window_manager"; }
-
- protected:
-  // Implements IVrWindowManagerBinder.
-  ::android::binder::Status connectController(
-      const ::android::base::unique_fd& fd) override;
-  ::android::binder::Status disconnectController() override;
-  ::android::binder::Status enterVrMode() override;
-  ::android::binder::Status exitVrMode() override;
-  ::android::binder::Status setDebugMode(int32_t mode) override;
-  ::android::binder::Status set2DMode(int32_t mode) override;
-  ::android::binder::Status setRotation(int32_t angle) override;
-
-  // Implements BBinder::dump().
-  status_t dump(int fd, const Vector<String16>& args) override;
-
- private:
-  android::dvr::ShellViewBinderInterface& app_;
-
-  VrWindowManagerBinder(const VrWindowManagerBinder&) = delete;
-  void operator=(const VrWindowManagerBinder&) = delete;
-};
-
-}  // namespace vr
-}  // namespace service
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_VR_WINDOW_MANAGER_BINDER_H_
diff --git a/services/vr/vr_window_manager/vr_window_manager_binder_test.cpp b/services/vr/vr_window_manager/vr_window_manager_binder_test.cpp
deleted file mode 100644
index f43e803..0000000
--- a/services/vr/vr_window_manager/vr_window_manager_binder_test.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <cutils/log.h>
-
-#include "vr_window_manager_binder.h"
-
-int main() {
-  ALOGI("Starting");
-  android::service::vr::VrWindowManagerBinder service;
-  const int status = service.Initialize();
-  LOG_ALWAYS_FATAL_IF(status != 0, "initialization failed: %d", status);
-
-  signal(SIGPIPE, SIG_IGN);
-  android::sp<android::ProcessState> ps(android::ProcessState::self());
-  ps->setThreadPoolMaxThreadCount(4);
-  ps->startThreadPool();
-  ps->giveThreadPoolName();
-
-  android::sp<android::IServiceManager> sm(android::defaultServiceManager());
-  const android::status_t service_status = sm->addService(
-      android::service::vr::VrWindowManagerBinder::SERVICE_NAME(), &service,
-      false /*allowIsolated*/);
-  LOG_ALWAYS_FATAL_IF(service_status != android::OK, "service not added: %d",
-                      static_cast<int>(service_status));
-
-  android::IPCThreadState::self()->joinThreadPool();
-  return 0;
-}
diff --git a/services/vr/vr_window_manager/vr_wm.rc b/services/vr/vr_window_manager/vr_wm.rc
deleted file mode 100644
index e515bb7..0000000
--- a/services/vr/vr_window_manager/vr_wm.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-service vr_wm /system/bin/vr_wm
-  class core
-  user system
-  group system graphics input
-  writepid /dev/cpuset/system/tasks
diff --git a/services/vr/vr_window_manager/vr_wm_ctl.cpp b/services/vr/vr_window_manager/vr_wm_ctl.cpp
deleted file mode 100644
index 758e02b..0000000
--- a/services/vr/vr_window_manager/vr_wm_ctl.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <android/service/vr/BpVrWindowManager.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <inttypes.h>
-
-void usage() { fprintf(stderr, "usage: vr_wm_ctl [enter|exit|debug N]\n"); }
-
-int report(const android::binder::Status& status) {
-  if (status.isOk()) {
-    fprintf(stderr, "ok\n");
-    return 0;
-  }
-  fprintf(stderr, "failed (%" PRId32 ") %s\n", status.exceptionCode(),
-          status.exceptionMessage().string());
-  return (int)status.exceptionCode();
-}
-
-int main(int argc, char* argv[]) {
-  android::sp<android::IServiceManager> sm(android::defaultServiceManager());
-  if (sm == nullptr) {
-    fprintf(stderr, "service manager not found\n");
-    exit(1);
-  }
-
-  android::sp<android::service::vr::IVrWindowManager> vrwm =
-      android::interface_cast<android::service::vr::IVrWindowManager>(
-          sm->getService(
-              android::service::vr::IVrWindowManager::SERVICE_NAME()));
-  if (vrwm == nullptr) {
-    fprintf(stderr, "service not found\n");
-    exit(1);
-  }
-
-  android::binder::Status status;
-  if ((argc == 2) && (strcmp(argv[1], "enter") == 0)) {
-    exit(report(vrwm->enterVrMode()));
-  } else if ((argc == 2) && (strcmp(argv[1], "exit") == 0)) {
-    exit(report(vrwm->exitVrMode()));
-  } else if ((argc == 3) && (strcmp(argv[1], "debug") == 0)) {
-    exit(report(vrwm->setDebugMode(atoi(argv[2]))));
-  } else if ((argc == 3) && (strcmp(argv[1], "2d") == 0)) {
-    exit(report(vrwm->set2DMode(atoi(argv[2]))));
-  } else if ((argc == 3) && (strcmp(argv[1], "rotate") == 0)) {
-    exit(report(vrwm->setRotation(atoi(argv[2]))));
-  } else {
-    usage();
-    exit(2);
-  }
-
-  return 0;
-}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index f2cd8e6..6f425f5 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
@@ -887,6 +878,19 @@
     const VkAllocationCallbacks& data_allocator =
         (pAllocator) ? *pAllocator : GetDefaultAllocator();
 
+    if (pCreateInfo->pApplicationInfo &&
+        pCreateInfo->pApplicationInfo->apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+        ALOGI(
+            "Requested Vulkan instance version %d.%d is greater than max "
+            "supported version (1.0)",
+            VK_VERSION_MAJOR(pCreateInfo->pApplicationInfo->apiVersion),
+            VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion));
+#pragma clang diagnostic pop
+        return VK_ERROR_INCOMPATIBLE_DRIVER;
+    }
+
     CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
     VkResult result = wrapper.Validate();
     if (result != VK_SUCCESS)
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index caa2674..e2c8c06 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1092,12 +1092,9 @@
         image_native_buffer.stride = img.buffer->stride;
         image_native_buffer.format = img.buffer->format;
         image_native_buffer.usage = img.buffer->usage;
-        // TODO: Adjust once ANativeWindowBuffer supports gralloc1-style usage.
-        // For now, this is the same translation Gralloc1On0Adapter does.
-        image_native_buffer.usage2.consumer =
-            static_cast<uint64_t>(img.buffer->usage);
-        image_native_buffer.usage2.producer =
-            static_cast<uint64_t>(img.buffer->usage);
+        android_convertGralloc0To1Usage(img.buffer->usage,
+            &image_native_buffer.usage2.producer,
+            &image_native_buffer.usage2.consumer);
 
         result =
             dispatch.CreateImage(device, &image_create, nullptr, &img.image);