Merge "Correct PowerManager transaction IDs." into oc-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 84820a6..f8e0ad5 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -450,8 +450,8 @@
         return false;
     }
 
-    char buf[100];
-    ssize_t n = read(fd, buf, 99);
+    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,
@@ -475,38 +475,13 @@
     return strcmp(mode, start) == 0;
 }
 
-// Read the trace_clock sysfs file and return true if it contains the requested
-// value.  The trace_clock file format is:
-// local [global] counter uptime perf
-static bool traceClockContains(const char *mode)
-{
-    int fd = open((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
-    if (fd == -1) {
-        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath,
-            strerror(errno), errno);
-        return false;
-    }
-
-    char buf[100];
-    ssize_t n = read(fd, buf, 99);
-    close(fd);
-    if (n == -1) {
-        fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
-            strerror(errno), errno);
-        return false;
-    }
-    buf[n] = '\0';
-
-    return strstr(buf, mode) != NULL;
-}
-
-// Set the clock to the best available option while tracing. Use 'boot' if it's
-// available; otherwise, use 'mono'.
+// 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.
 // 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 setClock()
+static bool setGlobalClockEnable(bool enable)
 {
-    const char* clock = traceClockContains("boot") ? "boot" : "mono";
+    const char *clock = enable ? "global" : "local";
 
     if (isTraceClock(clock)) {
         return true;
@@ -808,7 +783,7 @@
     ok &= setCategoriesEnableFromFile(g_categoriesFile);
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
-    ok &= setClock();
+    ok &= setGlobalClockEnable(true);
     ok &= setPrintTgidEnableIfPresent(true);
     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
 
@@ -884,6 +859,7 @@
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
     setTraceBufferSizeKB(1);
+    setGlobalClockEnable(false);
     setPrintTgidEnableIfPresent(false);
     setKernelTraceFuncs(NULL);
 }
@@ -1234,7 +1210,7 @@
 
     if (ok && traceStart) {
         if (!traceStream) {
-            printf("capturing trace...\n");
+            printf("capturing trace...");
             fflush(stdout);
         }
 
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index cfd2659..cef41be 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -124,10 +124,6 @@
     write /sys/kernel/debug/tracing/tracing_on 0
     write /sys/kernel/tracing/tracing_on 0
 
-    # Set the trace clock to boot if it exists, falling back to mono if not.
-    write /d/tracing/trace_clock mono
-    write /d/tracing/trace_clock boot
-
 # Allow only the shell group to read and truncate the kernel trace.
     chown root shell /sys/kernel/debug/tracing/trace
     chown root shell /sys/kernel/tracing/trace
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 5dad511..f84d86d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -998,13 +998,8 @@
     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
 
-    if (true) {
-        // TODO: temporary disabled because /data/misc/bluetooth/logs/btsnoop_hci.log can be huge
-        MYLOGD("Skipping /data/misc/bluetooth/logs");
-    } else {
-        /* Dump Bluetooth HCI logs */
-        ds.AddDir("/data/misc/bluetooth/logs", true);
-    }
+    /* Dump Bluetooth HCI logs */
+    ds.AddDir("/data/misc/bluetooth/logs", true);
 
     if (!ds.do_early_screenshot_) {
         MYLOGI("taking late screenshot\n");
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..a0d987d 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -205,15 +205,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 +906,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);
         }
@@ -952,13 +957,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 +978,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) {
@@ -1089,10 +1100,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 +1759,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;
@@ -2219,9 +2233,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 +2246,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 +2278,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..200fc77 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -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/dexopt.cpp b/cmds/installd/dexopt.cpp
index e9d06d1..6472a0f 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -321,11 +321,11 @@
 
     bool have_dex2oat_compiler_filter_flag;
     if (skip_compilation) {
-        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
+        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=interpret-only");
+        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=") <
@@ -1149,8 +1149,8 @@
 // Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
 // out_vdex_wrapper_fd. Returns true for success or false in case of errors.
 bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
-        const char* instruction_set, bool is_public, bool profile_guided,
-        int uid, bool is_secondary_dex, Dex2oatFileWrapper* in_vdex_wrapper_fd,
+        const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
+        Dex2oatFileWrapper* in_vdex_wrapper_fd,
         Dex2oatFileWrapper* out_vdex_wrapper_fd) {
     CHECK(in_vdex_wrapper_fd != nullptr);
     CHECK(out_vdex_wrapper_fd != nullptr);
@@ -1160,9 +1160,7 @@
     int dexopt_action = abs(dexopt_needed);
     bool is_odex_location = dexopt_needed < 0;
     std::string in_vdex_path_str;
-    // Disable passing an input vdex when the compilation is profile-guided. The dexlayout
-    // optimization in dex2oat is incompatible with it. b/35872504.
-    if (dexopt_action != DEX2OAT_FROM_SCRATCH && !profile_guided) {
+    if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
         // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
         const char* path = nullptr;
         if (is_odex_location) {
@@ -1200,7 +1198,11 @@
     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());
+        // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
+        // have bogus stale vdex files.
+        out_vdex_wrapper_fd->reset(
+              in_vdex_wrapper_fd->get(),
+              [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
         // Disable auto close for the in wrapper fd (it will be done when destructing the out
         // wrapper).
         in_vdex_wrapper_fd->DisableAutoClose();
@@ -1523,8 +1525,8 @@
     // Open vdex files.
     Dex2oatFileWrapper in_vdex_fd;
     Dex2oatFileWrapper out_vdex_fd;
-    if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public,
-            profile_guided, uid, is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
+    if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
+            is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
         return -1;
     }
 
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/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 4b698c0..85d8938 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -322,8 +322,10 @@
                     break;
                 }
                 if (hal->hasVersion(version)) {
-                    hal->interfaces[interfaceName].name = interfaceName;
-                    hal->interfaces[interfaceName].instances.insert(instanceName);
+                    if (&table != &mImplementationsTable) {
+                        hal->interfaces[interfaceName].name = interfaceName;
+                        hal->interfaces[interfaceName].instances.insert(instanceName);
+                    }
                     done = true;
                     break;
                 }
@@ -331,12 +333,17 @@
             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 = {{interfaceName, {interfaceName, {{instanceName}}}}}})) {
+                    .interfaces = interfaces})) {
                 mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
             }
         }
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/cmds/vr/vrscreencap/Android.mk b/cmds/vr/vrscreencap/Android.mk
deleted file mode 100644
index 804afc9..0000000
--- a/cmds/vr/vrscreencap/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-	vrscreencap.cpp
-
-LOCAL_STATIC_LIBRARIES := \
-	libbufferhub \
-	libdisplay \
-	libimageio \
-	libpdx_default_transport \
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	liblog \
-	libpng \
-	libsync \
-	libui \
-
-LOCAL_MODULE := vrscreencap
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/vr/vrscreencap/vrscreencap.cpp b/cmds/vr/vrscreencap/vrscreencap.cpp
deleted file mode 100644
index 3d0d112..0000000
--- a/cmds/vr/vrscreencap/vrscreencap.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-// screencap is a tool for taking screenshots using the screenshot service.
-
-#include <fstream>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include <private/dvr/image_io.h>
-#include <private/dvr/screenshot_client.h>
-
-namespace {
-
-// Attempt to take a screenshot and save it to |filename|.
-// Returns zero on success, or a non-zero exit code otherwise.
-int TakeScreenshot(const std::string& app_name, const std::string& filename,
-                   int index) {
-  auto error_out = [app_name]() -> std::ostream& {
-    return std::cerr << app_name << ": ";
-  };
-
-  auto info_out = [app_name]() -> std::ostream& {
-    return std::cout << app_name << ": ";
-  };
-
-  auto client = android::dvr::ScreenshotClient::Create();
-
-  if (client->format() != HAL_PIXEL_FORMAT_RGB_888) {
-    error_out() << "The screenshot format for this device is not supported."
-                << std::endl;
-    return 1;
-  }
-
-  std::vector<uint8_t> image;
-  int width = 0;
-  int height = 0;
-  if (client->Take(&image, index, &width, &height) != 0) {
-    error_out() << "Failed to take screenshot." << std::endl;
-    return 1;
-  }
-
-  info_out() << "Got " << width << "x" << height << " screenshot." << std::endl;
-
-  if (!image_io_write_rgb888(filename.c_str(), width, height, image.data())) {
-    error_out() << "Failed to write image to output file " << filename
-                << std::endl;
-    return 1;
-  }
-
-  return 0;
-}
-
-}  // namespace
-
-int main(int argc, char** argv) {
-  // Parse arguments
-  if (argc != 2 && argc != 3) {
-    std::cerr
-        << "Usage: " << argv[0]
-        << " filename.[" DVR_IMAGE_IO_SUPPORTED_WRITE
-           "] [INDEX]\n"
-           "INDEX: specify 1..n to grab hw_composer layers by index.\n"
-           "       specify -n to grab pre-warp layers (-1 is base layer).\n"
-           "       the default is 1 (the base hw_composer layer).\n"
-           "       an invalid index will result in an error.\n";
-    return 1;
-  }
-  const std::string filename(argv[1]);
-  int index = 1;
-  if (argc > 2)
-    index = atoi(argv[2]);
-
-  // Perform the actual screenshot.
-  return TakeScreenshot(argv[0], filename, index);
-}
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/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/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/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 68b9c81..452bad0 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -25,7 +25,6 @@
 staticLibraries = [
     "libdvrcommon",
     "libpdx_default_transport",
-    "libgrallocusage",
 ]
 
 sharedLibraries = [
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index a1f952e..a09a7a1 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -53,44 +53,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,11 +92,11 @@
 }
 
 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);
@@ -199,26 +189,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",
@@ -239,27 +227,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);
+      name, user_id, group_id, width, height, format,
+      (producer_usage | consumer_usage), meta_size_bytes);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -294,10 +282,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());
@@ -332,10 +321,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);
+      name, user_id, group_id, width, height, format,
+      (producer_usage | consumer_usage), meta_size_bytes);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create persistent "
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 c772ed3..83e9255 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,36 +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(); }
-  uint64_t producer_usage() const { return slices_[0].producer_usage(); }
-  uint64_t consumer_usage() const { return slices_[0].consumer_usage(); }
+  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 buffer_.usage(); }
+  uint64_t consumer_usage() const { return buffer_.usage(); }
 
  protected:
   explicit BufferHubBuffer(LocalChannelHandle channel);
@@ -133,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
@@ -222,11 +202,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
@@ -242,12 +221,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 b6302f1..ffdc9e2 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -23,9 +23,9 @@
         stride_(buffer.stride()),
         width_(buffer.width()),
         height_(buffer.height()),
+        layer_count_(buffer.layer_count()),
         format_(buffer.format()),
-        producer_usage_(buffer.producer_usage()),
-        consumer_usage_(buffer.consumer_usage()) {
+        usage_(buffer.usage()) {
     // Populate the fd and int vectors: native_handle->data[] is an array of fds
     // followed by an array of opaque ints.
     const int fd_count = buffer.handle()->numFds;
@@ -50,8 +50,8 @@
 
     const int ret =
         buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
-                       opaque_ints_.size(), width_, height_, stride_, format_,
-                       producer_usage_, consumer_usage_);
+                       opaque_ints_.size(), width_, height_, layer_count_,
+                       stride_, format_, usage_);
     if (ret < 0)
       return ret;
 
@@ -74,21 +74,20 @@
   uint32_t stride_;
   uint32_t width_;
   uint32_t height_;
+  uint32_t layer_count_;
   uint32_t format_;
-  uint64_t producer_usage_;
-  uint64_t consumer_usage_;
+  uint64_t usage_;
   std::vector<int> opaque_ints_;
   std::vector<FileHandleType> fds_;
 
   void Clear() {
     id_ = -1;
-    stride_ = width_ = height_ = format_ = producer_usage_ = consumer_usage_ =
-        0;
+    stride_ = width_ = height_ = format_ = usage_ = 0;
   }
 
   PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
-                           width_, height_, format_, producer_usage_,
-                           consumer_usage_, opaque_ints_, fds_);
+                           width_, height_, layer_count_, format_, usage_,
+                           opaque_ints_, fds_);
 
   NativeBufferHandle(const NativeBufferHandle&) = delete;
   void operator=(const NativeBufferHandle&) = delete;
@@ -139,20 +138,14 @@
 };
 
 struct UsagePolicy {
-  uint64_t producer_set_mask;
-  uint64_t producer_clear_mask;
-  uint64_t producer_deny_set_mask;
-  uint64_t producer_deny_clear_mask;
-  uint64_t consumer_set_mask;
-  uint64_t consumer_clear_mask;
-  uint64_t consumer_deny_set_mask;
-  uint64_t consumer_deny_clear_mask;
+  uint64_t usage_set_mask;
+  uint64_t usage_clear_mask;
+  uint64_t usage_deny_set_mask;
+  uint64_t usage_deny_clear_mask;
 
  private:
-  PDX_SERIALIZABLE_MEMBERS(UsagePolicy, producer_set_mask, producer_clear_mask,
-                           producer_deny_set_mask, producer_deny_clear_mask,
-                           consumer_set_mask, consumer_clear_mask,
-                           consumer_deny_set_mask, consumer_deny_clear_mask);
+  PDX_SERIALIZABLE_MEMBERS(UsagePolicy, usage_set_mask, usage_clear_mask,
+                           usage_deny_set_mask, usage_deny_clear_mask);
 };
 
 // BufferHub Service RPC interface. Defines the endpoints, op codes, and method
@@ -176,7 +169,6 @@
     kOpCreatePersistentBuffer,
     kOpGetPersistentBuffer,
     kOpGetBuffer,
-    kOpGetBuffers,
     kOpNewConsumer,
     kOpProducerMakePersistent,
     kOpProducerRemovePersistence,
@@ -202,19 +194,15 @@
   // Methods.
   PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
                     void(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 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 producer_usage, uint64_t consumer_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));
@@ -239,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 producer_usage, uint64_t consumer_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 e167a17..0d337f7 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -12,20 +12,12 @@
 class IonBuffer {
  public:
   IonBuffer();
-  IonBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
-  IonBuffer(uint32_t width, uint32_t height, uint32_t format,
-            uint64_t producer_usage, uint64_t consumer_usage);
+  IonBuffer(uint32_t width, uint32_t height, uint32_t format, uint64_t usage);
   IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
-            uint32_t stride, uint32_t format, uint32_t usage);
+            uint32_t stride, uint32_t format, uint64_t usage);
   IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
-            uint32_t stride, uint32_t format, uint64_t producer_usage,
-            uint64_t consumer_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, uint32_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 producer_usage, uint64_t consumer_usage);
+            uint32_t layer_count, uint32_t stride, uint32_t format,
+            uint64_t usage);
   ~IonBuffer();
 
   IonBuffer(IonBuffer&& other);
@@ -39,36 +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, uint32_t usage);
-  int Alloc(uint32_t width, uint32_t height, uint32_t format,
-            uint64_t producer_usage, uint64_t consumer_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, uint32_t usage);
-  void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
-             uint32_t stride, uint32_t format, uint64_t producer_usage,
-             uint64_t consumer_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, uint32_t usage);
-  int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
-             uint32_t stride, uint32_t format, uint64_t producer_usage,
-             uint64_t consumer_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, uint32_t usage);
-  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 producer_usage, uint64_t consumer_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
@@ -91,23 +76,16 @@
     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;
   }
-  uint64_t producer_usage() const { return producer_usage_; }
-  uint64_t consumer_usage() const { return consumer_usage_; }
-  uint32_t usage() const { return buffer_.get() ? buffer_->getUsage() : 0; }
+  uint64_t usage() const {
+    return buffer_.get() ? static_cast<uint64_t>(buffer_->getUsage()) : 0;
+  }
 
  private:
   sp<GraphicBuffer> buffer_;
 
-  // GraphicBuffer doesn't expose these separately. Keep these values cached for
-  // BufferHub to check policy against. Clients that import these buffers won't
-  // get the full picture, which is okay.
-  uint64_t producer_usage_;
-  uint64_t consumer_usage_;
-
   IonBuffer(const IonBuffer&) = delete;
   void operator=(const IonBuffer&) = delete;
 };
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 0a6996e..cbaa24a 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -2,7 +2,6 @@
 
 #include <log/log.h>
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <grallocusage/GrallocUsageConversion.h>
 #include <utils/Trace.h>
 
 #include <mutex>
@@ -16,49 +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,
-                     uint32_t usage)
-    : IonBuffer(width, height, format, usage, usage) {}
-
-IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
-                     uint64_t producer_usage, uint64_t consumer_usage)
+                     uint64_t usage)
     : IonBuffer() {
-  Alloc(width, height, format, producer_usage, consumer_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, uint32_t usage)
-    : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
+                     uint32_t stride, uint32_t format, uint64_t 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, uint32_t usage)
-    : IonBuffer(handle, width, height, layer_count, stride, layer_stride,
-                format, usage, 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 producer_usage, uint64_t consumer_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 producer_usage=%" PRIx64
-           " consumer_usage=%" PRIx64,
-           handle, width, height, layer_count, stride, layer_stride, format,
-           producer_usage, consumer_usage);
+           "stride=%u format=%u usage=%" PRIx64,
+           handle, width, height, layer_count, stride, format, usage);
   if (handle != 0) {
-    Import(handle, width, height, stride, format, producer_usage,
-           consumer_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();
 }
@@ -82,105 +68,67 @@
   if (buffer_.get()) {
     // GraphicBuffer unregisters and cleans up the handle if needed
     buffer_ = nullptr;
-    producer_usage_ = 0;
-    consumer_usage_ = 0;
   }
 }
 
-int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
-                     uint32_t usage) {
-  return Alloc(width, height, format, usage, 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 layer_count=%u format=%u "
+           "usage=%" PRIx64, width, height, layer_count, format, usage);
 
-int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
-                     uint64_t producer_usage, uint64_t consumer_usage) {
-  ALOGD_IF(
-      TRACE,
-      "IonBuffer::Alloc: width=%u height=%u format=%u producer_usage=%" PRIx64
-      " consumer_usage=%" PRIx64,
-      width, height, format, producer_usage, consumer_usage);
-
-  // TODO: forget about split producer/consumer usage
-  sp<GraphicBuffer> buffer = new GraphicBuffer(
-      width, height, format, kDefaultGraphicBufferLayerCount,
-      android_convertGralloc1To0Usage(producer_usage, consumer_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;
   } else {
     buffer_ = buffer;
-    producer_usage_ = producer_usage;
-    consumer_usage_ = consumer_usage;
     return 0;
   }
 }
 
 void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint32_t usage) {
-  Reset(handle, width, height, stride, format, usage, usage);
-}
-
-void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint64_t producer_usage,
-                      uint64_t consumer_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 "
-           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
-           handle, width, height, stride, format, producer_usage,
-           consumer_usage);
-  Import(handle, width, height, stride, format, producer_usage, consumer_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, uint32_t usage) {
-  return Import(handle, width, height, stride, format, usage, usage);
-}
-
-int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint64_t producer_usage,
-                      uint64_t consumer_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 "
-      "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
-      handle, width, height, stride, format, producer_usage, consumer_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,
-                        static_cast<uint64_t>(android_convertGralloc1To0Usage(
-                            producer_usage, consumer_usage)),
-                        stride);
+                        height, format, layer_count, usage, stride);
   if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Import: Failed to import buffer");
     return -EINVAL;
   } else {
     buffer_ = buffer;
-    producer_usage_ = producer_usage;
-    consumer_usage_ = consumer_usage;
     return 0;
   }
 }
 
 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, uint32_t usage) {
-  return Import(fd_array, fd_count, int_array, int_count, width, height, stride,
-                format, usage, usage);
-}
-
-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 producer_usage,
-                      uint64_t consumer_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 producer_usage=%" PRIx64
-           " consumer_usage=%" PRIx64,
-           fd_count, int_count, width, height, stride, format, producer_usage,
-           consumer_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.");
@@ -198,8 +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, producer_usage,
-                         consumer_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));
@@ -235,8 +183,8 @@
          sizeof(int) * int_count);
 
   const int ret =
-      Import(handle, other->width(), other->height(), other->stride(),
-             other->format(), other->producer_usage(), other->consumer_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/ion_buffer/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h
index fac6db0..8929c95 100644
--- a/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h
@@ -17,10 +17,11 @@
   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));
+                           int layer_count, int stride, int format, int usage));
+  MOCK_METHOD9(Import,
+               int(const int* fd_array, int fd_count, const int* int_array,
+                   int int_count, int width, int height, int layer_count,
+                   int stride, int format, int usage));
   MOCK_METHOD6(Lock, int(int usage, int x, int y, int width, int height,
                          void** address));
   MOCK_METHOD0(Unlock, int());
@@ -29,7 +30,6 @@
   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());
 };
@@ -46,15 +46,16 @@
   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(buffer_handle_t handle, int width, int height, int layer_count,
+             int stride, int format, int usage) {
+    return mock_->Import(handle, width, height, layer_count, stride, format,
+                         usage);
   }
   int Import(const int* fd_array, int fd_count, const int* int_array,
-             int int_count, int width, int height, int stride, int format,
-             int usage) {
+             int int_count, int width, int height, int layer_count, int stride,
+             int format, int usage) {
     return mock_->Import(fd_array, fd_count, int_array, int_count, width,
-                         height, stride, format, usage);
+                         height, layer_count, stride, format, usage);
   }
   int Lock(int usage, int x, int y, int width, int height, void** address) {
     return mock_->Lock(usage, x, y, width, height, address);
@@ -65,7 +66,6 @@
   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_;
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index b431d2f..012a4e7 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -2,6 +2,7 @@
 
 #include <inttypes.h>
 #include <log/log.h>
+#include <poll.h>
 #include <sys/epoll.h>
 
 #include <array>
@@ -11,6 +12,15 @@
 #include <pdx/file_handle.h>
 #include <private/dvr/bufferhub_rpc.h>
 
+#define RETRY_EINTR(fnc_call)                 \
+  ([&]() -> decltype(fnc_call) {              \
+    decltype(fnc_call) result;                \
+    do {                                      \
+      result = (fnc_call);                    \
+    } while (result == -1 && errno == EINTR); \
+    return result;                            \
+  })()
+
 using android::pdx::ErrorStatus;
 using android::pdx::LocalChannelHandle;
 using android::pdx::Status;
@@ -87,6 +97,14 @@
     return nullptr;
 }
 
+std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateSilentConsumerQueue() {
+  if (auto status = CreateConsumerQueueHandle())
+    return std::unique_ptr<ConsumerQueue>(
+        new ConsumerQueue(status.take(), true));
+  else
+    return nullptr;
+}
+
 Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle() {
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>();
   if (!status) {
@@ -103,12 +121,23 @@
 bool BufferHubQueue::WaitForBuffers(int timeout) {
   std::array<epoll_event, kMaxEvents> events;
 
-  while (count() == 0) {
-    int ret = epoll_fd_.Wait(events.data(), events.size(), timeout);
+  // Loop at least once to check for hangups.
+  do {
+    ALOGD_IF(
+        TRACE,
+        "BufferHubQueue::WaitForBuffers: queue_id=%d count=%zu capacity=%zu",
+        id(), count(), capacity());
+
+    // If there is already a buffer then just check for hangup without waiting.
+    const int ret = epoll_fd_.Wait(events.data(), events.size(),
+                                   count() == 0 ? timeout : 0);
 
     if (ret == 0) {
-      ALOGD_IF(TRACE, "Wait on epoll returns nothing before timeout.");
-      return false;
+      ALOGI_IF(TRACE,
+               "BufferHubQueue::WaitForBuffers: No events before timeout: "
+               "queue_id=%d",
+               id());
+      return count() != 0;
     }
 
     if (ret < 0 && ret != -EINTR) {
@@ -125,45 +154,57 @@
     for (int i = 0; i < num_events; i++) {
       int64_t index = static_cast<int64_t>(events[i].data.u64);
 
-      ALOGD_IF(TRACE, "New BufferHubQueue event %d: index=%" PRId64, i, index);
+      ALOGD_IF(TRACE,
+               "BufferHubQueue::WaitForBuffers: event %d: index=%" PRId64, i,
+               index);
 
       if (is_buffer_event_index(index)) {
-        HandleBufferEvent(static_cast<size_t>(index), events[i]);
+        HandleBufferEvent(static_cast<size_t>(index), events[i].events);
       } else if (is_queue_event_index(index)) {
-        HandleQueueEvent(events[i]);
+        HandleQueueEvent(events[i].events);
       } else {
         ALOGW("BufferHubQueue::WaitForBuffers: Unknown event index: %" PRId64,
               index);
       }
     }
-  }
+  } while (count() == 0 && capacity() > 0 && !hung_up());
 
-  return true;
+  return count() != 0;
 }
 
-void BufferHubQueue::HandleBufferEvent(size_t slot, const epoll_event& event) {
+void BufferHubQueue::HandleBufferEvent(size_t slot, int poll_events) {
   auto buffer = buffers_[slot];
   if (!buffer) {
     ALOGW("BufferHubQueue::HandleBufferEvent: Invalid buffer slot: %zu", slot);
     return;
   }
 
-  auto status = buffer->GetEventMask(event.events);
+  auto status = buffer->GetEventMask(poll_events);
   if (!status) {
     ALOGW("BufferHubQueue::HandleBufferEvent: Failed to get event mask: %s",
           status.GetErrorMessage().c_str());
     return;
   }
 
-  int events = status.get();
+  const int events = status.get();
   if (events & EPOLLIN) {
-    int ret = OnBufferReady(buffer, &fences_[slot]);
-    if (ret < 0) {
-      ALOGE("BufferHubQueue::HandleBufferEvent: Failed to set buffer ready: %s",
-            strerror(-ret));
-      return;
+    const int ret = OnBufferReady(buffer, &fences_[slot]);
+    if (ret == 0 || ret == -EALREADY || ret == -EBUSY) {
+      // Only enqueue the buffer if it moves to or is already in the state
+      // requested in OnBufferReady(). If the buffer is busy this means that the
+      // buffer moved from released to posted when a new consumer was created
+      // before the ProducerQueue had a chance to regain it. This is a valid
+      // transition that we have to handle because edge triggered poll events
+      // latch the ready state even if it is later de-asserted -- don't enqueue
+      // or print an error log in this case.
+      if (ret != -EBUSY)
+        Enqueue(buffer, slot);
+    } else {
+      ALOGE(
+          "BufferHubQueue::HandleBufferEvent: Failed to set buffer ready, "
+          "queue_id=%d buffer_id=%d: %s",
+          id(), buffer->id(), strerror(-ret));
     }
-    Enqueue(buffer, slot);
   } else if (events & EPOLLHUP) {
     // This might be caused by producer replacing an existing buffer slot, or
     // when BufferHubQueue is shutting down. For the first case, currently the
@@ -186,15 +227,15 @@
   }
 }
 
-void BufferHubQueue::HandleQueueEvent(const epoll_event& event) {
-  auto status = GetEventMask(event.events);
+void BufferHubQueue::HandleQueueEvent(int poll_event) {
+  auto status = GetEventMask(poll_event);
   if (!status) {
     ALOGW("BufferHubQueue::HandleQueueEvent: Failed to get event mask: %s",
           status.GetErrorMessage().c_str());
     return;
   }
 
-  int events = status.get();
+  const int events = status.get();
   if (events & EPOLLIN) {
     // Note that after buffer imports, if |count()| still returns 0, epoll
     // wait will be tried again to acquire the newly imported buffer.
@@ -203,8 +244,11 @@
       ALOGE("BufferHubQueue::HandleQueueEvent: Failed to import buffer: %s",
             buffer_status.GetErrorMessage().c_str());
     }
+  } else if (events & EPOLLHUP) {
+    ALOGD_IF(TRACE, "BufferHubQueue::HandleQueueEvent: hang up event!");
+    hung_up_ = true;
   } else {
-    ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%d", events);
+    ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%x", events);
   }
 }
 
@@ -260,7 +304,7 @@
   return 0;
 }
 
-void BufferHubQueue::Enqueue(std::shared_ptr<BufferHubBuffer> buf,
+void BufferHubQueue::Enqueue(const std::shared_ptr<BufferHubBuffer>& buf,
                              size_t slot) {
   if (count() == capacity_) {
     ALOGE("BufferHubQueue::Enqueue: Buffer queue is full!");
@@ -272,22 +316,19 @@
   // the limitation of the RingBuffer we are using. Would be better to refactor
   // that.
   BufferInfo buffer_info(slot, meta_size_);
-  // Swap buffer into vector.
-  std::swap(buffer_info.buffer, buf);
+  buffer_info.buffer = buf;
   // Swap metadata loaded during onBufferReady into vector.
   std::swap(buffer_info.metadata, meta_buffer_tmp_);
 
   available_buffers_.Append(std::move(buffer_info));
 }
 
-std::shared_ptr<BufferHubBuffer> BufferHubQueue::Dequeue(int timeout,
-                                                         size_t* slot,
-                                                         void* meta,
-                                                         LocalHandle* fence) {
+Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(
+    int timeout, size_t* slot, void* meta, LocalHandle* fence) {
   ALOGD_IF(TRACE, "Dequeue: count=%zu, timeout=%d", count(), timeout);
 
-  if (count() == 0 && !WaitForBuffers(timeout))
-    return nullptr;
+  if (!WaitForBuffers(timeout))
+    return ErrorStatus(ETIMEDOUT);
 
   std::shared_ptr<BufferHubBuffer> buf;
   BufferInfo& buffer_info = available_buffers_.Front();
@@ -305,7 +346,7 @@
 
   if (!buf) {
     ALOGE("BufferHubQueue::Dequeue: Buffer to be dequeued is nullptr");
-    return nullptr;
+    return ErrorStatus(ENOBUFS);
   }
 
   if (meta) {
@@ -313,11 +354,11 @@
               reinterpret_cast<uint8_t*>(meta));
   }
 
-  return buf;
+  return {std::move(buf)};
 }
 
 ProducerQueue::ProducerQueue(size_t meta_size)
-    : ProducerQueue(meta_size, 0, 0, 0, 0, 0, 0, 0, 0) {}
+    : ProducerQueue(meta_size, 0, 0, 0, 0) {}
 
 ProducerQueue::ProducerQueue(LocalChannelHandle handle)
     : BASE(std::move(handle)) {
@@ -329,22 +370,14 @@
   }
 }
 
-ProducerQueue::ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
-                             uint64_t producer_usage_clear_mask,
-                             uint64_t producer_usage_deny_set_mask,
-                             uint64_t producer_usage_deny_clear_mask,
-                             uint64_t consumer_usage_set_mask,
-                             uint64_t consumer_usage_clear_mask,
-                             uint64_t consumer_usage_deny_set_mask,
-                             uint64_t consumer_usage_deny_clear_mask)
+ProducerQueue::ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
+                             uint64_t usage_clear_mask,
+                             uint64_t usage_deny_set_mask,
+                             uint64_t usage_deny_clear_mask)
     : BASE(BufferHubRPC::kClientPath) {
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
-      meta_size,
-      UsagePolicy{producer_usage_set_mask, producer_usage_clear_mask,
-                  producer_usage_deny_set_mask, producer_usage_deny_clear_mask,
-                  consumer_usage_set_mask, consumer_usage_clear_mask,
-                  consumer_usage_deny_set_mask,
-                  consumer_usage_deny_clear_mask});
+      meta_size, UsagePolicy{usage_set_mask, usage_clear_mask,
+                             usage_deny_set_mask, usage_deny_clear_mask});
   if (!status) {
     ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
           status.GetErrorMessage().c_str());
@@ -356,16 +389,8 @@
 }
 
 int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
-                                  uint32_t format, uint32_t usage,
-                                  size_t slice_count, size_t* out_slot) {
-  return AllocateBuffer(width, height, format, usage, usage, slice_count,
-                        out_slot);
-}
-
-int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
-                                  uint32_t format, uint64_t producer_usage,
-                                  uint64_t consumer_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;
@@ -378,15 +403,12 @@
   }
 
   const size_t kBufferCount = 1U;
-
   Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
-          width, height, format, producer_usage, consumer_usage, slice_count,
-          kBufferCount);
+          width, height, layer_count, format, usage, kBufferCount);
   if (!status) {
-    ALOGE(
-        "ProducerQueue::AllocateBuffer failed to create producer buffer "
-        "through BufferHub.");
+    ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
+          status.GetErrorMessage().c_str());
     return -status.error();
   }
 
@@ -409,6 +431,8 @@
 
 int ProducerQueue::AddBuffer(const std::shared_ptr<BufferProducer>& buf,
                              size_t slot) {
+  ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
+           id(), buf->id(), slot);
   // For producer buffer, we need to enqueue the newly added buffer
   // immediately. Producer queue starts with all buffers in available state.
   const int ret = BufferHubQueue::AddBuffer(buf, slot);
@@ -423,37 +447,40 @@
   auto status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(slot);
   if (!status) {
-    ALOGE(
-        "ProducerQueue::DetachBuffer failed to detach producer buffer through "
-        "BufferHub, error: %s",
-        status.GetErrorMessage().c_str());
+    ALOGE("ProducerQueue::DetachBuffer: Failed to detach producer buffer: %s",
+          status.GetErrorMessage().c_str());
     return -status.error();
   }
 
   return BufferHubQueue::DetachBuffer(slot);
 }
 
-std::shared_ptr<BufferProducer> ProducerQueue::Dequeue(
+Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
     int timeout, size_t* slot, LocalHandle* release_fence) {
   if (slot == nullptr || release_fence == nullptr) {
-    ALOGE(
-        "ProducerQueue::Dequeue: invalid parameter, slot=%p, release_fence=%p",
-        slot, release_fence);
-    return nullptr;
+    ALOGE("ProducerQueue::Dequeue: Invalid parameter: slot=%p release_fence=%p",
+          slot, release_fence);
+    return ErrorStatus(EINVAL);
   }
 
-  auto buf = BufferHubQueue::Dequeue(timeout, slot, nullptr, release_fence);
-  return std::static_pointer_cast<BufferProducer>(buf);
+  auto buffer_status =
+      BufferHubQueue::Dequeue(timeout, slot, nullptr, release_fence);
+  if (!buffer_status)
+    return buffer_status.error_status();
+
+  return {std::static_pointer_cast<BufferProducer>(buffer_status.take())};
 }
 
-int ProducerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+int ProducerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
                                  LocalHandle* release_fence) {
+  ALOGD_IF(TRACE, "ProducerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
+           id(), buf->id());
   auto buffer = std::static_pointer_cast<BufferProducer>(buf);
   return buffer->Gain(release_fence);
 }
 
-ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
-    : BufferHubQueue(std::move(handle)) {
+ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import)
+    : BufferHubQueue(std::move(handle)), ignore_on_import_(ignore_on_import) {
   auto status = ImportQueue();
   if (!status) {
     ALOGE("ConsumerQueue::ConsumerQueue: Failed to import queue: %s",
@@ -461,34 +488,55 @@
     Close(-status.error());
   }
 
-  // TODO(b/34387835) Import buffers in case the ProducerQueue we are
-  // based on was not empty.
+  auto import_status = ImportBuffers();
+  if (import_status) {
+    ALOGI("ConsumerQueue::ConsumerQueue: Imported %zu buffers.",
+          import_status.get());
+  } else {
+    ALOGE("ConsumerQueue::ConsumerQueue: Failed to import buffers: %s",
+          import_status.GetErrorMessage().c_str());
+  }
 }
 
 Status<size_t> ConsumerQueue::ImportBuffers() {
   auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>();
   if (!status) {
-    ALOGE(
-        "ConsumerQueue::ImportBuffers failed to import consumer buffer through "
-        "BufferBub, error: %s",
-        status.GetErrorMessage().c_str());
+    ALOGE("ConsumerQueue::ImportBuffers: Failed to import consumer buffer: %s",
+          status.GetErrorMessage().c_str());
     return ErrorStatus(status.error());
   }
 
+  int ret;
   int last_error = 0;
   int imported_buffers = 0;
 
   auto buffer_handle_slots = status.take();
   for (auto& buffer_handle_slot : buffer_handle_slots) {
-    ALOGD_IF(TRACE,
-             "ConsumerQueue::ImportBuffers, new buffer, buffer_handle: %d",
+    ALOGD_IF(TRACE, "ConsumerQueue::ImportBuffers: buffer_handle=%d",
              buffer_handle_slot.first.value());
 
     std::unique_ptr<BufferConsumer> buffer_consumer =
         BufferConsumer::Import(std::move(buffer_handle_slot.first));
-    int ret = AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
+
+    // Setup ignore state before adding buffer to the queue.
+    if (ignore_on_import_) {
+      ALOGD_IF(TRACE,
+               "ConsumerQueue::ImportBuffers: Setting buffer to ignored state: "
+               "buffer_id=%d",
+               buffer_consumer->id());
+      ret = buffer_consumer->SetIgnore(true);
+      if (ret < 0) {
+        ALOGE(
+            "ConsumerQueue::ImportBuffers: Failed to set ignored state on "
+            "imported buffer buffer_id=%d: %s",
+            buffer_consumer->id(), strerror(-ret));
+        last_error = ret;
+      }
+    }
+
+    ret = AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
     if (ret < 0) {
-      ALOGE("ConsumerQueue::ImportBuffers failed to add buffer, ret: %s",
+      ALOGE("ConsumerQueue::ImportBuffers: Failed to add buffer: %s",
             strerror(-ret));
       last_error = ret;
       continue;
@@ -505,11 +553,33 @@
 
 int ConsumerQueue::AddBuffer(const std::shared_ptr<BufferConsumer>& buf,
                              size_t slot) {
-  // Consumer queue starts with all buffers in unavailable state.
-  return BufferHubQueue::AddBuffer(buf, slot);
+  ALOGD_IF(TRACE, "ConsumerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
+           id(), buf->id(), slot);
+  const int ret = BufferHubQueue::AddBuffer(buf, slot);
+  if (ret < 0)
+    return ret;
+
+  // Check to see if the buffer is already signaled. This is necessary to catch
+  // cases where buffers are already available; epoll edge triggered mode does
+  // not fire until and edge transition when adding new buffers to the epoll
+  // set.
+  const int kTimeoutMs = 0;
+  pollfd pfd{buf->event_fd(), POLLIN, 0};
+  const int count = RETRY_EINTR(poll(&pfd, 1, kTimeoutMs));
+  if (count < 0) {
+    const int error = errno;
+    ALOGE("ConsumerQueue::AddBuffer: Failed to poll consumer buffer: %s",
+          strerror(errno));
+    return -error;
+  }
+
+  if (count == 1)
+    HandleBufferEvent(slot, pfd.revents);
+
+  return 0;
 }
 
-std::shared_ptr<BufferConsumer> ConsumerQueue::Dequeue(
+Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
     int timeout, size_t* slot, void* meta, size_t meta_size,
     LocalHandle* acquire_fence) {
   if (meta_size != meta_size_) {
@@ -517,23 +587,29 @@
         "ConsumerQueue::Dequeue: Metadata size (%zu) for the dequeuing buffer "
         "does not match metadata size (%zu) for the queue.",
         meta_size, meta_size_);
-    return nullptr;
+    return ErrorStatus(EINVAL);
   }
 
-  if (slot == nullptr || meta == nullptr || acquire_fence == nullptr) {
+  if (slot == nullptr || acquire_fence == nullptr) {
     ALOGE(
-        "ConsumerQueue::Dequeue: Invalid parameter, slot=%p, meta=%p, "
+        "ConsumerQueue::Dequeue: Invalid parameter: slot=%p meta=%p "
         "acquire_fence=%p",
         slot, meta, acquire_fence);
-    return nullptr;
+    return ErrorStatus(EINVAL);
   }
 
-  auto buf = BufferHubQueue::Dequeue(timeout, slot, meta, acquire_fence);
-  return std::static_pointer_cast<BufferConsumer>(buf);
+  auto buffer_status =
+      BufferHubQueue::Dequeue(timeout, slot, meta, acquire_fence);
+  if (!buffer_status)
+    return buffer_status.error_status();
+
+  return {std::static_pointer_cast<BufferConsumer>(buffer_status.take())};
 }
 
-int ConsumerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+int ConsumerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
                                  LocalHandle* acquire_fence) {
+  ALOGD_IF(TRACE, "ConsumerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
+           id(), buf->id());
   auto buffer = std::static_pointer_cast<BufferConsumer>(buf);
   return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
 }
@@ -548,7 +624,9 @@
     ALOGW("ConsumerQueue::OnBufferAllocated: No new buffers allocated!");
     return ErrorStatus(ENOBUFS);
   } else {
-    ALOGD_IF(TRACE, "Imported %zu consumer buffers.", status.get());
+    ALOGD_IF(TRACE,
+             "ConsumerQueue::OnBufferAllocated: Imported %zu consumer buffers.",
+             status.get());
     return {};
   }
 }
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
index 00ff137..31cccf0 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
@@ -33,13 +33,14 @@
       unique_id_(getUniqueId()) {}
 
 status_t BufferHubQueueCore::AllocateBuffer(uint32_t width, uint32_t height,
-                                            PixelFormat format, uint32_t usage,
-                                            size_t slice_count) {
+                                            uint32_t layer_count,
+                                            PixelFormat format,
+                                            uint64_t usage) {
   size_t slot;
 
   // Allocate new buffer through BufferHub and add it into |producer_| queue for
   // bookkeeping.
-  if (producer_->AllocateBuffer(width, height, format, usage, slice_count,
+  if (producer_->AllocateBuffer(width, height, layer_count, format, usage,
                                 &slot) < 0) {
     ALOGE("Failed to allocate new buffer in BufferHub.");
     return NO_MEMORY;
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 8216a39..5121508 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -121,6 +121,7 @@
     return NO_INIT;
   }
 
+  const uint32_t kLayerCount = 1;
   if (static_cast<int32_t>(core_->producer_->capacity()) <
       max_dequeued_buffer_count_ +
           BufferHubQueueCore::kDefaultUndequeuedBuffers) {
@@ -128,7 +129,7 @@
     // |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 = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
     if (ret < 0)
       return ret;
   }
@@ -138,8 +139,10 @@
 
   for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
     LocalHandle fence;
-    buffer_producer =
+    auto buffer_status =
         core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot, &fence);
+
+    buffer_producer = buffer_status.take();
     if (!buffer_producer)
       return NO_MEMORY;
 
@@ -170,7 +173,7 @@
     // 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);
+    ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
     if (ret < 0)
       return ret;
   }
@@ -532,7 +535,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;
   }
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 6467c3c..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
@@ -33,6 +33,11 @@
   // a new consumer queue client or nullptr on failure.
   std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
 
+  // Create a new consumer queue that is attached to the producer. This queue
+  // sets each of its imported consumer buffers to the ignored state to avoid
+  // participation in lifecycle events.
+  std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
+
   // Return the default buffer width of this buffer queue.
   size_t default_width() const { return default_width_; }
 
@@ -71,9 +76,19 @@
     }
   }
 
+  // Returns an fd that signals pending queue events using
+  // EPOLLIN/POLLIN/readible. Either HandleQueueEvents or WaitForBuffers may be
+  // called to handle pending queue events.
+  int queue_fd() const { return epoll_fd_.Get(); }
+
+  // Handles any pending events, returning available buffers to the queue and
+  // reaping disconnected buffers. Returns true if successful, false if an error
+  // occurred.
+  bool HandleQueueEvents() { return WaitForBuffers(0); }
+
   // Enqueue a buffer marks buffer to be available (|Gain|'ed for producer
   // and |Acquire|'ed for consumer. This is only used for internal bookkeeping.
-  void Enqueue(std::shared_ptr<BufferHubBuffer> buf, size_t slot);
+  void Enqueue(const std::shared_ptr<BufferHubBuffer>& buf, size_t slot);
 
   // |BufferHubQueue| will keep track of at most this value of buffers.
   static constexpr size_t kMaxQueueCapacity =
@@ -88,6 +103,7 @@
   static constexpr int kNoTimeOut = -1;
 
   int id() const { return id_; }
+  bool hung_up() const { return hung_up_; }
 
  protected:
   BufferHubQueue(LocalChannelHandle channel);
@@ -113,15 +129,17 @@
   // block. Specifying a timeout of -1 causes |Dequeue()| to block indefinitely,
   // while specifying a timeout equal to zero cause |Dequeue()| to return
   // immediately, even if no buffers are available.
-  std::shared_ptr<BufferHubBuffer> Dequeue(int timeout, size_t* slot,
-                                           void* meta, LocalHandle* fence);
+  pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
+                                                        size_t* slot,
+                                                        void* meta,
+                                                        LocalHandle* fence);
 
   // Wait for buffers to be released and re-add them to the queue.
   bool WaitForBuffers(int timeout);
-  void HandleBufferEvent(size_t slot, const epoll_event& event);
-  void HandleQueueEvent(const epoll_event& event);
+  void HandleBufferEvent(size_t slot, int poll_events);
+  void HandleQueueEvent(int poll_events);
 
-  virtual int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+  virtual int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
                             LocalHandle* fence) = 0;
 
   // Called when a buffer is allocated remotely.
@@ -248,6 +266,12 @@
   // Epoll fd used to wait for BufferHub events.
   EpollFileDescriptor epoll_fd_;
 
+  // Flag indicating that the other side hung up. For ProducerQueues this
+  // triggers when BufferHub dies or explicitly closes the queue channel. For
+  // ConsumerQueues this can either mean the same or that the ProducerQueue on
+  // the other end hung up.
+  bool hung_up_{false};
+
   // Global id for the queue that is consistent across processes.
   int id_;
 
@@ -261,6 +285,9 @@
   static std::unique_ptr<ProducerQueue> Create() {
     return BASE::Create(sizeof(Meta));
   }
+  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes) {
+    return BASE::Create(meta_size_bytes);
+  }
 
   // Usage bits in |usage_set_mask| will be automatically masked on. Usage bits
   // in |usage_clear_mask| will be automatically masked off. Note that
@@ -279,22 +306,15 @@
                                                uint32_t usage_deny_set_mask,
                                                uint32_t usage_deny_clear_mask) {
     return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask,
-                        usage_set_mask, usage_clear_mask, usage_deny_set_mask,
-                        usage_deny_clear_mask);
+                        usage_deny_set_mask, usage_deny_clear_mask);
   }
-  template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create(
-      uint64_t producer_usage_set_mask, uint64_t producer_usage_clear_mask,
-      uint64_t producer_usage_deny_set_mask,
-      uint64_t producer_usage_deny_clear_mask, uint64_t consumer_usage_set_mask,
-      uint64_t consumer_usage_clear_mask, uint64_t consumer_usage_deny_set_mask,
-      uint64_t consumer_usage_deny_clear_mask) {
-    return BASE::Create(sizeof(Meta), producer_usage_set_mask,
-                        producer_usage_clear_mask, producer_usage_deny_set_mask,
-                        producer_usage_deny_clear_mask, consumer_usage_set_mask,
-                        consumer_usage_clear_mask, consumer_usage_deny_set_mask,
-                        consumer_usage_deny_clear_mask);
+  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes,
+                                               uint32_t usage_set_mask,
+                                               uint32_t usage_clear_mask,
+                                               uint32_t usage_deny_set_mask,
+                                               uint32_t usage_deny_clear_mask) {
+    return BASE::Create(meta_size_bytes, usage_set_mask, usage_clear_mask,
+                        usage_deny_set_mask, usage_deny_clear_mask);
   }
 
   // Import a |ProducerQueue| from a channel handle.
@@ -316,11 +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,
-                     uint32_t usage, size_t slice_count, size_t* out_slot);
-  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
-                     uint64_t producer_usage, uint64_t consumer_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).
@@ -334,8 +351,8 @@
   // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
   // and caller should call Post() once it's done writing to release the buffer
   // to the consumer side.
-  std::shared_ptr<BufferProducer> Dequeue(int timeout, size_t* slot,
-                                          LocalHandle* release_fence);
+  pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+      int timeout, size_t* slot, LocalHandle* release_fence);
 
  private:
   friend BASE;
@@ -345,33 +362,47 @@
   // arguments as the constructors.
   explicit ProducerQueue(size_t meta_size);
   ProducerQueue(LocalChannelHandle handle);
-  ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
-                uint64_t producer_usage_clear_mask,
-                uint64_t producer_usage_deny_set_mask,
-                uint64_t producer_usage_deny_clear_mask,
-                uint64_t consumer_usage_set_mask,
-                uint64_t consumer_usage_clear_mask,
-                uint64_t consumer_usage_deny_set_mask,
-                uint64_t consumer_usage_deny_clear_mask);
+  ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
+                uint64_t usage_clear_mask, uint64_t usage_deny_set_mask,
+                uint64_t usage_deny_clear_mask);
 
-  int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+  int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
                     LocalHandle* release_fence) override;
 };
 
+// Explicit specializations of ProducerQueue::Create for void metadata type.
+template <>
+inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>() {
+  return ProducerQueue::Create(0);
+}
+template <>
+inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>(
+    uint32_t usage_set_mask, uint32_t usage_clear_mask,
+    uint32_t usage_deny_set_mask, uint32_t usage_deny_clear_mask) {
+  return ProducerQueue::Create(0, usage_set_mask, usage_clear_mask,
+                               usage_deny_set_mask, usage_deny_clear_mask);
+}
+
 class ConsumerQueue : public BufferHubQueue {
  public:
   // Get a buffer consumer. Note that the method doesn't check whether the
   // buffer slot has a valid buffer that has been imported already. When no
-  // buffer has been imported before it returns |nullptr|; otherwise it returns
-  // a shared pointer to a |BufferConsumer|.
+  // buffer has been imported before it returns nullptr; otherwise returns a
+  // shared pointer to a BufferConsumer.
   std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const {
     return std::static_pointer_cast<BufferConsumer>(
         BufferHubQueue::GetBuffer(slot));
   }
 
-  // Import a |ConsumerQueue| from a channel handle.
-  static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle) {
-    return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(std::move(handle)));
+  // Import a ConsumerQueue from a channel handle. |ignore_on_import| controls
+  // whether or not buffers are set to be ignored when imported. This may be
+  // used to avoid participation in the buffer lifecycle by a consumer queue
+  // that is only used to spawn other consumer queues, such as in an
+  // intermediate service.
+  static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle,
+                                               bool ignore_on_import = false) {
+    return std::unique_ptr<ConsumerQueue>(
+        new ConsumerQueue(std::move(handle), ignore_on_import));
   }
 
   // Import newly created buffers from the service side.
@@ -385,19 +416,23 @@
   // Dequeue() is done with the corect metadata type and size with those used
   // when the buffer is orignally created.
   template <typename Meta>
-  std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, Meta* meta,
-                                          LocalHandle* acquire_fence) {
+  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+      int timeout, size_t* slot, Meta* meta, LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
   }
+  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+      int timeout, size_t* slot, LocalHandle* acquire_fence) {
+    return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
+  }
 
-  std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
-                                          size_t meta_size,
-                                          LocalHandle* acquire_fence);
+  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+      int timeout, size_t* slot, void* meta, size_t meta_size,
+      LocalHandle* acquire_fence);
 
  private:
   friend BufferHubQueue;
 
-  ConsumerQueue(LocalChannelHandle handle);
+  ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import = false);
 
   // Add a consumer buffer to populate the queue. Once added, a consumer buffer
   // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
@@ -405,32 +440,17 @@
   // consumer.
   int AddBuffer(const std::shared_ptr<BufferConsumer>& buf, size_t slot);
 
-  int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+  int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
                     LocalHandle* acquire_fence) override;
 
   Status<void> OnBufferAllocated() override;
+
+  // Flag indicating that imported (consumer) buffers should be ignored when
+  // imported to avoid participating in the buffer ownership flow.
+  bool ignore_on_import_;
 };
 
 }  // namespace dvr
 }  // namespace android
 
-// Concrete C type definition for DVR API.
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct DvrWriteBufferQueue {
-  std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
-  ANativeWindow* native_window_{nullptr};
-};
-
-struct DvrReadBufferQueue {
-  std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue_;
-};
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
 #endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
index 9a8a2c9..180906b 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
@@ -118,8 +118,8 @@
   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);
+  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+                     PixelFormat format, uint64_t usage);
 
   // Detach a buffer producer through BufferHub.
   int DetachBuffer(size_t slot);
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..bf916ba 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
@@ -29,8 +29,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 +40,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 +59,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;
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 171577d..fe0b12a 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -15,35 +15,48 @@
 
 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:
   template <typename Meta>
-  bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
-                    int usage_deny_set_mask = 0,
-                    int usage_deny_clear_mask = 0) {
+  bool CreateProducerQueue(uint64_t usage_set_mask = 0,
+                           uint64_t usage_clear_mask = 0,
+                           uint64_t usage_deny_set_mask = 0,
+                           uint64_t usage_deny_clear_mask = 0) {
     producer_queue_ =
         ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask,
                                     usage_deny_set_mask, usage_deny_clear_mask);
-    if (!producer_queue_)
-      return false;
+    return producer_queue_ != nullptr;
+  }
 
-    consumer_queue_ = producer_queue_->CreateConsumerQueue();
-    if (!consumer_queue_)
+  bool CreateConsumerQueue() {
+    if (producer_queue_) {
+      consumer_queue_ = producer_queue_->CreateConsumerQueue();
+      return consumer_queue_ != nullptr;
+    } else {
       return false;
+    }
+  }
 
-    return true;
+  template <typename Meta>
+  bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
+                    int usage_deny_set_mask = 0,
+                    int usage_deny_clear_mask = 0) {
+    return CreateProducerQueue<Meta>(usage_set_mask, usage_clear_mask,
+                                     usage_deny_set_mask,
+                                     usage_deny_clear_mask) &&
+           CreateConsumerQueue();
   }
 
   void AllocateBuffer() {
     // 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);
   }
 
@@ -64,12 +77,16 @@
   for (size_t i = 0; i < nb_dequeue_times; i++) {
     size_t slot;
     LocalHandle fence;
-    auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+    auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+    ASSERT_TRUE(p1_status.ok());
+    auto p1 = p1_status.take();
     ASSERT_NE(nullptr, p1);
     size_t mi = i;
     ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
     size_t mo;
-    auto c1 = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
+    auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
+    ASSERT_TRUE(c1_status.ok());
+    auto c1 = c1_status.take();
     ASSERT_NE(nullptr, c1);
     ASSERT_EQ(mi, mo);
     c1->Release(LocalHandle());
@@ -94,23 +111,27 @@
     ASSERT_EQ(consumer_queue_->count(), 0U);
     // Consumer queue does not import buffers until a dequeue is issued.
     ASSERT_EQ(consumer_queue_->capacity(), i);
-    // Dequeue returns nullptr since no buffer is ready to consumer, but
+    // Dequeue returns timeout since no buffer is ready to consumer, but
     // this implicitly triggers buffer import and bump up |capacity|.
     LocalHandle fence;
-    auto consumer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
-    ASSERT_EQ(nullptr, consumer_null);
+    auto status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
+    ASSERT_FALSE(status.ok());
+    ASSERT_EQ(ETIMEDOUT, status.error());
     ASSERT_EQ(consumer_queue_->capacity(), i + 1);
   }
 
   for (size_t i = 0; i < nb_buffer; i++) {
     LocalHandle fence;
     // First time, there is no buffer available to dequeue.
-    auto buffer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
-    ASSERT_EQ(nullptr, buffer_null);
+    auto consumer_status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
+    ASSERT_FALSE(consumer_status.ok());
+    ASSERT_EQ(ETIMEDOUT, consumer_status.error());
 
     // Make sure Producer buffer is Post()'ed so that it's ready to Accquire
     // in the consumer's Dequeue() function.
-    auto producer = producer_queue_->Dequeue(0, &slot, &fence);
+    auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+    ASSERT_TRUE(producer_status.ok());
+    auto producer = producer_status.take();
     ASSERT_NE(nullptr, producer);
 
     uint64_t seq_in = static_cast<uint64_t>(i);
@@ -118,12 +139,86 @@
 
     // Second time, the just |Post()|'ed buffer should be dequeued.
     uint64_t seq_out = 0;
-    auto consumer = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
+    consumer_status = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
+    ASSERT_TRUE(consumer_status.ok());
+    auto consumer = consumer_status.take();
     ASSERT_NE(nullptr, consumer);
     ASSERT_EQ(seq_in, seq_out);
   }
 }
 
+TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
+  ASSERT_TRUE(CreateProducerQueue<void>());
+
+  // Allocate buffers.
+  const size_t kBufferCount = 4u;
+  for (size_t i = 0; i < kBufferCount; i++) {
+    AllocateBuffer();
+  }
+  ASSERT_EQ(kBufferCount, producer_queue_->count());
+
+  // Build a silent consumer queue to test multi-consumer queue features.
+  auto silent_queue = producer_queue_->CreateSilentConsumerQueue();
+  ASSERT_NE(nullptr, silent_queue);
+
+  // Check that buffers are correctly imported on construction.
+  EXPECT_EQ(kBufferCount, silent_queue->capacity());
+
+  // Dequeue and post a buffer.
+  size_t slot;
+  LocalHandle fence;
+  auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+  ASSERT_TRUE(producer_status.ok());
+  auto producer_buffer = producer_status.take();
+  ASSERT_NE(nullptr, producer_buffer);
+  ASSERT_EQ(0, producer_buffer->Post<void>({}));
+
+  // Currently we expect no buffer to be available prior to calling
+  // WaitForBuffers/HandleQueueEvents.
+  // TODO(eieio): Note this behavior may change in the future.
+  EXPECT_EQ(0u, silent_queue->count());
+  EXPECT_FALSE(silent_queue->HandleQueueEvents());
+  EXPECT_EQ(0u, silent_queue->count());
+
+  // Build a new consumer queue to test multi-consumer queue features.
+  consumer_queue_ = silent_queue->CreateConsumerQueue();
+  ASSERT_NE(nullptr, consumer_queue_);
+
+  // Check that buffers are correctly imported on construction.
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_EQ(1u, consumer_queue_->count());
+
+  // Reclaim released/ignored buffers.
+  producer_queue_->HandleQueueEvents();
+  ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
+
+  // Post another buffer.
+  producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+  ASSERT_TRUE(producer_status.ok());
+  producer_buffer = producer_status.take();
+  ASSERT_NE(nullptr, producer_buffer);
+  ASSERT_EQ(0, producer_buffer->Post<void>({}));
+
+  // Verify that the consumer queue receives it.
+  EXPECT_EQ(1u, consumer_queue_->count());
+  EXPECT_TRUE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(2u, consumer_queue_->count());
+
+  // Dequeue and acquire/release (discard) buffers on the consumer end.
+  auto consumer_status = consumer_queue_->Dequeue(0, &slot, &fence);
+  ASSERT_TRUE(consumer_status.ok());
+  auto consumer_buffer = consumer_status.take();
+  ASSERT_NE(nullptr, consumer_buffer);
+  consumer_buffer->Discard();
+
+  // Buffer should be returned to the producer queue without being handled by
+  // the silent consumer queue.
+  EXPECT_EQ(1u, consumer_queue_->count());
+  EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
+  EXPECT_TRUE(producer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
+}
+
 struct TestMetadata {
   char a;
   int32_t b;
@@ -140,11 +235,15 @@
   for (auto mi : ms) {
     size_t slot;
     LocalHandle fence;
-    auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+    auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+    ASSERT_TRUE(p1_status.ok());
+    auto p1 = p1_status.take();
     ASSERT_NE(nullptr, p1);
     ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
     TestMetadata mo;
-    auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+    auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+    ASSERT_TRUE(c1_status.ok());
+    auto c1 = c1_status.take();
     ASSERT_EQ(mi.a, mo.a);
     ASSERT_EQ(mi.b, mo.b);
     ASSERT_EQ(mi.c, mo.c);
@@ -159,14 +258,16 @@
   int64_t mi = 3;
   size_t slot;
   LocalHandle fence;
-  auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+  ASSERT_TRUE(p1_status.ok());
+  auto p1 = p1_status.take();
   ASSERT_NE(nullptr, p1);
   ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
 
   int32_t mo;
   // Acquire a buffer with mismatched metadata is not OK.
-  auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
-  ASSERT_EQ(nullptr, c1);
+  auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+  ASSERT_FALSE(c1_status.ok());
 }
 
 TEST_F(BufferHubQueueTest, TestEnqueue) {
@@ -175,13 +276,15 @@
 
   size_t slot;
   LocalHandle fence;
-  auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+  ASSERT_TRUE(p1_status.ok());
+  auto p1 = p1_status.take();
   ASSERT_NE(nullptr, p1);
 
   int64_t mo;
   producer_queue_->Enqueue(p1, slot);
-  auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
-  ASSERT_EQ(nullptr, c1);
+  auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+  ASSERT_FALSE(c1_status.ok());
 }
 
 TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
@@ -190,13 +293,16 @@
   size_t s1;
   AllocateBuffer();
   LocalHandle fence;
-  auto p1 = producer_queue_->Dequeue(0, &s1, &fence);
+  auto p1_status = producer_queue_->Dequeue(0, &s1, &fence);
+  ASSERT_TRUE(p1_status.ok());
+  auto p1 = p1_status.take();
   ASSERT_NE(nullptr, p1);
 
   // producer queue is exhausted
   size_t s2;
-  auto p2_null = producer_queue_->Dequeue(0, &s2, &fence);
-  ASSERT_EQ(nullptr, p2_null);
+  auto p2_status = producer_queue_->Dequeue(0, &s2, &fence);
+  ASSERT_FALSE(p2_status.ok());
+  ASSERT_EQ(ETIMEDOUT, p2_status.error());
 
   // dynamically add buffer.
   AllocateBuffer();
@@ -204,7 +310,9 @@
   ASSERT_EQ(producer_queue_->capacity(), 2U);
 
   // now we can dequeue again
-  auto p2 = producer_queue_->Dequeue(0, &s2, &fence);
+  p2_status = producer_queue_->Dequeue(0, &s2, &fence);
+  ASSERT_TRUE(p2_status.ok());
+  auto p2 = p2_status.take();
   ASSERT_NE(nullptr, p2);
   ASSERT_EQ(producer_queue_->count(), 0U);
   // p1 and p2 should have different slot number
@@ -217,85 +325,93 @@
   int64_t seq = 1;
   ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
   size_t cs1, cs2;
-  auto c1 = consumer_queue_->Dequeue(0, &cs1, &seq, &fence);
+  auto c1_status = consumer_queue_->Dequeue(0, &cs1, &seq, &fence);
+  ASSERT_TRUE(c1_status.ok());
+  auto c1 = c1_status.take();
   ASSERT_NE(nullptr, c1);
   ASSERT_EQ(consumer_queue_->count(), 0U);
   ASSERT_EQ(consumer_queue_->capacity(), 2U);
   ASSERT_EQ(cs1, s1);
 
   ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
-  auto c2 = consumer_queue_->Dequeue(0, &cs2, &seq, &fence);
+  auto c2_status = consumer_queue_->Dequeue(0, &cs2, &seq, &fence);
+  ASSERT_TRUE(c2_status.ok());
+  auto c2 = c2_status.take();
   ASSERT_NE(nullptr, c2);
   ASSERT_EQ(cs2, s2);
 }
 
 TEST_F(BufferHubQueueTest, TestUsageSetMask) {
-  const int set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
+  const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
   ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0));
 
   // When allocation, leave out |set_mask| from usage bits on purpose.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage & ~set_mask,
-      kBufferSliceCount, &slot);
-  ASSERT_EQ(ret, 0);
+  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                            kBufferFormat, kBufferLayerCount,
+                                            kBufferUsage & ~set_mask, &slot);
+  ASSERT_EQ(0, ret);
 
   LocalHandle fence;
-  auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+  ASSERT_TRUE(p1_status.ok());
+  auto p1 = p1_status.take();
   ASSERT_EQ(p1->usage() & set_mask, set_mask);
 }
 
 TEST_F(BufferHubQueueTest, TestUsageClearMask) {
-  const int clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
+  const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
   ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0));
 
   // When allocation, add |clear_mask| into usage bits on purpose.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage | clear_mask,
-      kBufferSliceCount, &slot);
-  ASSERT_EQ(ret, 0);
+  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                            kBufferLayerCount, kBufferFormat,
+                                            kBufferUsage | clear_mask, &slot);
+  ASSERT_EQ(0, ret);
 
   LocalHandle fence;
-  auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
-  ASSERT_EQ(p1->usage() & clear_mask, 0);
+  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+  ASSERT_TRUE(p1_status.ok());
+  auto p1 = p1_status.take();
+  ASSERT_EQ(0u, p1->usage() & clear_mask);
 }
 
 TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
-  const int deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
+  const uint32_t deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
   ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0));
 
   // Now that |deny_set_mask| is illegal, allocation without those bits should
   // be able to succeed.
   size_t slot;
   int ret = producer_queue_->AllocateBuffer(
-      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);
 }
 
 TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
-  const int deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
+  const uint32_t deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
   ASSERT_TRUE(CreateQueues<int64_t>(0, 0, 0, deny_clear_mask));
 
   // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
   // mandatory), allocation with those bits should be able to succeed.
   size_t slot;
   int ret = producer_queue_->AllocateBuffer(
-      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/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index de2a56e..41baef8 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -15,16 +15,14 @@
 sourceFiles = [
     "native_buffer_queue.cpp",
     "display_client.cpp",
-    "display_manager_client_impl.cpp",
-    "display_rpc.cpp",
+    "display_manager_client.cpp",
+    "display_protocol.cpp",
     "dummy_native_window.cpp",
+    "frame_history.cpp",
     "gl_fenced_flush.cpp",
     "graphics.cpp",
     "late_latch.cpp",
-    "video_mesh_surface_client.cpp",
     "vsync_client.cpp",
-    "screenshot_client.cpp",
-    "frame_history.cpp",
 ]
 
 localIncludeFiles = [
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index ef50a0f..5c9ebd4 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -8,10 +8,11 @@
 
 #include <mutex>
 
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/display_protocol.h>
 #include <private/dvr/late_latch.h>
 #include <private/dvr/native_buffer.h>
 
+using android::pdx::ErrorStatus;
 using android::pdx::LocalHandle;
 using android::pdx::LocalChannelHandle;
 using android::pdx::Status;
@@ -20,99 +21,61 @@
 
 namespace android {
 namespace dvr {
+namespace display {
 
-SurfaceClient::SurfaceClient(LocalChannelHandle channel_handle,
-                             SurfaceType type)
-    : Client{pdx::default_transport::ClientChannel::Create(
-          std::move(channel_handle))},
-      type_(type) {}
-
-SurfaceClient::SurfaceClient(const std::string& endpoint_path, SurfaceType type)
-    : Client{pdx::default_transport::ClientChannelFactory::Create(
-                 endpoint_path),
-             kInfiniteTimeout},
-      type_(type) {}
-
-int SurfaceClient::GetMetadataBufferFd(LocalHandle* out_fd) {
-  auto buffer_producer = GetMetadataBuffer();
-  if (!buffer_producer)
-    return -ENOMEM;
-
-  *out_fd = buffer_producer->GetBlobFd();
-  return 0;
-}
-
-std::shared_ptr<BufferProducer> SurfaceClient::GetMetadataBuffer() {
-  if (!metadata_buffer_) {
-    auto status = InvokeRemoteMethod<DisplayRPC::GetMetadataBuffer>();
-    if (!status) {
-      ALOGE(
-          "SurfaceClient::AllocateMetadataBuffer: Failed to allocate buffer: "
-          "%s",
+Surface::Surface(LocalChannelHandle channel_handle, int* error)
+    : BASE{pdx::default_transport::ClientChannel::Create(
+          std::move(channel_handle))} {
+  auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>();
+  if (!status) {
+    ALOGE("Surface::Surface: Failed to get surface info: %s",
           status.GetErrorMessage().c_str());
-      return nullptr;
-    }
-
-    metadata_buffer_ = BufferProducer::Import(status.take());
-  }
-
-  return metadata_buffer_;
-}
-
-DisplaySurfaceClient::DisplaySurfaceClient(int width, int height, int format,
-                                           int usage, int flags)
-    : BASE(DisplayRPC::kClientPath, SurfaceTypeEnum::Normal),
-      width_(width),
-      height_(height),
-      format_(format),
-      usage_(usage),
-      flags_(flags),
-      z_order_(0),
-      visible_(true),
-      exclude_from_blur_(false),
-      blur_behind_(true),
-      mapped_metadata_buffer_(nullptr) {
-  auto status = InvokeRemoteMethod<DisplayRPC::CreateSurface>(
-      width, height, format, usage, flags);
-  if (!status) {
-    ALOGE(
-        "DisplaySurfaceClient::DisplaySurfaceClient: Failed to create display "
-        "surface: %s",
-        status.GetErrorMessage().c_str());
     Close(status.error());
+    if (error)
+      *error = status.error();
   }
+
+  surface_id_ = status.get().surface_id;
+  z_order_ = status.get().z_order;
+  visible_ = status.get().visible;
 }
 
-void DisplaySurfaceClient::SetVisible(bool visible) {
-  SetAttributes({{DisplaySurfaceAttributeEnum::Visible,
-                  DisplaySurfaceAttributeValue{visible}}});
+Surface::Surface(const SurfaceAttributes& attributes, int* error)
+    : BASE{pdx::default_transport::ClientChannelFactory::Create(
+               DisplayProtocol::kClientPath),
+           kInfiniteTimeout} {
+  auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes);
+  if (!status) {
+    ALOGE("Surface::Surface: Failed to create display surface: %s",
+          status.GetErrorMessage().c_str());
+    Close(status.error());
+    if (error)
+      *error = status.error();
+  }
+
+  surface_id_ = status.get().surface_id;
+  z_order_ = status.get().z_order;
+  visible_ = status.get().visible;
 }
 
-void DisplaySurfaceClient::SetZOrder(int z_order) {
-  SetAttributes({{DisplaySurfaceAttributeEnum::ZOrder,
-                  DisplaySurfaceAttributeValue{z_order}}});
+Status<void> Surface::SetVisible(bool visible) {
+  return SetAttributes(
+      {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
 }
 
-void DisplaySurfaceClient::SetExcludeFromBlur(bool exclude_from_blur) {
-  SetAttributes({{DisplaySurfaceAttributeEnum::ExcludeFromBlur,
-                  DisplaySurfaceAttributeValue{exclude_from_blur}}});
+Status<void> Surface::SetZOrder(int z_order) {
+  return SetAttributes(
+      {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
 }
 
-void DisplaySurfaceClient::SetBlurBehind(bool blur_behind) {
-  SetAttributes({{DisplaySurfaceAttributeEnum::BlurBehind,
-                  DisplaySurfaceAttributeValue{blur_behind}}});
-}
-
-void DisplaySurfaceClient::SetAttributes(
-    const DisplaySurfaceAttributes& attributes) {
-  Status<int> status =
-      InvokeRemoteMethod<DisplayRPC::SetAttributes>(attributes);
+Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
+  auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
   if (!status) {
     ALOGE(
-        "DisplaySurfaceClient::SetAttributes: Failed to set display surface "
+        "Surface::SetAttributes: Failed to set display surface "
         "attributes: %s",
         status.GetErrorMessage().c_str());
-    return;
+    return status.error_status();
   }
 
   // Set the local cached copies of the attributes we care about from the full
@@ -122,159 +85,127 @@
     const auto* variant = &attribute.second;
     bool invalid_value = false;
     switch (key) {
-      case DisplaySurfaceAttributeEnum::Visible:
+      case SurfaceAttribute::Visible:
         invalid_value =
             !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
         break;
-      case DisplaySurfaceAttributeEnum::ZOrder:
+      case SurfaceAttribute::ZOrder:
         invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
         break;
-      case DisplaySurfaceAttributeEnum::ExcludeFromBlur:
-        invalid_value =
-            !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &exclude_from_blur_);
-        break;
-      case DisplaySurfaceAttributeEnum::BlurBehind:
-        invalid_value =
-            !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &blur_behind_);
-        break;
     }
 
     if (invalid_value) {
       ALOGW(
-          "DisplaySurfaceClient::SetAttributes: Failed to set display "
-          "surface attribute '%s' because of incompatible type: %d",
-          DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index());
-    }
-  }
-}
-
-std::shared_ptr<ProducerQueue> DisplaySurfaceClient::GetProducerQueue() {
-  if (producer_queue_ == nullptr) {
-    // Create producer queue through DisplayRPC
-    auto status = InvokeRemoteMethod<DisplayRPC::CreateBufferQueue>();
-    if (!status) {
-      ALOGE(
-          "DisplaySurfaceClient::GetProducerQueue: failed to create producer "
-          "queue: %s",
-          status.GetErrorMessage().c_str());
-      return nullptr;
-    }
-
-    producer_queue_ = ProducerQueue::Import(status.take());
-  }
-  return producer_queue_;
-}
-
-volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() {
-  if (!mapped_metadata_buffer_) {
-    if (auto buffer_producer = GetMetadataBuffer()) {
-      void* addr = nullptr;
-      const int ret = buffer_producer->GetBlobReadWritePointer(
-          sizeof(DisplaySurfaceMetadata), &addr);
-      if (ret < 0) {
-        ALOGE(
-            "DisplaySurfaceClient::GetMetadataBufferPtr: Failed to map surface "
-            "metadata: %s",
-            strerror(-ret));
-        return nullptr;
-      }
-      mapped_metadata_buffer_ = static_cast<DisplaySurfaceMetadata*>(addr);
+          "Surface::SetAttributes: Failed to set display surface "
+          "attribute %d because of incompatible type: %d",
+          key, variant->index());
     }
   }
 
-  return mapped_metadata_buffer_;
+  return {};
 }
 
-LocalChannelHandle DisplaySurfaceClient::CreateVideoMeshSurface() {
-  auto status = InvokeRemoteMethod<DisplayRPC::CreateVideoMeshSurface>();
+Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() {
+  ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
+  auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0);
   if (!status) {
-    ALOGE(
-        "DisplaySurfaceClient::CreateVideoMeshSurface: Failed to create "
-        "video mesh surface: %s",
-        status.GetErrorMessage().c_str());
+    ALOGE("Surface::CreateQueue: Failed to create queue: %s",
+          status.GetErrorMessage().c_str());
+    return status.error_status();
   }
-  return status.take();
+
+  auto producer_queue = ProducerQueue::Import(status.take());
+  if (!producer_queue) {
+    ALOGE("Surface::CreateQueue: Failed to import producer queue!");
+    return ErrorStatus(ENOMEM);
+  }
+
+  return {std::move(producer_queue)};
+}
+
+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 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();
+
+  auto producer_queue = status.take();
+
+  ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
+  for (size_t i = 0; i < capacity; i++) {
+    size_t slot;
+    const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
+                                                   format, usage, &slot);
+    if (ret < 0) {
+      ALOGE(
+          "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
+          producer_queue->id(), strerror(-ret));
+      return ErrorStatus(ENOMEM);
+    }
+    ALOGD_IF(
+        TRACE,
+        "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
+        slot, capacity);
+  }
+
+  return {std::move(producer_queue)};
 }
 
 DisplayClient::DisplayClient(int* error)
     : BASE(pdx::default_transport::ClientChannelFactory::Create(
-               DisplayRPC::kClientPath),
+               DisplayProtocol::kClientPath),
            kInfiniteTimeout) {
   if (error)
     *error = Client::error();
 }
 
-int DisplayClient::GetDisplayMetrics(SystemDisplayMetrics* metrics) {
-  auto status = InvokeRemoteMethod<DisplayRPC::GetMetrics>();
-  if (!status) {
-    ALOGE("DisplayClient::GetDisplayMetrics: Failed to get metrics: %s",
-          status.GetErrorMessage().c_str());
-    return -status.error();
-  }
-
-  *metrics = status.get();
-  return 0;
+Status<Metrics> DisplayClient::GetDisplayMetrics() {
+  return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
 }
 
-pdx::Status<void> DisplayClient::SetViewerParams(
-    const ViewerParams& viewer_params) {
-  auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params);
-  if (!status) {
-    ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s",
-          status.GetErrorMessage().c_str());
-  }
-  return status;
+Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
+    const SurfaceAttributes& attributes) {
+  int error;
+  if (auto client = Surface::Create(attributes, &error))
+    return {std::move(client)};
+  else
+    return ErrorStatus(error);
 }
 
-int DisplayClient::GetLastFrameEdsTransform(LateLatchOutput* ll_out) {
-  auto status = InvokeRemoteMethod<DisplayRPC::GetEdsCapture>();
-  if (!status) {
-    ALOGE(
-        "DisplayClient::GetLastFrameLateLatch: Failed to get most recent late"
-        " latch: %s",
-        status.GetErrorMessage().c_str());
-    return -status.error();
-  }
-
-  if (status.get().size() != sizeof(LateLatchOutput)) {
-    ALOGE(
-        "DisplayClient::GetLastFrameLateLatch: Error expected to receive %zu "
-        "bytes but received %zu",
-        sizeof(LateLatchOutput), status.get().size());
-    return -EIO;
-  }
-
-  *ll_out = *reinterpret_cast<const LateLatchOutput*>(status.get().data());
-  return 0;
-}
-
-std::unique_ptr<DisplaySurfaceClient> DisplayClient::CreateDisplaySurface(
-    int width, int height, int format, int usage, int flags) {
-  return DisplaySurfaceClient::Create(width, height, format, usage, flags);
-}
-
-std::unique_ptr<IonBuffer> DisplayClient::GetNamedBuffer(
+Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
     const std::string& name) {
-  auto status = InvokeRemoteMethod<DisplayRPC::GetNamedBuffer>(name);
+  auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
   if (!status) {
     ALOGE(
-        "DisplayClient::GetNamedBuffer: Failed to get pose buffer. name=%s, "
+        "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
         "error=%s",
         name.c_str(), status.GetErrorMessage().c_str());
-    return nullptr;
+    return status.error_status();
   }
 
   auto ion_buffer = std::make_unique<IonBuffer>();
-  status.take().Import(ion_buffer.get());
-  return ion_buffer;
+  auto native_buffer_handle = status.take();
+  const int ret = native_buffer_handle.Import(ion_buffer.get());
+  if (ret < 0) {
+    ALOGE(
+        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
+        "name=%s; error=%s",
+        name.c_str(), strerror(-ret));
+    return ErrorStatus(-ret);
+  }
+
+  return {std::move(ion_buffer)};
 }
 
-bool DisplayClient::IsVrAppRunning() {
-  auto status = InvokeRemoteMethod<DisplayRPC::IsVrAppRunning>();
-  if (!status)
-    return 0;
-  return static_cast<bool>(status.get());
+Status<bool> DisplayClient::IsVrAppRunning() {
+  return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
 }
 
+}  // namespace display
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libdisplay/display_manager_client.cpp b/libs/vr/libdisplay/display_manager_client.cpp
new file mode 100644
index 0000000..82dacf7
--- /dev/null
+++ b/libs/vr/libdisplay/display_manager_client.cpp
@@ -0,0 +1,78 @@
+#include "include/private/dvr/display_manager_client.h"
+
+#include <pdx/default_transport/client_channel_factory.h>
+#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_protocol.h>
+#include <utils/Log.h>
+
+using android::pdx::ErrorStatus;
+using android::pdx::LocalChannelHandle;
+using android::pdx::Transaction;
+
+namespace android {
+namespace dvr {
+namespace display {
+
+DisplayManagerClient::DisplayManagerClient()
+    : BASE(pdx::default_transport::ClientChannelFactory::Create(
+          DisplayManagerProtocol::kClientPath)) {}
+
+DisplayManagerClient::~DisplayManagerClient() {}
+
+pdx::Status<std::vector<display::SurfaceState>>
+DisplayManagerClient::GetSurfaceState() {
+  auto status = InvokeRemoteMethod<DisplayManagerProtocol::GetSurfaceState>();
+  if (!status) {
+    ALOGE(
+        "DisplayManagerClient::GetSurfaceState: Failed to get surface info: %s",
+        status.GetErrorMessage().c_str());
+  }
+
+  return status;
+}
+
+pdx::Status<std::unique_ptr<IonBuffer>> DisplayManagerClient::SetupNamedBuffer(
+    const std::string& name, size_t size, uint64_t usage) {
+  auto status = InvokeRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
+      name, size, usage);
+  if (!status) {
+    ALOGE(
+        "DisplayManagerClient::SetupPoseBuffer: Failed to create the named "
+        "buffer %s",
+        status.GetErrorMessage().c_str());
+    return status.error_status();
+  }
+
+  auto ion_buffer = std::make_unique<IonBuffer>();
+  auto native_buffer_handle = status.take();
+  const int ret = native_buffer_handle.Import(ion_buffer.get());
+  if (ret < 0) {
+    ALOGE(
+        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
+        "name=%s; error=%s",
+        name.c_str(), strerror(-ret));
+    return ErrorStatus(-ret);
+  }
+
+  return {std::move(ion_buffer)};
+}
+
+pdx::Status<std::unique_ptr<ConsumerQueue>>
+DisplayManagerClient::GetSurfaceQueue(int surface_id, int queue_id) {
+  auto status = InvokeRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
+      surface_id, queue_id);
+  if (!status) {
+    ALOGE(
+        "DisplayManagerClient::GetSurfaceQueue: Failed to get queue for "
+        "surface_id=%d queue_id=%d: %s",
+        surface_id, queue_id, status.GetErrorMessage().c_str());
+    return status.error_status();
+  }
+
+  return {ConsumerQueue::Import(status.take())};
+}
+
+}  // namespace display
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libdisplay/display_manager_client_impl.cpp b/libs/vr/libdisplay/display_manager_client_impl.cpp
deleted file mode 100644
index 44b3c4b..0000000
--- a/libs/vr/libdisplay/display_manager_client_impl.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "include/private/dvr/display_manager_client_impl.h"
-
-#include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/display_rpc.h>
-#include <utils/Log.h>
-
-using android::pdx::LocalChannelHandle;
-using android::pdx::Transaction;
-
-namespace android {
-namespace dvr {
-
-DisplayManagerClient::DisplayManagerClient()
-    : BASE(pdx::default_transport::ClientChannelFactory::Create(
-          DisplayManagerRPC::kClientPath)) {}
-
-DisplayManagerClient::~DisplayManagerClient() {}
-
-int DisplayManagerClient::GetSurfaceList(
-    std::vector<DisplaySurfaceInfo>* surface_list) {
-  auto status = InvokeRemoteMethod<DisplayManagerRPC::GetSurfaceList>();
-  if (!status) {
-    ALOGE(
-        "DisplayManagerClient::GetSurfaceList: Failed to get surface info: %s",
-        status.GetErrorMessage().c_str());
-    return -status.error();
-  }
-
-  *surface_list = status.take();
-  return 0;
-}
-
-std::unique_ptr<IonBuffer> DisplayManagerClient::SetupNamedBuffer(
-    const std::string& name, size_t size, uint64_t producer_usage,
-    uint64_t consumer_usage) {
-  auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
-      name, size, producer_usage, consumer_usage);
-  if (!status) {
-    ALOGE(
-        "DisplayManagerClient::SetupNamedBuffer: Failed to create the named "
-        "buffer: name=%s, error=%s",
-        name.c_str(), status.GetErrorMessage().c_str());
-    return {};
-  }
-
-  auto ion_buffer = std::make_unique<IonBuffer>();
-  status.take().Import(ion_buffer.get());
-  return ion_buffer;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdisplay/display_protocol.cpp b/libs/vr/libdisplay/display_protocol.cpp
new file mode 100644
index 0000000..773f9a5
--- /dev/null
+++ b/libs/vr/libdisplay/display_protocol.cpp
@@ -0,0 +1,13 @@
+#include "include/private/dvr/display_protocol.h"
+
+namespace android {
+namespace dvr {
+namespace display {
+
+constexpr char DisplayProtocol::kClientPath[];
+constexpr char DisplayManagerProtocol::kClientPath[];
+constexpr char VSyncProtocol::kClientPath[];
+
+}  // namespace display
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libdisplay/display_rpc.cpp b/libs/vr/libdisplay/display_rpc.cpp
deleted file mode 100644
index f5693bd..0000000
--- a/libs/vr/libdisplay/display_rpc.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "include/private/dvr/display_rpc.h"
-
-namespace android {
-namespace dvr {
-
-constexpr char DisplayRPC::kClientPath[];
-constexpr char DisplayManagerRPC::kClientPath[];
-constexpr char DisplayScreenshotRPC::kClientPath[];
-constexpr char DisplayVSyncRPC::kClientPath[];
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libdisplay/graphics.cpp b/libs/vr/libdisplay/graphics.cpp
index 2abdf8e..36f8095 100644
--- a/libs/vr/libdisplay/graphics.cpp
+++ b/libs/vr/libdisplay/graphics.cpp
@@ -13,20 +13,19 @@
 #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/display_types.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/sensor_constants.h>
-#include <private/dvr/video_mesh_surface_client.h>
-#include <private/dvr/vsync_client.h>
 #include <private/dvr/platform_defines.h>
+#include <private/dvr/sensor_constants.h>
+#include <private/dvr/vsync_client.h>
 
 #include <android/native_window.h>
 
@@ -35,21 +34,30 @@
 #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::DisplaySurfaceAttributeEnum;
-using android::dvr::DisplaySurfaceAttributeValue;
+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 int kDefaultDisplaySurfaceUsage =
-    GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE |
-    GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
-constexpr int kDefaultDisplaySurfaceFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+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 int kDefaultBufferCount = 4;
+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};
@@ -279,51 +287,119 @@
   return 0;
 }
 
-}  // anonymous namespace
+// 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;
+};
 
-// TODO(hendrikw): When we remove the calls to this in native_window.cpp, move
-// this back into the anonymous namespace
-std::shared_ptr<android::dvr::DisplaySurfaceClient> CreateDisplaySurfaceClient(
-    struct DvrSurfaceParameter* parameters,
-    /*out*/ android::dvr::SystemDisplayMetrics* metrics) {
-  auto client = android::dvr::DisplayClient::Create();
-  if (!client) {
-    ALOGE("Failed to create display client!");
-    return nullptr;
+Status<std::tuple<std::shared_ptr<android::dvr::ProducerQueue>,
+                  std::shared_ptr<android::dvr::BufferProducer>,
+                  volatile DisplaySurfaceMetadata*>>
+CreateMetadataBuffer(const std::shared_ptr<Surface>& surface,
+                     bool direct_surface) {
+  std::shared_ptr<android::dvr::ProducerQueue> queue;
+  std::shared_ptr<android::dvr::BufferProducer> buffer;
+
+  if (!direct_surface) {
+    auto queue_status = surface->CreateQueue(
+        sizeof(DisplaySurfaceMetadata), 1, 1, HAL_PIXEL_FORMAT_BLOB,
+        GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET |
+            GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN |
+            GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER,
+        1);
+    if (!queue_status) {
+      ALOGE("CreateMetadataBuffer: Failed to create queue: %s",
+            queue_status.GetErrorMessage().c_str());
+      return queue_status.error_status();
+    }
+
+    queue = queue_status.take();
+    LocalHandle fence;
+    size_t slot;
+    auto buffer_status = queue->Dequeue(-1, &slot, &fence);
+    if (!buffer_status) {
+      ALOGE("CreateMetadataBuffer: Failed to dequeue buffer: %s",
+            buffer_status.GetErrorMessage().c_str());
+      return buffer_status.error_status();
+    }
+    buffer = buffer_status.take();
+  } else {
+    buffer = android::dvr::BufferProducer::CreateUncachedBlob(
+        sizeof(DisplaySurfaceMetadata));
+    if (!buffer) {
+      ALOGE("CreateMetadataBuffer: Failed to create stand-in buffer!");
+      return ErrorStatus(ENOMEM);
+    }
   }
 
-  const int ret = client->GetDisplayMetrics(metrics);
+  void* address = nullptr;
+  int ret =
+      buffer->GetBlobReadWritePointer(sizeof(DisplaySurfaceMetadata), &address);
+
   if (ret < 0) {
-    ALOGE("Failed to get display metrics: %s", strerror(-ret));
-    return nullptr;
+    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.
-  int request_width = -1;
-  int request_height = -1;
-  int request_flags = 0;
+
+  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 = true;
+  bool request_visible = false;
   bool vertical_flip = false;
+  bool direct_surface = false;
   int request_z_order = 0;
-  bool request_exclude_from_blur = false;
-  bool request_blur_behind = true;
-  int request_format = kDefaultDisplaySurfaceFormat;
-  int request_usage = kDefaultDisplaySurfaceUsage;
-  int geometry_type = DVR_SURFACE_GEOMETRY_SINGLE;
 
   // Handle parameter inputs.
   for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
     switch (p->key) {
-      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_DISABLE_DISTORTION_IN:
         disable_distortion = !!p->value;
         break;
@@ -339,20 +415,23 @@
       case DVR_SURFACE_PARAMETER_Z_ORDER_IN:
         request_z_order = p->value;
         break;
-      case DVR_SURFACE_PARAMETER_EXCLUDE_FROM_BLUR_IN:
-        request_exclude_from_blur = !!p->value;
-        break;
-      case DVR_SURFACE_PARAMETER_BLUR_BEHIND_IN:
-        request_blur_behind = !!p->value;
-        break;
       case DVR_SURFACE_PARAMETER_VERTICAL_FLIP_IN:
         vertical_flip = !!p->value;
         break;
-      case DVR_SURFACE_PARAMETER_GEOMETRY_IN:
-        geometry_type = p->value;
+      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 = DvrToHalSurfaceFormat(p->value);
+        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:
@@ -376,113 +455,90 @@
       case DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_FORMAT_OUT:
         break;
       default:
-        ALOGE("Invalid display surface parameter: key=%d value=%" PRId64,
-              p->key, p->value);
-        return nullptr;
+        ALOGE(
+            "CreateSurface: Invalid display surface parameter: key=%d "
+            "value=%" PRId64,
+            p->key, p->value);
+        return ErrorStatus(EINVAL);
     }
   }
 
-  request_flags |= disable_distortion
-                       ? DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION
-                       : 0;
-  request_flags |=
-      disable_stabilization ? DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_EDS : 0;
-  request_flags |=
-      disable_cac ? DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC : 0;
-  request_flags |= vertical_flip ? DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP : 0;
-  request_flags |= (geometry_type == DVR_SURFACE_GEOMETRY_SEPARATE_2)
-                       ? DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2
-                       : 0;
+  // TODO(eieio): Setup a "surface flags" attribute based on the surface
+  // parameters gathered above.
+  SurfaceAttributes surface_attributes;
 
-  if (request_width == -1) {
-    request_width = disable_distortion ? metrics->display_native_width
-                                       : metrics->distorted_width;
-    if (!disable_distortion &&
-        geometry_type == DVR_SURFACE_GEOMETRY_SEPARATE_2) {
-      // The metrics always return the single wide buffer resolution.
-      // When split between eyes, we need to halve the width of the surface.
-      request_width /= 2;
-    }
-  }
-  if (request_height == -1) {
-    request_height = disable_distortion ? metrics->display_native_height
-                                        : metrics->distorted_height;
+  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();
   }
 
-  std::shared_ptr<android::dvr::DisplaySurfaceClient> surface =
-      client->CreateDisplaySurface(request_width, request_height,
-                                   request_format, request_usage,
-                                   request_flags);
-  surface->SetAttributes(
-      {{DisplaySurfaceAttributeEnum::Visible,
-        DisplaySurfaceAttributeValue{request_visible}},
-       {DisplaySurfaceAttributeEnum::ZOrder,
-        DisplaySurfaceAttributeValue{request_z_order}},
-       {DisplaySurfaceAttributeEnum::ExcludeFromBlur,
-        DisplaySurfaceAttributeValue{request_exclude_from_blur}},
-       {DisplaySurfaceAttributeEnum::BlurBehind,
-        DisplaySurfaceAttributeValue{request_blur_behind}}});
+  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) = metrics->display_native_width;
+        *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) = metrics->display_native_height;
-        break;
-      case DVR_SURFACE_PARAMETER_SURFACE_WIDTH_OUT:
-        *static_cast<int32_t*>(p->value_out) = surface->width();
-        break;
-      case DVR_SURFACE_PARAMETER_SURFACE_HEIGHT_OUT:
-        *static_cast<int32_t*>(p->value_out) = surface->height();
-        break;
-      case DVR_SURFACE_PARAMETER_INTER_LENS_METERS_OUT:
-        *static_cast<float*>(p->value_out) = metrics->inter_lens_distance_m;
-        break;
-      case DVR_SURFACE_PARAMETER_LEFT_FOV_LRBT_OUT:
-        for (int i = 0; i < 4; ++i) {
-          float* float_values_out = static_cast<float*>(p->value_out);
-          float_values_out[i] = metrics->left_fov_lrbt[i];
-        }
-        break;
-      case DVR_SURFACE_PARAMETER_RIGHT_FOV_LRBT_OUT:
-        for (int i = 0; i < 4; ++i) {
-          float* float_values_out = static_cast<float*>(p->value_out);
-          float_values_out[i] = metrics->right_fov_lrbt[i];
-        }
+        *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) = metrics->vsync_period_ns;
+        *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;
+  return surface_status;
 }
 
-extern "C" int dvrGetNativeDisplayDimensions(int* native_width,
-                                             int* native_height) {
+extern "C" int dvrGetNativeDisplayDimensions(int* display_width,
+                                             int* display_height) {
   int error = 0;
-  auto client = android::dvr::DisplayClient::Create(&error);
+  auto client = DisplayClient::Create(&error);
   if (!client) {
-    ALOGE("Failed to create display client!");
-    return error;
+    ALOGE("dvrGetNativeDisplayDimensions: Failed to create display client!");
+    return -error;
   }
 
-  android::dvr::SystemDisplayMetrics metrics;
-  const int ret = client->GetDisplayMetrics(&metrics);
-
-  if (ret != 0) {
-    ALOGE("Failed to get display metrics!");
-    return ret;
+  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();
   }
 
-  *native_width = static_cast<int>(metrics.display_native_width);
-  *native_height = static_cast<int>(metrics.display_native_height);
+  *display_width = static_cast<int>(metrics_status.get().display_width);
+  *display_height = static_cast<int>(metrics_status.get().display_height);
   return 0;
 }
 
@@ -524,9 +580,12 @@
   } vk;
 
   // Display surface, metrics, and buffer management members.
-  std::shared_ptr<android::dvr::DisplaySurfaceClient> display_surface;
-  android::dvr::SystemDisplayMetrics display_metrics;
-  std::unique_ptr<android::dvr::NativeBufferQueue> buffer_queue;
+  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;
 
@@ -536,16 +595,17 @@
 
   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 android::dvr::DisplaySurfaceMetadata* surface_metadata;
+  volatile DisplaySurfaceMetadata* surface_metadata;
 
   // LateLatch support.
   std::unique_ptr<android::dvr::LateLatch> late_latch;
 
-  // Video mesh support.
-  std::vector<std::shared_ptr<android::dvr::VideoMeshSurfaceClient>>
-      video_mesh_surfaces;
-
  private:
   // ANativeWindow function implementations
   std::mutex lock_;
@@ -616,7 +676,7 @@
 
 int dvrGraphicsContextCreate(struct DvrSurfaceParameter* parameters,
                              DvrGraphicsContext** return_graphics_context) {
-  std::unique_ptr<DvrGraphicsContext> context(new DvrGraphicsContext);
+  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) {
@@ -681,46 +741,66 @@
     return -EINVAL;
   }
 
-  context->display_surface =
-      CreateDisplaySurfaceClient(parameters, &context->display_metrics);
-  if (!context->display_surface) {
-    ALOGE("Error: failed to create display surface client");
-    return -ECOMM;
+  auto surface_status = CreateApplicationSurface(parameters);
+  if (!surface_status) {
+    ALOGE("dvrGraphicsContextCreate: Failed to create surface: %s",
+          surface_status.GetErrorMessage().c_str());
+    return -surface_status.error();
   }
 
-  context->buffer_queue.reset(new android::dvr::NativeBufferQueue(
-      context->gl.egl_display, context->display_surface, kDefaultBufferCount));
+  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->GetQueueCapacity() + 1);
+  context->frame_history.Reset(context->buffer_queue->capacity() + 1);
 
-  context->vsync_client = android::dvr::VSyncClient::Create();
+  context->vsync_client = VSyncClient::Create();
   if (!context->vsync_client) {
-    ALOGE("Error: failed to create vsync client");
+    ALOGE("dvrGraphicsContextCreate: failed to create vsync client");
     return -ECOMM;
   }
 
   context->timerfd.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
   if (!context->timerfd) {
-    ALOGE("Error: timerfd_create failed because: %s", strerror(errno));
+    ALOGE("dvrGraphicsContextCreate: timerfd_create failed because: %s",
+          strerror(errno));
     return -EPERM;
   }
 
-  context->surface_metadata = context->display_surface->GetMetadataBufferPtr();
-  if (!context->surface_metadata) {
-    ALOGE("Error: surface metadata allocation failed");
-    return -ENOMEM;
-  }
-
-  ALOGI("buffer: %d x %d\n", context->display_surface->width(),
-        context->display_surface->height());
-
   if (context->graphics_api == DVR_GRAPHICS_API_GLES) {
-    context->gl.texture_count = (context->display_surface->flags() &
-                                 DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2)
-                                    ? 2
-                                    : 1;
+    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);
@@ -729,8 +809,7 @@
     // 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());
+    LOG_ALWAYS_FATAL_IF(context->gl.texture_count != 1);
     for (int i = 0; i < context->gl.texture_count; ++i) {
       glBindTexture(context->gl.texture_target_type, context->gl.texture_id[i]);
       glEGLImageTargetTexture2DOES(context->gl.texture_target_type,
@@ -761,14 +840,9 @@
 
     // Initialize late latch.
     if (is_late_latch) {
-      LocalHandle fd;
-      int ret = context->display_surface->GetMetadataBufferFd(&fd);
-      if (ret == 0) {
-        context->late_latch.reset(
-            new android::dvr::LateLatch(true, std::move(fd)));
-      } else {
-        ALOGE("Error: failed to get surface metadata buffer fd for 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;
@@ -968,7 +1042,7 @@
   std::lock_guard<std::mutex> autolock(self->lock_);
 
   if (!self->current_buffer) {
-    self->current_buffer = self->buffer_queue.get()->Dequeue();
+    self->current_buffer = self->buffer_queue->Dequeue();
   }
   ATRACE_ASYNC_BEGIN("BufferDraw", self->current_buffer->buffer()->id());
   *fence_fd = self->current_buffer->ClaimReleaseFence().Release();
@@ -1035,7 +1109,7 @@
     }
   }
   if (do_enqueue) {
-    self->buffer_queue.get()->Enqueue(native_buffer);
+    self->buffer_queue->Enqueue(native_buffer);
   }
   if (fence_fd >= 0)
     close(fence_fd);
@@ -1053,13 +1127,13 @@
 
   switch (what) {
     case NATIVE_WINDOW_WIDTH:
-      *value = self->display_surface->width();
+      *value = self->width;
       return android::NO_ERROR;
     case NATIVE_WINDOW_HEIGHT:
-      *value = self->display_surface->height();
+      *value = self->height;
       return android::NO_ERROR;
     case NATIVE_WINDOW_FORMAT:
-      *value = self->display_surface->format();
+      *value = self->format;
       return android::NO_ERROR;
     case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
       *value = 1;
@@ -1071,10 +1145,10 @@
       *value = 1;
       return android::NO_ERROR;
     case NATIVE_WINDOW_DEFAULT_WIDTH:
-      *value = self->display_surface->width();
+      *value = self->width;
       return android::NO_ERROR;
     case NATIVE_WINDOW_DEFAULT_HEIGHT:
-      *value = self->display_surface->height();
+      *value = self->height;
       return android::NO_ERROR;
     case NATIVE_WINDOW_TRANSFORM_HINT:
       *value = 0;
@@ -1201,10 +1275,8 @@
   // 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 android::dvr::DisplaySurfaceMetadata* data =
-        graphics_context->surface_metadata;
-    uint32_t buffer_index =
-        graphics_context->current_buffer->surface_buffer_index();
+    volatile DisplaySurfaceMetadata* data = graphics_context->surface_metadata;
+    uint32_t buffer_index = 0;
     ALOGE_IF(TRACE, "write pose index %d %f %f", buffer_index,
              render_pose_orientation[0], render_pose_orientation[1]);
     data->orientation[buffer_index] = render_pose_orientation;
@@ -1249,6 +1321,7 @@
   CHECK_GL();
   return 0;
 }
+
 int dvrBeginRenderFrameEdsVk(DvrGraphicsContext* graphics_context,
                              float32x4_t render_pose_orientation,
                              float32x4_t render_pose_translation,
@@ -1426,7 +1499,7 @@
 
     auto buffer = graphics_context->current_buffer->buffer().get();
     ATRACE_ASYNC_BEGIN("BufferPost", buffer->id());
-    int result = buffer->Post<uint64_t>(LocalHandle(), 0);
+    int result = buffer->Post<void>(LocalHandle());
     if (result < 0)
       ALOGE("Buffer post failed: %d (%s)", result, strerror(-result));
   }
@@ -1457,7 +1530,7 @@
   ATRACE_ASYNC_END("BufferDraw", buffer->id());
   if (!graphics_context->buffer_already_posted) {
     ATRACE_ASYNC_BEGIN("BufferPost", buffer->id());
-    int result = buffer->Post<uint64_t>(fence_fd, 0);
+    int result = buffer->Post<void>(fence_fd);
     if (result < 0)
       ALOGE("Buffer post failed: %d (%s)", result, strerror(-result));
   }
@@ -1520,7 +1593,7 @@
 
 extern "C" int dvrGraphicsSurfaceGetVisible(
     DvrGraphicsContext* graphics_context) {
-  return graphics_context->display_surface->visible() ? 1 : 0;
+  return !!graphics_context->display_surface->visible();
 }
 
 extern "C" void dvrGraphicsSurfaceSetZOrder(
@@ -1532,45 +1605,3 @@
     DvrGraphicsContext* graphics_context) {
   return graphics_context->display_surface->z_order();
 }
-
-extern "C" DvrVideoMeshSurface* dvrGraphicsVideoMeshSurfaceCreate(
-    DvrGraphicsContext* graphics_context) {
-  auto display_surface = graphics_context->display_surface;
-  // A DisplaySurface must be created prior to the creation of a
-  // VideoMeshSurface.
-  LOG_ALWAYS_FATAL_IF(display_surface == nullptr);
-
-  LocalChannelHandle surface_handle = display_surface->CreateVideoMeshSurface();
-  if (!surface_handle.valid()) {
-    return nullptr;
-  }
-
-  std::unique_ptr<DvrVideoMeshSurface> surface(new DvrVideoMeshSurface);
-  surface->client =
-      android::dvr::VideoMeshSurfaceClient::Import(std::move(surface_handle));
-
-  // TODO(jwcai) The next line is not needed...
-  auto producer_queue = surface->client->GetProducerQueue();
-  return surface.release();
-}
-
-extern "C" void dvrGraphicsVideoMeshSurfaceDestroy(
-    DvrVideoMeshSurface* surface) {
-  delete surface;
-}
-
-extern "C" void dvrGraphicsVideoMeshSurfacePresent(
-    DvrGraphicsContext* graphics_context, DvrVideoMeshSurface* surface,
-    const int eye, const float* transform) {
-  volatile android::dvr::VideoMeshSurfaceMetadata* metadata =
-      surface->client->GetMetadataBufferPtr();
-
-  const uint32_t graphics_buffer_index =
-      graphics_context->current_buffer->surface_buffer_index();
-
-  for (int i = 0; i < 4; ++i) {
-    metadata->transform[graphics_buffer_index][eye].val[i] = {
-        transform[i + 0], transform[i + 4], transform[i + 8], transform[i + 12],
-    };
-  }
-}
diff --git a/libs/vr/libdisplay/include/dvr/dvr_display_types.h b/libs/vr/libdisplay/include/dvr/dvr_display_types.h
new file mode 100644
index 0000000..25364d8
--- /dev/null
+++ b/libs/vr/libdisplay/include/dvr/dvr_display_types.h
@@ -0,0 +1,65 @@
+#ifndef ANDROID_DVR_DISPLAY_TYPES_H_
+#define ANDROID_DVR_DISPLAY_TYPES_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// Define types used in pose buffer fields. These types have atomicity
+// guarantees that are useful in lock-free shared memory ring buffers.
+#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
+
+// VrFlinger display manager surface state snapshots per surface flags
+// indicating what changed since the last snapshot.
+enum {
+  // No changes.
+  DVR_SURFACE_UPDATE_FLAGS_NONE = 0,
+  // This surface is new.
+  DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE = (1 << 0),
+  // Buffer queues added/removed.
+  DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED = (1 << 1),
+  // Visibility/z-order changed.
+  DVR_SURFACE_UPDATE_FLAGS_VISIBILITY_CHANGED = (1 << 2),
+  // Generic attributes changed.
+  DVR_SURFACE_UPDATE_FLAGS_ATTRIBUTES_CHANGED = (1 << 3),
+};
+
+// Surface attribute keys. VrFlinger defines keys in the negative integer space.
+// The compositor is free to use keys in the positive integer space for
+// implementation-defined purposes.
+enum {
+  // DIRECT: bool
+  // Determines whether a direct surface is created (compositor output) or an
+  // application surface. Defaults to false (application surface). May only be
+  // set to true by a process with either UID=root or UID validated with
+  // IsTrustedUid() (VrCore).
+  DVR_SURFACE_ATTRIBUTE_DIRECT = -3,
+  // Z_ORDER: int32_t
+  // Interpreted by VrFlinger only on direct surfaces to order the corresponding
+  // hardware layers. More positive values render on top of more negative
+  // values.
+  DVR_SURFACE_ATTRIBUTE_Z_ORDER = -2,
+  // VISIBLE: bool
+  // Interpreted by VrFlinger only on direct surfaces to determine whether a
+  // surface is assigned to a hardware layer or ignored.
+  DVR_SURFACE_ATTRIBUTE_VISIBLE = -1,
+  // INVALID
+  // Invalid key. No attributes should have this key.
+  DVR_SURFACE_ATTRIBUTE_INVALID = 0,
+  // FIRST_USER_KEY
+  // VrFlinger ingores any keys with this value or greater, passing them to the
+  // compositor through surface state query results.
+  DVR_SURFACE_ATTRIBUTE_FIRST_USER_KEY = 1,
+};
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_DISPLAY_TYPES_H_
diff --git a/libs/vr/libdisplay/include/dvr/graphics.h b/libs/vr/libdisplay/include/dvr/graphics.h
index ac8b27f..c83a698 100644
--- a/libs/vr/libdisplay/include/dvr/graphics.h
+++ b/libs/vr/libdisplay/include/dvr/graphics.h
@@ -9,7 +9,7 @@
 #else
 #ifndef __FLOAT32X4T_86
 #define __FLOAT32X4T_86
-typedef float float32x4_t __attribute__ ((__vector_size__ (16)));
+typedef float float32x4_t __attribute__((__vector_size__(16)));
 typedef struct float32x4x4_t { float32x4_t val[4]; };
 #endif
 #endif
@@ -112,6 +112,10 @@
   // 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 {
@@ -439,8 +443,7 @@
 // Present a VideoMeshSurface with the current video mesh transfromation matrix.
 void dvrGraphicsVideoMeshSurfacePresent(DvrGraphicsContext* graphics_context,
                                         DvrVideoMeshSurface* surface,
-                                        const int eye,
-                                        const float* transform);
+                                        const int eye, const float* transform);
 
 __END_DECLS
 
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index fec2ea5..7a7f670 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -6,112 +6,74 @@
 #include <pdx/file_handle.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/buffer_hub_queue_client.h>
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/display_protocol.h>
 
 namespace android {
 namespace dvr {
+namespace display {
 
-struct LateLatchOutput;
-
-// Abstract base class for all surface types maintained in DVR's display
-// service.
-// TODO(jwcai) Explain more, surface is a channel...
-class SurfaceClient : public pdx::Client {
+class Surface : public pdx::ClientBase<Surface> {
  public:
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-  SurfaceType type() const { return type_; }
+  // Utility named constructor. This can be removed once ClientBase::Create is
+  // refactored to return Status<T> types.
+  static pdx::Status<std::unique_ptr<Surface>> CreateSurface(
+      const SurfaceAttributes& attributes) {
+    int error;
+    pdx::Status<std::unique_ptr<Surface>> status;
+    if (auto surface = Create(attributes, &error))
+      status.SetValue(std::move(surface));
+    else
+      status.SetError(error);
+    return status;
+  }
 
-  // Get the shared memory metadata buffer fd for this display surface. If it is
-  // not yet allocated, this will allocate it.
-  int GetMetadataBufferFd(pdx::LocalHandle* out_fd);
-
-  // Allocate the single metadata buffer for providing metadata associated with
-  // posted buffers for this surface. This can be used to provide rendered poses
-  // for EDS, for example. The buffer format is defined by the struct
-  // DisplaySurfaceMetadata.
-  // The first call to this method will allocate the buffer in via IPC to the
-  // display surface.
-  std::shared_ptr<BufferProducer> GetMetadataBuffer();
-
- protected:
-  SurfaceClient(LocalChannelHandle channel_handle, SurfaceType type);
-  SurfaceClient(const std::string& endpoint_path, SurfaceType type);
-
- private:
-  SurfaceType type_;
-  std::shared_ptr<BufferProducer> metadata_buffer_;
-};
-
-// DisplaySurfaceClient represents the client interface to a displayd display
-// surface.
-class DisplaySurfaceClient
-    : public pdx::ClientBase<DisplaySurfaceClient, SurfaceClient> {
- public:
-  using LocalHandle = pdx::LocalHandle;
-
-  int width() const { return width_; }
-  int height() const { return height_; }
-  int format() const { return format_; }
-  int usage() const { return usage_; }
-  int flags() const { return flags_; }
+  int surface_id() const { return surface_id_; }
   int z_order() const { return z_order_; }
   bool visible() const { return visible_; }
 
-  void SetVisible(bool visible);
-  void SetZOrder(int z_order);
-  void SetExcludeFromBlur(bool exclude_from_blur);
-  void SetBlurBehind(bool blur_behind);
-  void SetAttributes(const DisplaySurfaceAttributes& attributes);
+  pdx::Status<void> SetVisible(bool visible);
+  pdx::Status<void> SetZOrder(int z_order);
+  pdx::Status<void> SetAttributes(const SurfaceAttributes& attributes);
 
-  // Get the producer end of the buffer queue that transports graphics buffer
-  // from the application side to the compositor side.
-  std::shared_ptr<ProducerQueue> GetProducerQueue();
+  // Creates an empty queue.
+  pdx::Status<std::unique_ptr<ProducerQueue>> CreateQueue();
 
-  // Get the shared memory metadata buffer for this display surface. If it is
-  // not yet allocated, this will allocate it.
-  volatile DisplaySurfaceMetadata* GetMetadataBufferPtr();
-
-  // Create a VideoMeshSurface that is attached to the display sruface.
-  LocalChannelHandle CreateVideoMeshSurface();
+  // Creates a queue and populates it with |capacity| buffers of the specified
+  // 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);
 
  private:
   friend BASE;
 
-  DisplaySurfaceClient(int width, int height, int format, int usage, int flags);
+  int surface_id_ = -1;
+  int z_order_ = 0;
+  bool visible_ = false;
 
-  int width_;
-  int height_;
-  int format_;
-  int usage_;
-  int flags_;
-  int z_order_;
-  bool visible_;
-  bool exclude_from_blur_;
-  bool blur_behind_;
-  DisplaySurfaceMetadata* mapped_metadata_buffer_;
+  // TODO(eieio,avakulenko): Remove error param once pdx::ClientBase::Create()
+  // returns Status<T>.
+  explicit Surface(const SurfaceAttributes& attributes, int* error = nullptr);
+  explicit Surface(pdx::LocalChannelHandle channel_handle,
+                   int* error = nullptr);
 
-  // TODO(jwcai) Add support for multiple queues.
-  std::shared_ptr<ProducerQueue> producer_queue_;
-
-  DisplaySurfaceClient(const DisplaySurfaceClient&) = delete;
-  void operator=(const DisplaySurfaceClient&) = delete;
+  Surface(const Surface&) = delete;
+  void operator=(const Surface&) = delete;
 };
 
 class DisplayClient : public pdx::ClientBase<DisplayClient> {
  public:
-  int GetDisplayMetrics(SystemDisplayMetrics* metrics);
-  pdx::Status<void> SetViewerParams(const ViewerParams& viewer_params);
-
-  // Pull the latest eds pose data from the display service renderer
-  int GetLastFrameEdsTransform(LateLatchOutput* ll_out);
-
-  std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
-      int width, int height, int format, int usage, int flags);
-
-  std::unique_ptr<IonBuffer> GetNamedBuffer(const std::string& name);
+  pdx::Status<Metrics> GetDisplayMetrics();
+  pdx::Status<std::unique_ptr<IonBuffer>> GetNamedBuffer(
+      const std::string& name);
+  pdx::Status<std::unique_ptr<Surface>> CreateSurface(
+      const SurfaceAttributes& attributes);
 
   // Temporary query for current VR status. Will be removed later.
-  bool IsVrAppRunning();
+  pdx::Status<bool> IsVrAppRunning();
 
  private:
   friend BASE;
@@ -122,6 +84,7 @@
   void operator=(const DisplayClient&) = delete;
 };
 
+}  // namespace display
 }  // namespace dvr
 }  // namespace android
 
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
new file mode 100644
index 0000000..fea8415
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
@@ -0,0 +1,51 @@
+#ifndef ANDROID_DVR_DISPLAY_MANAGER_CLIENT_H_
+#define ANDROID_DVR_DISPLAY_MANAGER_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include <pdx/client.h>
+#include <pdx/status.h>
+#include <private/dvr/display_protocol.h>
+
+namespace android {
+namespace dvr {
+
+class IonBuffer;
+class ConsumerQueue;
+
+namespace display {
+
+class DisplayManagerClient : public pdx::ClientBase<DisplayManagerClient> {
+ public:
+  ~DisplayManagerClient() override;
+
+  pdx::Status<std::vector<SurfaceState>> GetSurfaceState();
+  pdx::Status<std::unique_ptr<IonBuffer>> SetupNamedBuffer(
+      const std::string& name, size_t size, uint64_t usage);
+  pdx::Status<std::unique_ptr<ConsumerQueue>> GetSurfaceQueue(int surface_id,
+                                                              int queue_id);
+
+  using Client::event_fd;
+
+  pdx::Status<int> GetEventMask(int events) {
+    if (auto* client_channel = GetChannel())
+      return client_channel->GetEventMask(events);
+    else
+      return pdx::ErrorStatus(EINVAL);
+  }
+
+ private:
+  friend BASE;
+
+  DisplayManagerClient();
+
+  DisplayManagerClient(const DisplayManagerClient&) = delete;
+  void operator=(const DisplayManagerClient&) = delete;
+};
+
+}  // namespace display
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_DISPLAY_MANAGER_CLIENT_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
deleted file mode 100644
index b0a7d13..0000000
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef ANDROID_DVR_DISPLAY_MANAGER_CLIENT_IMPL_H_
-#define ANDROID_DVR_DISPLAY_MANAGER_CLIENT_IMPL_H_
-
-#include <vector>
-
-#include <pdx/client.h>
-#include <private/dvr/display_rpc.h>
-
-namespace android {
-namespace dvr {
-
-class BufferProducer;
-
-class DisplayManagerClient : public pdx::ClientBase<DisplayManagerClient> {
- public:
-  ~DisplayManagerClient() override;
-
-  int GetSurfaceList(std::vector<DisplaySurfaceInfo>* surface_list);
-
-  std::unique_ptr<IonBuffer> SetupNamedBuffer(const std::string& name,
-                                              size_t size,
-                                              uint64_t producer_usage,
-                                              uint64_t consumer_usage);
-
-  using Client::event_fd;
-  using Client::GetChannel;
-
- private:
-  friend BASE;
-
-  DisplayManagerClient();
-
-  DisplayManagerClient(const DisplayManagerClient&) = delete;
-  void operator=(const DisplayManagerClient&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_DISPLAY_MANAGER_CLIENT_IMPL_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
new file mode 100644
index 0000000..f34d61f
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -0,0 +1,283 @@
+#ifndef ANDROID_DVR_DISPLAY_PROTOCOL_H_
+#define ANDROID_DVR_DISPLAY_PROTOCOL_H_
+
+#include <sys/types.h>
+
+#include <array>
+#include <map>
+
+#include <dvr/dvr_display_types.h>
+
+#include <pdx/rpc/remote_method.h>
+#include <pdx/rpc/serializable.h>
+#include <pdx/rpc/variant.h>
+#include <private/dvr/bufferhub_rpc.h>
+
+// RPC protocol definitions for DVR display services (VrFlinger).
+
+namespace android {
+namespace dvr {
+namespace display {
+
+// Native display metrics.
+struct Metrics {
+  // Basic display properties.
+  uint32_t display_width;
+  uint32_t display_height;
+  uint32_t display_x_dpi;
+  uint32_t display_y_dpi;
+  uint32_t vsync_period_ns;
+
+  // HMD metrics.
+  // TODO(eieio): Determine how these fields should be populated. On phones
+  // these values are determined at runtime by VrCore based on which headset the
+  // phone is in. On dedicated hardware this needs to come from somewhere else.
+  // Perhaps these should be moved to a separate structure that is returned by a
+  // separate runtime call.
+  uint32_t distorted_width;
+  uint32_t distorted_height;
+  uint32_t hmd_ipd_mm;
+  float inter_lens_distance_m;
+  std::array<float, 4> left_fov_lrbt;
+  std::array<float, 4> right_fov_lrbt;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(Metrics, display_width, display_height,
+                           display_x_dpi, display_y_dpi, vsync_period_ns,
+                           distorted_width, distorted_height, hmd_ipd_mm,
+                           inter_lens_distance_m, left_fov_lrbt,
+                           right_fov_lrbt);
+};
+
+// Serializable base type for enum structs. Enum structs are easier to use than
+// enum classes, especially for bitmasks. This base type provides common
+// utilities for flags types.
+template <typename Integer>
+class Flags {
+ public:
+  using Base = Flags<Integer>;
+  using Type = Integer;
+
+  Flags(const Integer& value) : value_{value} {}
+  Flags(const Flags&) = default;
+  Flags& operator=(const Flags&) = default;
+
+  Integer value() const { return value_; }
+  operator Integer() const { return value_; }
+
+  bool IsSet(Integer bits) const { return (value_ & bits) == bits; }
+  bool IsClear(Integer bits) const { return (value_ & bits) == 0; }
+
+  void Set(Integer bits) { value_ |= bits; }
+  void Clear(Integer bits) { value_ &= ~bits; }
+
+  Integer operator|(Integer bits) const { return value_ | bits; }
+  Integer operator&(Integer bits) const { return value_ & bits; }
+
+  Flags& operator|=(Integer bits) {
+    value_ |= bits;
+    return *this;
+  }
+  Flags& operator&=(Integer bits) {
+    value_ &= bits;
+    return *this;
+  }
+
+ private:
+  Integer value_;
+
+  PDX_SERIALIZABLE_MEMBERS(Flags<Integer>, value_);
+};
+
+// Flags indicating what changed since last update.
+struct SurfaceUpdateFlags : public Flags<uint32_t> {
+  enum : Type {
+    None = DVR_SURFACE_UPDATE_FLAGS_NONE,
+    NewSurface = DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE,
+    BuffersChanged = DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED,
+    VisibilityChanged = DVR_SURFACE_UPDATE_FLAGS_VISIBILITY_CHANGED,
+    AttributesChanged = DVR_SURFACE_UPDATE_FLAGS_ATTRIBUTES_CHANGED,
+  };
+
+  SurfaceUpdateFlags() : Base{None} {}
+  using Base::Base;
+};
+
+// Surface attribute key/value types.
+using SurfaceAttributeKey = int32_t;
+using SurfaceAttributeValue =
+    pdx::rpc::Variant<int32_t, int64_t, bool, float, std::array<float, 2>,
+                      std::array<float, 3>, std::array<float, 4>,
+                      std::array<float, 8>, std::array<float, 16>>;
+
+// Defined surface attribute keys.
+struct SurfaceAttribute : public Flags<SurfaceAttributeKey> {
+  enum : Type {
+    // Keys in the negative integer space are interpreted by VrFlinger for
+    // direct surfaces.
+    Direct = DVR_SURFACE_ATTRIBUTE_DIRECT,
+    ZOrder = DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+    Visible = DVR_SURFACE_ATTRIBUTE_VISIBLE,
+
+    // Invalid key. May be used to terminate C style lists in public API code.
+    Invalid = DVR_SURFACE_ATTRIBUTE_INVALID,
+
+    // Positive keys are interpreted by the compositor only.
+    FirstUserKey = DVR_SURFACE_ATTRIBUTE_FIRST_USER_KEY,
+  };
+
+  SurfaceAttribute() : Base{Invalid} {}
+  using Base::Base;
+};
+
+// Collection of surface attribute key/value pairs.
+using SurfaceAttributes = std::map<SurfaceAttributeKey, SurfaceAttributeValue>;
+
+struct SurfaceState {
+  int32_t surface_id;
+  int32_t process_id;
+  int32_t user_id;
+
+  SurfaceAttributes surface_attributes;
+  SurfaceUpdateFlags update_flags;
+  std::vector<int32_t> queue_ids;
+
+  // Convenience accessors.
+  bool GetVisible() const {
+    bool bool_value = false;
+    GetAttribute(SurfaceAttribute::Visible, &bool_value,
+                 ValidTypes<int32_t, int64_t, bool, float>{});
+    return bool_value;
+  }
+
+  int GetZOrder() const {
+    int int_value = 0;
+    GetAttribute(SurfaceAttribute::ZOrder, &int_value,
+                 ValidTypes<int32_t, int64_t, float>{});
+    return int_value;
+  }
+
+ private:
+  template <typename... Types>
+  struct ValidTypes {};
+
+  template <typename ReturnType, typename... Types>
+  bool GetAttribute(SurfaceAttributeKey key, ReturnType* out_value,
+                    ValidTypes<Types...>) const {
+    auto search = surface_attributes.find(key);
+    if (search != surface_attributes.end())
+      return pdx::rpc::IfAnyOf<Types...>::Get(&search->second, out_value);
+    else
+      return false;
+  }
+
+  PDX_SERIALIZABLE_MEMBERS(SurfaceState, surface_id, process_id,
+                           surface_attributes, update_flags, queue_ids);
+};
+
+struct SurfaceInfo {
+  int surface_id;
+  bool visible;
+  int z_order;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(SurfaceInfo, surface_id, visible, z_order);
+};
+
+struct DisplayProtocol {
+  // Service path.
+  static constexpr char kClientPath[] = "system/vr/display/client";
+
+  // Op codes.
+  enum {
+    kOpGetMetrics = 0,
+    kOpGetNamedBuffer,
+    kOpIsVrAppRunning,
+    kOpCreateSurface,
+    kOpGetSurfaceInfo,
+    kOpCreateQueue,
+    kOpSetAttributes,
+  };
+
+  // Aliases.
+  using LocalChannelHandle = pdx::LocalChannelHandle;
+  using Void = pdx::rpc::Void;
+
+  // Methods.
+  PDX_REMOTE_METHOD(GetMetrics, kOpGetMetrics, Metrics(Void));
+  PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
+                    LocalNativeBufferHandle(std::string name));
+  PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, bool(Void));
+  PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
+                    SurfaceInfo(const SurfaceAttributes& attributes));
+  PDX_REMOTE_METHOD(GetSurfaceInfo, kOpGetSurfaceInfo, SurfaceInfo(Void));
+  PDX_REMOTE_METHOD(CreateQueue, kOpCreateQueue,
+                    LocalChannelHandle(size_t meta_size_bytes));
+  PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
+                    void(const SurfaceAttributes& attributes));
+};
+
+struct DisplayManagerProtocol {
+  // Service path.
+  static constexpr char kClientPath[] = "system/vr/display/manager";
+
+  // Op codes.
+  enum {
+    kOpGetSurfaceState = 0,
+    kOpGetSurfaceQueue,
+    kOpSetupNamedBuffer,
+  };
+
+  // Aliases.
+  using LocalChannelHandle = pdx::LocalChannelHandle;
+  using Void = pdx::rpc::Void;
+
+  // Methods.
+  PDX_REMOTE_METHOD(GetSurfaceState, kOpGetSurfaceState,
+                    std::vector<SurfaceState>(Void));
+  PDX_REMOTE_METHOD(GetSurfaceQueue, kOpGetSurfaceQueue,
+                    LocalChannelHandle(int surface_id, int queue_id));
+  PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
+                    LocalNativeBufferHandle(const std::string& name,
+                                            size_t size, uint64_t usage));
+};
+
+struct VSyncSchedInfo {
+  int64_t vsync_period_ns;
+  int64_t timestamp_ns;
+  uint32_t next_vsync_count;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(VSyncSchedInfo, vsync_period_ns, timestamp_ns,
+                           next_vsync_count);
+};
+
+struct VSyncProtocol {
+  // Service path.
+  static constexpr char kClientPath[] = "system/vr/display/vsync";
+
+  // Op codes.
+  enum {
+    kOpWait = 0,
+    kOpAck,
+    kOpGetLastTimestamp,
+    kOpGetSchedInfo,
+    kOpAcknowledge,
+  };
+
+  // Aliases.
+  using Void = pdx::rpc::Void;
+  using Timestamp = int64_t;
+
+  // Methods.
+  PDX_REMOTE_METHOD(Wait, kOpWait, Timestamp(Void));
+  PDX_REMOTE_METHOD(GetLastTimestamp, kOpGetLastTimestamp, Timestamp(Void));
+  PDX_REMOTE_METHOD(GetSchedInfo, kOpGetSchedInfo, VSyncSchedInfo(Void));
+  PDX_REMOTE_METHOD(Acknowledge, kOpAcknowledge, void(Void));
+};
+
+}  // namespace display
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_DISPLAY_PROTOCOL_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
deleted file mode 100644
index 778032f..0000000
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ /dev/null
@@ -1,343 +0,0 @@
-#ifndef ANDROID_DVR_DISPLAY_RPC_H_
-#define ANDROID_DVR_DISPLAY_RPC_H_
-
-#include <sys/types.h>
-
-#include <array>
-#include <map>
-
-#include <pdx/rpc/remote_method.h>
-#include <pdx/rpc/serializable.h>
-#include <pdx/rpc/variant.h>
-#include <private/dvr/bufferhub_rpc.h>
-#include <private/dvr/display_types.h>
-
-namespace android {
-namespace dvr {
-
-struct SystemDisplayMetrics {
-  uint32_t display_native_width;
-  uint32_t display_native_height;
-  uint32_t display_x_dpi;
-  uint32_t display_y_dpi;
-  uint32_t distorted_width;
-  uint32_t distorted_height;
-  uint32_t vsync_period_ns;
-  uint32_t hmd_ipd_mm;
-  float inter_lens_distance_m;
-  std::array<float, 4> left_fov_lrbt;
-  std::array<float, 4> right_fov_lrbt;
-
- private:
-  PDX_SERIALIZABLE_MEMBERS(SystemDisplayMetrics, display_native_width,
-                           display_native_height, display_x_dpi, display_y_dpi,
-                           distorted_width, distorted_height, vsync_period_ns,
-                           hmd_ipd_mm, inter_lens_distance_m, left_fov_lrbt,
-                           right_fov_lrbt);
-};
-
-using SurfaceType = uint32_t;
-struct SurfaceTypeEnum {
-  enum : SurfaceType {
-    Normal = DVR_SURFACE_TYPE_NORMAL,
-    VideoMesh = DVR_SURFACE_TYPE_VIDEO_MESH,
-    Overlay = DVR_SURFACE_TYPE_OVERLAY,
-  };
-};
-
-using DisplaySurfaceFlags = uint32_t;
-enum class DisplaySurfaceFlagsEnum : DisplaySurfaceFlags {
-  DisableSystemEds = DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_EDS,
-  DisableSystemDistortion = DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION,
-  VerticalFlip = DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP,
-  SeparateGeometry = DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2,
-  DisableSystemCac = DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC,
-};
-
-using DisplaySurfaceInfoFlags = uint32_t;
-enum class DisplaySurfaceInfoFlagsEnum : DisplaySurfaceInfoFlags {
-  BuffersChanged = DVR_DISPLAY_SURFACE_ITEM_FLAGS_BUFFERS_CHANGED,
-};
-
-using DisplaySurfaceAttributeValue =
-    pdx::rpc::Variant<int32_t, int64_t, bool, float, std::array<float, 2>,
-                      std::array<float, 3>, std::array<float, 4>,
-                      std::array<float, 16>>;
-using DisplaySurfaceAttribute = uint32_t;
-struct DisplaySurfaceAttributeEnum {
-  enum : DisplaySurfaceAttribute {
-    ZOrder = DVR_DISPLAY_SURFACE_ATTRIBUTE_Z_ORDER,
-    Visible = DVR_DISPLAY_SURFACE_ATTRIBUTE_VISIBLE,
-    // Manager only.
-    Blur = DVR_DISPLAY_SURFACE_ATTRIBUTE_BLUR,
-    // Client only.
-    ExcludeFromBlur = DVR_DISPLAY_SURFACE_ATTRIBUTE_EXCLUDE_FROM_BLUR,
-    BlurBehind = DVR_DISPLAY_SURFACE_ATTRIBUTE_BLUR_BEHIND,
-  };
-
-  static std::string ToString(DisplaySurfaceAttribute attribute) {
-    switch (attribute) {
-      case ZOrder:
-        return "z-order";
-      case Visible:
-        return "visible";
-      case Blur:
-        return "blur";
-      case ExcludeFromBlur:
-        return "exclude-from-blur";
-      case BlurBehind:
-        return "blur-behind";
-      default:
-        return "unknown";
-    }
-  }
-};
-
-using DisplaySurfaceAttributes =
-    std::map<DisplaySurfaceAttribute, DisplaySurfaceAttributeValue>;
-
-struct DisplaySurfaceInfo {
-  int surface_id;
-  int process_id;
-  SurfaceType type;
-  DisplaySurfaceFlags flags;
-  DisplaySurfaceInfoFlags info_flags;
-  DisplaySurfaceAttributes client_attributes;
-  DisplaySurfaceAttributes manager_attributes;
-
-  // Convenience accessors.
-  bool IsClientVisible() const {
-    const auto* variant =
-        FindClientAttribute(DisplaySurfaceAttributeEnum::Visible);
-    bool bool_value;
-    if (variant && pdx::rpc::IfAnyOf<int32_t, int64_t, bool, float>::Get(
-                       variant, &bool_value))
-      return bool_value;
-    else
-      return false;
-  }
-
-  int ClientZOrder() const {
-    const auto* variant =
-        FindClientAttribute(DisplaySurfaceAttributeEnum::ZOrder);
-    int int_value;
-    if (variant &&
-        pdx::rpc::IfAnyOf<int32_t, int64_t, float>::Get(variant, &int_value))
-      return int_value;
-    else
-      return 0;
-  }
-
- private:
-  const DisplaySurfaceAttributeValue* FindClientAttribute(
-      DisplaySurfaceAttribute key) const {
-    auto search = client_attributes.find(key);
-    return (search != client_attributes.end()) ? &search->second : nullptr;
-  }
-
-  PDX_SERIALIZABLE_MEMBERS(DisplaySurfaceInfo, surface_id, process_id, type,
-                           flags, info_flags, client_attributes,
-                           manager_attributes);
-};
-
-struct AlignmentMarker {
- public:
-  float horizontal;
-  float vertical;
-
-  PDX_SERIALIZABLE_MEMBERS(AlignmentMarker, horizontal, vertical);
-};
-
-struct DaydreamInternalParams {
- public:
-  int32_t version;
-  std::vector<AlignmentMarker> alignment_markers;
-
-  PDX_SERIALIZABLE_MEMBERS(DaydreamInternalParams, version, alignment_markers);
-};
-
-struct ViewerParams {
- public:
-  // TODO(hendrikw): Do we need viewer_vendor_name and viewer_model_name?
-  float screen_to_lens_distance;
-  float inter_lens_distance;
-  float screen_center_to_lens_distance;
-  std::vector<float> left_eye_field_of_view_angles;
-
-  enum VerticalAlignmentType : int32_t {
-    BOTTOM = 0,  // phone rests against a fixed bottom tray
-    CENTER = 1,  // phone screen assumed to be centered w.r.t. lenses
-    TOP = 2      // phone rests against a fixed top tray
-  };
-
-  enum EyeOrientation : int32_t {
-    kCCW0Degrees = 0,
-    kCCW90Degrees = 1,
-    kCCW180Degrees = 2,
-    kCCW270Degrees = 3,
-    kCCW0DegreesMirrored = 4,
-    kCCW90DegreesMirrored = 5,
-    kCCW180DegreesMirrored = 6,
-    kCCW270DegreesMirrored = 7
-  };
-
-  VerticalAlignmentType vertical_alignment;
-  std::vector<EyeOrientation> eye_orientations;
-
-  float tray_to_lens_distance;
-
-  std::vector<float> distortion_coefficients_r;
-  std::vector<float> distortion_coefficients_g;
-  std::vector<float> distortion_coefficients_b;
-
-  DaydreamInternalParams daydream_internal;
-
-  PDX_SERIALIZABLE_MEMBERS(ViewerParams, screen_to_lens_distance,
-                           inter_lens_distance, screen_center_to_lens_distance,
-                           left_eye_field_of_view_angles, vertical_alignment,
-                           eye_orientations, tray_to_lens_distance,
-                           distortion_coefficients_r, distortion_coefficients_g,
-                           distortion_coefficients_b, daydream_internal);
-};
-
-struct DisplayRPC {
-  // Service path.
-  static constexpr char kClientPath[] = "system/vr/display/client";
-
-  // Op codes.
-  enum {
-    kOpGetMetrics = 0,
-    kOpGetEdsCapture,
-    kOpCreateSurface,
-    kOpCreateBufferQueue,
-    kOpSetAttributes,
-    kOpGetMetadataBuffer,
-    kOpCreateVideoMeshSurface,
-    kOpVideoMeshSurfaceCreateProducerQueue,
-    kOpSetViewerParams,
-    kOpGetNamedBuffer,
-    kOpIsVrAppRunning,
-  };
-
-  // Aliases.
-  using ByteBuffer = pdx::rpc::BufferWrapper<std::vector<uint8_t>>;
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-  using Void = pdx::rpc::Void;
-
-  // Methods.
-  PDX_REMOTE_METHOD(GetMetrics, kOpGetMetrics, SystemDisplayMetrics(Void));
-  PDX_REMOTE_METHOD(GetEdsCapture, kOpGetEdsCapture, ByteBuffer(Void));
-  PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
-                    int(int width, int height, int format, int usage,
-                        DisplaySurfaceFlags flags));
-  PDX_REMOTE_METHOD(CreateBufferQueue, kOpCreateBufferQueue,
-                    LocalChannelHandle(Void));
-  PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
-                    int(const DisplaySurfaceAttributes& attributes));
-  PDX_REMOTE_METHOD(GetMetadataBuffer, kOpGetMetadataBuffer,
-                    LocalChannelHandle(Void));
-  // VideoMeshSurface methods
-  PDX_REMOTE_METHOD(CreateVideoMeshSurface, kOpCreateVideoMeshSurface,
-                    LocalChannelHandle(Void));
-  PDX_REMOTE_METHOD(VideoMeshSurfaceCreateProducerQueue,
-                    kOpVideoMeshSurfaceCreateProducerQueue,
-                    LocalChannelHandle(Void));
-  PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
-                    void(const ViewerParams& viewer_params));
-  PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
-                    LocalNativeBufferHandle(const std::string& name));
-  PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, int(Void));
-};
-
-struct DisplayManagerRPC {
-  // Service path.
-  static constexpr char kClientPath[] = "system/vr/display/manager";
-
-  // Op codes.
-  enum {
-    kOpGetSurfaceList = 0,
-    kOpUpdateSurfaces,
-    kOpSetupNamedBuffer,
-  };
-
-  // Aliases.
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-  using Void = pdx::rpc::Void;
-
-  // Methods.
-  PDX_REMOTE_METHOD(GetSurfaceList, kOpGetSurfaceList,
-                    std::vector<DisplaySurfaceInfo>(Void));
-  PDX_REMOTE_METHOD(
-      UpdateSurfaces, kOpUpdateSurfaces,
-      int(const std::map<int, DisplaySurfaceAttributes>& updates));
-  PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
-                    LocalNativeBufferHandle(const std::string& name,
-                                            size_t size,
-                                            uint64_t producer_usage,
-                                            uint64_t consumer_usage));
-};
-
-struct ScreenshotData {
-  int width;
-  int height;
-  std::vector<uint8_t> buffer;
-
- private:
-  PDX_SERIALIZABLE_MEMBERS(ScreenshotData, width, height, buffer);
-};
-
-struct DisplayScreenshotRPC {
-  // Service path.
-  static constexpr char kClientPath[] = "system/vr/display/screenshot";
-
-  // Op codes.
-  enum {
-    kOpGetFormat = 0,
-    kOpTakeScreenshot,
-  };
-
-  using Void = pdx::rpc::Void;
-
-  PDX_REMOTE_METHOD(GetFormat, kOpGetFormat, int(Void));
-  PDX_REMOTE_METHOD(TakeScreenshot, kOpTakeScreenshot,
-                    ScreenshotData(int layer_index));
-};
-
-struct VSyncSchedInfo {
-  int64_t vsync_period_ns;
-  int64_t timestamp_ns;
-  uint32_t next_vsync_count;
-
- private:
-  PDX_SERIALIZABLE_MEMBERS(VSyncSchedInfo, vsync_period_ns, timestamp_ns,
-                           next_vsync_count);
-};
-
-struct DisplayVSyncRPC {
-  // Service path.
-  static constexpr char kClientPath[] = "system/vr/display/vsync";
-
-  // Op codes.
-  enum {
-    kOpWait = 0,
-    kOpAck,
-    kOpGetLastTimestamp,
-    kOpGetSchedInfo,
-    kOpAcknowledge,
-  };
-
-  // Aliases.
-  using Void = pdx::rpc::Void;
-  using Timestamp = int64_t;
-
-  // Methods.
-  PDX_REMOTE_METHOD(Wait, kOpWait, Timestamp(Void));
-  PDX_REMOTE_METHOD(GetLastTimestamp, kOpGetLastTimestamp, Timestamp(Void));
-  PDX_REMOTE_METHOD(GetSchedInfo, kOpGetSchedInfo, VSyncSchedInfo(Void));
-  PDX_REMOTE_METHOD(Acknowledge, kOpAcknowledge, int(Void));
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_DISPLAY_RPC_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_types.h b/libs/vr/libdisplay/include/private/dvr/display_types.h
deleted file mode 100644
index 2bd02bd..0000000
--- a/libs/vr/libdisplay/include/private/dvr/display_types.h
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef ANDROID_DVR_DISPLAY_TYPES_H_
-#define ANDROID_DVR_DISPLAY_TYPES_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 <cutils/native_handle.h>
-
-// DVR display-related data types.
-
-enum dvr_display_surface_type {
-  // Normal display surface meant to be used by applications' GL context to
-  // render into.
-  DVR_SURFACE_TYPE_NORMAL = 0,
-
-  // VideoMeshSurface is used to composite video frames into the 3D world.
-  DVR_SURFACE_TYPE_VIDEO_MESH,
-
-  // System overlay surface type. This is not currently in use.
-  DVR_SURFACE_TYPE_OVERLAY,
-};
-
-enum dvr_display_surface_flags {
-  DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_EDS = (1 << 0),
-  DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION = (1 << 1),
-  DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP = (1 << 2),
-  DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2 = (1 << 3),
-  DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC = (1 << 4),
-};
-
-enum dvr_display_surface_item_flags {
-  DVR_DISPLAY_SURFACE_ITEM_FLAGS_BUFFERS_CHANGED = (1 << 0),
-};
-
-enum dvr_display_surface_attribute {
-  DVR_DISPLAY_SURFACE_ATTRIBUTE_Z_ORDER = (1<<0),
-  DVR_DISPLAY_SURFACE_ATTRIBUTE_VISIBLE = (1<<1),
-  DVR_DISPLAY_SURFACE_ATTRIBUTE_BLUR = (1<<2),
-  DVR_DISPLAY_SURFACE_ATTRIBUTE_EXCLUDE_FROM_BLUR = (1<<3),
-  DVR_DISPLAY_SURFACE_ATTRIBUTE_BLUR_BEHIND = (1<<4),
-};
-
-// Maximum number of buffers for a surface. Each buffer represents a single
-// frame and may actually be a buffer array if multiview rendering is in use.
-// Define so that it can be used in shader code.
-#define kSurfaceBufferMaxCount 4
-
-// Maximum number of views per surface. Each eye is a view, for example.
-#define kSurfaceViewMaxCount 4
-
-namespace android {
-namespace dvr {
-
-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];
-};
-
-struct __attribute__((packed, aligned(16))) VideoMeshSurfaceMetadata {
-  // Array of transform matrices corresponding with surface buffers.
-  // Note that The index is associated with each allocated buffer by
-  // DisplaySurface instead of VideoMeshSurface due to the fact that the
-  // metadata here is interpreted as video mesh's transformation in each
-  // application's rendering frame.
-  float32x4x4_t transform[4][2];
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_DISPLAY_TYPES_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/graphics_private.h b/libs/vr/libdisplay/include/private/dvr/graphics_private.h
index 57c99da..a08b0df 100644
--- a/libs/vr/libdisplay/include/private/dvr/graphics_private.h
+++ b/libs/vr/libdisplay/include/private/dvr/graphics_private.h
@@ -17,6 +17,19 @@
 
 __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
diff --git a/libs/vr/libdisplay/include/private/dvr/late_latch.h b/libs/vr/libdisplay/include/private/dvr/late_latch.h
index b7c5e4f..c91d15c 100644
--- a/libs/vr/libdisplay/include/private/dvr/late_latch.h
+++ b/libs/vr/libdisplay/include/private/dvr/late_latch.h
@@ -5,11 +5,12 @@
 #include <thread>
 #include <vector>
 
+#include <dvr/dvr_display_types.h>
 #include <dvr/pose_client.h>
 #include <pdx/file_handle.h>
-#include <private/dvr/display_types.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;
diff --git a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
index 4b1fa98..a260f17 100644
--- a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
+++ b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
@@ -13,30 +13,43 @@
 
 namespace android {
 namespace dvr {
+namespace display {
 
 // A wrapper over dvr::ProducerQueue that caches EGLImage.
 class NativeBufferQueue {
  public:
-  // Create a queue with the given number of free buffers.
   NativeBufferQueue(EGLDisplay display,
-                    const std::shared_ptr<DisplaySurfaceClient>& surface,
-                    size_t capacity);
+                    const std::shared_ptr<ProducerQueue>& producer_queue,
+                    uint32_t width, uint32_t height, uint32_t format,
+                    uint64_t usage, size_t capacity);
 
-  size_t GetQueueCapacity() const { return producer_queue_->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) {}
+  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
 
diff --git a/libs/vr/libdisplay/include/private/dvr/screenshot_client.h b/libs/vr/libdisplay/include/private/dvr/screenshot_client.h
deleted file mode 100644
index b6fc859..0000000
--- a/libs/vr/libdisplay/include/private/dvr/screenshot_client.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef ANDROID_DVR_SCREENSHOT_CLIENT_H_
-#define ANDROID_DVR_SCREENSHOT_CLIENT_H_
-
-#include <memory>
-#include <vector>
-
-#include <pdx/client.h>
-#include <private/dvr/display_rpc.h>
-#include <system/graphics.h>
-
-namespace android {
-namespace dvr {
-
-// Represents a connection to the screenshot service, which allows capturing an
-// upcoming frame as it is being rendered to the display.
-class ScreenshotClient : public pdx::ClientBase<ScreenshotClient> {
- public:
-  int format() const { return format_; }
-
-  // Attempts to take a screenshot. If successful, sets *data to the contents
-  // of the screenshot and returns zero. Otherwise, returns a negative error
-  // code.
-  // |index| is used to match the requested buffer with various buffer layers.
-  int Take(std::vector<uint8_t>* data, int index, int* return_width,
-           int* return_height);
-
- private:
-  friend BASE;
-
-  ScreenshotClient();
-
-  // Layout information for screenshots.
-  int format_;
-
-  ScreenshotClient(const ScreenshotClient&) = delete;
-  void operator=(const ScreenshotClient&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SCREENSHOT_CLIENT_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
deleted file mode 100644
index 3a7f125..0000000
--- a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef ANDROID_DVR_VIDEO_MESH_SURFACE_CLIENT_H_
-#define ANDROID_DVR_VIDEO_MESH_SURFACE_CLIENT_H_
-
-#include <private/dvr/buffer_hub_queue_client.h>
-#include <private/dvr/display_client.h>
-
-namespace android {
-namespace dvr {
-
-class VideoMeshSurfaceClient
-    : pdx::ClientBase<VideoMeshSurfaceClient, SurfaceClient> {
- public:
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-
-  // This call assumes ownership of |handle|.
-  static std::unique_ptr<VideoMeshSurfaceClient> Import(
-      LocalChannelHandle handle);
-
-  std::shared_ptr<ProducerQueue> GetProducerQueue();
-
-  // Get the shared memory metadata buffer for this video mesh surface. If it is
-  // not yet allocated, this will allocate it.
-  volatile VideoMeshSurfaceMetadata* GetMetadataBufferPtr();
-
- private:
-  friend BASE;
-
-  std::shared_ptr<ProducerQueue> producer_queue_;
-  VideoMeshSurfaceMetadata* mapped_metadata_buffer_;
-
-  explicit VideoMeshSurfaceClient(LocalChannelHandle handle);
-};
-
-}  // namespace dvr
-}  // namespace android
-
-struct DvrVideoMeshSurface {
-  std::shared_ptr<android::dvr::VideoMeshSurfaceClient> client;
-};
-
-#endif  // ANDROID_DVR_VIDEO_MESH_SURFACE_CLIENT_H_
diff --git a/libs/vr/libdisplay/native_buffer_queue.cpp b/libs/vr/libdisplay/native_buffer_queue.cpp
index d516d63..1bb05d8 100644
--- a/libs/vr/libdisplay/native_buffer_queue.cpp
+++ b/libs/vr/libdisplay/native_buffer_queue.cpp
@@ -7,58 +7,59 @@
 
 #include <array>
 
-#include <private/dvr/display_types.h>
+#include <dvr/dvr_display_types.h>
 
 namespace android {
 namespace dvr {
+namespace display {
 
 NativeBufferQueue::NativeBufferQueue(
-    EGLDisplay display, const std::shared_ptr<DisplaySurfaceClient>& surface,
+    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), buffers_(capacity) {
-  std::shared_ptr<ProducerQueue> queue = surface->GetProducerQueue();
-
+    : 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.
-    int ret =
-        queue->AllocateBuffer(surface->width(), surface->height(),
-                              surface->format(), surface->usage(), 1, &slot);
+    const int ret = producer_queue_->AllocateBuffer(width_, height_, 1, format_,
+                                                    usage_, &slot);
     if (ret < 0) {
       ALOGE(
-          "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer, "
-          "error=%d",
-          ret);
+          "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer: %s",
+          strerror(-ret));
       return;
     }
 
-    ALOGD_IF(TRACE,
-             "NativeBufferQueue::NativeBufferQueue: New buffer allocated at "
-             "slot=%zu",
-             slot);
+    ALOGD_IF(TRACE, "NativeBufferQueue::NativeBufferQueue: slot=%zu", slot);
   }
-
-  producer_queue_ = std::move(queue);
 }
 
 NativeBufferProducer* NativeBufferQueue::Dequeue() {
   ATRACE_NAME("NativeBufferQueue::Dequeue");
-
-  // This never times out.
   size_t slot;
   pdx::LocalHandle fence;
-  std::shared_ptr<BufferProducer> buffer =
-      producer_queue_->Dequeue(-1, &slot, &fence);
-
-  if (buffers_[slot] == nullptr) {
-    buffers_[slot] = new NativeBufferProducer(buffer, display_, slot);
+  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;
   }
 
-  ALOGD_IF(TRACE,
-           "NativeBufferQueue::Dequeue: dequeue buffer at slot=%zu, buffer=%p",
-           slot, buffers_[slot].get());
+  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/screenshot_client.cpp b/libs/vr/libdisplay/screenshot_client.cpp
deleted file mode 100644
index 3ad0c68..0000000
--- a/libs/vr/libdisplay/screenshot_client.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "include/private/dvr/screenshot_client.h"
-
-#include <log/log.h>
-
-#include <mutex>
-
-#include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/display_rpc.h>
-
-using android::pdx::Transaction;
-using android::pdx::rpc::ClientPayload;
-using android::pdx::rpc::MessageBuffer;
-using android::pdx::rpc::ReplyBuffer;
-
-namespace android {
-namespace dvr {
-
-namespace {
-// Maximum supported pixels for screenshot capture. If the actual target buffer
-// is more than this, an error will be reported.
-constexpr int kMaxScreenshotPixels = 6000 * 4000;
-}  // namespace
-
-int ScreenshotClient::Take(std::vector<uint8_t>* out_image, int index,
-                           int* return_width, int* return_height) {
-  if (format_ != HAL_PIXEL_FORMAT_RGB_888) {
-    ALOGE("ScreenshotClient::Take: Unsupported layout format: format=%d",
-          format_);
-    return -ENOSYS;
-  }
-
-  // TODO(eieio): Make a cleaner way to ensure enough capacity for send or
-  // receive buffers. This method assumes TLS buffers that will maintain
-  // capacity across calls within the same thread.
-  MessageBuffer<ReplyBuffer>::Reserve(kMaxScreenshotPixels * 3);
-  auto status = InvokeRemoteMethod<DisplayScreenshotRPC::TakeScreenshot>(index);
-  if (!status) {
-    ALOGE("ScreenshotClient::Take: Failed to take screenshot: %s",
-          status.GetErrorMessage().c_str());
-    return -status.error();
-  }
-
-  *return_width = status.get().width;
-  *return_height = status.get().height;
-  *out_image = std::move(status.take().buffer);
-  return 0;
-}
-
-ScreenshotClient::ScreenshotClient()
-    : BASE(pdx::default_transport::ClientChannelFactory::Create(
-          DisplayScreenshotRPC::kClientPath)) {
-  auto status = InvokeRemoteMethod<DisplayScreenshotRPC::GetFormat>();
-  if (!status) {
-    ALOGE(
-        "ScreenshotClient::ScreenshotClient: Failed to retrieve screenshot "
-        "layout: %s",
-        status.GetErrorMessage().c_str());
-
-    Close(status.error());
-  } else {
-    format_ = status.get();
-  }
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdisplay/tests/graphics_app_tests.cpp b/libs/vr/libdisplay/tests/graphics_app_tests.cpp
index f51dd8a..c592ba9 100644
--- a/libs/vr/libdisplay/tests/graphics_app_tests.cpp
+++ b/libs/vr/libdisplay/tests/graphics_app_tests.cpp
@@ -57,6 +57,8 @@
   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);
@@ -64,10 +66,10 @@
 
   dvrBeginRenderFrame(context);
 
-  // Check range of vsync period from 70fps to 100fps.
+  // Check range of vsync period from 60fps to 100fps.
   // TODO(jbates) Once we have stable hardware, clamp this range down further.
-  EXPECT_LT(vsync_period, 1000000000ul / 70ul);
-  EXPECT_GT(vsync_period, 1000000000ul / 100ul);
+  EXPECT_LE(vsync_period, 1000000000ul / 60ul);
+  EXPECT_GE(vsync_period, 1000000000ul / 100ul);
 
   dvrPresent(context);
   dvrGraphicsContextDestroy(context);
@@ -103,15 +105,3 @@
   dvrGraphicsContextDestroy(context);
 }
 
-TEST(GraphicsAppTests, CreateVideoMeshSurface) {
-  DvrSurfaceParameter surface_params[] = {DVR_SURFACE_PARAMETER_LIST_END};
-  DvrGraphicsContext* context = nullptr;
-  int result = dvrGraphicsContextCreate(surface_params, &context);
-  EXPECT_NE(nullptr, context);
-  EXPECT_EQ(result, 0);
-
-  DvrVideoMeshSurface* surface = dvrGraphicsVideoMeshSurfaceCreate(context);
-  EXPECT_NE(nullptr, surface);
-
-  dvrGraphicsVideoMeshSurfaceDestroy(surface);
-}
diff --git a/libs/vr/libdisplay/video_mesh_surface_client.cpp b/libs/vr/libdisplay/video_mesh_surface_client.cpp
deleted file mode 100644
index a2307e5..0000000
--- a/libs/vr/libdisplay/video_mesh_surface_client.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "include/private/dvr/video_mesh_surface_client.h"
-
-using android::pdx::LocalChannelHandle;
-
-namespace android {
-namespace dvr {
-
-/* static */
-std::unique_ptr<VideoMeshSurfaceClient> VideoMeshSurfaceClient::Import(
-    LocalChannelHandle handle) {
-  return VideoMeshSurfaceClient::Create(std::move(handle));
-}
-
-VideoMeshSurfaceClient::VideoMeshSurfaceClient(LocalChannelHandle handle)
-    : BASE(std::move(handle), SurfaceTypeEnum::VideoMesh),
-      mapped_metadata_buffer_(nullptr) {
-  // TODO(jwcai) import more data if needed.
-}
-
-std::shared_ptr<ProducerQueue> VideoMeshSurfaceClient::GetProducerQueue() {
-  if (producer_queue_ == nullptr) {
-    // Create producer queue through DisplayRPC
-    auto status =
-        InvokeRemoteMethod<DisplayRPC::VideoMeshSurfaceCreateProducerQueue>();
-    if (!status) {
-      ALOGE(
-          "VideoMeshSurfaceClient::GetProducerQueue: failed to create producer "
-          "queue: %s",
-          status.GetErrorMessage().c_str());
-      return nullptr;
-    }
-
-    producer_queue_ = ProducerQueue::Import(status.take());
-  }
-  return producer_queue_;
-}
-
-volatile VideoMeshSurfaceMetadata*
-VideoMeshSurfaceClient::GetMetadataBufferPtr() {
-  if (!mapped_metadata_buffer_) {
-    if (auto buffer_producer = GetMetadataBuffer()) {
-      void* addr = nullptr;
-      const int ret = buffer_producer->GetBlobReadWritePointer(
-          sizeof(VideoMeshSurfaceMetadata), &addr);
-      if (ret < 0) {
-        ALOGE(
-            "VideoMeshSurfaceClient::GetMetadataBufferPtr: Failed to map "
-            "surface metadata: %s",
-            strerror(-ret));
-        return nullptr;
-      }
-      mapped_metadata_buffer_ = static_cast<VideoMeshSurfaceMetadata*>(addr);
-    }
-  }
-
-  return mapped_metadata_buffer_;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdisplay/vsync_client.cpp b/libs/vr/libdisplay/vsync_client.cpp
index c928a08..bc6cf6c 100644
--- a/libs/vr/libdisplay/vsync_client.cpp
+++ b/libs/vr/libdisplay/vsync_client.cpp
@@ -3,8 +3,9 @@
 #include <log/log.h>
 
 #include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/display_protocol.h>
 
+using android::dvr::display::VSyncProtocol;
 using android::pdx::Transaction;
 
 namespace android {
@@ -12,15 +13,15 @@
 
 VSyncClient::VSyncClient(long timeout_ms)
     : BASE(pdx::default_transport::ClientChannelFactory::Create(
-               DisplayVSyncRPC::kClientPath),
+               VSyncProtocol::kClientPath),
            timeout_ms) {}
 
 VSyncClient::VSyncClient()
     : BASE(pdx::default_transport::ClientChannelFactory::Create(
-          DisplayVSyncRPC::kClientPath)) {}
+          VSyncProtocol::kClientPath)) {}
 
 int VSyncClient::Wait(int64_t* timestamp_ns) {
-  auto status = InvokeRemoteMethod<DisplayVSyncRPC::Wait>();
+  auto status = InvokeRemoteMethod<VSyncProtocol::Wait>();
   if (!status) {
     ALOGE("VSyncClient::Wait: Failed to wait for vsync: %s",
           status.GetErrorMessage().c_str());
@@ -36,7 +37,7 @@
 int VSyncClient::GetFd() { return event_fd(); }
 
 int VSyncClient::GetLastTimestamp(int64_t* timestamp_ns) {
-  auto status = InvokeRemoteMethod<DisplayVSyncRPC::GetLastTimestamp>();
+  auto status = InvokeRemoteMethod<VSyncProtocol::GetLastTimestamp>();
   if (!status) {
     ALOGE("VSyncClient::GetLastTimestamp: Failed to get vsync timestamp: %s",
           status.GetErrorMessage().c_str());
@@ -51,7 +52,7 @@
   if (!vsync_period_ns || !timestamp_ns || !next_vsync_count)
     return -EINVAL;
 
-  auto status = InvokeRemoteMethod<DisplayVSyncRPC::GetSchedInfo>();
+  auto status = InvokeRemoteMethod<VSyncProtocol::GetSchedInfo>();
   if (!status) {
     ALOGE("VSyncClient::GetSchedInfo:: Failed to get warp timestamp: %s",
           status.GetErrorMessage().c_str());
@@ -65,7 +66,7 @@
 }
 
 int VSyncClient::Acknowledge() {
-  auto status = InvokeRemoteMethod<DisplayVSyncRPC::Acknowledge>();
+  auto status = InvokeRemoteMethod<VSyncProtocol::Acknowledge>();
   ALOGE_IF(!status, "VSuncClient::Acknowledge: Failed to ack vsync because: %s",
            status.GetErrorMessage().c_str());
   return ReturnStatusOrError(status);
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
new file mode 100644
index 0000000..3876745
--- /dev/null
+++ b/libs/vr/libdvr/Android.bp
@@ -0,0 +1,67 @@
+// 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"],
+}
+
+cc_library_static {
+    name: "libdvr",
+    owner: "google",
+
+    cflags: [
+        "-fvisibility=hidden",
+        "-DLOG_TAG=\"libdvr\"",
+        "-DDVR_EXPORT=__attribute__((visibility(\"default\")))",
+    ],
+
+    header_libs: ["libdvr_headers"],
+    export_header_lib_headers: ["libdvr_headers"],
+
+    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",
+    ],
+
+    shared_libs: [
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hidl.token@1.0-utils",
+        "libbase",
+        "libnativewindow",
+    ],
+
+}
+
+subdirs = [
+    "tests",
+]
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
deleted file mode 100644
index aa4513e..0000000
--- a/libs/vr/libdvr/Android.mk
+++ /dev/null
@@ -1,58 +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 \
-    -D DVR_EXPORT='__attribute__ ((visibility ("default")))'
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/include \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/include \
-
-LOCAL_SRC_FILES := \
-    display_manager_client.cpp \
-    dvr_api.cpp \
-    dvr_buffer.cpp \
-    dvr_buffer_queue.cpp \
-    dvr_hardware_composer_client.cpp \
-    dvr_surface.cpp \
-    vsync_client_api.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/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
deleted file mode 100644
index e469e3e..0000000
--- a/libs/vr/libdvr/display_manager_client.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-#include "include/dvr/display_manager_client.h"
-
-#include <dvr/dvr_buffer.h>
-#include <grallocusage/GrallocUsageConversion.h>
-#include <private/android/AHardwareBufferHelpers.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/display_manager_client_impl.h>
-
-using android::dvr::DisplaySurfaceAttributeEnum;
-
-extern "C" {
-
-struct DvrDisplayManagerClient {
-  DvrDisplayManagerClient()
-      : client(android::dvr::DisplayManagerClient::Create()) {}
-  ~DvrDisplayManagerClient() {}
-
-  std::unique_ptr<android::dvr::DisplayManagerClient> client;
-};
-
-struct DvrDisplayManagerClientSurfaceList {
-  DvrDisplayManagerClientSurfaceList(
-      std::vector<android::dvr::DisplaySurfaceInfo> surface_list)
-      : list(std::move(surface_list)) {}
-  ~DvrDisplayManagerClientSurfaceList() {}
-
-  std::vector<android::dvr::DisplaySurfaceInfo> list;
-};
-
-struct DvrDisplayManagerClientSurfaceBuffers {
-  DvrDisplayManagerClientSurfaceBuffers(
-      std::vector<std::unique_ptr<android::dvr::BufferConsumer>> buffer_list)
-      : list(std::move(buffer_list)) {}
-  ~DvrDisplayManagerClientSurfaceBuffers() {}
-
-  std::vector<std::unique_ptr<android::dvr::BufferConsumer>> list;
-};
-
-DvrDisplayManagerClient* dvrDisplayManagerClientCreate() {
-  return new DvrDisplayManagerClient();
-}
-
-void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client) {
-  delete client;
-}
-
-DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
-                                             const char* name, size_t size,
-                                             uint64_t hardware_buffer_usage,
-                                             uint64_t unused) {
-  uint64_t producer_usage = 0;
-  uint64_t consumer_usage = 0;
-
-  // Note: AHardwareBuffer no longer uses usage0/usage1
-  uint64_t gralloc_usage =
-      android::AHardwareBuffer_convertToGrallocUsageBits(hardware_buffer_usage);
-
-  // Note: split producer/consumer usage is deprecated, grallocV2 uses single
-  // 64-bits usage
-  // And, currently, 64-bits gralloc usage flags can safely be truncated to
-  // 32-bits
-  android_convertGralloc0To1Usage((uint32_t)gralloc_usage, &producer_usage,
-                                  &consumer_usage);
-
-  auto ion_buffer = client->client->SetupNamedBuffer(name, size, producer_usage,
-                                                     consumer_usage);
-  if (ion_buffer) {
-    return CreateDvrBufferFromIonBuffer(std::move(ion_buffer));
-  }
-  return nullptr;
-}
-
-int dvrDisplayManagerClientGetEventFd(DvrDisplayManagerClient* client) {
-  return client->client->event_fd();
-}
-
-int dvrDisplayManagerClientTranslateEpollEventMask(
-    DvrDisplayManagerClient* client, int in_events, int* out_events) {
-  auto result = client->client->GetChannel()->GetEventMask(in_events);
-
-  if (!result) {
-    return -EIO;
-  }
-
-  *out_events = result.get();
-
-  return 0;
-}
-
-int dvrDisplayManagerClientGetSurfaceList(
-    DvrDisplayManagerClient* client,
-    DvrDisplayManagerClientSurfaceList** surface_list) {
-  std::vector<android::dvr::DisplaySurfaceInfo> list;
-  int ret = client->client->GetSurfaceList(&list);
-  if (ret < 0)
-    return ret;
-
-  *surface_list = new DvrDisplayManagerClientSurfaceList(std::move(list));
-  return ret;
-}
-
-void dvrDisplayManagerClientSurfaceListDestroy(
-    DvrDisplayManagerClientSurfaceList* surface_list) {
-  delete surface_list;
-}
-
-size_t dvrDisplayManagerClientSurfaceListGetSize(
-    DvrDisplayManagerClientSurfaceList* surface_list) {
-  return surface_list->list.size();
-}
-
-int dvrDisplayManagerClientSurfaceListGetSurfaceId(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
-  return surface_list->list[index].surface_id;
-}
-
-int dvrDisplayManagerClientSurfaceListGetClientZOrder(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
-  return surface_list->list[index].ClientZOrder();
-}
-
-bool dvrDisplayManagerClientSurfaceListGetClientIsVisible(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
-  return surface_list->list[index].IsClientVisible();
-}
-
-int dvrDisplayManagerClientGetSurfaceBuffers(
-    DvrDisplayManagerClient* /* client */, int /* surface_id */,
-    DvrDisplayManagerClientSurfaceBuffers** /* surface_buffers */) {
-  // TODO(jwcai, hendrikw) Remove this after we replacing
-  // dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
-  return -1;
-}
-
-void dvrDisplayManagerClientSurfaceBuffersDestroy(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers) {
-  delete surface_buffers;
-}
-
-size_t dvrDisplayManagerClientSurfaceBuffersGetSize(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers) {
-  return surface_buffers->list.size();
-}
-
-int dvrDisplayManagerClientSurfaceBuffersGetFd(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index) {
-  return surface_buffers->list[index]->event_fd();
-}
-
-}  // extern "C"
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index c4634b1..4d7e1a6 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -1,13 +1,14 @@
 #include "include/dvr/dvr_api.h"
 
 #include <errno.h>
+#include <utils/Log.h>
 
 // Headers from libdvr
-#include <dvr/display_manager_client.h>
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_display_manager.h>
 #include <dvr/dvr_surface.h>
-#include <dvr/vsync_client_api.h>
+#include <dvr/dvr_vsync.h>
 
 // Headers not yet moved into libdvr.
 // TODO(jwcai) Move these once their callers are moved into Google3.
@@ -18,134 +19,28 @@
 extern "C" {
 
 DVR_EXPORT 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) {
     if (struct_size != sizeof(DvrApi_v1)) {
+      ALOGE("dvrGetApi: Size mismatch: expected %zu; actual %zu",
+            sizeof(DvrApi_v1), struct_size);
       return -EINVAL;
     }
     DvrApi_v1* dvr_api = static_cast<DvrApi_v1*>(api);
 
-    // display_manager_client.h
-    dvr_api->display_manager_client_create = dvrDisplayManagerClientCreate;
-    dvr_api->display_manager_client_destroy = dvrDisplayManagerClientDestroy;
-    dvr_api->display_manager_client_get_surface_list =
-        dvrDisplayManagerClientGetSurfaceList;
-    dvr_api->display_manager_client_surface_list_destroy =
-        dvrDisplayManagerClientSurfaceListDestroy;
-    dvr_api->display_manager_setup_named_buffer =
-        dvrDisplayManagerSetupNamedBuffer;
-    dvr_api->display_manager_client_surface_list_get_size =
-        dvrDisplayManagerClientSurfaceListGetSize;
-    dvr_api->display_manager_client_surface_list_get_surface_id =
-        dvrDisplayManagerClientSurfaceListGetSurfaceId;
-    dvr_api->display_manager_client_get_surface_buffer_list =
-        dvrDisplayManagerClientGetSurfaceBuffers;
-    dvr_api->display_manager_client_surface_buffer_list_destroy =
-        dvrDisplayManagerClientSurfaceBuffersDestroy;
-    dvr_api->display_manager_client_surface_buffer_list_get_size =
-        dvrDisplayManagerClientSurfaceBuffersGetSize;
-    dvr_api->display_manager_client_surface_buffer_list_get_fd =
-        dvrDisplayManagerClientSurfaceBuffersGetFd;
+// Defines an API entry for V1 (no version suffix).
+#define DVR_V1_API_ENTRY(name) dvr_api->name = dvr##name
 
-    // dvr_buffer.h
-    dvr_api->write_buffer_destroy = dvrWriteBufferDestroy;
-    dvr_api->write_buffer_get_ahardwarebuffer =
-        dvrWriteBufferGetAHardwareBuffer;
-    dvr_api->write_buffer_post = dvrWriteBufferPost;
-    dvr_api->write_buffer_gain = dvrWriteBufferGain;
-    dvr_api->write_buffer_gain_async = dvrWriteBufferGainAsync;
-    dvr_api->write_buffer_get_native_handle = dvrWriteBufferGetNativeHandle;
+#include "include/dvr/dvr_api_entries.h"
 
-    dvr_api->read_buffer_destroy = dvrReadBufferDestroy;
-    dvr_api->read_buffer_get_ahardwarebuffer = dvrReadBufferGetAHardwareBuffer;
-    dvr_api->read_buffer_acquire = dvrReadBufferAcquire;
-    dvr_api->read_buffer_release = dvrReadBufferRelease;
-    dvr_api->read_buffer_release_async = dvrReadBufferReleaseAsync;
-    dvr_api->read_buffer_get_native_handle = dvrReadBufferGetNativeHandle;
-
-    dvr_api->buffer_destroy = dvrBufferDestroy;
-    dvr_api->buffer_get_ahardwarebuffer = dvrBufferGetAHardwareBuffer;
-    dvr_api->buffer_get_native_handle = dvrBufferGetNativeHandle;
-
-    // dvr_buffer_queue.h
-    dvr_api->write_buffer_queue_destroy = dvrWriteBufferQueueDestroy;
-    dvr_api->write_buffer_queue_get_capacity = dvrWriteBufferQueueGetCapacity;
-    dvr_api->write_buffer_queue_get_external_surface =
-        dvrWriteBufferQueueGetExternalSurface;
-    dvr_api->write_buffer_queue_create_read_queue =
-        dvrWriteBufferQueueCreateReadQueue;
-    dvr_api->write_buffer_queue_dequeue = dvrWriteBufferQueueDequeue;
-    dvr_api->read_buffer_queue_destroy = dvrReadBufferQueueDestroy;
-    dvr_api->read_buffer_queue_get_capacity = dvrReadBufferQueueGetCapacity;
-    dvr_api->read_buffer_queue_create_read_queue =
-        dvrReadBufferQueueCreateReadQueue;
-    dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
-
-    // dvr_surface.h
-    dvr_api->get_named_buffer = dvrGetNamedBuffer;
-    dvr_api->surface_create = dvrSurfaceCreate;
-    dvr_api->surface_get_write_buffer_queue = dvrSurfaceGetWriteBufferQueue;
-
-    // vsync_client_api.h
-    dvr_api->vsync_client_create = dvr_vsync_client_create;
-    dvr_api->vsync_client_destroy = dvr_vsync_client_destroy;
-    dvr_api->vsync_client_get_sched_info = dvr_vsync_client_get_sched_info;
-
-    // pose_client.h
-    dvr_api->pose_client_create = dvrPoseCreate;
-    dvr_api->pose_client_destroy = dvrPoseDestroy;
-    dvr_api->pose_get = dvrPoseGet;
-    dvr_api->pose_get_vsync_count = dvrPoseGetVsyncCount;
-    dvr_api->pose_get_controller = dvrPoseGetController;
-
-    // virtual_touchpad_client.h
-    dvr_api->virtual_touchpad_create = dvrVirtualTouchpadCreate;
-    dvr_api->virtual_touchpad_destroy = dvrVirtualTouchpadDestroy;
-    dvr_api->virtual_touchpad_attach = dvrVirtualTouchpadAttach;
-    dvr_api->virtual_touchpad_detach = dvrVirtualTouchpadDetach;
-    dvr_api->virtual_touchpad_touch = dvrVirtualTouchpadTouch;
-    dvr_api->virtual_touchpad_button_state = dvrVirtualTouchpadButtonState;
-
-    // dvr_hardware_composer_client.h
-    dvr_api->hwc_client_create = dvrHwcClientCreate;
-    dvr_api->hwc_client_destroy = dvrHwcClientDestroy;
-    dvr_api->hwc_frame_destroy = dvrHwcFrameDestroy;
-    dvr_api->hwc_frame_get_display_id = dvrHwcFrameGetDisplayId;
-    dvr_api->hwc_frame_get_display_width = dvrHwcFrameGetDisplayWidth;
-    dvr_api->hwc_frame_get_display_height = dvrHwcFrameGetDisplayHeight;
-    dvr_api->hwc_frame_get_display_removed = dvrHwcFrameGetDisplayRemoved;
-    dvr_api->hwc_frame_get_active_config = dvrHwcFrameGetActiveConfig;
-    dvr_api->hwc_frame_get_color_mode = dvrHwcFrameGetColorMode;
-    dvr_api->hwc_frame_get_color_transform = dvrHwcFrameGetColorTransform;
-    dvr_api->hwc_frame_get_power_mode = dvrHwcFrameGetPowerMode;
-    dvr_api->hwc_frame_get_vsync_enabled = dvrHwcFrameGetVsyncEnabled;
-    dvr_api->hwc_frame_get_layer_count = dvrHwcFrameGetLayerCount;
-    dvr_api->hwc_frame_get_layer_id = dvrHwcFrameGetLayerId;
-    dvr_api->hwc_frame_get_layer_buffer = dvrHwcFrameGetLayerBuffer;
-    dvr_api->hwc_frame_get_layer_fence = dvrHwcFrameGetLayerFence;
-    dvr_api->hwc_frame_get_layer_display_frame =
-        dvrHwcFrameGetLayerDisplayFrame;
-    dvr_api->hwc_frame_get_layer_crop = dvrHwcFrameGetLayerCrop;
-    dvr_api->hwc_frame_get_layer_blend_mode = dvrHwcFrameGetLayerBlendMode;
-    dvr_api->hwc_frame_get_layer_alpha = dvrHwcFrameGetLayerAlpha;
-    dvr_api->hwc_frame_get_layer_type = dvrHwcFrameGetLayerType;
-    dvr_api->hwc_frame_get_layer_application_id =
-        dvrHwcFrameGetLayerApplicationId;
-    dvr_api->hwc_frame_get_layer_z_order = dvrHwcFrameGetLayerZOrder;
-    dvr_api->hwc_frame_get_layer_cursor = dvrHwcFrameGetLayerCursor;
-    dvr_api->hwc_frame_get_layer_transform = dvrHwcFrameGetLayerTransform;
-    dvr_api->hwc_frame_get_layer_dataspace = dvrHwcFrameGetLayerDataspace;
-    dvr_api->hwc_frame_get_layer_color = dvrHwcFrameGetLayerColor;
-    dvr_api->hwc_frame_get_layer_num_visible_regions =
-        dvrHwcFrameGetLayerNumVisibleRegions;
-    dvr_api->hwc_frame_get_layer_visible_region =
-        dvrHwcFrameGetLayerVisibleRegion;
-    dvr_api->hwc_frame_get_layer_num_damaged_regions =
-        dvrHwcFrameGetLayerNumDamagedRegions;
-    dvr_api->hwc_frame_get_layer_damaged_region =
-        dvrHwcFrameGetLayerDamagedRegion;
+// Undefine macro definitions to play nice with Google3 style rules.
+#undef DVR_V1_API_ENTRY
 
     return 0;
   }
+
+  ALOGE("dvrGetApi: Unknown API version=%d", version);
   return -EINVAL;
 }
 
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 28820e7..82469b8 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -4,37 +4,13 @@
 #include <private/dvr/buffer_hub_client.h>
 #include <ui/GraphicBuffer.h>
 
+#include "dvr_internal.h"
+
 using namespace android;
 
-struct DvrWriteBuffer {
-  std::shared_ptr<dvr::BufferProducer> write_buffer;
-};
-
-struct DvrReadBuffer {
-  std::shared_ptr<dvr::BufferConsumer> read_buffer;
-};
-
-struct DvrBuffer {
-  std::shared_ptr<dvr::IonBuffer> buffer;
-};
-
 namespace android {
 namespace dvr {
 
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
-    const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
-  if (!buffer_producer)
-    return nullptr;
-  return new DvrWriteBuffer{std::move(buffer_producer)};
-}
-
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
-    const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
-  if (!buffer_consumer)
-    return nullptr;
-  return new DvrReadBuffer{std::move(buffer_consumer)};
-}
-
 DvrBuffer* CreateDvrBufferFromIonBuffer(
     const std::shared_ptr<IonBuffer>& ion_buffer) {
   if (!ion_buffer)
@@ -47,14 +23,6 @@
 
 namespace {
 
-void InitializeGraphicBuffer(const dvr::BufferHubBuffer* buffer,
-                             sp<GraphicBuffer>* graphic_buffer) {
-  *graphic_buffer = sp<GraphicBuffer>(new GraphicBuffer(
-      buffer->width(), buffer->height(), buffer->format(), 1, /* layer count */
-      buffer->usage(), buffer->stride(), buffer->native_handle(),
-      false /* keep ownership */));
-}
-
 int ConvertToAHardwareBuffer(GraphicBuffer* graphic_buffer,
                              AHardwareBuffer** hardware_buffer) {
   if (!hardware_buffer || !graphic_buffer) {
@@ -69,28 +37,57 @@
 
 extern "C" {
 
+void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer) {
+  if (write_buffer)
+    *write_buffer = new DvrWriteBuffer;
+}
+
 void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
   delete write_buffer;
 }
 
+int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer) {
+  return write_buffer && write_buffer->write_buffer;
+}
+
+int dvrWriteBufferClear(DvrWriteBuffer* write_buffer) {
+  if (!write_buffer)
+    return -EINVAL;
+
+  write_buffer->write_buffer = nullptr;
+  return 0;
+}
+
 int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return -EINVAL;
+
   return write_buffer->write_buffer->id();
 }
 
 int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return -EINVAL;
+
   return ConvertToAHardwareBuffer(
       write_buffer->write_buffer->buffer()->buffer().get(), hardware_buffer);
 }
 
 int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return -EINVAL;
+
   pdx::LocalHandle fence(ready_fence_fd);
   int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
   return result;
 }
 
 int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
+  if (!write_buffer || !write_buffer->write_buffer || !release_fence_fd)
+    return -EINVAL;
+
   pdx::LocalHandle release_fence;
   int result = write_buffer->write_buffer->Gain(&release_fence);
   *release_fence_fd = release_fence.Release();
@@ -98,23 +95,52 @@
 }
 
 int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return -EINVAL;
+
   return write_buffer->write_buffer->GainAsync();
 }
 
+void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer) {
+  if (read_buffer)
+    *read_buffer = new DvrReadBuffer;
+}
+
 void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
 
+int dvrReadBufferIsValid(DvrReadBuffer* read_buffer) {
+  return read_buffer && read_buffer->read_buffer;
+}
+
+int dvrReadBufferClear(DvrReadBuffer* read_buffer) {
+  if (!read_buffer)
+    return -EINVAL;
+
+  read_buffer->read_buffer = nullptr;
+  return 0;
+}
+
 int dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   return read_buffer->read_buffer->id();
 }
 
 int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   return ConvertToAHardwareBuffer(
       read_buffer->read_buffer->buffer()->buffer().get(), hardware_buffer);
 }
 
 int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
                          void* meta, size_t meta_size_bytes) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   pdx::LocalHandle ready_fence;
   int result =
       read_buffer->read_buffer->Acquire(&ready_fence, meta, meta_size_bytes);
@@ -123,12 +149,18 @@
 }
 
 int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   pdx::LocalHandle fence(release_fence_fd);
   int result = read_buffer->read_buffer->Release(fence);
   return result;
 }
 
 int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   return read_buffer->read_buffer->ReleaseAsync();
 }
 
@@ -136,21 +168,34 @@
 
 int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
                                 AHardwareBuffer** hardware_buffer) {
+  if (!buffer || !buffer->buffer || !hardware_buffer) {
+    return -EINVAL;
+  }
+
   return ConvertToAHardwareBuffer(buffer->buffer->buffer().get(),
                                   hardware_buffer);
 }
 
 const struct native_handle* dvrWriteBufferGetNativeHandle(
     DvrWriteBuffer* write_buffer) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return nullptr;
+
   return write_buffer->write_buffer->native_handle();
 }
 
 const struct native_handle* dvrReadBufferGetNativeHandle(
     DvrReadBuffer* read_buffer) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return nullptr;
+
   return read_buffer->read_buffer->native_handle();
 }
 
 const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer) {
+  if (!buffer || !buffer->buffer)
+    return nullptr;
+
   return buffer->buffer->handle();
 }
 
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 50c94cb..95c0e26 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -6,45 +6,77 @@
 #include <private/dvr/buffer_hub_queue_client.h>
 #include <private/dvr/buffer_hub_queue_producer.h>
 
+#include "dvr_internal.h"
+
 #define CHECK_PARAM(param)                                               \
   LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
                       __FUNCTION__)
 
 using namespace android;
 
+namespace android {
+namespace dvr {
+
+DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
+    const std::shared_ptr<dvr::ProducerQueue>& producer_queue) {
+  return new DvrWriteBufferQueue{std::move(producer_queue)};
+}
+
+DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
+    const std::shared_ptr<dvr::ConsumerQueue>& consumer_queue) {
+  return new DvrReadBufferQueue{std::move(consumer_queue)};
+}
+
+dvr::ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
+    DvrWriteBufferQueue* write_queue) {
+  return write_queue->producer_queue.get();
+}
+
+}  // namespace dvr
+}  // namespace android
+
 extern "C" {
 
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
-  if (write_queue != nullptr && write_queue->native_window_ != nullptr) {
-    ANativeWindow_release(write_queue->native_window_);
-  }
+  if (write_queue != nullptr && write_queue->native_window != nullptr)
+    ANativeWindow_release(write_queue->native_window);
+
   delete write_queue;
 }
 
-size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
-  CHECK_PARAM(write_queue);
-  return write_queue->producer_queue_->capacity();
+ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
+  if (!write_queue || !write_queue->producer_queue)
+    return -EINVAL;
+
+  return write_queue->producer_queue->capacity();
+}
+
+int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) {
+  if (!write_queue)
+    return -EINVAL;
+
+  return write_queue->producer_queue->id();
 }
 
 int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
                                           ANativeWindow** out_window) {
-  CHECK_PARAM(write_queue);
-  CHECK_PARAM(out_window);
+  if (!write_queue || !out_window)
+    return -EINVAL;
 
-  if (write_queue->producer_queue_->metadata_size() !=
+  if (write_queue->producer_queue->metadata_size() !=
       sizeof(DvrNativeBufferMetadata)) {
     ALOGE(
-        "The size of buffer metadata (%u) of the write queue does not match of "
-        "size of DvrNativeBufferMetadata (%u).",
-        write_queue->producer_queue_->metadata_size(),
+        "The size of buffer metadata (%zu) of the write queue does not match "
+        "of size of DvrNativeBufferMetadata (%zu).",
+        write_queue->producer_queue->metadata_size(),
         sizeof(DvrNativeBufferMetadata));
     return -EINVAL;
   }
 
-  // Lazy creation of |native_window_|.
-  if (write_queue->native_window_ == nullptr) {
+  // Lazy creation of |native_window|.
+  if (write_queue->native_window == nullptr) {
     std::shared_ptr<dvr::BufferHubQueueCore> core =
-        dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+        dvr::BufferHubQueueCore::Create(write_queue->producer_queue);
     if (core == nullptr) {
       ALOGE(
           "dvrWriteBufferQueueGetExternalSurface: Failed to create native "
@@ -54,24 +86,23 @@
 
     sp<IGraphicBufferProducer> gbp = new dvr::BufferHubQueueProducer(core);
     sp<Surface> surface = new Surface(gbp, true);
-    write_queue->native_window_ = static_cast<ANativeWindow*>(surface.get());
-    ANativeWindow_acquire(write_queue->native_window_);
+    write_queue->native_window = static_cast<ANativeWindow*>(surface.get());
+    ANativeWindow_acquire(write_queue->native_window);
   }
 
-  *out_window = write_queue->native_window_;
+  *out_window = write_queue->native_window;
   return 0;
 }
 
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue) {
-  CHECK_PARAM(write_queue);
-  CHECK_PARAM(write_queue->producer_queue_);
-  CHECK_PARAM(out_read_queue);
+  if (!write_queue || !write_queue->producer_queue || !out_read_queue)
+    return -EINVAL;
 
   auto read_queue = std::make_unique<DvrReadBufferQueue>();
-  read_queue->consumer_queue_ =
-      write_queue->producer_queue_->CreateConsumerQueue();
-  if (read_queue->consumer_queue_ == nullptr) {
+  read_queue->consumer_queue =
+      write_queue->producer_queue->CreateConsumerQueue();
+  if (read_queue->consumer_queue == nullptr) {
     ALOGE(
         "dvrWriteBufferQueueCreateReadQueue: Failed to create consumer queue "
         "from DvrWriteBufferQueue[%p].",
@@ -84,23 +115,25 @@
 }
 
 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
-                                  DvrWriteBuffer** out_buffer,
-                                  int* out_fence_fd) {
-  CHECK_PARAM(write_queue);
-  CHECK_PARAM(write_queue->producer_queue_);
-  CHECK_PARAM(out_buffer);
-  CHECK_PARAM(out_fence_fd);
+                               DvrWriteBuffer* write_buffer,
+                               int* out_fence_fd) {
+  if (!write_queue || !write_queue->producer_queue || !write_buffer ||
+      !out_fence_fd) {
+    return -EINVAL;
+  }
 
   size_t slot;
   pdx::LocalHandle release_fence;
-  std::shared_ptr<dvr::BufferProducer> buffer =
-      write_queue->producer_queue_->Dequeue(timeout, &slot, &release_fence);
-  if (buffer == nullptr) {
-    ALOGE("dvrWriteBufferQueueDequeue: Failed to dequeue buffer.");
-    return -ENOMEM;
+  auto buffer_status =
+      write_queue->producer_queue->Dequeue(timeout, &slot, &release_fence);
+  if (!buffer_status) {
+    ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+             "dvrWriteBufferQueueDequeue: Failed to dequeue buffer: %s",
+             buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
   }
 
-  *out_buffer = CreateDvrWriteBufferFromBufferProducer(buffer);
+  write_buffer->write_buffer = buffer_status.take();
   *out_fence_fd = release_fence.Release();
   return 0;
 }
@@ -110,22 +143,29 @@
   delete read_queue;
 }
 
-size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
-  CHECK_PARAM(read_queue);
+ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
+  if (!read_queue)
+    return -EINVAL;
 
-  return read_queue->consumer_queue_->capacity();
+  return read_queue->consumer_queue->capacity();
+}
+
+int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) {
+  if (!read_queue)
+    return -EINVAL;
+
+  return read_queue->consumer_queue->id();
 }
 
 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
                                       DvrReadBufferQueue** out_read_queue) {
-  CHECK_PARAM(read_queue);
-  CHECK_PARAM(read_queue->consumer_queue_);
-  CHECK_PARAM(out_read_queue);
+  if (!read_queue || !read_queue->consumer_queue || !out_read_queue)
+    return -EINVAL;
 
   auto new_read_queue = std::make_unique<DvrReadBufferQueue>();
-  new_read_queue->consumer_queue_ =
-      read_queue->consumer_queue_->CreateConsumerQueue();
-  if (new_read_queue->consumer_queue_ == nullptr) {
+  new_read_queue->consumer_queue =
+      read_queue->consumer_queue->CreateConsumerQueue();
+  if (new_read_queue->consumer_queue == nullptr) {
     ALOGE(
         "dvrReadBufferQueueCreateReadQueue: Failed to create consumer queue "
         "from DvrReadBufferQueue[%p].",
@@ -138,34 +178,33 @@
 }
 
 int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
-                              DvrReadBuffer** out_buffer, int* out_fence_fd,
+                              DvrReadBuffer* read_buffer, int* out_fence_fd,
                               void* out_meta, size_t meta_size_bytes) {
-  CHECK_PARAM(read_queue);
-  CHECK_PARAM(read_queue->consumer_queue_);
-  CHECK_PARAM(out_buffer);
-  CHECK_PARAM(out_fence_fd);
-  CHECK_PARAM(out_meta);
+  if (!read_queue || !read_queue->consumer_queue || !read_buffer ||
+      !out_fence_fd || !out_meta) {
+    return -EINVAL;
+  }
 
-  if (meta_size_bytes != read_queue->consumer_queue_->metadata_size()) {
+  if (meta_size_bytes != read_queue->consumer_queue->metadata_size()) {
     ALOGE(
         "dvrReadBufferQueueDequeue: Invalid metadata size, expected (%zu), "
         "but actual (%zu).",
-        read_queue->consumer_queue_->metadata_size(), meta_size_bytes);
+        read_queue->consumer_queue->metadata_size(), meta_size_bytes);
     return -EINVAL;
   }
 
   size_t slot;
   pdx::LocalHandle acquire_fence;
-  std::shared_ptr<dvr::BufferConsumer> buffer =
-      read_queue->consumer_queue_->Dequeue(timeout, &slot, out_meta,
-                                           meta_size_bytes, &acquire_fence);
-
-  if (buffer == nullptr) {
-    ALOGE("dvrReadBufferQueueGainBuffer: Failed to dequeue buffer.");
-    return -ENOMEM;
+  auto buffer_status = read_queue->consumer_queue->Dequeue(
+      timeout, &slot, out_meta, meta_size_bytes, &acquire_fence);
+  if (!buffer_status) {
+    ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+             "dvrReadBufferQueueDequeue: Failed to dequeue buffer: %s",
+             buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
   }
 
-  *out_buffer = CreateDvrReadBufferFromBufferConsumer(buffer);
+  read_buffer->read_buffer = buffer_status.take();
   *out_fence_fd = acquire_fence.Release();
   return 0;
 }
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
new file mode 100644
index 0000000..87636ec
--- /dev/null
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -0,0 +1,304 @@
+#include "include/dvr/dvr_display_manager.h"
+
+#include <dvr/dvr_buffer.h>
+#include <pdx/rpc/variant.h>
+#include <private/android/AHardwareBufferHelpers.h>
+#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_manager_client.h>
+
+#include "dvr_internal.h"
+
+using android::AHardwareBuffer_convertToGrallocUsageBits;
+using android::dvr::BufferConsumer;
+using android::dvr::display::DisplayManagerClient;
+using android::dvr::display::SurfaceAttributes;
+using android::dvr::display::SurfaceAttribute;
+using android::dvr::display::SurfaceState;
+using android::dvr::CreateDvrReadBufferQueueFromConsumerQueue;
+using android::pdx::rpc::EmptyVariant;
+
+namespace {
+
+// Extracts type and value from the attribute Variant and writes them into the
+// respective fields of DvrSurfaceAttribute.
+struct AttributeVisitor {
+  DvrSurfaceAttribute* attribute;
+
+  void operator()(int32_t value) {
+    attribute->value.int32_value = value;
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
+  }
+  void operator()(int64_t value) {
+    attribute->value.int64_value = value;
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT64;
+  }
+  void operator()(bool value) {
+    attribute->value.bool_value = value;
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
+  }
+  void operator()(float value) {
+    attribute->value.float_value = value;
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT;
+  }
+  void operator()(const std::array<float, 2>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float2_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2;
+  }
+  void operator()(const std::array<float, 3>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float3_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3;
+  }
+  void operator()(const std::array<float, 4>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float4_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4;
+  }
+  void operator()(const std::array<float, 8>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float8_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8;
+  }
+  void operator()(const std::array<float, 16>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float16_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16;
+  }
+  void operator()(EmptyVariant) {
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_NONE;
+  }
+};
+
+size_t ConvertSurfaceAttributes(const SurfaceAttributes& surface_attributes,
+                                DvrSurfaceAttribute* attributes,
+                                size_t max_count) {
+  size_t count = 0;
+  for (const auto& attribute : surface_attributes) {
+    if (count >= max_count)
+      break;
+
+    // Copy the key and extract the Variant value using a visitor.
+    attributes[count].key = attribute.first;
+    attribute.second.Visit(AttributeVisitor{&attributes[count]});
+    count++;
+  }
+
+  return count;
+}
+
+}  // anonymous namespace
+
+extern "C" {
+
+struct DvrDisplayManager {
+  std::unique_ptr<DisplayManagerClient> client;
+};
+
+struct DvrSurfaceState {
+  std::vector<SurfaceState> state;
+};
+
+int dvrDisplayManagerCreate(DvrDisplayManager** client_out) {
+  if (!client_out)
+    return -EINVAL;
+
+  auto client = DisplayManagerClient::Create();
+  if (!client) {
+    ALOGE("dvrDisplayManagerCreate: Failed to create display manager client!");
+    return -EIO;
+  }
+
+  *client_out = new DvrDisplayManager{std::move(client)};
+  return 0;
+}
+
+void dvrDisplayManagerDestroy(DvrDisplayManager* client) { delete client; }
+
+int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
+                                      const char* name, size_t size,
+                                      uint64_t usage, DvrBuffer** buffer_out) {
+  if (!client || !name || !buffer_out)
+    return -EINVAL;
+
+  uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
+
+  auto buffer_status =
+      client->client->SetupNamedBuffer(name, size, gralloc_usage);
+  if (!buffer_status) {
+    ALOGE("dvrDisplayManagerSetupPoseBuffer: Failed to setup named buffer: %s",
+          buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
+  }
+
+  *buffer_out = CreateDvrBufferFromIonBuffer(buffer_status.take());
+  return 0;
+}
+
+int dvrDisplayManagerGetEventFd(DvrDisplayManager* client) {
+  if (!client)
+    return -EINVAL;
+
+  return client->client->event_fd();
+}
+
+int dvrDisplayManagerTranslateEpollEventMask(DvrDisplayManager* client,
+                                             int in_events, int* out_events) {
+  if (!client || !out_events)
+    return -EINVAL;
+
+  auto status = client->client->GetEventMask(in_events);
+  if (!status)
+    return -status.error();
+
+  *out_events = status.get();
+  return 0;
+}
+
+int dvrDisplayManagerGetSurfaceState(DvrDisplayManager* client,
+                                     DvrSurfaceState* state) {
+  if (!client || !state)
+    return -EINVAL;
+
+  auto status = client->client->GetSurfaceState();
+  if (!status)
+    return -status.error();
+
+  state->state = status.take();
+  return 0;
+}
+
+int dvrDisplayManagerGetReadBufferQueue(DvrDisplayManager* client,
+                                        int surface_id, int queue_id,
+                                        DvrReadBufferQueue** queue_out) {
+  if (!client || !queue_out)
+    return -EINVAL;
+
+  auto status = client->client->GetSurfaceQueue(surface_id, queue_id);
+  if (!status) {
+    ALOGE("dvrDisplayManagerGetReadBufferQueue: Failed to get queue: %s",
+          status.GetErrorMessage().c_str());
+    return -status.error();
+  }
+
+  *queue_out = CreateDvrReadBufferQueueFromConsumerQueue(status.take());
+  return 0;
+}
+
+int dvrSurfaceStateCreate(DvrSurfaceState** surface_state_out) {
+  if (!surface_state_out)
+    return -EINVAL;
+
+  *surface_state_out = new DvrSurfaceState{};
+  return 0;
+}
+
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state) {
+  delete surface_state;
+}
+
+int dvrSurfaceStateGetSurfaceCount(DvrSurfaceState* surface_state,
+                                   size_t* count_out) {
+  if (!surface_state)
+    return -EINVAL;
+
+  *count_out = surface_state->state.size();
+  return 0;
+}
+
+int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
+                                  size_t surface_index,
+                                  DvrSurfaceUpdateFlags* flags_out) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  *flags_out = surface_state->state[surface_index].update_flags;
+  return 0;
+}
+
+int dvrSurfaceStateGetSurfaceId(DvrSurfaceState* surface_state,
+                                size_t surface_index, int* surface_id_out) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  *surface_id_out = surface_state->state[surface_index].surface_id;
+  return 0;
+}
+
+int dvrSurfaceStateGetProcessId(DvrSurfaceState* surface_state,
+                                size_t surface_index, int* process_id_out) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  *process_id_out = surface_state->state[surface_index].process_id;
+  return 0;
+}
+
+int dvrSurfaceStateGetQueueCount(DvrSurfaceState* surface_state,
+                                 size_t surface_index, size_t* count_out) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  *count_out = surface_state->state[surface_index].queue_ids.size();
+  return 0;
+}
+
+ssize_t dvrSurfaceStateGetQueueIds(DvrSurfaceState* surface_state,
+                                   size_t surface_index, int* queue_ids,
+                                   size_t max_count) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  size_t i;
+  const auto& state = surface_state->state[surface_index];
+  for (i = 0; i < std::min(max_count, state.queue_ids.size()); i++) {
+    queue_ids[i] = state.queue_ids[i];
+  }
+
+  return i;
+}
+
+int dvrSurfaceStateGetZOrder(DvrSurfaceState* surface_state,
+                             size_t surface_index, int* z_order_out) {
+  if (!surface_state || surface_index >= surface_state->state.size() ||
+      !z_order_out) {
+    return -EINVAL;
+  }
+
+  *z_order_out = surface_state->state[surface_index].GetZOrder();
+  return 0;
+}
+
+int dvrSurfaceStateGetVisible(DvrSurfaceState* surface_state,
+                              size_t surface_index, bool* visible_out) {
+  if (!surface_state || surface_index >= surface_state->state.size() ||
+      !visible_out) {
+    return -EINVAL;
+  }
+
+  *visible_out = surface_state->state[surface_index].GetVisible();
+  return 0;
+}
+
+int dvrSurfaceStateGetAttributeCount(DvrSurfaceState* surface_state,
+                                     size_t surface_index, size_t* count_out) {
+  if (!surface_state || surface_index >= surface_state->state.size() ||
+      !count_out) {
+    return -EINVAL;
+  }
+
+  *count_out = surface_state->state[surface_index].surface_attributes.size();
+  return 0;
+}
+
+ssize_t dvrSurfaceStateGetAttributes(DvrSurfaceState* surface_state,
+                                     size_t surface_index,
+                                     DvrSurfaceAttribute* attributes,
+                                     size_t max_count) {
+  if (!surface_state || surface_index >= surface_state->state.size() ||
+      !attributes) {
+    return -EINVAL;
+  }
+
+  return ConvertSurfaceAttributes(
+      surface_state->state[surface_index].surface_attributes, attributes,
+      max_count);
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
new file mode 100644
index 0000000..89bef09
--- /dev/null
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -0,0 +1,70 @@
+#ifndef ANDROID_DVR_INTERNAL_H_
+#define ANDROID_DVR_INTERNAL_H_
+
+#include <sys/cdefs.h>
+
+#include <memory>
+
+extern "C" {
+
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+}  // extern "C"
+
+namespace android {
+namespace dvr {
+
+class BufferProducer;
+class BufferConsumer;
+class ConsumerQueue;
+class IonBuffer;
+class ProducerQueue;
+
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+    const std::shared_ptr<IonBuffer>& ion_buffer);
+
+DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
+    const std::shared_ptr<BufferConsumer>& buffer_consumer);
+DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
+    const std::shared_ptr<BufferProducer>& buffer_producer);
+
+DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue);
+DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
+    const std::shared_ptr<ProducerQueue>& producer_queue);
+ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
+    DvrWriteBufferQueue* write_queue);
+
+}  // namespace dvr
+}  // namespace android
+
+extern "C" {
+
+struct DvrWriteBuffer {
+  std::shared_ptr<android::dvr::BufferProducer> write_buffer;
+};
+
+struct DvrReadBuffer {
+  std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
+};
+
+struct DvrBuffer {
+  std::shared_ptr<android::dvr::IonBuffer> buffer;
+};
+
+struct DvrWriteBufferQueue {
+  std::shared_ptr<android::dvr::ProducerQueue> producer_queue;
+  ANativeWindow* native_window{nullptr};
+};
+
+struct DvrReadBufferQueue {
+  std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue;
+};
+
+}  // extern "C"
+
+#endif  // ANDROID_DVR_INTERNAL_H_
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a04ed50..67e2ae8 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -1,65 +1,163 @@
 #include "include/dvr/dvr_surface.h"
 
+#include <inttypes.h>
+
 #include <private/dvr/display_client.h>
 
-using namespace android;
+#include "dvr_internal.h"
 
-struct DvrSurface {
-  std::unique_ptr<dvr::DisplaySurfaceClient> display_surface_;
-};
+using android::dvr::display::DisplayClient;
+using android::dvr::display::Surface;
+using android::dvr::display::SurfaceAttributes;
+using android::dvr::display::SurfaceAttributeValue;
+using android::dvr::CreateDvrReadBufferFromBufferConsumer;
+using android::dvr::CreateDvrWriteBufferQueueFromProducerQueue;
+
+namespace {
+
+bool ConvertSurfaceAttributes(const DvrSurfaceAttribute* attributes,
+                              size_t attribute_count,
+                              SurfaceAttributes* surface_attributes,
+                              size_t* error_index) {
+  for (size_t i = 0; i < attribute_count; i++) {
+    SurfaceAttributeValue value;
+    switch (attributes[i].value.type) {
+      case DVR_SURFACE_ATTRIBUTE_TYPE_INT32:
+        value = attributes[i].value.int32_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_INT64:
+        value = attributes[i].value.int64_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_BOOL:
+        value = attributes[i].value.bool_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT:
+        value = attributes[i].value.float_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2:
+        value = attributes[i].value.float2_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3:
+        value = attributes[i].value.float3_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4:
+        value = attributes[i].value.float4_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8:
+        value = attributes[i].value.float8_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16:
+        value = attributes[i].value.float16_value;
+        break;
+      default:
+        *error_index = i;
+        return false;
+    }
+
+    surface_attributes->emplace(attributes[i].key, value);
+  }
+
+  return true;
+}
+
+}  // anonymous namespace
 
 extern "C" {
 
-int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
-                     uint64_t usage1, int flags, DvrSurface** out_surface) {
+struct DvrSurface {
+  std::unique_ptr<Surface> surface;
+};
+
+int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
+                     size_t attribute_count, DvrSurface** out_surface) {
   if (out_surface == nullptr) {
-    ALOGE("dvrSurfaceCreate: invalid inputs: out_surface=%p.", out_surface);
+    ALOGE("dvrSurfaceCreate: Invalid inputs: out_surface=%p.", out_surface);
     return -EINVAL;
   }
 
-  int error;
-  auto client = dvr::DisplayClient::Create(&error);
-  if (!client) {
-    ALOGE("Failed to create display client!");
-    return error;
+  size_t error_index;
+  SurfaceAttributes surface_attributes;
+  if (!ConvertSurfaceAttributes(attributes, attribute_count,
+                                &surface_attributes, &error_index)) {
+    ALOGE("dvrSurfaceCreate: Invalid surface attribute type: %" PRIu64,
+          attributes[error_index].value.type);
+    return -EINVAL;
   }
 
-  // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
-  std::unique_ptr<dvr::DisplaySurfaceClient> surface =
-      client->CreateDisplaySurface(
-          width, height, static_cast<int>(usage0 | usage1), format, flags);
+  auto status = Surface::CreateSurface(surface_attributes);
+  if (!status) {
+    ALOGE("dvrSurfaceCreate:: Failed to create display surface: %s",
+          status.GetErrorMessage().c_str());
+    return -status.error();
+  }
 
-  DvrSurface* dvr_surface = new DvrSurface;
-  dvr_surface->display_surface_ = std::move(surface);
-  *out_surface = dvr_surface;
+  *out_surface = new DvrSurface{status.take()};
   return 0;
 }
 
-int dvrSurfaceGetWriteBufferQueue(DvrSurface* surface,
-                                  DvrWriteBufferQueue** out_writer) {
+void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; }
+
+int dvrSurfaceGetId(DvrSurface* surface) {
+  return surface->surface->surface_id();
+}
+
+int dvrSurfaceSetAttributes(DvrSurface* surface,
+                            const DvrSurfaceAttribute* attributes,
+                            size_t attribute_count) {
+  if (surface == nullptr || attributes == nullptr) {
+    ALOGE(
+        "dvrSurfaceSetAttributes: Invalid inputs: surface=%p attributes=%p "
+        "attribute_count=%zu",
+        surface, attributes, attribute_count);
+    return -EINVAL;
+  }
+
+  size_t error_index;
+  SurfaceAttributes surface_attributes;
+  if (!ConvertSurfaceAttributes(attributes, attribute_count,
+                                &surface_attributes, &error_index)) {
+    ALOGE("dvrSurfaceSetAttributes: Invalid surface attribute type: %" PRIu64,
+          attributes[error_index].value.type);
+    return -EINVAL;
+  }
+
+  auto status = surface->surface->SetAttributes(surface_attributes);
+  if (!status) {
+    ALOGE("dvrSurfaceSetAttributes: Failed to set attributes: %s",
+          status.GetErrorMessage().c_str());
+    return -status.error();
+  }
+
+  return 0;
+}
+
+int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
+                                     uint32_t height, uint32_t format,
+                                     uint32_t layer_count, uint64_t usage,
+                                     size_t capacity,
+                                     DvrWriteBufferQueue** out_writer) {
   if (surface == nullptr || out_writer == nullptr) {
     ALOGE(
-        "dvrSurfaceGetWriteBufferQueue: Invalid inputs: surface=%p, "
+        "dvrSurfaceCreateWriteBufferQueue: Invalid inputs: surface=%p, "
         "out_writer=%p.",
         surface, out_writer);
     return -EINVAL;
   }
-  DvrWriteBufferQueue* buffer_writer = new DvrWriteBufferQueue;
-  buffer_writer->producer_queue_ =
-      surface->display_surface_->GetProducerQueue();
-  if (buffer_writer->producer_queue_ == nullptr) {
-    ALOGE(
-        "dvrSurfaceGetWriteBufferQueue: Failed to get producer queue from "
-        "display surface.");
-    return -ENOMEM;
+
+  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());
+    return -status.error();
   }
 
-  *out_writer = buffer_writer;
+  *out_writer = CreateDvrWriteBufferQueueFromProducerQueue(status.take());
   return 0;
 }
 
 int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
-  auto client = android::dvr::DisplayClient::Create();
+  auto client = DisplayClient::Create();
   if (!client) {
     ALOGE("dvrGetNamedBuffer: Failed to create display client!");
     return -ECOMM;
@@ -71,12 +169,13 @@
     return -EINVAL;
   }
 
-  auto named_buffer = client->GetNamedBuffer(name);
-  if (!named_buffer) {
-    ALOGE("dvrGetNamedBuffer: Failed to find named buffer: %s.", name);
-    return -EINVAL;
+  auto status = client->GetNamedBuffer(name);
+  if (!status) {
+    ALOGE("dvrGetNamedBuffer: Failed to find named buffer name=%s: %s", name,
+          status.GetErrorMessage().c_str());
+    return -status.error();
   }
-  *out_buffer = CreateDvrBufferFromIonBuffer(std::move(named_buffer));
+  *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
   return 0;
 }
 
diff --git a/libs/vr/libdvr/dvr_vsync.cpp b/libs/vr/libdvr/dvr_vsync.cpp
new file mode 100644
index 0000000..099240e
--- /dev/null
+++ b/libs/vr/libdvr/dvr_vsync.cpp
@@ -0,0 +1,33 @@
+#include "include/dvr/dvr_vsync.h"
+
+#include <utils/Log.h>
+
+#include <private/dvr/vsync_client.h>
+
+extern "C" {
+
+struct DvrVSyncClient {
+  std::unique_ptr<android::dvr::VSyncClient> client;
+};
+
+int dvrVSyncClientCreate(DvrVSyncClient** client_out) {
+  auto client = android::dvr::VSyncClient::Create();
+  if (!client) {
+    ALOGE("dvrVSyncClientCreate: Failed to create vsync client!");
+    return -EIO;
+  }
+
+  *client_out = new DvrVSyncClient{std::move(client)};
+  return 0;
+}
+
+void dvrVSyncClientDestroy(DvrVSyncClient* client) { delete client; }
+
+int dvrVSyncClientGetSchedInfo(DvrVSyncClient* client, int64_t* vsync_period_ns,
+                               int64_t* next_timestamp_ns,
+                               uint32_t* next_vsync_count) {
+  return client->client->GetSchedInfo(vsync_period_ns, next_timestamp_ns,
+                                      next_vsync_count);
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/include/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
deleted file mode 100644
index 8cd948c..0000000
--- a/libs/vr/libdvr/include/dvr/display_manager_client.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef DVR_DISPLAY_MANAGER_CLIENT_H_
-#define DVR_DISPLAY_MANAGER_CLIENT_H_
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
-typedef struct DvrDisplayManagerClientSurfaceList
-    DvrDisplayManagerClientSurfaceList;
-typedef struct DvrDisplayManagerClientSurfaceBuffers
-    DvrDisplayManagerClientSurfaceBuffers;
-typedef struct DvrBuffer DvrBuffer;
-
-DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
-
-void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
-
-DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
-                                             const char* name, size_t size,
-                                             uint64_t usage0, uint64_t usage1);
-
-// Return an event fd for checking if there was an event on the server
-// Note that the only event which will be flagged is POLLIN. You must use
-// dvrDisplayManagerClientTranslateEpollEventMask in order to get the real
-// event flags.
-// @return the fd
-int dvrDisplayManagerClientGetEventFd(DvrDisplayManagerClient* client);
-
-// Once you have received an epoll event, you must translate it to its true
-// flags. This is a workaround for working with UDS.
-// @param in_events pass in the epoll revents that were initially returned
-// @param on success, this value will be overwritten with the true epoll values
-// @return 0 on success, non-zero otherwise
-int dvrDisplayManagerClientTranslateEpollEventMask(
-    DvrDisplayManagerClient* client, int in_events, int* out_events);
-
-// If successful, populates |surface_list| with a list of application
-// surfaces the display is currently using.
-//
-// @return 0 on success. Otherwise it returns a negative error value.
-int dvrDisplayManagerClientGetSurfaceList(
-    DvrDisplayManagerClient* client,
-    DvrDisplayManagerClientSurfaceList** surface_list);
-
-void dvrDisplayManagerClientSurfaceListDestroy(
-    DvrDisplayManagerClientSurfaceList* surface_list);
-
-// @return Returns the number of surfaces in the list.
-size_t dvrDisplayManagerClientSurfaceListGetSize(
-    DvrDisplayManagerClientSurfaceList* surface_list);
-
-// @return Return a unique identifier for a client surface. The identifier can
-// be used to query for other surface properties.
-int dvrDisplayManagerClientSurfaceListGetSurfaceId(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// @return Returns the stacking order of the client surface at |index|.
-int dvrDisplayManagerClientSurfaceListGetClientZOrder(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// @return Returns true if the client surface is visible, false otherwise.
-bool dvrDisplayManagerClientSurfaceListGetClientIsVisible(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// TODO(jwcai, hendrikw) Remove this after we replacing
-// dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
-int dvrDisplayManagerClientGetSurfaceBuffers(
-    DvrDisplayManagerClient* client, int surface_id,
-    DvrDisplayManagerClientSurfaceBuffers** surface_buffers);
-
-void dvrDisplayManagerClientSurfaceBuffersDestroy(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-
-// @return Returns the number of buffers.
-size_t dvrDisplayManagerClientSurfaceBuffersGetSize(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-
-// @return Returns the file descriptor for the buffer consumer at |index|.
-int dvrDisplayManagerClientSurfaceBuffersGetFd(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // DVR_DISPLAY_MANAGER_CLIENT_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 3cd401d..8a203e0 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -4,137 +4,178 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <sys/cdefs.h>
+#include <unistd.h>
 
 #include <dvr/dvr_hardware_composer_defs.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 typedef struct ANativeWindow ANativeWindow;
 
 typedef struct DvrPoseAsync DvrPoseAsync;
 
-typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
-typedef struct DvrDisplayManagerClientSurfaceList
-    DvrDisplayManagerClientSurfaceList;
-typedef struct DvrDisplayManagerClientSurfaceBuffers
-    DvrDisplayManagerClientSurfaceBuffers;
+typedef uint64_t DvrSurfaceUpdateFlags;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
 typedef struct DvrPose DvrPose;
-typedef struct dvr_vsync_client dvr_vsync_client;
+typedef struct DvrVSyncClient DvrVSyncClient;
 typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
 
-typedef DvrDisplayManagerClient* (*DvrDisplayManagerClientCreatePtr)(void);
-typedef void (*DvrDisplayManagerClientDestroyPtr)(
-    DvrDisplayManagerClient* client);
-
+typedef struct DvrBuffer DvrBuffer;
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
-typedef struct DvrBuffer DvrBuffer;
 typedef struct AHardwareBuffer AHardwareBuffer;
 
-typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 
 typedef struct DvrSurface DvrSurface;
+typedef uint64_t DvrSurfaceAttributeType;
+typedef int32_t DvrSurfaceAttributeKey;
+
+typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue;
+typedef struct DvrSurfaceAttribute DvrSurfaceAttribute;
 
 struct native_handle;
 
-// display_manager_client.h
-typedef int (*DvrDisplayManagerClientGetSurfaceListPtr)(
-    DvrDisplayManagerClient* client,
-    DvrDisplayManagerClientSurfaceList** surface_list);
-typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
-    DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrBuffer* (*DvrDisplayManagerSetupNamedBufferPtr)(
-    DvrDisplayManagerClient* client, const char* name, size_t size,
-    uint64_t usage0, uint64_t usage1);
-typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
-    DvrDisplayManagerClientSurfaceList* surface_list);
-typedef int (*DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr)(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-typedef int (*DvrDisplayManagerClientGetSurfaceBufferListPtr)(
-    DvrDisplayManagerClient* client, int surface_id,
-    DvrDisplayManagerClientSurfaceBuffers** surface_buffers);
-typedef void (*DvrDisplayManagerClientSurfaceBufferListDestroyPtr)(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-typedef size_t (*DvrDisplayManagerClientSurfaceBufferListGetSizePtr)(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-typedef int (*DvrDisplayManagerClientSurfaceBufferListGetFdPtr)(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index);
+// dvr_display_manager.h
+typedef int (*DvrDisplayManagerCreatePtr)(DvrDisplayManager** client_out);
+typedef void (*DvrDisplayManagerDestroyPtr)(DvrDisplayManager* client);
+typedef int (*DvrDisplayManagerSetupNamedBufferPtr)(DvrDisplayManager* client,
+                                                    const char* name,
+                                                    size_t size, uint64_t usage,
+                                                    DvrBuffer** buffer_out);
+typedef int (*DvrDisplayManagerGetEventFdPtr)(DvrDisplayManager* client);
+typedef int (*DvrDisplayManagerTranslateEpollEventMaskPtr)(
+    DvrDisplayManager* client, int in_events, int* out_events);
+typedef int (*DvrDisplayManagerGetSurfaceStatePtr)(
+    DvrDisplayManager* client, DvrSurfaceState* surface_state);
+typedef int (*DvrDisplayManagerGetReadBufferQueuePtr)(
+    DvrDisplayManager* client, int surface_id, int queue_id,
+    DvrReadBufferQueue** queue_out);
+typedef int (*DvrSurfaceStateCreatePtr)(DvrSurfaceState** surface_state);
+typedef void (*DvrSurfaceStateDestroyPtr)(DvrSurfaceState* surface_state);
+typedef int (*DvrSurfaceStateGetSurfaceCountPtr)(DvrSurfaceState* surface_state,
+                                                 size_t* count_out);
+typedef int (*DvrSurfaceStateGetUpdateFlagsPtr)(
+    DvrSurfaceState* surface_state, size_t surface_index,
+    DvrSurfaceUpdateFlags* flags_out);
+typedef int (*DvrSurfaceStateGetSurfaceIdPtr)(DvrSurfaceState* surface_state,
+                                              size_t surface_index,
+                                              int* surface_id_out);
+typedef int (*DvrSurfaceStateGetProcessIdPtr)(DvrSurfaceState* surface_state,
+                                              size_t surface_index,
+                                              int* process_id_out);
+typedef int (*DvrSurfaceStateGetQueueCountPtr)(DvrSurfaceState* surface_state,
+                                               size_t surface_index,
+                                               size_t* count_out);
+typedef ssize_t (*DvrSurfaceStateGetQueueIdsPtr)(DvrSurfaceState* surface_state,
+                                                 size_t surface_index,
+                                                 int* queue_ids,
+                                                 size_t max_count);
+typedef int (*DvrSurfaceStateGetZOrderPtr)(DvrSurfaceState* surface_state,
+                                           size_t surface_index,
+                                           int* z_order_out);
+typedef int (*DvrSurfaceStateGetVisiblePtr)(DvrSurfaceState* surface_state,
+                                            size_t surface_index,
+                                            bool* visible_out);
+typedef int (*DvrSurfaceStateGetAttributeCountPtr)(
+    DvrSurfaceState* surface_state, size_t surface_index, size_t* count_out);
+typedef ssize_t (*DvrSurfaceStateGetAttributesPtr)(
+    DvrSurfaceState* surface_state, size_t surface_index,
+    DvrSurfaceAttribute* attributes, size_t max_attribute_count);
 
 // dvr_buffer.h
-typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
+typedef void (*DvrWriteBufferCreateEmptyPtr)(DvrWriteBuffer** write_buffer_out);
+typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferIsValidPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferClearPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferGetIdPtr)(DvrWriteBuffer* write_buffer);
 typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
-    DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
-typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
-                                     const void* meta, size_t meta_size_bytes);
-typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* client,
+    DvrWriteBuffer* write_buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* write_buffer,
+                                     int ready_fence_fd, const void* meta,
+                                     size_t meta_size_bytes);
+typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* write_buffer,
                                      int* release_fence_fd);
-typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
-typedef const struct native_handle* (*DvrWriteBufferGetNativeHandle)(
+typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* write_buffer);
+typedef const struct native_handle* (*DvrWriteBufferGetNativeHandlePtr)(
     DvrWriteBuffer* write_buffer);
 
-typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
+typedef void (*DvrReadBufferCreateEmptyPtr)(DvrReadBuffer** read_buffer_out);
+typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferIsValidPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferClearPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferGetIdPtr)(DvrReadBuffer* read_buffer);
 typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
-    DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
-typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
+    DvrReadBuffer* read_buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* read_buffer,
                                        int* ready_fence_fd, void* meta,
                                        size_t meta_size_bytes);
-typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
+typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* read_buffer,
                                        int release_fence_fd);
-typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
-typedef const struct native_handle* (*DvrReadBufferGetNativeHandle)(
+typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* read_buffer);
+typedef const struct native_handle* (*DvrReadBufferGetNativeHandlePtr)(
     DvrReadBuffer* read_buffer);
 
-typedef void (*DvrBufferDestroy)(DvrBuffer* buffer);
-typedef int (*DvrBufferGetAHardwareBuffer)(DvrBuffer* buffer,
-                                           AHardwareBuffer** hardware_buffer);
-typedef const struct native_handle* (*DvrBufferGetNativeHandle)(
+typedef void (*DvrBufferDestroyPtr)(DvrBuffer* buffer);
+typedef int (*DvrBufferGetAHardwareBufferPtr)(
+    DvrBuffer* buffer, AHardwareBuffer** hardware_buffer);
+typedef const struct native_handle* (*DvrBufferGetNativeHandlePtr)(
     DvrBuffer* buffer);
 
 // dvr_buffer_queue.h
 typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
-typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
+typedef ssize_t (*DvrWriteBufferQueueGetCapacityPtr)(
     DvrWriteBufferQueue* write_queue);
+typedef int (*DvrWriteBufferQueueGetIdPtr)(DvrWriteBufferQueue* write_queue);
 typedef int (*DvrWriteBufferQueueGetExternalSurfacePtr)(
     DvrWriteBufferQueue* write_queue, ANativeWindow** out_window);
 typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
     DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
 typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
                                              int timeout,
-                                             DvrWriteBuffer** out_buffer,
+                                             DvrWriteBuffer* out_buffer,
                                              int* out_fence_fd);
 typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue);
-typedef size_t (*DvrReadBufferQueueGetCapacityPtr)(
+typedef ssize_t (*DvrReadBufferQueueGetCapacityPtr)(
     DvrReadBufferQueue* read_queue);
+typedef int (*DvrReadBufferQueueGetIdPtr)(DvrReadBufferQueue* read_queue);
 typedef int (*DvrReadBufferQueueCreateReadQueuePtr)(
     DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue);
 typedef int (*DvrReadBufferQueueDequeuePtr)(DvrReadBufferQueue* read_queue,
                                             int timeout,
-                                            DvrReadBuffer** out_buffer,
+                                            DvrReadBuffer* out_buffer,
                                             int* out_fence_fd, void* out_meta,
                                             size_t meta_size_bytes);
 
 // dvr_surface.h
 typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
-typedef int (*DvrSurfaceCreatePtr)(int width, int height, int format,
-                                   uint64_t usage0, uint64_t usage1, int flags,
-                                   DvrSurface** out_surface);
-typedef int (*DvrSurfaceGetWriteBufferQueuePtr)(
-    DvrSurface* surface, DvrWriteBufferQueue** out_writer);
+typedef int (*DvrSurfaceCreatePtr)(const DvrSurfaceAttribute* attributes,
+                                   size_t attribute_count,
+                                   DvrSurface** surface_out);
+typedef void (*DvrSurfaceDestroyPtr)(DvrSurface* surface);
+typedef int (*DvrSurfaceGetIdPtr)(DvrSurface* surface);
+typedef int (*DvrSurfaceSetAttributesPtr)(DvrSurface* surface,
+                                          const DvrSurfaceAttribute* attributes,
+                                          size_t attribute_count);
+typedef int (*DvrSurfaceCreateWriteBufferQueuePtr)(
+    DvrSurface* surface, uint32_t width, uint32_t height, uint32_t format,
+    uint32_t layer_count, uint64_t usage, size_t capacity,
+    DvrWriteBufferQueue** queue_out);
 
 // vsync_client_api.h
-typedef dvr_vsync_client* (*DvrVSyncClientCreatePtr)();
-typedef void (*DvrVSyncClientDestroyPtr)(dvr_vsync_client* client);
-typedef int (*DvrVSyncClientGetSchedInfoPtr)(dvr_vsync_client* client,
+typedef int (*DvrVSyncClientCreatePtr)(DvrVSyncClient** client_out);
+typedef void (*DvrVSyncClientDestroyPtr)(DvrVSyncClient* client);
+typedef int (*DvrVSyncClientGetSchedInfoPtr)(DvrVSyncClient* client,
                                              int64_t* vsync_period_ns,
                                              int64_t* next_timestamp_ns,
                                              uint32_t* next_vsync_count);
 
 // pose_client.h
-typedef DvrPose* (*DvrPoseClientCreatePtr)(void);
-typedef void (*DvrPoseClientDestroyPtr)(DvrPose* client);
+typedef DvrPose* (*DvrPoseCreatePtr)(void);
+typedef void (*DvrPoseDestroyPtr)(DvrPose* client);
 typedef int (*DvrPoseGetPtr)(DvrPose* client, uint32_t vsync_count,
                              DvrPoseAsync* out_pose);
 typedef uint32_t (*DvrPoseGetVsyncCountPtr)(DvrPose* client);
@@ -221,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;
@@ -257,127 +295,18 @@
 };
 
 struct DvrApi_v1 {
-  // Display manager client
-  DvrDisplayManagerClientCreatePtr display_manager_client_create;
-  DvrDisplayManagerClientDestroyPtr display_manager_client_destroy;
-  DvrDisplayManagerClientGetSurfaceListPtr
-      display_manager_client_get_surface_list;
-  DvrDisplayManagerClientSurfaceListDestroyPtr
-      display_manager_client_surface_list_destroy;
-  DvrDisplayManagerSetupNamedBufferPtr display_manager_setup_named_buffer;
-  DvrDisplayManagerClientSurfaceListGetSizePtr
-      display_manager_client_surface_list_get_size;
-  DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
-      display_manager_client_surface_list_get_surface_id;
-  DvrDisplayManagerClientGetSurfaceBufferListPtr
-      display_manager_client_get_surface_buffer_list;
-  DvrDisplayManagerClientSurfaceBufferListDestroyPtr
-      display_manager_client_surface_buffer_list_destroy;
-  DvrDisplayManagerClientSurfaceBufferListGetSizePtr
-      display_manager_client_surface_buffer_list_get_size;
-  DvrDisplayManagerClientSurfaceBufferListGetFdPtr
-      display_manager_client_surface_buffer_list_get_fd;
+// Defines an API entry for V1 (no version suffix).
+#define DVR_V1_API_ENTRY(name) Dvr##name##Ptr name
 
-  // Write buffer
-  DvrWriteBufferDestroyPtr write_buffer_destroy;
-  DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_ahardwarebuffer;
-  DvrWriteBufferPostPtr write_buffer_post;
-  DvrWriteBufferGainPtr write_buffer_gain;
-  DvrWriteBufferGainAsyncPtr write_buffer_gain_async;
-  DvrWriteBufferGetNativeHandle write_buffer_get_native_handle;
+// Include file with API entries.
+#include "dvr_api_entries.h"
 
-  // Read buffer
-  DvrReadBufferDestroyPtr read_buffer_destroy;
-  DvrReadBufferGetAHardwareBufferPtr read_buffer_get_ahardwarebuffer;
-  DvrReadBufferAcquirePtr read_buffer_acquire;
-  DvrReadBufferReleasePtr read_buffer_release;
-  DvrReadBufferReleaseAsyncPtr read_buffer_release_async;
-  DvrReadBufferGetNativeHandle read_buffer_get_native_handle;
-
-  // Buffer
-  DvrBufferDestroy buffer_destroy;
-  DvrBufferGetAHardwareBuffer buffer_get_ahardwarebuffer;
-  DvrBufferGetNativeHandle buffer_get_native_handle;
-
-  // Write buffer queue
-  DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy;
-  DvrWriteBufferQueueGetCapacityPtr write_buffer_queue_get_capacity;
-  DvrWriteBufferQueueGetExternalSurfacePtr
-      write_buffer_queue_get_external_surface;
-  DvrWriteBufferQueueCreateReadQueuePtr write_buffer_queue_create_read_queue;
-  DvrWriteBufferQueueDequeuePtr write_buffer_queue_dequeue;
-
-  // Read buffer queue
-  DvrReadBufferQueueDestroyPtr read_buffer_queue_destroy;
-  DvrReadBufferQueueGetCapacityPtr read_buffer_queue_get_capacity;
-  DvrReadBufferQueueCreateReadQueuePtr read_buffer_queue_create_read_queue;
-  DvrReadBufferQueueDequeuePtr read_buffer_queue_dequeue;
-
-  // V-Sync client
-  DvrVSyncClientCreatePtr vsync_client_create;
-  DvrVSyncClientDestroyPtr vsync_client_destroy;
-  DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info;
-
-  // Display surface
-  DvrGetNamedBufferPtr get_named_buffer;
-  DvrSurfaceCreatePtr surface_create;
-  DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue;
-
-  // Pose client
-  DvrPoseClientCreatePtr pose_client_create;
-  DvrPoseClientDestroyPtr pose_client_destroy;
-  DvrPoseGetPtr pose_get;
-  DvrPoseGetVsyncCountPtr pose_get_vsync_count;
-  DvrPoseGetControllerPtr pose_get_controller;
-
-  // Virtual touchpad client
-  DvrVirtualTouchpadCreatePtr virtual_touchpad_create;
-  DvrVirtualTouchpadDestroyPtr virtual_touchpad_destroy;
-  DvrVirtualTouchpadAttachPtr virtual_touchpad_attach;
-  DvrVirtualTouchpadDetachPtr virtual_touchpad_detach;
-  DvrVirtualTouchpadTouchPtr virtual_touchpad_touch;
-  DvrVirtualTouchpadButtonStatePtr virtual_touchpad_button_state;
-
-  // VR HWComposer client
-  DvrHwcClientCreatePtr hwc_client_create;
-  DvrHwcClientDestroyPtr hwc_client_destroy;
-  DvrHwcFrameDestroyPtr hwc_frame_destroy;
-  DvrHwcFrameGetDisplayIdPtr hwc_frame_get_display_id;
-  DvrHwcFrameGetDisplayWidthPtr hwc_frame_get_display_width;
-  DvrHwcFrameGetDisplayHeightPtr hwc_frame_get_display_height;
-  DvrHwcFrameGetDisplayRemovedPtr hwc_frame_get_display_removed;
-  DvrHwcFrameGetActiveConfigPtr hwc_frame_get_active_config;
-  DvrHwcFrameGetColorModePtr hwc_frame_get_color_mode;
-  DvrHwcFrameGetColorTransformPtr hwc_frame_get_color_transform;
-  DvrHwcFrameGetPowerModePtr hwc_frame_get_power_mode;
-  DvrHwcFrameGetVsyncEnabledPtr hwc_frame_get_vsync_enabled;
-  DvrHwcFrameGetLayerCountPtr hwc_frame_get_layer_count;
-  DvrHwcFrameGetLayerIdPtr hwc_frame_get_layer_id;
-  DvrHwcFrameGetLayerBufferPtr hwc_frame_get_layer_buffer;
-  DvrHwcFrameGetLayerFencePtr hwc_frame_get_layer_fence;
-  DvrHwcFrameGetLayerDisplayFramePtr hwc_frame_get_layer_display_frame;
-  DvrHwcFrameGetLayerCropPtr hwc_frame_get_layer_crop;
-  DvrHwcFrameGetLayerBlendModePtr hwc_frame_get_layer_blend_mode;
-  DvrHwcFrameGetLayerAlphaPtr hwc_frame_get_layer_alpha;
-  DvrHwcFrameGetLayerTypePtr hwc_frame_get_layer_type;
-  DvrHwcFrameGetLayerApplicationIdPtr hwc_frame_get_layer_application_id;
-  DvrHwcFrameGetLayerZOrderPtr hwc_frame_get_layer_z_order;
-  DvrHwcFrameGetLayerCursorPtr hwc_frame_get_layer_cursor;
-  DvrHwcFrameGetLayerTransformPtr hwc_frame_get_layer_transform;
-  DvrHwcFrameGetLayerDataspacePtr hwc_frame_get_layer_dataspace;
-  DvrHwcFrameGetLayerColorPtr hwc_frame_get_layer_color;
-  DvrHwcFrameGetLayerNumVisibleRegionsPtr
-      hwc_frame_get_layer_num_visible_regions;
-  DvrHwcFrameGetLayerVisibleRegionPtr hwc_frame_get_layer_visible_region;
-  DvrHwcFrameGetLayerNumDamagedRegionsPtr
-      hwc_frame_get_layer_num_damaged_regions;
-  DvrHwcFrameGetLayerDamagedRegionPtr hwc_frame_get_layer_damaged_region;
+// Undefine macro definitions to play nice with Google3 style rules.
+#undef DVR_V1_API_ENTRY
 };
 
 int dvrGetApi(void* api, size_t struct_size, int version);
 
-#ifdef __cplusplus
-}  // extern "C"
-#endif
+__END_DECLS
 
 #endif  // ANDROID_DVR_API_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
new file mode 100644
index 0000000..09568fd
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -0,0 +1,135 @@
+// dvr_api_entries.h
+//
+// Defines the DVR platform library API entries.
+//
+// Do not include this header directly.
+
+#ifndef DVR_V1_API_ENTRY
+#error Do not include this header directly.
+#endif
+
+// Display manager client
+DVR_V1_API_ENTRY(DisplayManagerCreate);
+DVR_V1_API_ENTRY(DisplayManagerDestroy);
+DVR_V1_API_ENTRY(DisplayManagerSetupNamedBuffer);
+DVR_V1_API_ENTRY(DisplayManagerGetEventFd);
+DVR_V1_API_ENTRY(DisplayManagerTranslateEpollEventMask);
+DVR_V1_API_ENTRY(DisplayManagerGetSurfaceState);
+DVR_V1_API_ENTRY(DisplayManagerGetReadBufferQueue);
+DVR_V1_API_ENTRY(SurfaceStateCreate);
+DVR_V1_API_ENTRY(SurfaceStateDestroy);
+DVR_V1_API_ENTRY(SurfaceStateGetSurfaceCount);
+DVR_V1_API_ENTRY(SurfaceStateGetUpdateFlags);
+DVR_V1_API_ENTRY(SurfaceStateGetSurfaceId);
+DVR_V1_API_ENTRY(SurfaceStateGetProcessId);
+DVR_V1_API_ENTRY(SurfaceStateGetQueueCount);
+DVR_V1_API_ENTRY(SurfaceStateGetQueueIds);
+DVR_V1_API_ENTRY(SurfaceStateGetZOrder);
+DVR_V1_API_ENTRY(SurfaceStateGetVisible);
+DVR_V1_API_ENTRY(SurfaceStateGetAttributeCount);
+DVR_V1_API_ENTRY(SurfaceStateGetAttributes);
+
+// Write buffer
+DVR_V1_API_ENTRY(WriteBufferCreateEmpty);
+DVR_V1_API_ENTRY(WriteBufferDestroy);
+DVR_V1_API_ENTRY(WriteBufferIsValid);
+DVR_V1_API_ENTRY(WriteBufferClear);
+DVR_V1_API_ENTRY(WriteBufferGetId);
+DVR_V1_API_ENTRY(WriteBufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(WriteBufferPost);
+DVR_V1_API_ENTRY(WriteBufferGain);
+DVR_V1_API_ENTRY(WriteBufferGainAsync);
+DVR_V1_API_ENTRY(WriteBufferGetNativeHandle);
+
+// Read buffer
+DVR_V1_API_ENTRY(ReadBufferCreateEmpty);
+DVR_V1_API_ENTRY(ReadBufferDestroy);
+DVR_V1_API_ENTRY(ReadBufferIsValid);
+DVR_V1_API_ENTRY(ReadBufferClear);
+DVR_V1_API_ENTRY(ReadBufferGetId);
+DVR_V1_API_ENTRY(ReadBufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(ReadBufferAcquire);
+DVR_V1_API_ENTRY(ReadBufferRelease);
+DVR_V1_API_ENTRY(ReadBufferReleaseAsync);
+DVR_V1_API_ENTRY(ReadBufferGetNativeHandle);
+
+// Buffer
+DVR_V1_API_ENTRY(BufferDestroy);
+DVR_V1_API_ENTRY(BufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(BufferGetNativeHandle);
+
+// Write buffer queue
+DVR_V1_API_ENTRY(WriteBufferQueueDestroy);
+DVR_V1_API_ENTRY(WriteBufferQueueGetCapacity);
+DVR_V1_API_ENTRY(WriteBufferQueueGetId);
+DVR_V1_API_ENTRY(WriteBufferQueueGetExternalSurface);
+DVR_V1_API_ENTRY(WriteBufferQueueCreateReadQueue);
+DVR_V1_API_ENTRY(WriteBufferQueueDequeue);
+
+// Read buffer queue
+DVR_V1_API_ENTRY(ReadBufferQueueDestroy);
+DVR_V1_API_ENTRY(ReadBufferQueueGetCapacity);
+DVR_V1_API_ENTRY(ReadBufferQueueGetId);
+DVR_V1_API_ENTRY(ReadBufferQueueCreateReadQueue);
+DVR_V1_API_ENTRY(ReadBufferQueueDequeue);
+
+// V-Sync client
+DVR_V1_API_ENTRY(VSyncClientCreate);
+DVR_V1_API_ENTRY(VSyncClientDestroy);
+DVR_V1_API_ENTRY(VSyncClientGetSchedInfo);
+
+// Display surface
+DVR_V1_API_ENTRY(SurfaceCreate);
+DVR_V1_API_ENTRY(SurfaceDestroy);
+DVR_V1_API_ENTRY(SurfaceGetId);
+DVR_V1_API_ENTRY(SurfaceSetAttributes);
+DVR_V1_API_ENTRY(SurfaceCreateWriteBufferQueue);
+DVR_V1_API_ENTRY(GetNamedBuffer);
+
+// Pose client
+DVR_V1_API_ENTRY(PoseCreate);
+DVR_V1_API_ENTRY(PoseDestroy);
+DVR_V1_API_ENTRY(PoseGet);
+DVR_V1_API_ENTRY(PoseGetVsyncCount);
+DVR_V1_API_ENTRY(PoseGetController);
+
+// Virtual touchpad client
+DVR_V1_API_ENTRY(VirtualTouchpadCreate);
+DVR_V1_API_ENTRY(VirtualTouchpadDestroy);
+DVR_V1_API_ENTRY(VirtualTouchpadAttach);
+DVR_V1_API_ENTRY(VirtualTouchpadDetach);
+DVR_V1_API_ENTRY(VirtualTouchpadTouch);
+DVR_V1_API_ENTRY(VirtualTouchpadButtonState);
+
+// VR HWComposer client
+DVR_V1_API_ENTRY(HwcClientCreate);
+DVR_V1_API_ENTRY(HwcClientDestroy);
+DVR_V1_API_ENTRY(HwcFrameDestroy);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayId);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayWidth);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayHeight);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayRemoved);
+DVR_V1_API_ENTRY(HwcFrameGetActiveConfig);
+DVR_V1_API_ENTRY(HwcFrameGetColorMode);
+DVR_V1_API_ENTRY(HwcFrameGetColorTransform);
+DVR_V1_API_ENTRY(HwcFrameGetPowerMode);
+DVR_V1_API_ENTRY(HwcFrameGetVsyncEnabled);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCount);
+DVR_V1_API_ENTRY(HwcFrameGetLayerId);
+DVR_V1_API_ENTRY(HwcFrameGetLayerBuffer);
+DVR_V1_API_ENTRY(HwcFrameGetLayerFence);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDisplayFrame);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCrop);
+DVR_V1_API_ENTRY(HwcFrameGetLayerBlendMode);
+DVR_V1_API_ENTRY(HwcFrameGetLayerAlpha);
+DVR_V1_API_ENTRY(HwcFrameGetLayerType);
+DVR_V1_API_ENTRY(HwcFrameGetLayerApplicationId);
+DVR_V1_API_ENTRY(HwcFrameGetLayerZOrder);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCursor);
+DVR_V1_API_ENTRY(HwcFrameGetLayerTransform);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDataspace);
+DVR_V1_API_ENTRY(HwcFrameGetLayerColor);
+DVR_V1_API_ENTRY(HwcFrameGetLayerNumVisibleRegions);
+DVR_V1_API_ENTRY(HwcFrameGetLayerVisibleRegion);
+DVR_V1_API_ENTRY(HwcFrameGetLayerNumDamagedRegions);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDamagedRegion);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index 3e8357c..af55698 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -3,11 +3,10 @@
 
 #include <stdbool.h>
 #include <stdint.h>
+#include <sys/cdefs.h>
 #include <memory>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
@@ -15,58 +14,91 @@
 typedef struct AHardwareBuffer AHardwareBuffer;
 struct native_handle;
 
-// Write buffer
+// Creates an empty write buffer that may be filled with an acutal buffer by
+// other functions.
+void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer);
+
+// Destroys the write buffer.
 void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+
+// Returns 1 if the given write buffer object contains a buffer, 0 otherwise.
+int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer);
+
+// Clears the contents of the buffer object. After a call to this function
+// dvrWriteBufferIsValid on the same buffer object returns 0.
+int dvrWriteBufferClear(DvrWriteBuffer* write_buffer);
+
+// Returns the global BufferHub id of this buffer.
 int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
+
+// Returns an AHardwareBuffer for the underlying buffer.
 // Caller must call AHardwareBuffer_release on hardware_buffer.
 int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer);
+
+// Posts the buffer, notifying any connected read buffers. Takes ownership of
+// |ready_fence_fd|.
 int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes);
+
+// Gains a buffer that has been released by all connected read buffers.
 int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
 int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
 const struct native_handle* dvrWriteBufferGetNativeHandle(
     DvrWriteBuffer* write_buffer);
 
-// Read buffer
+// Creates an empty read buffer that may be filled with and actual buffer by
+// other functions.
+void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer);
+
+// Destroys the read buffer.
 void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+
+// Returns 1 if the given write buffer object contains a buffer, 0 otherwise.
+int dvrReadBufferIsValid(DvrReadBuffer* read_buffer);
+
+// Clears the contents of the buffer object. After a call to this function
+// dvrReadBufferIsValid on the same buffer object returns 0.
+int dvrReadBufferClear(DvrReadBuffer* read_buffer);
+
+// Returns the global BufferHub id of this buffer.
 int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
+
+// Returns an AHardwareBuffer for the underlying buffer.
 // Caller must call AHardwareBuffer_release on hardware_buffer.
 int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer);
+
+// Acquires the read buffer after it has been posted by the write buffer it is
+// connected to.
 int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
                          void* meta, size_t meta_size_bytes);
+
+// Releases the read buffer, notifying the write buffer it is connected to.
+// Takes ownership of |release_fence_fd|.
 int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
 int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
 const struct native_handle* dvrReadBufferGetNativeHandle(
     DvrReadBuffer* read_buffer);
 
-// Buffer
+// Destroys the buffer.
 void dvrBufferDestroy(DvrBuffer* buffer);
+
+// Gets an AHardwareBuffer from the buffer.
 // Caller must call AHardwareBuffer_release on hardware_buffer.
 int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
                                 AHardwareBuffer** hardware_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
 const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer);
 
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-namespace android {
-namespace dvr {
-
-class BufferProducer;
-class BufferConsumer;
-class IonBuffer;
-
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
-    const std::shared_ptr<BufferProducer>& buffer_producer);
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
-    const std::shared_ptr<BufferConsumer>& buffer_consumer);
-DvrBuffer* CreateDvrBufferFromIonBuffer(
-    const std::shared_ptr<IonBuffer>& ion_buffer);
-
-}  // namespace dvr
-}  // namespace android
+__END_DECLS
 
 #endif  // ANDROID_DVR_BUFFER_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index ba39513..dd669dc 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -1,11 +1,11 @@
 #ifndef ANDROID_DVR_BUFFER_QUEUE_H_
 #define ANDROID_DVR_BUFFER_QUEUE_H_
 
+#include <sys/cdefs.h>
+
 #include <dvr/dvr_buffer.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 typedef struct ANativeWindow ANativeWindow;
 
@@ -14,7 +14,8 @@
 
 // WriteBufferQueue
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
-size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue);
 
 // Returns ANativeWindow. Can be casted to a Java Surface using
 // ANativeWindow_toSurface NDK API. Note that this method does not acquire an
@@ -26,19 +27,18 @@
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue);
 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
-                               DvrWriteBuffer** out_buffer, int* out_fence_fd);
+                               DvrWriteBuffer* out_buffer, int* out_fence_fd);
 
 // ReadeBufferQueue
 void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
-size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue);
 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
                                       DvrReadBufferQueue** out_read_queue);
 int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
-                              DvrReadBuffer** out_buffer, int* out_fence_fd,
+                              DvrReadBuffer* out_buffer, int* out_fence_fd,
                               void* out_meta, size_t meta_size_bytes);
 
-#ifdef __cplusplus
-}  // extern "C"
-#endif
+__END_DECLS
 
 #endif  // ANDROID_DVR_BUFFER_QUEUE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_deleter.h b/libs/vr/libdvr/include/dvr/dvr_deleter.h
new file mode 100644
index 0000000..943384f
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_deleter.h
@@ -0,0 +1,86 @@
+#ifndef ANDROID_DVR_DELETER_H_
+#define ANDROID_DVR_DELETER_H_
+
+#include <sys/cdefs.h>
+
+#include <memory>
+
+// Header-only C++ helper to delete opaque DVR objects.
+
+__BEGIN_DECLS
+
+// Use forward declarations to avoid dependency on other headers.
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
+typedef struct DvrSurface DvrSurface;
+typedef struct DvrHwcClient DvrHwcClient;
+typedef struct DvrHwcFrame DvrHwcFrame;
+typedef struct DvrVSyncClient DvrVSyncClient;
+
+void dvrBufferDestroy(DvrBuffer* buffer);
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
+void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
+void dvrDisplayManagerDestroy(DvrDisplayManager* client);
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state);
+void dvrSurfaceDestroy(DvrSurface* surface);
+void dvrHwcClientDestroy(DvrHwcClient* client);
+void dvrHwcFrameDestroy(DvrHwcFrame* frame);
+void dvrVSyncClientDestroy(DvrVSyncClient* client);
+
+__END_DECLS
+
+// Avoid errors if this header is included in C code.
+#if defined(__cplusplus)
+
+namespace android {
+namespace dvr {
+
+// Universal DVR object deleter. May be passed to smart pointer types to handle
+// deletion of DVR API objects.
+struct DvrObjectDeleter {
+  void operator()(DvrBuffer* p) { dvrBufferDestroy(p); }
+  void operator()(DvrReadBuffer* p) { dvrReadBufferDestroy(p); }
+  void operator()(DvrWriteBuffer* p) { dvrWriteBufferDestroy(p); }
+  void operator()(DvrReadBufferQueue* p) { dvrReadBufferQueueDestroy(p); }
+  void operator()(DvrWriteBufferQueue* p) { dvrWriteBufferQueueDestroy(p); }
+  void operator()(DvrDisplayManager* p) { dvrDisplayManagerDestroy(p); }
+  void operator()(DvrSurfaceState* p) { dvrSurfaceStateDestroy(p); }
+  void operator()(DvrSurface* p) { dvrSurfaceDestroy(p); }
+  void operator()(DvrHwcClient* p) { dvrHwcClientDestroy(p); }
+  void operator()(DvrHwcFrame* p) { dvrHwcFrameDestroy(p); }
+  void operator()(DvrVSyncClient* p) { dvrVSyncClientDestroy(p); }
+};
+
+// Helper to define unique pointers for DVR object types.
+template <typename T>
+using MakeUniqueDvrPointer = std::unique_ptr<T, DvrObjectDeleter>;
+
+// Unique pointer types for DVR objects.
+using UniqueDvrBuffer = MakeUniqueDvrPointer<DvrBuffer>;
+using UniqueDvrReadBuffer = MakeUniqueDvrPointer<DvrReadBuffer>;
+using UniqueDvrWriteBuffer = MakeUniqueDvrPointer<DvrWriteBuffer>;
+using UniqueDvrReadBufferQueue = MakeUniqueDvrPointer<DvrReadBufferQueue>;
+using UniqueDvrWriteBufferQueue = MakeUniqueDvrPointer<DvrWriteBufferQueue>;
+using UniqueDvrDisplayManager = MakeUniqueDvrPointer<DvrDisplayManager>;
+using UniqueDvrSurfaceState = MakeUniqueDvrPointer<DvrSurfaceState>;
+using UniqueDvrSurface = MakeUniqueDvrPointer<DvrSurface>;
+using UniqueDvrHwcClient = MakeUniqueDvrPointer<DvrHwcClient>;
+using UniqueDvrHwcFrame = MakeUniqueDvrPointer<DvrHwcFrame>;
+using UniqueDvrVSyncClient = MakeUniqueDvrPointer<DvrVSyncClient>;
+
+// TODO(eieio): Add an adapter for std::shared_ptr that injects the deleter into
+// the relevant constructors.
+
+}  // namespace dvr
+}  // namespace android
+
+#endif // defined(__cplusplus)
+
+#endif  // ANDROID_DVR_DELETER_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
new file mode 100644
index 0000000..d5aef8b
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
@@ -0,0 +1,140 @@
+#ifndef DVR_DISPLAY_MANAGER_CLIENT_H_
+#define DVR_DISPLAY_MANAGER_CLIENT_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include <dvr/dvr_display_types.h>
+#include <dvr/dvr_surface.h>
+
+__BEGIN_DECLS
+
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+typedef uint64_t DvrSurfaceUpdateFlags;
+
+// Attempts to connect to the display manager service.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerCreate(DvrDisplayManager** client_out);
+
+// Destroys the display manager client object.
+void dvrDisplayManagerDestroy(DvrDisplayManager* client);
+
+// Sets up a named buffer for shared memory data transfer between display
+// clients and the display manager.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
+                                      const char* name, size_t size,
+                                      uint64_t usage, DvrBuffer** buffer_out);
+
+// Returns an fd used to signal when surface updates occur. Note that depending
+// on the underlying transport, only a subset of the real event bits may be
+// supported. Use dvrDisplayManagerClientTranslateEpollEventMask to get the real
+// event flags.
+// @return the fd on success. Otherwise returns a negative error value.
+int dvrDisplayManagerGetEventFd(DvrDisplayManager* client);
+
+// @param in_events pass in the epoll revents that were initially returned by
+// poll/epoll.
+// @param on success, this value will be overwritten with the true poll/epoll
+// values.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerTranslateEpollEventMask(DvrDisplayManager* client,
+                                             int in_events, int* out_events);
+
+// Queries the display manager service for the current state of the display
+// surfaces and stores the results in the given surface state object.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerGetSurfaceState(DvrDisplayManager* client,
+                                     DvrSurfaceState* surface_state);
+
+// Gets a read buffer queue from the surface |surface_id| named |queue_id|. Each
+// call returns a different read buffer queue connected to the same write buffer
+// queue. Callers should cache these instead of requesting new ones when
+// possible.
+int dvrDisplayManagerGetReadBufferQueue(DvrDisplayManager* client,
+                                        int surface_id, int queue_id,
+                                        DvrReadBufferQueue** queue_out);
+
+// Creates a new surface state object. This object may be used to receive the
+// results of a surface state query. More than one state object may be created
+// to keep multiple snapshots, if desired.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateCreate(DvrSurfaceState** surface_state);
+
+// Destorys the surface state object.
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state);
+
+// Writes the number of surfaces described in the state object into |count_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetSurfaceCount(DvrSurfaceState* surface_state,
+                                   size_t* count_out);
+
+// Returns the update flags for the surface at |surface_index| in the state
+// object. The flags may be used to determine what changes, if any, occured to
+// the surface since the last state update.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
+                                  size_t surface_index,
+                                  DvrSurfaceUpdateFlags* flags_out);
+
+// Returns the unique identifier of surface at |surface_index| in the state
+// object. The identifier may be used to distinguish between surfaces.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetSurfaceId(DvrSurfaceState* surface_state,
+                                size_t surface_index, int* surface_id_out);
+
+// Returns the process id of surface at |surface_index| in the state object.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetProcessId(DvrSurfaceState* surface_state,
+                                size_t surface_index, int* process_id_out);
+
+// Writes the number of queues in the surface at |surface_index| in the state
+// object into |count_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetQueueCount(DvrSurfaceState* surface_state,
+                                 size_t surface_index, size_t* count_out);
+
+// Returns up to |max_count| queue ids for the queues belonging to the surface
+// at |surface_index| in the state object.
+// @return The number of queue ids written on success. Otherwise returns a
+// negative error value.
+ssize_t dvrSurfaceStateGetQueueIds(DvrSurfaceState* surface_state,
+                                   size_t surface_index, int* queue_ids,
+                                   size_t max_count);
+
+// Writes the z-order of the surface at |surface_index| in surface state object
+// into |z_order_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetZOrder(DvrSurfaceState* surface_state,
+                             size_t surface_index, int* z_order_out);
+
+// Writes the visible state of the surface at |surface_index| in the surface
+// state object into |visible_out|.
+// @return 0 on success. Otherwise it returns a negative error value.
+int dvrSurfaceStateGetVisible(DvrSurfaceState* surface_state,
+                              size_t surface_index, bool* visible_out);
+
+// Writes the number of attributes on the surface at |surface_index| in the
+// state object into |count_out|.
+// @return 0 on success. Otherwise it returns a negative error value.
+int dvrSurfaceStateGetAttributeCount(DvrSurfaceState* surface_state,
+                                     size_t surface_index, size_t* count_out);
+
+// Writes the list of attribute key/value pairs for the surface at
+// |surface_index| in the surface state object into |attributes|.
+// @return The number of attributes written on success. Otherwise returns a
+// negative error value.
+ssize_t dvrSurfaceStateGetAttributes(DvrSurfaceState* surface_state,
+                                     size_t surface_index,
+                                     DvrSurfaceAttribute* attributes,
+                                     size_t max_count);
+
+__END_DECLS
+
+#endif  // DVR_DISPLAY_MANAGER_CLIENT_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index e5228d6..361488e 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -1,28 +1,91 @@
 #ifndef ANDROID_DVR_SURFACE_H_
 #define ANDROID_DVR_SURFACE_H_
 
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_display_types.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
+typedef struct DvrBuffer DvrBuffer;
 typedef struct DvrSurface DvrSurface;
-typedef struct DvrSurfaceParameter DvrSurfaceParameter;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 
-// Get a pointer to the global pose buffer.
+// Attribute types. The values are one-hot encoded to support singluar types or
+// masks of supported types.
+enum {
+  DVR_SURFACE_ATTRIBUTE_TYPE_NONE = 0,
+  DVR_SURFACE_ATTRIBUTE_TYPE_INT32 = (1 << 0),
+  DVR_SURFACE_ATTRIBUTE_TYPE_INT64 = (1 << 1),
+  DVR_SURFACE_ATTRIBUTE_TYPE_BOOL = (1 << 2),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT = (1 << 3),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2 = (1 << 4),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3 = (1 << 5),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4 = (1 << 6),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8 = (1 << 7),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16 = (1 << 8),
+};
+
+typedef uint64_t DvrSurfaceAttributeType;
+typedef int32_t DvrSurfaceAttributeKey;
+
+typedef struct DvrSurfaceAttributeValue {
+  DvrSurfaceAttributeType type;
+  union {
+    int32_t int32_value;
+    int64_t int64_value;
+    bool bool_value;
+    float float_value;
+    float float2_value[2];
+    float float3_value[3];
+    float float4_value[4];
+    float float8_value[8];
+    float float16_value[16];
+  };
+} DvrSurfaceAttributeValue;
+
+typedef struct DvrSurfaceAttribute {
+  DvrSurfaceAttributeKey key;
+  DvrSurfaceAttributeValue value;
+} DvrSurfaceAttribute;
+
+// Creates a new display surface with the given attributes.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
+                     size_t attribute_count, DvrSurface** surface_out);
+
+// Destroys the display surface.
+void dvrSurfaceDestroy(DvrSurface* surface);
+
+// Gets the DisplayService global id for this surface.
+int dvrSurfaceGetId(DvrSurface* surface);
+
+// Sets attributes on the given display surface.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceSetAttributes(DvrSurface* surface,
+                            const DvrSurfaceAttribute* attributes,
+                            size_t attribute_count);
+
+// Creates a new write-side buffer queue on the given surface. Direct surfaces
+// may only have one queue, the latest call replacing any prior queue. Replaced
+// queues are still referenced and should be destryoed using the queue destroy
+// API.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
+                                     uint32_t height, uint32_t format,
+                                     uint32_t layer_count, uint64_t usage,
+                                     size_t capacity,
+                                     DvrWriteBufferQueue** queue_out);
+
+// Get a named buffer from the display service.
+// @return 0 on success. Otherwise returns a negative error value.
 int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
 
-int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
-                     uint64_t usage1, int flags, DvrSurface** out_surface);
-
-// TODO(eieio, jwcai) Change this once we have multiple buffer queue support.
-int dvrSurfaceGetWriteBufferQueue(DvrSurface* surface,
-                                  DvrWriteBufferQueue** out_writer);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
+__END_DECLS
 
 #endif  // ANDROID_DVR_SURFACE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h
new file mode 100644
index 0000000..1eea3d9
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_vsync.h
@@ -0,0 +1,26 @@
+#ifndef ANDROID_DVR_VSYNC_H_
+#define ANDROID_DVR_VSYNC_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+typedef struct DvrVSyncClient DvrVSyncClient;
+
+// Creates a new client to the system vsync service.
+int dvrVSyncClientCreate(DvrVSyncClient** client_out);
+
+// Destroys the vsync client.
+void dvrVSyncClientDestroy(DvrVSyncClient* client);
+
+// Get the estimated timestamp of the next GPU lens warp preemption event in/
+// ns. Also returns the corresponding vsync count that the next lens warp
+// operation will target.
+int dvrVSyncClientGetSchedInfo(DvrVSyncClient* client, int64_t* vsync_period_ns,
+                               int64_t* next_timestamp_ns,
+                               uint32_t* next_vsync_count);
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_VSYNC_H_
diff --git a/libs/vr/libdvr/include/dvr/vsync_client_api.h b/libs/vr/libdvr/include/dvr/vsync_client_api.h
deleted file mode 100644
index 0ae5cd5..0000000
--- a/libs/vr/libdvr/include/dvr/vsync_client_api.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef ANDROID_DVR_VSYNC_CLIENT_API_H_
-#define ANDROID_DVR_VSYNC_CLIENT_API_H_
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// A client of the vsync service.
-//
-// The "dvr_vsync_client" structure wraps a client connection to the
-// system vsync service. It is used to synchronize application drawing
-// with the scanout of the display.
-typedef struct dvr_vsync_client dvr_vsync_client;
-
-// Creates a new client to the system vsync service.
-dvr_vsync_client* dvr_vsync_client_create();
-
-// Destroys the vsync client.
-void dvr_vsync_client_destroy(dvr_vsync_client* client);
-
-// Get the estimated timestamp of the next GPU lens warp preemption event in
-// ns. Also returns the corresponding vsync count that the next lens warp
-// operation will target. This call has the same side effect on events as
-// Acknowledge, which saves an IPC message.
-int dvr_vsync_client_get_sched_info(dvr_vsync_client* client,
-                                    int64_t* vsync_period_ns,
-                                    int64_t* next_timestamp_ns,
-                                    uint32_t* next_vsync_count);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // ANDROID_DVR_VSYNC_CLIENT_API_H_
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
new file mode 100644
index 0000000..af202b4
--- /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",
+    "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 29cdc13..0000000
--- a/libs/vr/libdvr/tests/Android.mk
+++ /dev/null
@@ -1,34 +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_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 ea1273e..474e968 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -6,6 +6,8 @@
 #include <base/logging.h>
 #include <gtest/gtest.h>
 
+#include "../dvr_internal.h"
+
 namespace android {
 namespace dvr {
 
@@ -13,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;
@@ -23,9 +25,9 @@
 class DvrBufferQueueTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    write_queue_ = new DvrWriteBufferQueue;
-    write_queue_->producer_queue_ = ProducerQueue::Create<TestMeta>(0, 0, 0, 0);
-    ASSERT_NE(nullptr, write_queue_->producer_queue_);
+    write_queue_ = CreateDvrWriteBufferQueueFromProducerQueue(
+        ProducerQueue::Create<TestMeta>(0, 0, 0, 0));
+    ASSERT_NE(nullptr, write_queue_);
   }
 
   void TearDown() override {
@@ -38,9 +40,9 @@
   void AllocateBuffers(size_t buffer_count) {
     size_t out_slot;
     for (size_t i = 0; i < buffer_count; i++) {
-      int ret = write_queue_->producer_queue_->AllocateBuffer(
-          kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage,
-          kBufferSliceCount, &out_slot);
+      int ret = GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
+                    ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
+                                     kBufferFormat, kBufferUsage, &out_slot);
       ASSERT_EQ(0, ret);
     }
   }
@@ -88,6 +90,39 @@
   dvrReadBufferQueueDestroy(read_queue2);
 }
 
+TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) {
+  AllocateBuffers(3);
+
+  DvrReadBuffer* read_buffer = nullptr;
+  DvrWriteBuffer* write_buffer = nullptr;
+
+  EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
+  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+
+  dvrReadBufferCreateEmpty(&read_buffer);
+  ASSERT_NE(nullptr, read_buffer);
+
+  dvrWriteBufferCreateEmpty(&write_buffer);
+  ASSERT_NE(nullptr, write_buffer);
+
+  EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
+  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+
+  DvrReadBufferQueue* read_queue = nullptr;
+
+  ASSERT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
+
+  const int kTimeoutMs = 0;
+  int fence_fd = -1;
+  ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeoutMs,
+                                          write_buffer, &fence_fd));
+  EXPECT_EQ(-1, fence_fd);
+  EXPECT_TRUE(dvrWriteBufferIsValid(write_buffer));
+
+  ASSERT_EQ(0, dvrWriteBufferClear(write_buffer));
+  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+}
+
 TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
   static constexpr int kTimeout = 0;
   DvrReadBufferQueue* read_queue = nullptr;
@@ -100,12 +135,18 @@
   ASSERT_EQ(0, ret);
   ASSERT_NE(nullptr, read_queue);
 
+  dvrWriteBufferCreateEmpty(&wb);
+  ASSERT_NE(nullptr, wb);
+
+  dvrReadBufferCreateEmpty(&rb);
+  ASSERT_NE(nullptr, rb);
+
   AllocateBuffers(kQueueCapacity);
 
   // Gain buffer for writing.
-  ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, &wb, &fence_fd);
+  ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb, &fence_fd);
   ASSERT_EQ(0, ret);
-  ASSERT_NE(nullptr, wb);
+  ASSERT_TRUE(dvrWriteBufferIsValid(wb));
   ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
            wb, fence_fd);
   pdx::LocalHandle release_fence(fence_fd);
@@ -119,10 +160,10 @@
 
   // Acquire buffer for reading.
   TestMeta acquired_seq = 0U;
-  ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, &rb, &fence_fd,
+  ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, rb, &fence_fd,
                                   &acquired_seq, sizeof(acquired_seq));
   ASSERT_EQ(0, ret);
-  ASSERT_NE(nullptr, rb);
+  ASSERT_TRUE(dvrReadBufferIsValid(rb));
   ASSERT_EQ(seq, acquired_seq);
   ALOGD_IF(TRACE,
            "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
@@ -156,10 +197,11 @@
 
   // A write queue with DvrNativeBufferMetadata should work fine.
   std::unique_ptr<DvrWriteBufferQueue, decltype(&dvrWriteBufferQueueDestroy)>
-      write_queue(new DvrWriteBufferQueue, dvrWriteBufferQueueDestroy);
-  write_queue->producer_queue_ =
-      ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0);
-  ASSERT_NE(nullptr, write_queue->producer_queue_);
+      write_queue(
+          CreateDvrWriteBufferQueueFromProducerQueue(
+              ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0)),
+          dvrWriteBufferQueueDestroy);
+  ASSERT_NE(nullptr, write_queue.get());
 
   ret = dvrWriteBufferQueueGetExternalSurface(write_queue.get(), &window);
   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
new file mode 100644
index 0000000..a2414d6
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -0,0 +1,579 @@
+#include <base/logging.h>
+#include <gtest/gtest.h>
+#include <poll.h>
+
+#include <android/hardware_buffer.h>
+
+#include <algorithm>
+#include <set>
+#include <thread>
+#include <vector>
+
+#include <dvr/dvr_deleter.h>
+#include <dvr/dvr_display_manager.h>
+#include <dvr/dvr_surface.h>
+
+#include <pdx/status.h>
+
+using android::pdx::ErrorStatus;
+using android::pdx::Status;
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+DvrSurfaceAttribute GetAttribute(DvrSurfaceAttributeKey key, bool value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
+  attribute.value.bool_value = value;
+  return attribute;
+}
+
+DvrSurfaceAttribute GetAttribute(DvrSurfaceAttributeKey key, int32_t value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
+  attribute.value.bool_value = value;
+  return attribute;
+}
+
+Status<UniqueDvrSurface> CreateApplicationSurface(bool visible = false,
+                                                  int32_t z_order = 0) {
+  DvrSurface* surface = nullptr;
+  DvrSurfaceAttribute attributes[] = {
+      GetAttribute(DVR_SURFACE_ATTRIBUTE_Z_ORDER, z_order),
+      GetAttribute(DVR_SURFACE_ATTRIBUTE_VISIBLE, visible)};
+
+  const int ret = dvrSurfaceCreate(
+      attributes, std::extent<decltype(attributes)>::value, &surface);
+  if (ret < 0)
+    return ErrorStatus(-ret);
+  else
+    return {UniqueDvrSurface(surface)};
+}
+
+Status<UniqueDvrWriteBufferQueue> CreateSurfaceQueue(
+    const UniqueDvrSurface& surface, uint32_t width, uint32_t height,
+    uint32_t format, uint32_t layer_count, uint64_t usage, size_t capacity) {
+  DvrWriteBufferQueue* queue;
+  const int ret =
+      dvrSurfaceCreateWriteBufferQueue(surface.get(), width, height, format,
+                                       layer_count, usage, capacity, &queue);
+  if (ret < 0)
+    return ErrorStatus(-ret);
+  else
+    return {UniqueDvrWriteBufferQueue(queue)};
+}
+
+class TestDisplayManager {
+ public:
+  TestDisplayManager(UniqueDvrDisplayManager display_manager,
+                     UniqueDvrSurfaceState surface_state)
+      : display_manager_(std::move(display_manager)),
+        surface_state_(std::move(surface_state)) {
+    const int fd = dvrDisplayManagerGetEventFd(display_manager_.get());
+    LOG_IF(INFO, fd < 0) << "Failed to get event fd: " << strerror(-fd);
+    display_manager_event_fd_ = fd;
+  }
+
+  Status<UniqueDvrReadBufferQueue> GetReadBufferQueue(int surface_id,
+                                                      int queue_id) {
+    DvrReadBufferQueue* queue;
+    const int ret = dvrDisplayManagerGetReadBufferQueue(
+        display_manager_.get(), surface_id, queue_id, &queue);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {UniqueDvrReadBufferQueue(queue)};
+  }
+
+  Status<void> UpdateSurfaceState() {
+    const int ret = dvrDisplayManagerGetSurfaceState(display_manager_.get(),
+                                                     surface_state_.get());
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {};
+  }
+
+  Status<void> WaitForUpdate() {
+    if (display_manager_event_fd_ < 0)
+      return ErrorStatus(-display_manager_event_fd_);
+
+    const int kTimeoutMs = 10000;  // 10s
+    pollfd pfd = {display_manager_event_fd_, POLLIN, 0};
+    const int count = poll(&pfd, 1, kTimeoutMs);
+    if (count < 0)
+      return ErrorStatus(errno);
+    else if (count == 0)
+      return ErrorStatus(ETIMEDOUT);
+
+    int events;
+    const int ret = dvrDisplayManagerTranslateEpollEventMask(
+        display_manager_.get(), pfd.revents, &events);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else if (events & POLLIN)
+      return UpdateSurfaceState();
+    else
+      return ErrorStatus(EPROTO);
+  }
+
+  Status<size_t> GetSurfaceCount() {
+    size_t count = 0;
+    const int ret =
+        dvrSurfaceStateGetSurfaceCount(surface_state_.get(), &count);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {count};
+  }
+
+  Status<DvrSurfaceUpdateFlags> GetUpdateFlags(size_t surface_index) {
+    DvrSurfaceUpdateFlags update_flags;
+    const int ret = dvrSurfaceStateGetUpdateFlags(surface_state_.get(),
+                                                  surface_index, &update_flags);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {update_flags};
+  }
+
+  Status<int> GetSurfaceId(size_t surface_index) {
+    int surface_id;
+    const int ret = dvrSurfaceStateGetSurfaceId(surface_state_.get(),
+                                                surface_index, &surface_id);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {surface_id};
+  }
+
+  Status<int> GetProcessId(size_t surface_index) {
+    int process_id;
+    const int ret = dvrSurfaceStateGetProcessId(surface_state_.get(),
+                                                surface_index, &process_id);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {process_id};
+  }
+
+  Status<std::vector<DvrSurfaceAttribute>> GetAttributes(size_t surface_index) {
+    std::vector<DvrSurfaceAttribute> attributes;
+    size_t count = 0;
+    const int ret = dvrSurfaceStateGetAttributeCount(surface_state_.get(),
+                                                     surface_index, &count);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+
+    attributes.resize(count);
+    const ssize_t return_count = dvrSurfaceStateGetAttributes(
+        surface_state_.get(), surface_index, attributes.data(), count);
+    if (return_count < 0)
+      return ErrorStatus(-return_count);
+
+    attributes.resize(return_count);
+    return {std::move(attributes)};
+  }
+
+  Status<std::vector<int>> GetQueueIds(size_t surface_index) {
+    std::vector<int> queue_ids;
+    size_t count = 0;
+    const int ret = dvrSurfaceStateGetQueueCount(surface_state_.get(),
+                                                 surface_index, &count);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+
+    if (count > 0) {
+      queue_ids.resize(count);
+      const ssize_t return_count = dvrSurfaceStateGetQueueIds(
+          surface_state_.get(), surface_index, queue_ids.data(), count);
+      if (return_count < 0)
+        return ErrorStatus(-return_count);
+
+      queue_ids.resize(return_count);
+    }
+
+    return {std::move(queue_ids)};
+  }
+
+ private:
+  UniqueDvrDisplayManager display_manager_;
+  UniqueDvrSurfaceState surface_state_;
+
+  // Owned by object in display_manager_, do not explicitly close.
+  int display_manager_event_fd_;
+
+  TestDisplayManager(const TestDisplayManager&) = delete;
+  void operator=(const TestDisplayManager&) = delete;
+};
+
+class DvrDisplayManagerTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    int ret;
+    DvrDisplayManager* display_manager;
+    DvrSurfaceState* surface_state;
+
+    ret = dvrDisplayManagerCreate(&display_manager);
+    ASSERT_EQ(0, ret) << "Failed to create display manager client";
+    ASSERT_NE(nullptr, display_manager);
+
+    ret = dvrSurfaceStateCreate(&surface_state);
+    ASSERT_EQ(0, ret) << "Failed to create surface state object";
+    ASSERT_NE(nullptr, surface_state);
+
+    manager_.reset(
+        new TestDisplayManager(UniqueDvrDisplayManager(display_manager),
+                               UniqueDvrSurfaceState(surface_state)));
+  }
+  void TearDown() override {}
+
+  std::unique_ptr<TestDisplayManager> manager_;
+};
+
+// TODO(eieio): Consider moving these somewhere more central because they are
+// broadly useful.
+
+template <typename T>
+testing::AssertionResult StatusOk(const char* status_expression,
+                                  const Status<T>& status) {
+  if (!status.ok()) {
+    return testing::AssertionFailure()
+           << "(" << status_expression
+           << ") expected to indicate success but actually contains error ("
+           << status.error() << ")";
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+template <typename T>
+testing::AssertionResult StatusError(const char* status_expression,
+                                     const Status<T>& status) {
+  if (status.ok()) {
+    return testing::AssertionFailure()
+           << "(" << status_expression
+           << ") expected to indicate error but instead indicates success.";
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+template <typename T>
+testing::AssertionResult StatusHasError(const char* status_expression,
+                                        const char* /*error_code_expression*/,
+                                        const Status<T>& status,
+                                        int error_code) {
+  if (status.ok()) {
+    return StatusError(status_expression, status);
+  } else if (status.error() != error_code) {
+    return testing::AssertionFailure()
+           << "(" << status_expression << ") expected to indicate error ("
+           << error_code << ") but actually indicates error (" << status.error()
+           << ")";
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+template <typename T, typename U>
+testing::AssertionResult StatusHasValue(const char* status_expression,
+                                        const char* /*value_expression*/,
+                                        const Status<T>& status,
+                                        const U& value) {
+  if (!status.ok()) {
+    return StatusOk(status_expression, status);
+  } else if (status.get() != value) {
+    return testing::AssertionFailure()
+           << "(" << status_expression << ") expected to contain value ("
+           << testing::PrintToString(value) << ") but actually contains value ("
+           << testing::PrintToString(status.get()) << ")";
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+template <typename T, typename Op>
+testing::AssertionResult StatusPred(const char* status_expression,
+                                    const char* pred_expression,
+                                    const Status<T>& status, Op pred) {
+  if (!status.ok()) {
+    return StatusOk(status_expression, status);
+  } else if (!pred(status.get())) {
+    return testing::AssertionFailure()
+           << status_expression << " value ("
+           << testing::PrintToString(status.get())
+           << ") failed to pass predicate " << pred_expression;
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+#define ASSERT_STATUS_OK(status) ASSERT_PRED_FORMAT1(StatusOk, status)
+#define ASSERT_STATUS_ERROR(status) ASSERT_PRED_FORMAT1(StatusError, status)
+
+#define ASSERT_STATUS_ERROR_VALUE(value, status) \
+  ASSERT_PRED_FORMAT2(StatusHasError, status, value)
+
+#define ASSERT_STATUS_EQ(value, status) \
+  ASSERT_PRED_FORMAT2(StatusHasValue, status, value)
+
+#define EXPECT_STATUS_OK(status) EXPECT_PRED_FORMAT1(StatusOk, status)
+#define EXPECT_STATUS_ERROR(status) EXPECT_PRED_FORMAT1(StatusError, status)
+
+#define EXPECT_STATUS_ERROR_VALUE(value, status) \
+  EXPECT_PRED_FORMAT2(StatusHasError, status, value)
+
+#define EXPECT_STATUS_EQ(value, status) \
+  EXPECT_PRED_FORMAT2(StatusHasValue, status, value)
+
+#define EXPECT_STATUS_PRED(pred, status) \
+  EXPECT_PRED_FORMAT2(StatusPred, status, pred)
+
+#if 0
+// Verify utility predicate/macro functionality. This section is commented out
+// because it is designed to fail in some cases to validate the helpers.
+TEST_F(DvrDisplayManagerTest, ExpectVoid) {
+  Status<void> status_error{ErrorStatus{EINVAL}};
+  Status<void> status_ok{};
+
+  EXPECT_STATUS_ERROR(status_error);
+  EXPECT_STATUS_ERROR(status_ok);
+  EXPECT_STATUS_OK(status_error);
+  EXPECT_STATUS_OK(status_ok);
+
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, status_error);
+  EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_error);
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, status_ok);
+  EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_ok);
+}
+
+TEST_F(DvrDisplayManagerTest, ExpectInt) {
+  Status<int> status_error{ErrorStatus{EINVAL}};
+  Status<int> status_ok{10};
+
+  EXPECT_STATUS_ERROR(status_error);
+  EXPECT_STATUS_ERROR(status_ok);
+  EXPECT_STATUS_OK(status_error);
+  EXPECT_STATUS_OK(status_ok);
+
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, status_error);
+  EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_error);
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, status_ok);
+  EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_ok);
+
+  EXPECT_STATUS_EQ(10, status_error);
+  EXPECT_STATUS_EQ(20, status_error);
+  EXPECT_STATUS_EQ(10, status_ok);
+  EXPECT_STATUS_EQ(20, status_ok);
+
+  auto pred1 = [](const auto& value) { return value < 15; };
+  auto pred2 = [](const auto& value) { return value > 5; };
+  auto pred3 = [](const auto& value) { return value > 15; };
+  auto pred4 = [](const auto& value) { return value < 5; };
+
+  EXPECT_STATUS_PRED(pred1, status_error);
+  EXPECT_STATUS_PRED(pred2, status_error);
+  EXPECT_STATUS_PRED(pred3, status_error);
+  EXPECT_STATUS_PRED(pred4, status_error);
+  EXPECT_STATUS_PRED(pred1, status_ok);
+  EXPECT_STATUS_PRED(pred2, status_ok);
+  EXPECT_STATUS_PRED(pred3, status_ok);
+  EXPECT_STATUS_PRED(pred4, status_ok);
+}
+#endif
+
+TEST_F(DvrDisplayManagerTest, SurfaceCreateEvent) {
+  // Get surface state and verify there are no surfaces.
+  ASSERT_STATUS_OK(manager_->UpdateSurfaceState());
+  ASSERT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+
+  // Get flags for invalid surface index.
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, manager_->GetUpdateFlags(0));
+
+  // Create an application surface.
+  auto surface_status = CreateApplicationSurface();
+  ASSERT_STATUS_OK(surface_status);
+  UniqueDvrSurface surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  const int surface_id = dvrSurfaceGetId(surface.get());
+  ASSERT_GE(surface_id, 0);
+
+  // Now there should be one new surface.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  EXPECT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Verify the new surface flag is set.
+  auto check_flags = [](const auto& value) {
+    return value & DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE;
+  };
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  // Verify the surface id matches.
+  EXPECT_STATUS_EQ(surface_id, manager_->GetSurfaceId(0));
+
+  // Verify the owning process of the surface.
+  EXPECT_STATUS_EQ(getpid(), manager_->GetProcessId(0));
+
+  surface.reset();
+
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  EXPECT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+}
+
+TEST_F(DvrDisplayManagerTest, SurfaceAttributeEvent) {
+  // Get surface state and verify there are no surfaces.
+  ASSERT_STATUS_OK(manager_->UpdateSurfaceState());
+  ASSERT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+
+  // Get attributes for an invalid surface index.
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, manager_->GetAttributes(0));
+
+  const bool kInitialVisibility = true;
+  const int32_t kInitialZOrder = 10;
+  auto surface_status =
+      CreateApplicationSurface(kInitialVisibility, kInitialZOrder);
+  ASSERT_STATUS_OK(surface_status);
+  auto surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Check the initial attribute values.
+  auto attribute_status = manager_->GetAttributes(0);
+  ASSERT_STATUS_OK(attribute_status);
+  auto attributes = attribute_status.take();
+  EXPECT_GE(attributes.size(), 2u);
+
+  const std::set<int32_t> expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+                                           DVR_SURFACE_ATTRIBUTE_VISIBLE};
+
+  // Collect all the keys in attributes that match the expected keys.
+  std::set<int32_t> actual_keys;
+  std::for_each(attributes.begin(), attributes.end(),
+                [&expected_keys, &actual_keys](const auto& attribute) {
+                  if (expected_keys.find(attribute.key) != expected_keys.end())
+                    actual_keys.emplace(attribute.key);
+                });
+
+  // If the sets match then attributes contained at least the expected keys,
+  // even if other keys were also present.
+  EXPECT_EQ(expected_keys, actual_keys);
+}
+
+TEST_F(DvrDisplayManagerTest, SurfaceQueueEvent) {
+  // Create an application surface.
+  auto surface_status = CreateApplicationSurface();
+  ASSERT_STATUS_OK(surface_status);
+  UniqueDvrSurface surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  const int surface_id = dvrSurfaceGetId(surface.get());
+  ASSERT_GE(surface_id, 0);
+  // Get surface state and verify there is one surface.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Verify there are no queues for the surface recorded in the state snapshot.
+  EXPECT_STATUS_EQ(std::vector<int>{}, manager_->GetQueueIds(0));
+
+  // Create a new queue in the surface.
+  auto write_queue_status = CreateSurfaceQueue(
+      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();
+  ASSERT_NE(nullptr, write_queue.get());
+
+  const int queue_id = dvrWriteBufferQueueGetId(write_queue.get());
+  ASSERT_GE(queue_id, 0);
+
+  // Update surface state.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Verify the buffers changed flag is set.
+  auto check_flags = [](const auto& value) {
+    return value & DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED;
+  };
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  auto queue_ids_status = manager_->GetQueueIds(0);
+  ASSERT_STATUS_OK(queue_ids_status);
+
+  auto queue_ids = queue_ids_status.take();
+  ASSERT_EQ(1u, queue_ids.size());
+  EXPECT_EQ(queue_id, queue_ids[0]);
+
+  auto read_queue_status = manager_->GetReadBufferQueue(surface_id, queue_id);
+  ASSERT_STATUS_OK(read_queue_status);
+  UniqueDvrReadBufferQueue read_queue = read_queue_status.take();
+  ASSERT_NE(nullptr, read_queue.get());
+  EXPECT_EQ(queue_id, dvrReadBufferQueueGetId(read_queue.get()));
+
+  write_queue.reset();
+
+  // Verify that destroying the queue generates a surface update event.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Verify that the buffers changed flag is set.
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  // Verify that the queue ids reflect the change.
+  queue_ids_status = manager_->GetQueueIds(0);
+  ASSERT_STATUS_OK(queue_ids_status);
+
+  queue_ids = queue_ids_status.take();
+  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
+}  // namespace android
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index caf20a5..e65f6d5 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,6 +1,6 @@
 #include <android/hardware_buffer.h>
-#include <dvr/display_manager_client.h>
 #include <dvr/dvr_buffer.h>
+#include <dvr/dvr_display_manager.h>
 #include <dvr/dvr_surface.h>
 #include <system/graphics.h>
 
@@ -15,28 +15,31 @@
 class DvrNamedBufferTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    client_ = dvrDisplayManagerClientCreate();
+    const int ret = dvrDisplayManagerCreate(&client_);
+    ASSERT_EQ(0, ret);
     ASSERT_NE(nullptr, client_);
   }
 
   void TearDown() override {
-    if (client_ != nullptr) {
-      dvrDisplayManagerClientDestroy(client_);
-      client_ = nullptr;
-    }
+    dvrDisplayManagerDestroy(client_);
+    client_ = nullptr;
   }
 
-  DvrDisplayManagerClient* client_ = nullptr;
+  DvrDisplayManager* client_ = nullptr;
 };
 
 TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
   const char* buffer_name = "same_name";
-  DvrBuffer* buffer1 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  DvrBuffer* buffer1 = nullptr;
+  int ret1 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer1);
+  ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, buffer1);
 
-  DvrBuffer* buffer2 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  DvrBuffer* buffer2 = nullptr;
+  int ret2 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer2);
+  ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, buffer2);
 
   AHardwareBuffer* hardware_buffer1 = nullptr;
@@ -73,7 +76,7 @@
   ASSERT_EQ(0, e3);
 
   AHardwareBuffer* hardware_buffer3 = nullptr;
-  int e4 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer3);
+  int e4 = dvrBufferGetAHardwareBuffer(buffer3, &hardware_buffer3);
   ASSERT_EQ(0, e4);
   ASSERT_NE(nullptr, hardware_buffer3);
 
@@ -95,13 +98,17 @@
 TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
   const char* buffer_name1 = "test1";
   const char* buffer_name2 = "test2";
-  DvrBuffer* setup_buffer1 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0, 0);
+  DvrBuffer* setup_buffer1 = nullptr;
+  int ret1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0,
+                                               &setup_buffer1);
+  ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, setup_buffer1);
   dvrBufferDestroy(setup_buffer1);
 
-  DvrBuffer* setup_buffer2 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0, 0);
+  DvrBuffer* setup_buffer2 = nullptr;
+  int ret2 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0,
+                                               &setup_buffer2);
+  ASSERT_EQ(0, ret2);
   ASSERT_NE(nullptr, setup_buffer2);
   dvrBufferDestroy(setup_buffer2);
 
@@ -126,11 +133,13 @@
   // GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, and these two values are different.
   // If all is good, when we get the AHardwareBuffer, it should be converted
   // back to AHARDWAREBUFFER_USAGE_VIDEO_ENCODE.
-  const int64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
+  const uint64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
 
-  DvrBuffer* setup_buffer =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage, 0);
+  DvrBuffer* setup_buffer = nullptr;
+  int e1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage,
+                                             &setup_buffer);
   ASSERT_NE(nullptr, setup_buffer);
+  ASSERT_EQ(0, e1);
 
   AHardwareBuffer* hardware_buffer = nullptr;
   int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
@@ -139,14 +148,12 @@
 
   AHardwareBuffer_Desc desc = {};
   AHardwareBuffer_describe(hardware_buffer, &desc);
-
-  ASSERT_EQ(desc.usage, AHARDWAREBUFFER_USAGE_VIDEO_ENCODE);
+  ASSERT_EQ(usage, desc.usage);
 
   dvrBufferDestroy(setup_buffer);
   AHardwareBuffer_release(hardware_buffer);
 }
 
-
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdvr/vsync_client_api.cpp b/libs/vr/libdvr/vsync_client_api.cpp
deleted file mode 100644
index dbddd3d..0000000
--- a/libs/vr/libdvr/vsync_client_api.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "include/dvr/vsync_client_api.h"
-
-#include <private/dvr/vsync_client.h>
-
-extern "C" {
-
-dvr_vsync_client* dvr_vsync_client_create() {
-  auto client = android::dvr::VSyncClient::Create();
-  return static_cast<dvr_vsync_client*>(client.release());
-}
-
-void dvr_vsync_client_destroy(dvr_vsync_client* client) {
-  delete static_cast<android::dvr::VSyncClient*>(client);
-}
-
-int dvr_vsync_client_get_sched_info(dvr_vsync_client* client,
-                                    int64_t* vsync_period_ns,
-                                    int64_t* next_timestamp_ns,
-                                    uint32_t* next_vsync_count) {
-  return static_cast<android::dvr::VSyncClient*>(client)->GetSchedInfo(
-      vsync_period_ns, next_timestamp_ns, next_vsync_count);
-}
-
-}  // extern "C"
diff --git a/libs/vr/libdvrcommon/include/private/dvr/epoll_file_descriptor.h b/libs/vr/libdvrcommon/include/private/dvr/epoll_file_descriptor.h
index 91e12c5..099a409 100644
--- a/libs/vr/libdvrcommon/include/private/dvr/epoll_file_descriptor.h
+++ b/libs/vr/libdvrcommon/include/private/dvr/epoll_file_descriptor.h
@@ -52,6 +52,8 @@
       return ret;
   }
 
+  int Get() const { return fd_.get(); }
+
  private:
   base::unique_fd fd_;
 };
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/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..d96eeff 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -214,30 +214,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 +361,41 @@
   return ErrorStatus{EINVAL};
 }
 
+Status<void> Endpoint::CreateChannelSocketPair(LocalHandle* local_socket,
+                                               LocalHandle* remote_socket) {
+  Status<void> status;
+  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;
+  }
+
+  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/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 632978b..6218e8e 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -14,17 +14,11 @@
 
 sourceFiles = [
     "acquired_buffer.cpp",
-    "compositor.cpp",
-    "debug_hud_data.cpp",
-    "debug_hud_view.cpp",
+    "epoll_event_dispatcher.cpp",
     "display_manager_service.cpp",
     "display_service.cpp",
     "display_surface.cpp",
     "hardware_composer.cpp",
-    "screenshot_service.cpp",
-    "surface_channel.cpp",
-    "video_compositor.cpp",
-    "video_mesh_surface.cpp",
     "vr_flinger.cpp",
     "vsync_service.cpp",
 ]
@@ -36,7 +30,6 @@
     "libhwcomposer-command-buffer",
     "libbufferhub",
     "libbufferhubqueue",
-    "libeds",
     "libdisplay",
     "libdvrcommon",
     "libdvrgraphics",
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 5a3aa7f..7932a9c 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -9,7 +9,7 @@
 namespace dvr {
 
 AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
-                               LocalHandle acquire_fence, uint64_t /*sequence*/)
+                               LocalHandle acquire_fence)
     : buffer_(buffer), acquire_fence_(std::move(acquire_fence)) {}
 
 AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 1d14a38..dd4fcc5 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -21,7 +21,7 @@
   // this constructor; the constructor does not attempt to ACQUIRE the buffer
   // itself.
   AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
-                 pdx::LocalHandle acquire_fence, uint64_t sequence);
+                 pdx::LocalHandle acquire_fence);
 
   // Constructs an AcquiredBuffer from a BufferConsumer. The BufferConsumer MUST
   // be in the POSTED state prior to calling this constructor, as this
diff --git a/libs/vr/libvrflinger/compositor.cpp b/libs/vr/libvrflinger/compositor.cpp
deleted file mode 100644
index d1d4f45..0000000
--- a/libs/vr/libvrflinger/compositor.cpp
+++ /dev/null
@@ -1,878 +0,0 @@
-#include "compositor.h"
-
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-
-#include <memory>
-
-#include <cutils/properties.h>
-
-#include <dvr/graphics.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/debug.h>
-#include <private/dvr/device_metrics.h>
-#include <private/dvr/display_types.h>
-#include <private/dvr/dummy_native_window.h>
-#include <private/dvr/gl_fenced_flush.h>
-#include <private/dvr/graphics/blur.h>
-#include <private/dvr/graphics/gpu_profiler.h>
-#include <private/dvr/native_buffer.h>
-#include <private/dvr/platform_defines.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
-
-#include "debug_hud_data.h"
-#include "debug_hud_view.h"
-#include "display_surface.h"
-
-#define BINNING_CONTROL_HINT_QCOM 0x8FB0
-
-// Accepted by the <hint> parameter of glHint:
-#define BINNING_QCOM 0x8FB1
-#define VISIBILITY_OPTIMIZED_BINNING_QCOM 0x8FB2
-#define RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
-
-#ifndef EGL_CONTEXT_MAJOR_VERSION
-#define EGL_CONTEXT_MAJOR_VERSION 0x3098
-#define EGL_CONTEXT_MINOR_VERSION 0x30FB
-#endif
-
-using android::pdx::LocalHandle;
-
-static const int kDistortionMeshResolution = 40;
-
-static std::shared_ptr<int64_t> eds_gpu_duration_ns =
-    std::make_shared<int64_t>(0);
-
-static constexpr char kDisableLensDistortionProp[] =
-    "persist.dvr.disable_distort";
-
-static constexpr char kEnableEdsPoseSaveProp[] =
-    "persist.dvr.save_eds_pose";
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-// An implementation of ANativeWindowBuffer backed by a temporary IonBuffer.
-// Do not hold on to this kind of object, because the IonBuffer may become
-// invalid in other scopes.
-class TemporaryNativeBuffer
-    : public ANativeObjectBase<ANativeWindowBuffer, TemporaryNativeBuffer,
-                               LightRefBase<TemporaryNativeBuffer>> {
- public:
-  explicit TemporaryNativeBuffer(const IonBuffer* buffer) : BASE() {
-    ANativeWindowBuffer::width = buffer->width();
-    ANativeWindowBuffer::height = buffer->height();
-    ANativeWindowBuffer::stride = buffer->stride();
-    ANativeWindowBuffer::format = buffer->format();
-    ANativeWindowBuffer::usage = buffer->usage();
-    // TODO(eieio): Update NYC to support layer_count.
-    // ANativeWindowBuffer::layer_count = 1;
-    handle = buffer->handle();
-  }
-
- private:
-  friend class android::LightRefBase<TemporaryNativeBuffer>;
-
-  TemporaryNativeBuffer(const TemporaryNativeBuffer&) = delete;
-  void operator=(TemporaryNativeBuffer&) = delete;
-};
-
-std::vector<uint8_t> ReadTextureRGBA(GLuint texture_id, int width, int height) {
-  std::vector<uint8_t> data(width * height * 4);
-  GLuint fbo;
-  glGenFramebuffers(1, &fbo);
-  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                         texture_id, 0);
-  // Using default GL_PACK_ALIGNMENT of 4 for the 4 byte source data.
-  glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-  glDeleteFramebuffers(1, &fbo);
-  CHECK_GL();
-  return data;
-}
-
-}  // namespace
-
-class Compositor::Texture {
- public:
-  Texture(std::shared_ptr<BufferConsumer> consumer, EGLDisplay display,
-          int index);
-  ~Texture();
-
-  std::shared_ptr<BufferConsumer> consumer() const { return consumer_; }
-  GLuint texture_id() const { return texture_id_; }
-  vec2i size() const {
-    return vec2i(native_buffer_.get()->width, native_buffer_.get()->height);
-  }
-  int index() const { return index_; }
-
-  bool Initialize();
-
- private:
-  Texture(const Texture&) = delete;
-  void operator=(const Texture&) = delete;
-
-  std::shared_ptr<BufferConsumer> consumer_;
-
-  android::sp<NativeBufferConsumer> native_buffer_;
-
-  EGLDisplay display_;
-  EGLImageKHR image_;
-  GLuint texture_id_;
-  int index_;
-};
-
-Compositor::Texture::Texture(std::shared_ptr<BufferConsumer> consumer,
-                             EGLDisplay display, int index)
-    : consumer_(consumer),
-      display_(display),
-      image_(nullptr),
-      texture_id_(0),
-      index_(index) {}
-
-Compositor::Texture::~Texture() {
-  glDeleteTextures(1, &texture_id_);
-  eglDestroyImageKHR(display_, image_);
-}
-
-bool Compositor::Texture::Initialize() {
-  native_buffer_ = new NativeBufferConsumer(consumer_, index_);
-
-  CHECK_GL();
-  image_ = eglCreateImageKHR(
-      display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-      static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
-  if (!image_) {
-    ALOGE("Failed to create EGLImage\n");
-    return false;
-  }
-
-  glGenTextures(1, &texture_id_);
-  glActiveTexture(GL_TEXTURE0);
-  glBindTexture(GL_TEXTURE_2D, texture_id_);
-  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  CHECK_GL();
-  return true;
-}
-
-Compositor::RenderTarget::RenderTarget()
-    : buffer_texture_id_(0),
-      buffer_framebuffer_id_(0),
-      buffer_image_(nullptr) {}
-
-Compositor::RenderTarget::~RenderTarget() { Destroy(); }
-
-void Compositor::RenderTarget::Destroy() {
-  glDeleteFramebuffers(1, &buffer_framebuffer_id_);
-  glDeleteTextures(1, &buffer_texture_id_);
-  eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer_image_);
-  buffer_texture_id_ = 0;
-  buffer_framebuffer_id_ = 0;
-  buffer_image_ = nullptr;
-}
-
-void Compositor::RenderTarget::Initialize(int width, int height) {
-  LOG_ALWAYS_FATAL_IF(buffer_texture_id_ || buffer_framebuffer_id_ ||
-                      buffer_image_);
-  constexpr int usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER |
-                        GRALLOC_USAGE_HW_RENDER |
-                        GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
-  buffer_ = std::make_shared<IonBuffer>(width, height,
-                                        HAL_PIXEL_FORMAT_RGBA_8888, usage);
-
-  native_buffer_ = new NativeBuffer(buffer_);
-
-  buffer_image_ = eglCreateImageKHR(
-      eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
-      EGL_NATIVE_BUFFER_ANDROID,
-      static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
-
-  glGenTextures(1, &buffer_texture_id_);
-  glBindTexture(GL_TEXTURE_2D, buffer_texture_id_);
-  CHECK_GL();
-
-  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer_image_);
-  CHECK_GL();
-
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glBindTexture(GL_TEXTURE_2D, 0);
-
-  // Generate a framebuffer.
-  glGenFramebuffers(1, &buffer_framebuffer_id_);
-  glBindFramebuffer(GL_FRAMEBUFFER, buffer_framebuffer_id_);
-  CHECK_GL();
-
-  // Attach the color buffer
-  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                         buffer_texture_id_, 0);
-  CHECK_GL();
-  GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-  CHECK_GL();
-  if (result != GL_FRAMEBUFFER_COMPLETE) {
-    ALOGE("Framebuffer incomplete: %d", result);
-  }
-
-  // Clear the render target to black once. In direct render mode we never draw
-  // the corner pixels.
-  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-  glClear(GL_COLOR_BUFFER_BIT);
-  glFlush();
-
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-  CHECK_GL();
-}
-
-void Compositor::RenderTarget::BindFramebuffer() {
-  glBindFramebuffer(GL_FRAMEBUFFER, buffer_framebuffer_id_);
-}
-
-void Compositor::RenderTarget::DiscardColorAttachment() {
-  GLenum attachment = GL_COLOR_ATTACHMENT0;
-  glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
-  CHECK_GL();
-}
-
-class Compositor::RenderPoseBufferObject {
- public:
-  RenderPoseBufferObject(LocalHandle&& render_pose_buffer_fd) :
-      fd_(std::move(render_pose_buffer_fd)) {
-    // Create new pose tracking buffer for this surface.
-    glGenBuffers(1, &render_pose_buffer_object_);
-    glBindBuffer(GL_UNIFORM_BUFFER, render_pose_buffer_object_);
-    if (fd_) {
-      LOG_ALWAYS_FATAL_IF(!glBindSharedBufferQCOM);
-      if (glBindSharedBufferQCOM)
-        glBindSharedBufferQCOM(GL_UNIFORM_BUFFER,
-                               sizeof(DisplaySurfaceMetadata),
-                               fd_.Get());
-      else
-        ALOGE("Error: Missing gralloc buffer extension");
-      CHECK_GL();
-    }
-    glBindBuffer(GL_UNIFORM_BUFFER, 0);
-  }
-
-  ~RenderPoseBufferObject() { glDeleteBuffers(1, &render_pose_buffer_object_); }
-
-  GLuint object_id() const { return render_pose_buffer_object_; }
-
- private:
-  // Render pose buffer object. This contains an array of poses that corresponds
-  // with the surface buffers.
-  GLuint render_pose_buffer_object_;
-  LocalHandle fd_;
-
-  RenderPoseBufferObject(const RenderPoseBufferObject&) = delete;
-  void operator=(const RenderPoseBufferObject&) = delete;
-};
-
-HeadMountMetrics CreateDefaultHeadMountMetrics() {
-  const bool enable_distortion =
-      property_get_bool(kDisableLensDistortionProp, 0) == 0;
-  return enable_distortion ? CreateHeadMountMetrics()
-                           : CreateUndistortedHeadMountMetrics();
-}
-
-Compositor::Compositor()
-    : head_mount_metrics_(CreateDefaultHeadMountMetrics()),
-      display_(0),
-      config_(0),
-      surface_(0),
-      context_(0),
-      active_render_target_(0),
-      is_render_direct_(false),
-      compute_fbo_(0),
-      compute_fbo_texture_(0),
-      hmd_metrics_requires_update_(false),
-      eds_pose_capture_enabled_(false) {}
-
-Compositor::~Compositor() {}
-
-bool Compositor::Initialize(const DisplayMetrics& display_metrics) {
-  ATRACE_NAME("Compositor::Initialize");
-  if (!InitializeEGL())
-    return false;
-
-  display_metrics_ = display_metrics;
-  const int width = display_metrics_.GetSizePixels().x();
-  const int height = display_metrics_.GetSizePixels().y();
-
-  render_target_[0].Initialize(width, height);
-  render_target_[1].Initialize(width, height);
-
-  // EDS:
-  GpuProfiler::Get()->SetEnableGpuTracing(true);
-
-  eds_pose_capture_enabled_ = property_get_bool(kEnableEdsPoseSaveProp, 0) == 1;
-
-  CheckAndUpdateHeadMountMetrics(true);
-
-  debug_hud_.reset(new DebugHudView(*composite_hmd_.get()));
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-  return true;
-}
-
-void Compositor::UpdateHeadMountMetrics(
-    const HeadMountMetrics& head_mount_metrics) {
-  // Recalculating the mesh must be done in the draw loop, defer until then.
-  std::lock_guard<std::mutex> _lock(mutex_);
-  head_mount_metrics_ = head_mount_metrics;
-  hmd_metrics_requires_update_ = true;
-}
-
-void Compositor::CheckAndUpdateHeadMountMetrics(bool force_update) {
-  std::lock_guard<std::mutex> _lock(mutex_);
-  if (hmd_metrics_requires_update_ || force_update) {
-    hmd_metrics_requires_update_ = false;
-    composite_hmd_.reset(
-        new CompositeHmd(head_mount_metrics_, display_metrics_));
-    CHECK_GL();
-    eds_renderer_.reset(new DistortionRenderer(
-        *composite_hmd_.get(), display_metrics_.GetSizePixels(),
-        kDistortionMeshResolution, true, false, false, true, true));
-  }
-}
-
-bool Compositor::InitializeEGL() {
-  ATRACE_NAME("Compositor::InitializeEGL");
-  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  if (!display_) {
-    ALOGE("Failed to get egl display\n");
-    return false;
-  }
-
-  eglInitialize(display_, nullptr, nullptr);
-
-  EGLint attribs[] = {
-      EGL_BUFFER_SIZE,
-      32,
-      EGL_ALPHA_SIZE,
-      0,
-      EGL_BLUE_SIZE,
-      8,
-      EGL_RED_SIZE,
-      8,
-      EGL_GREEN_SIZE,
-      8,
-      EGL_DEPTH_SIZE,
-      0,
-      EGL_SURFACE_TYPE,
-      EGL_WINDOW_BIT,
-      EGL_RENDERABLE_TYPE,
-      EGL_OPENGL_ES2_BIT,
-      EGL_NONE,
-  };
-
-  EGLint num_configs;
-  if (!eglChooseConfig(display_, attribs, &config_, 1, &num_configs)) {
-    ALOGE("Couldn't find config");
-    return false;
-  }
-
-  std::unique_ptr<DummyNativeWindow> window(new DummyNativeWindow());
-
-  surface_ = eglCreateWindowSurface(display_, config_, window.get(), nullptr);
-  if (surface_ == EGL_NO_SURFACE) {
-    ALOGE("Failed to create egl surface");
-    return false;
-  }
-  window.release();
-
-  EGLint context_attribs[] = {EGL_CONTEXT_MAJOR_VERSION,
-                              3,
-                              EGL_CONTEXT_MINOR_VERSION,
-                              1,
-                              EGL_CONTEXT_PRIORITY_LEVEL_IMG,
-                              EGL_CONTEXT_PRIORITY_HIGH_IMG,
-                              EGL_NONE};
-  context_ = eglCreateContext(display_, config_, nullptr, context_attribs);
-  if (!eglMakeCurrent(display_, surface_, surface_, context_)) {
-    ALOGE("Unable to create GLESv2 context");
-    return false;
-  }
-
-  load_gl_extensions();
-  GpuProfiler::Get()->OnGlContextCreated();
-
-  glEnable(BINNING_CONTROL_HINT_QCOM);
-  glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
-  is_render_direct_ = true;
-  CHECK_GL();
-
-  // Initialize the placeholder 1x1 framebuffer that we bind during compute
-  // shader instances to avoid accesses to other framebuffers.
-  glGenFramebuffers(1, &compute_fbo_);
-  glGenTextures(1, &compute_fbo_texture_);
-  glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
-  glBindTexture(GL_TEXTURE_2D, compute_fbo_texture_);
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
-               nullptr);
-  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                         compute_fbo_texture_, 0);
-  CHECK_GL();
-  CHECK_GL_FBO();
-  glBindTexture(GL_TEXTURE_2D, 0);
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
-  return true;
-}
-
-void Compositor::Shutdown() {
-  glFinish();
-  render_target_[0].Destroy();
-  render_target_[1].Destroy();
-  layers_.clear();
-  glDeleteFramebuffers(1, &compute_fbo_);
-  glDeleteTextures(1, &compute_fbo_texture_);
-
-  debug_hud_.reset();
-  eds_renderer_.reset();
-
-  if (context_) {
-    GpuProfiler::Get()->OnGlContextDestroyed();
-    eglDestroyContext(display_, context_);
-    context_ = 0;
-  }
-
-  if (surface_ != EGL_NO_SURFACE) {
-    eglDestroySurface(display_, surface_);
-    surface_ = EGL_NO_SURFACE;
-  }
-}
-
-void Compositor::RemoveAllBuffers() { layers_.clear(); }
-
-void Compositor::UpdateSurfaces(
-    const std::vector<std::shared_ptr<DisplaySurface>>& surfaces) {
-  // Delete the removed surfaces.
-  layers_.erase(
-      std::remove_if(layers_.begin(), layers_.end(),
-                     [&surfaces](const AppFrame& layer) {
-                       for (const auto& surface : surfaces)
-                         if (surface->surface_id() == layer.surface_id())
-                           return false;
-                       return true;
-                     }),
-      layers_.end());
-  // New surfaces are added on-demand as buffers are posted.
-}
-
-Compositor::AppFrame::AppFrame()
-    : surface_id_(-1),
-      blur_(0.0f),
-      z_order_(0),
-      vertical_flip_(false),
-      enable_cac_(true),
-      render_buffer_index_(0) {}
-
-Compositor::AppFrame::~AppFrame() {}
-
-const Compositor::Texture* Compositor::AppFrame::GetGlTextureId(
-    EGLDisplay display, int index) {
-  auto buffer_consumer = buffer_.buffer();
-  if (!buffer_consumer) {
-    return nullptr;
-  }
-  auto texture_it = std::find_if(
-      textures_.begin(), textures_.end(),
-      [buffer_consumer, index](const std::shared_ptr<Texture>& t) {
-        return t->consumer() == buffer_consumer && t->index() == index;
-      });
-
-  if (texture_it != textures_.end()) {
-    return (*texture_it).get();
-  }
-
-  textures_.push_back(
-      std::make_shared<Texture>(buffer_consumer, display, index));
-  if (!textures_.back()->Initialize()) {
-    textures_.pop_back();
-    return nullptr;
-  }
-  return textures_.back().get();
-}
-
-bool Compositor::AppFrame::UpdateSurface(
-    const std::shared_ptr<DisplaySurface>& surface) {
-  int surface_id = surface->surface_id();
-  float blur = surface->manager_blur();
-  bool need_sort = false;
-  if (z_order_ != surface->layer_order()) {
-    need_sort = true;
-    z_order_ = surface->layer_order();
-  }
-
-  surface_id_ = surface_id;
-  if (!render_pose_buffer_object_) {
-    render_pose_buffer_object_.reset(
-        new RenderPoseBufferObject(surface->GetMetadataBufferFd()));
-  }
-
-  blur_ = blur;
-  vertical_flip_ =
-      !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP);
-  enable_cac_ =
-      !(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC);
-
-  AcquiredBuffer skipped_buffer;
-  AcquiredBuffer buffer =
-      surface->AcquireNewestAvailableBuffer(&skipped_buffer);
-  if (!skipped_buffer.IsEmpty()) {
-    DebugHudData::data.SkipLayerFrame(z_order_);
-    ATRACE_NAME("DropToCatchUp");
-    ATRACE_ASYNC_END("BufferPost", skipped_buffer.buffer()->id());
-  }
-  if (!buffer.IsEmpty()) {
-    DebugHudData::data.AddLayerFrame(z_order_);
-    // Buffer was already ready, so we don't need to wait on the fence.
-    buffer.ClaimAcquireFence().Close();
-    ATRACE_ASYNC_END("BufferPost", buffer.buffer()->id());
-
-    render_buffer_index_ = surface->GetRenderBufferIndex(buffer.buffer()->id());
-
-#ifdef TRACE
-    const volatile DisplaySurfaceMetadata* data =
-        surface->GetMetadataBufferPtr();
-#endif
-    ALOGE_IF(TRACE, "read pose index %d %f %f", render_buffer_index_,
-             data->orientation[render_buffer_index_][0],
-             data->orientation[render_buffer_index_][1]);
-
-    // Move the new buffer over the old. AcquiredBuffer releases the old one.
-    buffer_ = std::move(buffer);
-  }
-  return need_sort;
-}
-
-void Compositor::AppFrame::UpdateVideoMeshSurface(
-    const std::shared_ptr<DisplaySurface>& surface) {
-  // Update |video_compositors_| with |video_surface|. Note that
-  // |UpdateVideoMeshSurface| should only be called on the PostThread before
-  // |DrawFrame| is called. Thus, no synchronization is required for
-  // |video_compositors_|.
-  if (!surface->video_mesh_surfaces_updated())
-    return;
-
-  // TODO(jwcai) The following loop handles adding new surfaces; video mesh
-  // removal logic shall be handled by listening to |OnChannelClose| event from
-  // DisplayService.
-  for (const auto& video_surface : surface->GetVideoMeshSurfaces()) {
-    // Here we assume number of |video_surface|s is relatively small, thus, the
-    // merge should be efficient enough.
-    auto video_compositor_it = std::find_if(
-        video_compositors_.begin(), video_compositors_.end(),
-        [video_surface](const std::shared_ptr<VideoCompositor>& c) {
-          return c->surface_id() == video_surface->surface_id();
-        });
-
-    if (video_compositor_it == video_compositors_.end()) {
-      // This video surface is new, create a new VideoCompositor.
-      video_compositors_.push_back(std::make_shared<VideoCompositor>(
-          video_surface, surface->GetMetadataBufferPtr()));
-    } else {
-      // There is a compositor in |video_compositors_| is already set up for
-      // this |video_surface|.
-      ALOGW("Duplicated video_mesh_surface: surface_id=%d",
-            video_surface->surface_id());
-    }
-  }
-}
-
-void Compositor::AppFrame::ResetBlurrers() { blurrers_.clear(); }
-
-void Compositor::AppFrame::AddBlurrer(Blur* blurrer) {
-  blurrers_.emplace_back(blurrer);
-}
-
-void Compositor::PostBuffer(const std::shared_ptr<DisplaySurface>& surface) {
-  int surface_id = surface->surface_id();
-
-  ALOGD_IF(TRACE, "Post surface %d", surface_id);
-
-  auto layer_it = std::find_if(layers_.begin(), layers_.end(),
-                               [surface_id](const AppFrame& frame) {
-                                 return frame.surface_id() == surface_id;
-                               });
-
-  bool need_sort = false;
-  if (layer_it == layers_.end()) {
-    layers_.push_back(AppFrame());
-    layer_it = layers_.end() - 1;
-    need_sort = true;
-  }
-
-  need_sort |= layer_it->UpdateSurface(surface);
-  layer_it->UpdateVideoMeshSurface(surface);
-
-  if (need_sort) {
-    std::stable_sort(layers_.begin(), layers_.end());
-  }
-}
-
-std::vector<uint8_t> Compositor::ReadLayerPixels(size_t index, int* width,
-                                                 int* height) {
-  if (index >= layers_.size()) {
-    return {};
-  }
-
-  const Texture* texture = layers_[index].GetGlTextureId(display_, 0);
-  if (!texture) {
-    return {};
-  }
-
-  *width = texture->size()[0];
-  *height = texture->size()[1];
-  return ReadTextureRGBA(texture->texture_id(), *width, *height);
-}
-
-std::vector<uint8_t> Compositor::ReadBufferPixels(const IonBuffer* buffer) {
-  android::sp<TemporaryNativeBuffer> native_buffer =
-      new TemporaryNativeBuffer(buffer);
-
-  // Finish to make sure the GL driver has completed drawing of prior FBOs.
-  // Since we are creating an EGL image here, the driver will not know that
-  // there is a dependency on earlier GL draws.
-  glFinish();
-
-  EGLImageKHR image = eglCreateImageKHR(
-      display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-      static_cast<ANativeWindowBuffer*>(native_buffer.get()), nullptr);
-  if (!image) {
-    ALOGE("Failed to create EGLImage\n");
-    return {};
-  }
-
-  GLuint texture_id;
-  glGenTextures(1, &texture_id);
-  glActiveTexture(GL_TEXTURE0);
-  glBindTexture(GL_TEXTURE_2D, texture_id);
-  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
-
-  int width = buffer->width();
-  int height = buffer->height();
-  std::vector<uint8_t> data = ReadTextureRGBA(texture_id, width, height);
-
-  glBindTexture(GL_TEXTURE_2D, 0);
-  glDeleteTextures(1, &texture_id);
-  eglDestroyImageKHR(display_, image);
-  return data;
-}
-
-bool Compositor::DrawFrame(uint32_t target_vsync_count,
-                           LocalHandle* buffer_fence_fd) {
-  CheckAndUpdateHeadMountMetrics(false);
-
-  ATRACE_NAME("Compositor::DrawFrame");
-  GpuProfiler::Get()->PollGlTimerQueries();
-
-  if (buffer_fence_fd)
-    buffer_fence_fd->Close();
-
-  int num_layers = 0;
-  const int kMaxLayers = 4;
-  GLuint texture_id[2][kMaxLayers] = {{0}};
-  GLuint render_pose_buffer_id[kMaxLayers] = {0};
-  uint32_t render_buffer_index[kMaxLayers] = {0};
-  bool vertical_flip[kMaxLayers] = {false};
-  bool separate_eye_textures[kMaxLayers] = {false};
-  bool enable_cac[kMaxLayers] = {};
-  CHECK_GL();
-  for (auto& layer : layers_) {
-    if (!layer.buffer().buffer()) {
-      ATRACE_NAME("no_buffer");
-      continue;
-    }
-
-    // Extract surface parameters.
-    render_buffer_index[num_layers] = layer.render_buffer_index();
-    render_pose_buffer_id[num_layers] =
-        layer.render_pose_buffer_object()->object_id();
-    vertical_flip[num_layers] = layer.vertical_flip();
-    enable_cac[num_layers] =
-        head_mount_metrics_.supports_chromatic_aberration_correction() &&
-        layer.enable_cac();
-
-    // Extract per-eye textures. These may be separate or joined (atlased).
-    vec2i size(0, 0);
-    int view_count = layer.buffer().buffer()->slice_count();
-    ALOGE_IF(view_count > 2, "Error: more than 2 views not supported");
-    view_count = std::min(2, view_count);
-    separate_eye_textures[num_layers] = (view_count > 1);
-    bool is_missing_texture = false;
-    for (int eye = 0; eye < 2; ++eye) {
-      // If view_count is 1, each eye texture is the 0th.
-      int view_index = (view_count == 2) ? eye : 0;
-      const Texture* texture = layer.GetGlTextureId(display_, view_index);
-      // Texture will be null if the EGL image creation fails (hopefully never).
-      if (!texture) {
-        is_missing_texture = true;
-        break;
-      }
-      // All views are currently expected to have the same size.
-      size = texture->size();
-      texture_id[eye][num_layers] = texture->texture_id();
-    }
-    if (is_missing_texture) {
-      continue;
-    }
-
-    // Perform blur if requested.
-    if (fabs(layer.blur()) > 0.001f) {
-      // No need for CAC on blurred layers.
-      enable_cac[num_layers] = false;
-      if (layer.blurrer_count() < 1 || layer.blurrer(0)->width() != size[0] ||
-          layer.blurrer(0)->height() != size[1]) {
-        // Blur is created with the left eye texture, but the same instance
-        // can be used for the right eye as well.
-        layer.ResetBlurrers();
-        layer.AddBlurrer(new Blur(size[0], size[1], texture_id[0][num_layers],
-                                  GL_TEXTURE_2D, GL_TEXTURE_2D, true, display_,
-                                  view_count));
-      }
-      // Reset blur instances to prepare for drawing.
-      layer.blurrer(0)->StartFrame();
-      layer.blurrer(0)->set_scale(layer.blur());
-      // Perform blur and replace source texture with blurred output texture.
-      if (view_count == 1) {
-        // Single wide buffer for both eyes, blur both eyes in one operation.
-        texture_id[0][num_layers] = texture_id[1][num_layers] =
-            layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
-      } else {
-        // Split eye buffers in a single frame, blur each framebuffer.
-        texture_id[0][num_layers] =
-            layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
-        texture_id[1][num_layers] =
-            layer.blurrer(0)->DrawBlur(texture_id[1][num_layers]);
-      }
-    }
-
-    ++num_layers;
-    if (num_layers >= kMaxLayers)
-      break;
-  }
-
-  CHECK_GL();
-  // Set appropriate binning mode for the number of layers.
-  if (num_layers > 1 && is_render_direct_) {
-    is_render_direct_ = false;
-    glDisable(BINNING_CONTROL_HINT_QCOM);
-  } else if (num_layers <= 1 && !is_render_direct_) {
-    is_render_direct_ = true;
-    glEnable(BINNING_CONTROL_HINT_QCOM);
-    glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
-  }
-
-  // Workaround for GL driver bug that causes the currently bound FBO to be
-  // accessed during a compute shader pass (DoLateLatch below). Based on an
-  // analysis with systrace, the best pattern here was to run the compute shader
-  // with a *different* FBO than what will be drawn to afterward. So we bind
-  // a dummy 1x1 FBO here and discard it. If instead, the current render target
-  // is bound during the compute shader, the following draw calls will be forced
-  // into direct mode rendering.
-  glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
-  GLenum attachment = GL_COLOR_ATTACHMENT0;
-  glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
-
-  // Double buffer the render target.  Get the render target we're drawing into,
-  // and update the active buffer to the next buffer.
-  RenderTarget& render_target = GetRenderTarget();
-  SetNextRenderTarget();
-
-  if (num_layers > 0) {
-    // This trace prints the EDS+Warp GPU overhead and prints every 5 seconds:
-    TRACE_GPU_PRINT("GPU EDS+Warp", 5 * 60);
-    CHECK_GL();
-    eds_renderer_->DoLateLatch(target_vsync_count, render_buffer_index,
-                               render_pose_buffer_id, vertical_flip,
-                               separate_eye_textures, num_layers);
-
-    render_target.BindFramebuffer();
-
-    // Discard to avoid unresolving the framebuffer during tiled rendering.
-    render_target.DiscardColorAttachment();
-
-    // For tiled mode rendering, we clear every frame to avoid garbage showing
-    // up in the parts of tiles that are not rendered.
-    if (!is_render_direct_) {
-      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-      glClear(GL_COLOR_BUFFER_BIT);
-    }
-
-    for (int eye = kLeftEye; eye <= kRightEye; ++eye) {
-      eds_renderer_->PrepGlState(static_cast<EyeType>(eye));
-      for (int layer_i = 0; layer_i < num_layers; ++layer_i) {
-        bool blend_with_previous = layer_i > 0;
-        uint32_t current_buffer_index = render_buffer_index[layer_i];
-
-        // Render video mesh in the background of each graphics layer.
-        layers_[layer_i].ForEachVideoCompositor([this, eye, layer_i,
-                                                 current_buffer_index,
-                                                 &blend_with_previous](
-            const std::shared_ptr<VideoCompositor>& video_compositor) mutable {
-          eds_renderer_->DrawVideoQuad(
-              static_cast<EyeType>(eye), layer_i,
-              video_compositor->GetActiveTextureId(display_),
-              video_compositor->GetTransform(eye, current_buffer_index));
-          blend_with_previous = true;
-        });
-
-        // Apply distortion to frame submitted from the app's GL context.
-        eds_renderer_->SetChromaticAberrationCorrectionEnabled(
-            enable_cac[layer_i]);
-        eds_renderer_->ApplyDistortionCorrectionToTexture(
-            static_cast<EyeType>(eye), &texture_id[eye][layer_i],
-            &vertical_flip[layer_i], &separate_eye_textures[layer_i], &layer_i,
-            1, blend_with_previous, false);
-      }
-    }
-    eds_renderer_->ResetGlState(1);
-    CHECK_GL();
-  } else {
-    ALOGI("No buffers for compositing, clearing to black.");
-    render_target.BindFramebuffer();
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-  }
-
-  debug_hud_->Update();
-  debug_hud_->Draw();
-
-  LocalHandle fence_fd = CreateGLSyncAndFlush(display_);
-
-  if (buffer_fence_fd)
-    *buffer_fence_fd = std::move(fence_fd);
-
-  if (eds_pose_capture_enabled_) {
-    std::lock_guard<std::mutex> _lock(mutex_);
-    eds_renderer_->GetLastEdsPose(&eds_pose_capture_);
-  }
-
-  return true;
-}
-
-bool Compositor::GetLastEdsPose(LateLatchOutput* out_data) {
-  if (eds_pose_capture_enabled_) {
-    std::lock_guard<std::mutex> _lock(mutex_);
-    *out_data = eds_pose_capture_;
-    return true;
-  } else {
-    ALOGE("Eds pose capture is not enabled.");
-    return false;
-  }
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/compositor.h b/libs/vr/libvrflinger/compositor.h
deleted file mode 100644
index be26d31..0000000
--- a/libs/vr/libvrflinger/compositor.h
+++ /dev/null
@@ -1,233 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
-
-#include <EGL/egl.h>
-#include <log/log.h>
-#include <utils/StrongPointer.h>
-
-#include <memory>
-#include <mutex>
-#include <queue>
-#include <vector>
-
-#include <pdx/file_handle.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/display_metrics.h>
-#include <private/dvr/distortion_renderer.h>
-#include <private/dvr/frame_time_history.h>
-#include <private/dvr/ion_buffer.h>
-#include <private/dvr/native_buffer.h>
-
-#include "acquired_buffer.h"
-#include "video_compositor.h"
-struct DvrPose;
-
-namespace android {
-namespace dvr {
-
-class Blur;
-class BufferConsumer;
-class CompositeHmd;
-class DebugHudView;
-class DisplaySurface;
-
-// This is a GPU compositor for software EDS and lens warp on buffers provided
-// by HardwareComposer.
-class Compositor {
- public:
-  Compositor();
-  ~Compositor();
-
-  bool Initialize(const DisplayMetrics& display_metrics);
-  void UpdateHeadMountMetrics(const HeadMountMetrics& head_mount_metrics);
-  void Shutdown();
-
-  // Renders a frame with the latest buffers with EDS and warp applied.
-  // buffer_fence_fd can be used to get a fence for the rendered frame. It can
-  // be set to null if the fence isn't needed.
-  bool DrawFrame(uint32_t target_vsync_count,
-                 pdx::LocalHandle* buffer_fence_fd);
-
-  // Remove all buffers.
-  void RemoveAllBuffers();
-
-  // Synchronize compositor layers with in given surfaces.
-  void UpdateSurfaces(
-      const std::vector<std::shared_ptr<DisplaySurface>>& surfaces);
-
-  // This must be called for each surface before DrawFrame is called.
-  void PostBuffer(const std::shared_ptr<DisplaySurface>& surface);
-
-  std::shared_ptr<IonBuffer> GetBuffer() const {
-    return render_target_[active_render_target_].buffer();
-  }
-
-  // Returns the number of layers being rendered by the compositor.
-  size_t GetLayerCount() const { return layers_.size(); }
-
-  // Returns the source buffer at the given layer index or nullptr if none is
-  // available.
-  std::shared_ptr<BufferConsumer> PeekAtLayer(size_t index) const {
-    if (index >= GetLayerCount())
-      return nullptr;
-    return layers_[index].buffer().buffer();
-  }
-
-  // Expensive operation to transfer the pixels of the given layer index into
-  // unformatted memory and return as a RGBA buffer.
-  // On success, returns non-zero sized vector and sets width and height.
-  // On failure, returns empty vector.
-  std::vector<uint8_t> ReadLayerPixels(size_t index, int* width, int* height);
-
-  // Expensive operation to transfer the pixels of the given buffer into
-  // unformatted memory and return as a RGBA buffer.
-  // On success, returns non-zero sized vector.
-  // On failure, returns empty vector.
-  std::vector<uint8_t> ReadBufferPixels(const IonBuffer* buffer);
-
-  bool GetLastEdsPose(LateLatchOutput* out_data);
-
-  const HeadMountMetrics& head_mount_metrics() const {
-    return head_mount_metrics_;
-  }
-
- private:
-  class Texture;
-  class RenderPoseBufferObject;
-
-  // A rendered frame from an application.
-  class AppFrame {
-   public:
-    AppFrame();
-    ~AppFrame();
-
-    AppFrame(AppFrame&& other) = default;
-    AppFrame& operator=(AppFrame&&) = default;
-
-    // Gets a GL texture object for the current buffer. The resulting texture
-    // object will be cached for future calls. Returns a pointer for temporary
-    // access - not meant to hold on to.
-    const Texture* GetGlTextureId(EGLDisplay display, int index);
-
-    bool operator<(const AppFrame& rhs) const {
-      return z_order_ < rhs.z_order_;
-    }
-    int z_order() const { return z_order_; }
-    // Return true if this surface z order has been changed.
-    bool UpdateSurface(const std::shared_ptr<DisplaySurface>& surface);
-    void UpdateVideoMeshSurface(const std::shared_ptr<DisplaySurface>& surface);
-    void ResetBlurrers();
-    void AddBlurrer(Blur* blurrer);
-
-    const AcquiredBuffer& buffer() const { return buffer_; }
-    int surface_id() const { return surface_id_; }
-    float blur() const { return blur_; }
-    bool vertical_flip() const { return vertical_flip_; }
-    bool enable_cac() const { return enable_cac_; }
-    size_t blurrer_count() const { return blurrers_.size(); }
-    Blur* blurrer(size_t i) {
-      return blurrers_.size() < i ? nullptr : blurrers_[i].get();
-    }
-    uint32_t render_buffer_index() const { return render_buffer_index_; }
-    const RenderPoseBufferObject* render_pose_buffer_object() const {
-      return render_pose_buffer_object_.get();
-    }
-
-    template <class A>
-    void ForEachVideoCompositor(A action) const {
-      for (auto& c : video_compositors_) {
-        action(c);
-      }
-    }
-
-   private:
-    int surface_id_;
-    float blur_;
-    int z_order_;
-    bool vertical_flip_;
-    bool enable_cac_;
-    std::vector<std::unique_ptr<Blur>> blurrers_;
-    AcquiredBuffer buffer_;
-    std::vector<std::shared_ptr<Texture>> textures_;
-    uint32_t render_buffer_index_;
-    std::unique_ptr<RenderPoseBufferObject> render_pose_buffer_object_;
-
-    // Active video mesh compositors
-    std::vector<std::shared_ptr<VideoCompositor>> video_compositors_;
-
-    AppFrame(const AppFrame& other) = delete;
-    AppFrame& operator=(const AppFrame&) = delete;
-  };
-
-  class RenderTarget {
-   public:
-    RenderTarget();
-    ~RenderTarget();
-
-    void Initialize(int width, int height);
-    void Destroy();
-    void BindFramebuffer();
-    void DiscardColorAttachment();
-
-    std::shared_ptr<IonBuffer> buffer() const { return buffer_; }
-
-   private:
-    std::shared_ptr<IonBuffer> buffer_;
-    android::sp<NativeBuffer> native_buffer_;
-
-    GLuint buffer_texture_id_;
-    GLuint buffer_framebuffer_id_;
-    EGLImageKHR buffer_image_;
-  };
-
-  Compositor(const Compositor&) = delete;
-  void operator=(const Compositor&) = delete;
-
-  bool InitializeEGL();
-
-  void UpdateHudToggle();
-  void PrintStatsHud();
-  void CheckAndUpdateHeadMountMetrics(bool force_update);
-
-  RenderTarget& GetRenderTarget() {
-    return render_target_[active_render_target_];
-  }
-
-  void SetNextRenderTarget() {
-    active_render_target_ = (active_render_target_ + 1) & 1;
-  }
-
-  std::vector<AppFrame> layers_;
-
-  DisplayMetrics display_metrics_;
-  HeadMountMetrics head_mount_metrics_;
-
-  EGLDisplay display_;
-  EGLConfig config_;
-  EGLSurface surface_;
-  EGLContext context_;
-  int active_render_target_;
-  RenderTarget render_target_[2];
-  bool is_render_direct_;
-
-  // FBO for compute shader.
-  GLuint compute_fbo_;
-  GLuint compute_fbo_texture_;
-
-  std::unique_ptr<DebugHudView> debug_hud_;
-
-  // EDS:
-  std::unique_ptr<CompositeHmd> composite_hmd_;
-  bool hmd_metrics_requires_update_;
-  std::unique_ptr<DistortionRenderer> eds_renderer_;
-
-  bool eds_pose_capture_enabled_;
-  std::mutex mutex_;
-  LateLatchOutput eds_pose_capture_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
diff --git a/libs/vr/libvrflinger/debug_hud_data.cpp b/libs/vr/libvrflinger/debug_hud_data.cpp
deleted file mode 100644
index d387bba..0000000
--- a/libs/vr/libvrflinger/debug_hud_data.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "debug_hud_data.h"
-
-namespace android {
-namespace dvr {
-
-DebugHudData DebugHudData::data;
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/debug_hud_data.h b/libs/vr/libvrflinger/debug_hud_data.h
deleted file mode 100644
index 778169d..0000000
--- a/libs/vr/libvrflinger/debug_hud_data.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
-
-#include <stdint.h>
-
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/frame_time_history.h>
-
-namespace android {
-namespace dvr {
-
-// Tracks debug stats for the displayd debug HUD. Unless otherwise noted,
-// there is no synchronization of data accesses to avoid performance impact.
-// All accesses to this data are on the displayd HWC post thread. Accesses from
-// other threads will need to be duly protected from races.
-// This is a lightweight struct to make it easy to add and remove
-// tracking data.
-struct DebugHudData {
-  // Maximum supported layers for the debug HUD.
-  enum { kMaxLayers = 4 };
-
-  // The global singleton HUD data instance.
-  static DebugHudData data;
-
-  // Tracks framerate and skipped frames.
-  struct FrameStats {
-    void AddFrame() {
-      int64_t now = GetSystemClockNs();
-      frame_time.AddSample(now - last_frame_ts);
-      last_frame_ts = now;
-    }
-
-    void SkipFrame() {
-      AddFrame();
-      ++drops;
-    }
-
-    int drops = 0;
-    int64_t last_frame_ts = 0;
-    FrameTimeHistory frame_time;
-  };
-
-  // Debug data for compositor layers (applications, system UI, etc).
-  struct LayerData {
-    void Reset() {
-      ResetStats();
-      width = 0;
-      height = 0;
-      is_separate = false;
-    }
-
-    void ResetStats() { frame_stats.drops = 0; }
-
-    FrameStats frame_stats;
-    int width = 0;
-    int height = 0;
-    bool is_separate = false;
-  };
-
-  // Resets the stats.
-  void ResetStats() {
-    hwc_frame_stats.drops = 0;
-    hwc_latency = 0;
-    for (auto& l : layer_data)
-      l.ResetStats();
-  }
-
-  // Resets the layer configuration.
-  void ResetLayers() {
-    num_layers = 0;
-    for (auto& l : layer_data)
-      l.Reset();
-  }
-
-  // Tracks a frame arrival for the given layer.
-  void AddLayerFrame(size_t layer) {
-    if (layer < kMaxLayers) {
-      num_layers = std::max(layer + 1, num_layers);
-      layer_data[layer].frame_stats.AddFrame();
-    }
-  }
-
-  // Tracks a frame skip/drop for the given layer.
-  void SkipLayerFrame(size_t layer) {
-    if (layer < kMaxLayers) {
-      num_layers = std::max(layer + 1, num_layers);
-      layer_data[layer].frame_stats.SkipFrame();
-    }
-  }
-
-  // Sets the resolution and other details of the layer.
-  void SetLayerInfo(size_t layer, int width, int height, bool is_separate) {
-    if (layer < kMaxLayers) {
-      num_layers = std::max(layer + 1, num_layers);
-      layer_data[layer].width = width;
-      layer_data[layer].height = height;
-      layer_data[layer].is_separate = is_separate;
-    }
-  }
-
-  FrameStats hwc_frame_stats;
-  int64_t hwc_latency = 0;
-  size_t num_layers = 0;
-  LayerData layer_data[kMaxLayers];
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
diff --git a/libs/vr/libvrflinger/debug_hud_view.cpp b/libs/vr/libvrflinger/debug_hud_view.cpp
deleted file mode 100644
index 4936ac6..0000000
--- a/libs/vr/libvrflinger/debug_hud_view.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include "debug_hud_view.h"
-
-#include <dvr/pose_client.h>
-
-#include "debug_hud_data.h"
-
-namespace android {
-namespace dvr {
-
-DebugHudView::DebugHudView(const CompositeHmd& hmd) {
-  pose_client_ = dvrPoseCreate();
-
-  display_size_ = hmd.GetDisplayMetrics().GetSizePixels();
-  vec2 display_size_meters = hmd.GetDisplayMetrics().GetSizeMeters();
-  inter_lens_dist_screen_space_ =
-      2.0f * hmd.GetHeadMountMetrics().GetInterLensDistance() /
-      std::max(display_size_meters[0], display_size_meters[1]);
-}
-
-DebugHudView::~DebugHudView() {
-  if (pose_client_)
-    dvrPoseDestroy(pose_client_);
-  pose_client_ = nullptr;
-}
-
-void DebugHudView::Update() {
-  // Check for gesture that enables the debug stats HUD.
-  if (!pose_client_)
-    return;
-  DvrPoseAsync pose;
-  dvrPoseGet(pose_client_, 0, &pose);
-  float32x4_t q = pose.orientation;
-  quat orientation(q[3], q[0], q[1], q[2]);
-  vec3 up = orientation * vec3(0, 1, 0);
-  if (up[1] < -0.8f) {
-    ++switch_timer_;
-  } else {
-    switch_timer_ = 0;
-  }
-  // A few seconds upside down => toggle stats HUD.
-  if (switch_timer_ > 200) {
-    switch_timer_ = 0;
-    enabled_ = !enabled_;
-    DebugHudData::data.ResetStats();
-    ALOGE("Toggle debug stats HUD: %s", enabled_ ? "ON" : "OFF");
-  }
-}
-
-void DebugHudView::Draw() {
-  if (!enabled_)
-    return;
-  if (!debug_text_)
-    debug_text_.reset(new DebugText(400, display_size_[0], display_size_[1]));
-
-  const DebugHudData& data = DebugHudData::data;
-  const size_t layer_char_count = 50;
-  char layer_data[DebugHudData::kMaxLayers][layer_char_count];
-  for (size_t i = 0; i < data.num_layers; ++i) {
-    float fps = data.layer_data[i].frame_stats.frame_time.GetAverageFps();
-    snprintf(layer_data[i], layer_char_count,
-             "Layer %d %dx%d%s FPS: %.2f Drops: %d\n", static_cast<int>(i),
-             data.layer_data[i].width, data.layer_data[i].height,
-             data.layer_data[i].is_separate ? "x2" : "", fps,
-             data.layer_data[i].frame_stats.drops);
-  }
-
-  float hwc_fps = data.hwc_frame_stats.frame_time.GetAverageFps();
-
-  char text[400];
-  float hwc_latency_ms = static_cast<float>(data.hwc_latency) / 1000000.0f;
-  snprintf(text, sizeof(text), "HWC FPS: %.2f Latency: %.3f ms Skips: %d\n",
-           hwc_fps, hwc_latency_ms, data.hwc_frame_stats.drops);
-
-  for (size_t i = 0; i < data.num_layers; ++i) {
-    strncat(text, layer_data[i], sizeof(text) - strlen(text) - 1);
-  }
-
-  // Ensure text termination.
-  text[sizeof(text) - 1] = '\0';
-
-  glViewport(0, 0, display_size_[0], display_size_[1]);
-  glEnable(GL_BLEND);
-  // No stereo, because you can see the HUD OK in one eye. Stereo actually
-  // makes it more difficult to focus sometimes. To enable stereo:
-  // replace the second to last parameter with inter_lens_dist_screen_space_.
-  debug_text_->Draw(0.0f, -0.7f * inter_lens_dist_screen_space_, text, 0.0f, 1);
-  glDisable(GL_BLEND);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/debug_hud_view.h b/libs/vr/libvrflinger/debug_hud_view.h
deleted file mode 100644
index 50f38a8..0000000
--- a/libs/vr/libvrflinger/debug_hud_view.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
-
-#include <stdint.h>
-
-#include <utils/Log.h>
-
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/graphics/debug_text.h>
-
-struct DvrPose;
-
-namespace android {
-namespace dvr {
-
-class CompositeHmd;
-
-// The view and the controller for the displayd debug HUD.
-// The HUD is enabled and disabled by internally tracking the head pose.
-// When the head pose is upside down for ~3 seconds, the enabled state toggles.
-// See DebugHudData for the data that is reported.
-class DebugHudView {
- public:
-  DebugHudView(const CompositeHmd& hmd);
-  ~DebugHudView();
-
-  // Updates HUD state.
-  void Update();
-
-  // Draws HUD into the current framebuffer if it is currently enabled.
-  void Draw();
-
- private:
-  DebugHudView(const DebugHudView&) = delete;
-  DebugHudView& operator=(const DebugHudView&) = delete;
-
-  DvrPose* pose_client_ = nullptr;
-  vec2i display_size_;
-  bool enabled_ = false;
-  int switch_timer_ = 0;
-  float inter_lens_dist_screen_space_ = 0.0f;
-  std::unique_ptr<DebugText> debug_text_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 99f93bf..a0b3efe 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -3,32 +3,21 @@
 #include <pdx/channel_handle.h>
 #include <pdx/default_transport/service_endpoint.h>
 #include <private/android_filesystem_config.h>
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/display_protocol.h>
 #include <private/dvr/trusted_uids.h>
 #include <sys/poll.h>
 
 #include <array>
 
+using android::dvr::display::DisplayManagerProtocol;
 using android::pdx::Channel;
 using android::pdx::LocalChannelHandle;
 using android::pdx::Message;
 using android::pdx::default_transport::Endpoint;
+using android::pdx::ErrorStatus;
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::rpc::IfAnyOf;
-
-namespace {
-
-// As a first line of defense, the display manager endpoint is only accessible
-// to the user and group.
-
-// TODO(dnicoara): Remove read/write permission for others. This is in here just
-// to allow us to experiment with cast functionality from a plain old app.
-constexpr mode_t kDisplayManagerEndpointFileMode =
-    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-
-constexpr size_t kMaxSurfacesPerRequest = 32;
-
-}  // anonymous namespace
+using android::pdx::rpc::RemoteMethodError;
 
 namespace android {
 namespace dvr {
@@ -45,8 +34,7 @@
 DisplayManagerService::DisplayManagerService(
     const std::shared_ptr<DisplayService>& display_service)
     : BASE("DisplayManagerService",
-           Endpoint::Create(DisplayManagerRPC::kClientPath,
-                            kDisplayManagerEndpointFileMode)),
+           Endpoint::Create(DisplayManagerProtocol::kClientPath)),
       display_service_(display_service) {
   display_service_->SetDisplayConfigurationUpdateNotifier(
       std::bind(&DisplayManagerService::OnDisplaySurfaceChange, this));
@@ -54,9 +42,15 @@
 
 std::shared_ptr<pdx::Channel> DisplayManagerService::OnChannelOpen(
     pdx::Message& message) {
-  // Prevent more than one display manager from registering at a time.
-  if (display_manager_)
-    REPLY_ERROR_RETURN(message, EPERM, nullptr);
+  const int user_id = message.GetEffectiveUserId();
+  const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+
+  // Prevent more than one display manager from registering at a time or
+  // untrusted UIDs from connecting.
+  if (display_manager_ || !trusted) {
+    RemoteMethodError(message, EPERM);
+    return nullptr;
+  }
 
   display_manager_ =
       std::make_shared<DisplayManager>(this, message.GetChannelId());
@@ -74,18 +68,18 @@
   auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
 
   switch (message.GetOp()) {
-    case DisplayManagerRPC::GetSurfaceList::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::GetSurfaceList>(
-          *this, &DisplayManagerService::OnGetSurfaceList, message);
+    case DisplayManagerProtocol::GetSurfaceState::Opcode:
+      DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceState>(
+          *this, &DisplayManagerService::OnGetSurfaceState, message);
       return {};
 
-    case DisplayManagerRPC::UpdateSurfaces::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::UpdateSurfaces>(
-          *this, &DisplayManagerService::OnUpdateSurfaces, message);
+    case DisplayManagerProtocol::GetSurfaceQueue::Opcode:
+      DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
+          *this, &DisplayManagerService::OnGetSurfaceQueue, message);
       return {};
 
-    case DisplayManagerRPC::SetupNamedBuffer::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+    case DisplayManagerProtocol::SetupNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
           *this, &DisplayManagerService::OnSetupNamedBuffer, message);
       return {};
 
@@ -94,130 +88,67 @@
   }
 }
 
-std::vector<DisplaySurfaceInfo> DisplayManagerService::OnGetSurfaceList(
-    pdx::Message& /*message*/) {
-  std::vector<DisplaySurfaceInfo> items;
+pdx::Status<std::vector<display::SurfaceState>>
+DisplayManagerService::OnGetSurfaceState(pdx::Message& /*message*/) {
+  std::vector<display::SurfaceState> items;
 
   display_service_->ForEachDisplaySurface(
+      SurfaceType::Application,
       [&items](const std::shared_ptr<DisplaySurface>& surface) mutable {
-        DisplaySurfaceInfo item;
-
-        item.surface_id = surface->surface_id();
-        item.process_id = surface->process_id();
-        item.type = surface->type();
-        item.flags = 0;  // TODO(eieio)
-        item.client_attributes = DisplaySurfaceAttributes{
-            {DisplaySurfaceAttributeEnum::Visible,
-             DisplaySurfaceAttributeValue{surface->client_visible()}},
-            {DisplaySurfaceAttributeEnum::ZOrder,
-             DisplaySurfaceAttributeValue{surface->client_z_order()}},
-            {DisplaySurfaceAttributeEnum::Blur,
-             DisplaySurfaceAttributeValue{0.f}}};
-        item.manager_attributes = DisplaySurfaceAttributes{
-            {DisplaySurfaceAttributeEnum::Visible,
-             DisplaySurfaceAttributeValue{surface->manager_visible()}},
-            {DisplaySurfaceAttributeEnum::ZOrder,
-             DisplaySurfaceAttributeValue{surface->manager_z_order()}},
-            {DisplaySurfaceAttributeEnum::Blur,
-             DisplaySurfaceAttributeValue{surface->manager_blur()}}};
-
-        items.push_back(item);
+        items.push_back({surface->surface_id(), surface->process_id(),
+                         surface->user_id(), surface->attributes(),
+                         surface->update_flags(), surface->GetQueueIds()});
+        surface->ClearUpdate();
       });
 
   // The fact that we're in the message handler implies that display_manager_ is
   // not nullptr. No check required, unless this service becomes multi-threaded.
   display_manager_->SetNotificationsPending(false);
-
   return items;
 }
 
-int DisplayManagerService::OnUpdateSurfaces(
-    pdx::Message& /*message*/,
-    const std::map<int, DisplaySurfaceAttributes>& updates) {
-  for (const auto& surface_update : updates) {
-    const int surface_id = surface_update.first;
-    const DisplaySurfaceAttributes& attributes = surface_update.second;
+pdx::Status<pdx::LocalChannelHandle> DisplayManagerService::OnGetSurfaceQueue(
+    pdx::Message& /*message*/, int surface_id, int queue_id) {
+  auto surface = display_service_->GetDisplaySurface(surface_id);
+  if (!surface || surface->surface_type() != SurfaceType::Application)
+    return ErrorStatus(EINVAL);
 
-    std::shared_ptr<DisplaySurface> surface =
-        display_service_->GetDisplaySurface(surface_id);
+  auto queue =
+      std::static_pointer_cast<ApplicationDisplaySurface>(surface)->GetQueue(
+          queue_id);
+  if (!queue)
+    return ErrorStatus(EINVAL);
 
-    if (!surface)
-      return -ENOENT;
+  auto status = queue->CreateConsumerQueueHandle();
+  ALOGE_IF(
+      !status,
+      "DisplayManagerService::OnGetSurfaceQueue: Failed to create consumer "
+      "queue for queue_id=%d: %s",
+      queue->id(), status.GetErrorMessage().c_str());
 
-    for (const auto& attribute : attributes) {
-      const auto& key = attribute.first;
-      const auto* variant = &attribute.second;
-      bool invalid_value = false;
-      switch (key) {
-        case DisplaySurfaceAttributeEnum::ZOrder:
-          invalid_value =
-              !IfAnyOf<int32_t>::Call(variant, [&surface](const auto& value) {
-                surface->ManagerSetZOrder(value);
-              });
-          break;
-        case DisplaySurfaceAttributeEnum::Visible:
-          invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
-              variant, [&surface](const auto& value) {
-                surface->ManagerSetVisible(value);
-              });
-          break;
-        case DisplaySurfaceAttributeEnum::Blur:
-          invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
-              variant, [&surface](const auto& value) {
-                surface->ManagerSetBlur(value);
-              });
-          break;
-        default:
-          ALOGW(
-              "DisplayManagerService::OnUpdateSurfaces: Attempt to set invalid "
-              "attribute %u on surface %d",
-              key, surface_id);
-          break;
-      }
-
-      if (invalid_value) {
-        ALOGW(
-            "DisplayManagerService::OnUpdateSurfaces: Failed to set display "
-            "surface attribute '%s' because of incompatible type: %d",
-            DisplaySurfaceAttributeEnum::ToString(key).c_str(),
-            variant->index());
-      }
-    }
-  }
-
-  // Reconfigure the display layers for any active surface changes.
-  display_service_->UpdateActiveDisplaySurfaces();
-  return 0;
+  return status;
 }
 
 pdx::Status<BorrowedNativeBufferHandle>
 DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
                                           const std::string& name, size_t size,
-                                          uint64_t producer_usage,
-                                          uint64_t consumer_usage) {
-  if (message.GetEffectiveUserId() != AID_ROOT &&
-      !IsTrustedUid(message.GetEffectiveUserId())) {
-    // Only trusted users can setup named buffers.
-    ALOGE("DisplayService::SetupNamedBuffer: Called by untrusted user: uid=%d.",
-          message.GetEffectiveUserId());
-    return {};
+                                          uint64_t usage) {
+  const int user_id = message.GetEffectiveUserId();
+  const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+
+  if (!trusted) {
+    ALOGE(
+        "DisplayService::SetupNamedBuffer: Named buffers may only be created "
+        "by trusted UIDs: user_id=%d",
+        user_id);
+    return ErrorStatus(EPERM);
   }
-  return display_service_->SetupNamedBuffer(name, size, producer_usage,
-                                            consumer_usage);
+  return display_service_->SetupNamedBuffer(name, size, usage);
 }
 
 void DisplayManagerService::OnDisplaySurfaceChange() {
-  if (display_manager_) {
+  if (display_manager_)
     display_manager_->SetNotificationsPending(true);
-  } else {
-    // If there isn't a display manager registered, default all display surfaces
-    // to visible.
-    display_service_->ForEachDisplaySurface(
-        [](const std::shared_ptr<DisplaySurface>& surface) {
-          surface->ManagerSetVisible(true);
-        });
-    display_service_->UpdateActiveDisplaySurfaces();
-  }
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 7b037de..0857eb5 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -1,8 +1,9 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
+#ifndef ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
+#define ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
 
 #include <pdx/service.h>
-#include <private/dvr/display_rpc.h>
+#include <pdx/status.h>
+#include <private/dvr/display_protocol.h>
 
 #include "display_service.h"
 
@@ -50,13 +51,14 @@
   explicit DisplayManagerService(
       const std::shared_ptr<DisplayService>& display_service);
 
-  std::vector<DisplaySurfaceInfo> OnGetSurfaceList(pdx::Message& message);
-  int OnUpdateSurfaces(pdx::Message& message,
-                       const std::map<int, DisplaySurfaceAttributes>& updates);
-
+  pdx::Status<std::vector<display::SurfaceState>> OnGetSurfaceState(
+      pdx::Message& message);
+  pdx::Status<pdx::LocalChannelHandle> OnGetSurfaceQueue(pdx::Message& message,
+                                                         int surface_id,
+                                                         int queue_id);
   pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
       pdx::Message& message, const std::string& name, size_t size,
-      uint64_t producer_usage, uint64_t consumer_usage);
+      uint64_t usage);
 
   // Called by the display service to indicate changes to display surfaces that
   // the display manager should evaluate.
@@ -72,4 +74,4 @@
 }  // namespace dvr
 }  // namespace android
 
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
+#endif  // ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index d3d50d0..47efa76 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -3,30 +3,30 @@
 #include <unistd.h>
 #include <vector>
 
+#include <dvr/dvr_display_types.h>
 #include <pdx/default_transport/service_endpoint.h>
 #include <pdx/rpc/remote_method.h>
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/device_metrics.h>
-#include <private/dvr/display_rpc.h>
-#include <private/dvr/display_types.h>
+#include <private/dvr/display_protocol.h>
 #include <private/dvr/numeric.h>
-#include <private/dvr/polynomial_radial_distortion.h>
 #include <private/dvr/types.h>
 
+using android::dvr::display::DisplayProtocol;
 using android::pdx::Channel;
+using android::pdx::ErrorStatus;
 using android::pdx::Message;
+using android::pdx::Status;
 using android::pdx::default_transport::Endpoint;
 using android::pdx::rpc::DispatchRemoteMethod;
-using android::pdx::rpc::WrapBuffer;
 
 namespace android {
 namespace dvr {
 
-DisplayService::DisplayService() : DisplayService(nullptr) {}
-
-DisplayService::DisplayService(Hwc2::Composer* hidl)
-    : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
-      hardware_composer_(hidl) {
+DisplayService::DisplayService(Hwc2::Composer* hidl,
+                               RequestDisplayCallback request_display_callback)
+    : BASE("DisplayService",
+           Endpoint::Create(display::DisplayProtocol::kClientPath)),
+      hardware_composer_(hidl, request_display_callback),
+      request_display_callback_(request_display_callback) {
   hardware_composer_.Initialize();
 }
 
@@ -34,68 +34,51 @@
   return BASE::IsInitialized() && hardware_composer_.IsInitialized();
 }
 
-std::string DisplayService::DumpState(size_t max_length) {
-  std::vector<char> buffer(max_length);
-  uint32_t max_len_p = static_cast<uint32_t>(max_length);
-  hardware_composer_.Dump(buffer.data(), &max_len_p);
-  return std::string(buffer.data());
+std::string DisplayService::DumpState(size_t /*max_length*/) {
+  return hardware_composer_.Dump();
 }
 
-void DisplayService::OnChannelClose(pdx::Message& /*message*/,
+void DisplayService::OnChannelClose(pdx::Message& message,
                                     const std::shared_ptr<Channel>& channel) {
-  auto surface = std::static_pointer_cast<SurfaceChannel>(channel);
-  if (surface && surface->type() == SurfaceTypeEnum::Normal) {
-    auto display_surface = std::static_pointer_cast<DisplaySurface>(surface);
-    display_surface->ManagerSetVisible(false);
-    display_surface->ClientSetVisible(false);
-    NotifyDisplayConfigurationUpdate();
+  if (auto surface = std::static_pointer_cast<DisplaySurface>(channel)) {
+    surface->OnSetAttributes(message,
+                             {{display::SurfaceAttribute::Visible,
+                               display::SurfaceAttributeValue{false}}});
+    SurfaceUpdated(surface->surface_type(),
+                   display::SurfaceUpdateFlags::VisibilityChanged);
   }
-  // TODO(jwcai) Handle ChannelClose of VideoMeshSurface.
 }
 
 // First-level dispatch for display service messages. Directly handles messages
 // that are independent of the display surface (metrics, creation) and routes
 // surface-specific messages to the per-instance handlers.
-pdx::Status<void> DisplayService::HandleMessage(pdx::Message& message) {
-  auto channel = message.GetChannel<SurfaceChannel>();
-
+Status<void> DisplayService::HandleMessage(pdx::Message& message) {
+  ALOGD_IF(TRACE, "DisplayService::HandleMessage: opcode=%d", message.GetOp());
   switch (message.GetOp()) {
-    case DisplayRPC::GetMetrics::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetMetrics>(
+    case DisplayProtocol::GetMetrics::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetMetrics>(
           *this, &DisplayService::OnGetMetrics, message);
       return {};
 
-    case DisplayRPC::GetEdsCapture::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetEdsCapture>(
-          *this, &DisplayService::OnGetEdsCapture, message);
-      return {};
-
-    case DisplayRPC::CreateSurface::Opcode:
-      DispatchRemoteMethod<DisplayRPC::CreateSurface>(
+    case DisplayProtocol::CreateSurface::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::CreateSurface>(
           *this, &DisplayService::OnCreateSurface, message);
       return {};
 
-    case DisplayRPC::SetViewerParams::Opcode:
-      DispatchRemoteMethod<DisplayRPC::SetViewerParams>(
-          *this, &DisplayService::OnSetViewerParams, message);
-      return {};
-
-    case DisplayRPC::GetNamedBuffer::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetNamedBuffer>(
+    case DisplayProtocol::GetNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetNamedBuffer>(
           *this, &DisplayService::OnGetNamedBuffer, message);
       return {};
 
-    case DisplayRPC::IsVrAppRunning::Opcode:
-      DispatchRemoteMethod<DisplayRPC::IsVrAppRunning>(
+    case DisplayProtocol::IsVrAppRunning::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::IsVrAppRunning>(
           *this, &DisplayService::IsVrAppRunning, message);
       return {};
 
     // Direct the surface specific messages to the surface instance.
-    case DisplayRPC::CreateBufferQueue::Opcode:
-    case DisplayRPC::SetAttributes::Opcode:
-    case DisplayRPC::GetMetadataBuffer::Opcode:
-    case DisplayRPC::CreateVideoMeshSurface::Opcode:
-    case DisplayRPC::VideoMeshSurfaceCreateProducerQueue::Opcode:
+    case DisplayProtocol::SetAttributes::Opcode:
+    case DisplayProtocol::CreateQueue::Opcode:
+    case DisplayProtocol::GetSurfaceInfo::Opcode:
       return HandleSurfaceMessage(message);
 
     default:
@@ -103,49 +86,29 @@
   }
 }
 
-SystemDisplayMetrics DisplayService::OnGetMetrics(pdx::Message& message) {
-  const Compositor* compositor = hardware_composer_.GetCompositor();
-  if (compositor == nullptr)
-    REPLY_ERROR_RETURN(message, EINVAL, {});
-
-  HeadMountMetrics head_mount = compositor->head_mount_metrics();
-  CompositeHmd hmd(head_mount, hardware_composer_.GetHmdDisplayMetrics());
-  vec2i distorted_render_size = hmd.GetRecommendedRenderTargetSize();
-  FieldOfView left_fov = hmd.GetEyeFov(kLeftEye);
-  FieldOfView right_fov = hmd.GetEyeFov(kRightEye);
-
-  SystemDisplayMetrics metrics;
-
-  metrics.display_native_width = GetDisplayMetrics().width;
-  metrics.display_native_height = GetDisplayMetrics().height;
-  metrics.display_x_dpi = GetDisplayMetrics().dpi.x;
-  metrics.display_y_dpi = GetDisplayMetrics().dpi.y;
-  metrics.distorted_width = distorted_render_size[0];
-  metrics.distorted_height = distorted_render_size[1];
-  metrics.vsync_period_ns =
-      hardware_composer_.native_display_metrics().vsync_period_ns;
-  metrics.hmd_ipd_mm = 0;
-  metrics.inter_lens_distance_m = head_mount.GetInterLensDistance();
-  metrics.left_fov_lrbt[0] = left_fov.GetLeft();
-  metrics.left_fov_lrbt[1] = left_fov.GetRight();
-  metrics.left_fov_lrbt[2] = left_fov.GetBottom();
-  metrics.left_fov_lrbt[3] = left_fov.GetTop();
-  metrics.right_fov_lrbt[0] = right_fov.GetLeft();
-  metrics.right_fov_lrbt[1] = right_fov.GetRight();
-  metrics.right_fov_lrbt[2] = right_fov.GetBottom();
-  metrics.right_fov_lrbt[3] = right_fov.GetTop();
-
-  return metrics;
+Status<display::Metrics> DisplayService::OnGetMetrics(
+    pdx::Message& /*message*/) {
+  return {{static_cast<uint32_t>(GetDisplayMetrics().width),
+           static_cast<uint32_t>(GetDisplayMetrics().height),
+           static_cast<uint32_t>(GetDisplayMetrics().dpi.x),
+           static_cast<uint32_t>(GetDisplayMetrics().dpi.y),
+           static_cast<uint32_t>(
+               hardware_composer_.native_display_metrics().vsync_period_ns),
+           0,
+           0,
+           0,
+           0.0,
+           {},
+           {}}};
 }
 
 // Creates a new DisplaySurface and associates it with this channel. This may
 // only be done once per channel.
-int DisplayService::OnCreateSurface(pdx::Message& message, int width,
-                                    int height, int format, int usage,
-                                    DisplaySurfaceFlags flags) {
+Status<display::SurfaceInfo> DisplayService::OnCreateSurface(
+    pdx::Message& message, const display::SurfaceAttributes& attributes) {
   // A surface may only be created once per channel.
   if (message.GetChannel())
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
 
   ALOGI_IF(TRACE, "DisplayService::OnCreateSurface: cid=%d",
            message.GetChannelId());
@@ -153,119 +116,66 @@
   // Use the channel id as the unique surface id.
   const int surface_id = message.GetChannelId();
   const int process_id = message.GetProcessId();
+  const int user_id = message.GetEffectiveUserId();
 
   ALOGI_IF(TRACE,
-           "DisplayService::OnCreateSurface: surface_id=%d process_id=%d "
-           "width=%d height=%d format=%x usage=%x flags=%x",
-           surface_id, process_id, width, height, format, usage, flags);
+           "DisplayService::OnCreateSurface: surface_id=%d process_id=%d",
+           surface_id, process_id);
 
-  // TODO(eieio,jbates): Validate request parameters.
-  auto channel = std::make_shared<DisplaySurface>(
-      this, surface_id, process_id, width, height, format, usage, flags);
+  auto surface_status =
+      DisplaySurface::Create(this, surface_id, process_id, user_id, attributes);
+  if (!surface_status) {
+    ALOGE("DisplayService::OnCreateSurface: Failed to create surface: %s",
+          surface_status.GetErrorMessage().c_str());
+    return ErrorStatus(surface_status.error());
+  }
 
-  message.SetChannel(channel);
-  NotifyDisplayConfigurationUpdate();
-  return 0;
+  SurfaceType surface_type = surface_status.get()->surface_type();
+  display::SurfaceUpdateFlags update_flags =
+      surface_status.get()->update_flags();
+  display::SurfaceInfo surface_info{surface_status.get()->surface_id(),
+                                    surface_status.get()->visible(),
+                                    surface_status.get()->z_order()};
+
+  message.SetChannel(surface_status.take());
+
+  SurfaceUpdated(surface_type, update_flags);
+  return {surface_info};
 }
 
-DisplayRPC::ByteBuffer DisplayService::OnGetEdsCapture(pdx::Message& message) {
-  Compositor* compositor = hardware_composer_.GetCompositor();
-  if (compositor == nullptr)
-    REPLY_ERROR_RETURN(message, EINVAL, {});
-
-  std::vector<std::uint8_t> buffer(sizeof(LateLatchOutput));
-
-  if (!compositor->GetLastEdsPose(
-          reinterpret_cast<LateLatchOutput*>(buffer.data()))) {
-    REPLY_ERROR_RETURN(message, EPERM, {});
+void DisplayService::SurfaceUpdated(SurfaceType surface_type,
+                                    display::SurfaceUpdateFlags update_flags) {
+  ALOGD_IF(TRACE, "DisplayService::SurfaceUpdated: update_flags=%x",
+           update_flags.value());
+  if (update_flags.value() != 0) {
+    if (surface_type == SurfaceType::Application)
+      NotifyDisplayConfigurationUpdate();
+    else
+      UpdateActiveDisplaySurfaces();
   }
-
-  return WrapBuffer(std::move(buffer));
-}
-
-void DisplayService::OnSetViewerParams(pdx::Message& message,
-                                       const ViewerParams& view_params) {
-  Compositor* compositor = hardware_composer_.GetCompositor();
-  if (compositor == nullptr)
-    REPLY_ERROR_RETURN(message, EINVAL);
-
-  FieldOfView left(55.0f, 55.0f, 55.0f, 55.0f);
-  FieldOfView right(55.0f, 55.0f, 55.0f, 55.0f);
-  if (view_params.left_eye_field_of_view_angles.size() >= 4) {
-    left = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[0]),
-                       ToRad(view_params.left_eye_field_of_view_angles[1]),
-                       ToRad(view_params.left_eye_field_of_view_angles[2]),
-                       ToRad(view_params.left_eye_field_of_view_angles[3]));
-    right = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[1]),
-                        ToRad(view_params.left_eye_field_of_view_angles[0]),
-                        ToRad(view_params.left_eye_field_of_view_angles[2]),
-                        ToRad(view_params.left_eye_field_of_view_angles[3]));
-  }
-
-  std::shared_ptr<ColorChannelDistortion> red_distortion;
-  std::shared_ptr<ColorChannelDistortion> green_distortion;
-  std::shared_ptr<ColorChannelDistortion> blue_distortion;
-
-  // We should always have a red distortion.
-  LOG_FATAL_IF(view_params.distortion_coefficients_r.empty());
-  red_distortion = std::make_shared<PolynomialRadialDistortion>(
-      view_params.distortion_coefficients_r);
-
-  if (!view_params.distortion_coefficients_g.empty()) {
-    green_distortion = std::make_shared<PolynomialRadialDistortion>(
-        view_params.distortion_coefficients_g);
-  }
-
-  if (!view_params.distortion_coefficients_b.empty()) {
-    blue_distortion = std::make_shared<PolynomialRadialDistortion>(
-        view_params.distortion_coefficients_b);
-  }
-
-  HeadMountMetrics::EyeOrientation left_orientation =
-      HeadMountMetrics::EyeOrientation::kCCW0Degrees;
-  HeadMountMetrics::EyeOrientation right_orientation =
-      HeadMountMetrics::EyeOrientation::kCCW0Degrees;
-
-  if (view_params.eye_orientations.size() > 1) {
-    left_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
-        view_params.eye_orientations[0]);
-    right_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
-        view_params.eye_orientations[1]);
-  }
-
-  HeadMountMetrics head_mount_metrics(
-      view_params.inter_lens_distance, view_params.tray_to_lens_distance,
-      view_params.screen_to_lens_distance,
-      static_cast<HeadMountMetrics::VerticalAlignment>(
-          view_params.vertical_alignment),
-      left, right, red_distortion, green_distortion, blue_distortion,
-      left_orientation, right_orientation,
-      view_params.screen_center_to_lens_distance);
-
-  compositor->UpdateHeadMountMetrics(head_mount_metrics);
 }
 
 pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
     pdx::Message& /* message */, const std::string& name) {
+  ALOGD_IF(TRACE, "displayService::OnGetNamedBuffer: name=%s", name.c_str());
   auto named_buffer = named_buffers_.find(name);
-  if (named_buffer != named_buffers_.end()) {
+  if (named_buffer != named_buffers_.end())
     return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
-  }
-
-  return pdx::ErrorStatus(EINVAL);
+  else
+    return pdx::ErrorStatus(EINVAL);
 }
 
 // Calls the message handler for the DisplaySurface associated with this
 // channel.
-pdx::Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
-  auto surface = std::static_pointer_cast<SurfaceChannel>(message.GetChannel());
+Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
+  auto surface = std::static_pointer_cast<DisplaySurface>(message.GetChannel());
   ALOGW_IF(!surface,
            "DisplayService::HandleSurfaceMessage: surface is nullptr!");
 
   if (surface)
     return surface->HandleMessage(message);
   else
-    REPLY_ERROR_RETURN(message, EINVAL, {});
+    return ErrorStatus(EINVAL);
 }
 
 std::shared_ptr<DisplaySurface> DisplayService::GetDisplaySurface(
@@ -278,14 +188,18 @@
   return GetChannels<DisplaySurface>();
 }
 
-std::vector<std::shared_ptr<DisplaySurface>>
+std::vector<std::shared_ptr<DirectDisplaySurface>>
 DisplayService::GetVisibleDisplaySurfaces() const {
-  std::vector<std::shared_ptr<DisplaySurface>> visible_surfaces;
+  std::vector<std::shared_ptr<DirectDisplaySurface>> visible_surfaces;
 
   ForEachDisplaySurface(
+      SurfaceType::Direct,
       [&](const std::shared_ptr<DisplaySurface>& surface) mutable {
-        if (surface->IsVisible())
-          visible_surfaces.push_back(surface);
+        if (surface->visible()) {
+          visible_surfaces.push_back(
+              std::static_pointer_cast<DirectDisplaySurface>(surface));
+          surface->ClearUpdate();
+        }
       });
 
   return visible_surfaces;
@@ -294,46 +208,25 @@
 void DisplayService::UpdateActiveDisplaySurfaces() {
   auto visible_surfaces = GetVisibleDisplaySurfaces();
 
-  // Sort the surfaces based on manager z order first, then client z order.
   std::sort(visible_surfaces.begin(), visible_surfaces.end(),
             [](const std::shared_ptr<DisplaySurface>& a,
                const std::shared_ptr<DisplaySurface>& b) {
-              return a->manager_z_order() != b->manager_z_order()
-                         ? a->manager_z_order() < b->manager_z_order()
-                         : a->client_z_order() < b->client_z_order();
+              return a->z_order() < b->z_order();
             });
 
   ALOGD_IF(TRACE,
            "DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces",
            visible_surfaces.size());
 
-  // TODO(jbates) Have the shell manage blurred layers.
-  bool blur_requested = false;
-  auto end = visible_surfaces.crend();
-  for (auto it = visible_surfaces.crbegin(); it != end; ++it) {
-    auto surface = *it;
-    // Surfaces with exclude_from_blur==true are not blurred
-    // and are excluded from blur computation of other layers.
-    if (surface->client_exclude_from_blur()) {
-      surface->ManagerSetBlur(0.0f);
-      continue;
-    }
-    surface->ManagerSetBlur(blur_requested ? 1.0f : 0.0f);
-    if (surface->client_blur_behind())
-      blur_requested = true;
-  }
-
   hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
 pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
-    const std::string& name, size_t size, int producer_usage,
-    int consumer_usage) {
+    const std::string& name, size_t size, uint64_t usage) {
   auto named_buffer = named_buffers_.find(name);
   if (named_buffer == named_buffers_.end()) {
-    auto ion_buffer = std::make_unique<IonBuffer>(
-        static_cast<int>(size), 1, HAL_PIXEL_FORMAT_BLOB, producer_usage,
-        consumer_usage);
+    auto ion_buffer = std::make_unique<IonBuffer>(static_cast<int>(size), 1,
+                                                  HAL_PIXEL_FORMAT_BLOB, usage);
     named_buffer =
         named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
             .first;
@@ -356,15 +249,16 @@
     update_notifier_();
 }
 
-int DisplayService::IsVrAppRunning(pdx::Message& message) {
+Status<bool> DisplayService::IsVrAppRunning(pdx::Message& /*message*/) {
   bool visible = false;
   ForEachDisplaySurface(
+      SurfaceType::Application,
       [&visible](const std::shared_ptr<DisplaySurface>& surface) {
-        if (surface->client_z_order() == 0 && surface->IsVisible())
+        if (surface->visible())
           visible = true;
       });
 
-  REPLY_SUCCESS_RETURN(message, visible, 0);
+  return {visible};
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index db89064..bb4eeef 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -2,10 +2,10 @@
 #define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
 
 #include <pdx/service.h>
+#include <pdx/status.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/bufferhub_rpc.h>
-#include <private/dvr/display_rpc.h>
-#include <private/dvr/late_latch.h>
+#include <private/dvr/display_protocol.h>
 
 #include <functional>
 #include <iterator>
@@ -15,12 +15,13 @@
 
 #include "acquired_buffer.h"
 #include "display_surface.h"
+#include "epoll_event_dispatcher.h"
 #include "hardware_composer.h"
 
 namespace android {
 namespace dvr {
 
-// DisplayService implements the displayd display service over ServiceFS.
+// DisplayService implements the display service component of VrFlinger.
 class DisplayService : public pdx::ServiceBase<DisplayService> {
  public:
   bool IsInitialized() const override;
@@ -32,7 +33,7 @@
 
   std::shared_ptr<DisplaySurface> GetDisplaySurface(int surface_id) const;
   std::vector<std::shared_ptr<DisplaySurface>> GetDisplaySurfaces() const;
-  std::vector<std::shared_ptr<DisplaySurface>> GetVisibleDisplaySurfaces()
+  std::vector<std::shared_ptr<DirectDisplaySurface>> GetVisibleDisplaySurfaces()
       const;
 
   // Updates the list of actively displayed surfaces. This must be called after
@@ -40,15 +41,15 @@
   void UpdateActiveDisplaySurfaces();
 
   pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
-      const std::string& name, size_t size, int producer_usage,
-      int consumer_usage);
+      const std::string& name, size_t size, uint64_t usage);
 
   template <class A>
-  void ForEachDisplaySurface(A action) const {
-    ForEachChannel([action](const ChannelIterator::value_type& pair) mutable {
-      auto surface = std::static_pointer_cast<SurfaceChannel>(pair.second);
-      if (surface->type() == SurfaceTypeEnum::Normal)
-        action(std::static_pointer_cast<DisplaySurface>(surface));
+  void ForEachDisplaySurface(SurfaceType surface_type, A action) const {
+    ForEachChannel([surface_type,
+                    action](const ChannelIterator::value_type& pair) mutable {
+      auto surface = std::static_pointer_cast<DisplaySurface>(pair.second);
+      if (surface->surface_type() == surface_type)
+        action(surface);
     });
   }
 
@@ -76,22 +77,30 @@
 
   friend class VrDisplayStateService;
 
-  DisplayService();
-  DisplayService(android::Hwc2::Composer* hidl);
+  using RequestDisplayCallback = std::function<void(bool)>;
 
-  SystemDisplayMetrics OnGetMetrics(pdx::Message& message);
-  int OnCreateSurface(pdx::Message& message, int width, int height, int format,
-                      int usage, DisplaySurfaceFlags flags);
+  DisplayService(android::Hwc2::Composer* hidl,
+                 RequestDisplayCallback request_display_callback);
 
-  DisplayRPC::ByteBuffer OnGetEdsCapture(pdx::Message& message);
-
-  void OnSetViewerParams(pdx::Message& message,
-                         const ViewerParams& view_params);
   pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
       pdx::Message& message, const std::string& name);
+  pdx::Status<display::Metrics> OnGetMetrics(pdx::Message& message);
+  pdx::Status<display::SurfaceInfo> OnCreateSurface(
+      pdx::Message& message, const display::SurfaceAttributes& attributes);
 
   // Temporary query for current VR status. Will be removed later.
-  int IsVrAppRunning(pdx::Message& message);
+  pdx::Status<bool> IsVrAppRunning(pdx::Message& message);
+
+  pdx::Status<void> AddEventHandler(int fd, int events,
+                                    EpollEventDispatcher::Handler handler) {
+    return dispatcher_.AddEventHandler(fd, events, handler);
+  }
+  pdx::Status<void> RemoveEventHandler(int fd) {
+    return dispatcher_.RemoveEventHandler(fd);
+  }
+
+  void SurfaceUpdated(SurfaceType surface_type,
+                      display::SurfaceUpdateFlags update_flags);
 
   // Called by DisplaySurface to signal that a surface property has changed and
   // the display manager should be notified.
@@ -99,13 +108,15 @@
 
   pdx::Status<void> HandleSurfaceMessage(pdx::Message& message);
 
-  DisplayService(const DisplayService&) = delete;
-  void operator=(const DisplayService&) = delete;
-
   HardwareComposer hardware_composer_;
+  RequestDisplayCallback request_display_callback_;
+  EpollEventDispatcher dispatcher_;
   DisplayConfigurationUpdateNotifier update_notifier_;
 
   std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
+
+  DisplayService(const DisplayService&) = delete;
+  void operator=(const DisplayService&) = delete;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index a7220fe..5829788 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -1,16 +1,21 @@
 #include "display_surface.h"
 
+#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"
 #include "hardware_composer.h"
 
 #define LOCAL_TRACE 1
 
+using android::dvr::display::DisplayProtocol;
 using android::pdx::BorrowedChannelHandle;
+using android::pdx::ErrorStatus;
 using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
 using android::pdx::Message;
 using android::pdx::RemoteChannelHandle;
 using android::pdx::Status;
@@ -20,104 +25,320 @@
 namespace android {
 namespace dvr {
 
-DisplaySurface::DisplaySurface(DisplayService* service, int surface_id,
-                               int process_id, int width, int height,
-                               int format, int usage, int flags)
-    : SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal,
-                     sizeof(DisplaySurfaceMetadata)),
+DisplaySurface::DisplaySurface(DisplayService* service,
+                               SurfaceType surface_type, int surface_id,
+                               int process_id, int user_id,
+                               const display::SurfaceAttributes& attributes)
+    : service_(service),
+      surface_type_(surface_type),
+      surface_id_(surface_id),
       process_id_(process_id),
-      acquired_buffers_(kMaxPostedBuffers),
-      video_mesh_surfaces_updated_(false),
-      width_(width),
-      height_(height),
-      format_(format),
-      usage_(usage),
-      flags_(flags),
-      client_visible_(false),
-      client_z_order_(0),
-      client_exclude_from_blur_(false),
-      client_blur_behind_(false),
-      manager_visible_(false),
-      manager_z_order_(0),
-      manager_blur_(0.0f),
-      layer_order_(0),
-      allocated_buffer_index_(0) {}
+      user_id_(user_id),
+      attributes_(attributes),
+      update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
 
 DisplaySurface::~DisplaySurface() {
   ALOGD_IF(LOCAL_TRACE,
            "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
-           surface_id(), process_id_);
+           surface_id(), process_id());
 }
 
-void DisplaySurface::ManagerSetVisible(bool visible) {
+Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
+  switch (message.GetOp()) {
+    case DisplayProtocol::SetAttributes::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::SetAttributes>(
+          *this, &DisplaySurface::OnSetAttributes, message);
+      break;
+
+    case DisplayProtocol::GetSurfaceInfo::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetSurfaceInfo>(
+          *this, &DisplaySurface::OnGetSurfaceInfo, message);
+      break;
+
+    case DisplayProtocol::CreateQueue::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::CreateQueue>(
+          *this, &DisplaySurface::OnCreateQueue, message);
+      break;
+  }
+
+  return {};
+}
+
+Status<void> DisplaySurface::OnSetAttributes(
+    pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) {
+  display::SurfaceUpdateFlags update_flags;
+
+  for (const auto& attribute : attributes) {
+    const auto& key = attribute.first;
+    const auto* variant = &attribute.second;
+    bool invalid_value = false;
+    bool visibility_changed = false;
+
+    // Catch attributes that have significance to the display service.
+    switch (key) {
+      case display::SurfaceAttribute::ZOrder:
+        invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
+            variant, [&](const auto& value) {
+              if (z_order_ != value) {
+                visibility_changed = true;
+                z_order_ = value;
+              }
+            });
+        break;
+      case display::SurfaceAttribute::Visible:
+        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
+            variant, [&](const auto& value) {
+              if (visible_ != value) {
+                visibility_changed = true;
+                visible_ = value;
+              }
+            });
+        break;
+    }
+
+    if (invalid_value) {
+      ALOGW(
+          "DisplaySurface::OnClientSetAttributes: Failed to set display "
+          "surface attribute '%d' because of incompatible type: %d",
+          key, variant->index());
+    } else {
+      // Only update the attribute map with valid values.
+      attributes_[attribute.first] = attribute.second;
+
+      // All attribute changes generate a notification, even if the value
+      // doesn't change. Visibility attributes set a flag only if the value
+      // changes.
+      update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged);
+      if (visibility_changed)
+        update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged);
+    }
+  }
+
+  SurfaceUpdated(update_flags);
+  return {};
+}
+
+void DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) {
+  ALOGD_IF(TRACE,
+           "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x",
+           surface_id(), update_flags.value());
+
+  update_flags_.Set(update_flags);
+  service()->SurfaceUpdated(surface_type(), update_flags_);
+}
+
+void DisplaySurface::ClearUpdate() {
+  ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id());
+  update_flags_ = display::SurfaceUpdateFlags::None;
+}
+
+Status<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo(
+    Message& /*message*/) {
+  ALOGD_IF(
+      TRACE,
+      "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d",
+      surface_id(), visible(), z_order());
+  return {{surface_id(), visible(), z_order()}};
+}
+
+Status<void> DisplaySurface::RegisterQueue(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue) {
+  ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d",
+           surface_id(), consumer_queue->id());
+  // Capture references for the lambda to work around apparent clang bug.
+  // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when
+  // capturing self and consumer_queue by copy in the following case:
+  //    auto self = Self();
+  //    [self, consumer_queue](int events) {
+  //        self->OnQueueEvent(consuemr_queue, events); }
+  //
+  struct State {
+    std::shared_ptr<DisplaySurface> surface;
+    std::shared_ptr<ConsumerQueue> queue;
+  };
+  State state{Self(), consumer_queue};
+
+  return service()->AddEventHandler(
+      consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET,
+      [state](int events) {
+        state.surface->OnQueueEvent(state.queue, events);
+      });
+}
+
+Status<void> DisplaySurface::UnregisterQueue(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue) {
+  ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d",
+           surface_id(), consumer_queue->id());
+  return service()->RemoveEventHandler(consumer_queue->queue_fd());
+}
+
+void DisplaySurface::OnQueueEvent(
+    const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) {
+  ALOGE(
+      "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be "
+      "called!!!");
+}
+
+std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
+    int32_t queue_id) {
+  ALOGD_IF(TRACE,
+           "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
+           surface_id(), queue_id);
+
+  auto search = consumer_queues_.find(queue_id);
+  if (search != consumer_queues_.end())
+    return search->second;
+  else
+    return nullptr;
+}
+
+std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
+  std::vector<int32_t> queue_ids;
+  for (const auto& entry : consumer_queues_)
+    queue_ids.push_back(entry.first);
+  return queue_ids;
+}
+
+Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
+    Message& /*message*/, size_t meta_size_bytes) {
+  ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
+  ALOGD_IF(TRACE,
+           "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
+           "meta_size_bytes=%zu",
+           surface_id(), meta_size_bytes);
+
   std::lock_guard<std::mutex> autolock(lock_);
-  manager_visible_ = visible;
-}
-
-void DisplaySurface::ManagerSetZOrder(int z_order) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  manager_z_order_ = z_order;
-}
-
-void DisplaySurface::ManagerSetBlur(float blur) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  manager_blur_ = blur;
-}
-
-void DisplaySurface::ClientSetVisible(bool visible) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  client_visible_ = visible;
-}
-
-void DisplaySurface::ClientSetZOrder(int z_order) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  client_z_order_ = z_order;
-}
-
-void DisplaySurface::ClientSetExcludeFromBlur(bool exclude_from_blur) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  client_exclude_from_blur_ = exclude_from_blur;
-}
-
-void DisplaySurface::ClientSetBlurBehind(bool blur_behind) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  client_blur_behind_ = blur_behind;
-}
-
-void DisplaySurface::DequeueBuffersLocked() {
-  if (consumer_queue_ == nullptr) {
+  auto producer = ProducerQueue::Create(meta_size_bytes);
+  if (!producer) {
     ALOGE(
-        "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
+        "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
+        "queue!");
+    return ErrorStatus(ENOMEM);
+  }
+
+  std::shared_ptr<ConsumerQueue> consumer =
+      producer->CreateSilentConsumerQueue();
+  auto status = RegisterQueue(consumer);
+  if (!status) {
+    ALOGE(
+        "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer "
+        "queue: %s",
+        status.GetErrorMessage().c_str());
+    return status.error_status();
+  }
+
+  consumer_queues_[consumer->id()] = std::move(consumer);
+
+  SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
+  return std::move(producer->GetChannelHandle());
+}
+
+void ApplicationDisplaySurface::OnQueueEvent(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
+  ALOGD_IF(TRACE,
+           "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
+           consumer_queue->id(), events);
+
+  // Always give the queue a chance to handle its internal bookkeeping.
+  consumer_queue->HandleQueueEvents();
+
+  // Check for hangup and remove a queue that is no longer needed.
+  std::lock_guard<std::mutex> autolock(lock_);
+  if (consumer_queue->hung_up()) {
+    ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue.");
+    UnregisterQueue(consumer_queue);
+    auto search = consumer_queues_.find(consumer_queue->id());
+    if (search != consumer_queues_.end()) {
+      consumer_queues_.erase(search);
+    } else {
+      ALOGE(
+          "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d",
+          consumer_queue->id());
+    }
+    SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
+  }
+}
+
+Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
+    Message& /*message*/, size_t meta_size_bytes) {
+  ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
+  ALOGD_IF(
+      TRACE,
+      "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
+      surface_id(), meta_size_bytes);
+
+  std::lock_guard<std::mutex> autolock(lock_);
+  if (!direct_queue_) {
+    auto producer = ProducerQueue::Create(meta_size_bytes);
+    if (!producer) {
+      ALOGE(
+          "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
+          "queue!");
+      return ErrorStatus(ENOMEM);
+    }
+
+    direct_queue_ = producer->CreateConsumerQueue();
+    auto status = RegisterQueue(direct_queue_);
+    if (!status) {
+      ALOGE(
+          "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
+          "queue: %s",
+          status.GetErrorMessage().c_str());
+      return status.error_status();
+    }
+
+    return std::move(producer->GetChannelHandle());
+  } else {
+    return ErrorStatus(EALREADY);
+  }
+}
+
+void DirectDisplaySurface::OnQueueEvent(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
+  ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
+           consumer_queue->id(), events);
+
+  // Always give the queue a chance to handle its internal bookkeeping.
+  consumer_queue->HandleQueueEvents();
+
+  // Check for hangup and remove a queue that is no longer needed.
+  std::lock_guard<std::mutex> autolock(lock_);
+  if (consumer_queue->hung_up()) {
+    ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
+    UnregisterQueue(consumer_queue);
+    direct_queue_ = nullptr;
+  }
+}
+
+void DirectDisplaySurface::DequeueBuffersLocked() {
+  if (direct_queue_ == nullptr) {
+    ALOGE(
+        "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
         "initialized.");
     return;
   }
 
-  size_t slot;
-  uint64_t sequence;
   while (true) {
     LocalHandle acquire_fence;
-    auto buffer_consumer =
-        consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
-    if (!buffer_consumer) {
-      ALOGD_IF(TRACE,
-               "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
-               "available buffers.");
+    size_t slot;
+    auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
+    if (!buffer_status) {
+      ALOGD_IF(
+          TRACE && buffer_status.error() == ETIMEDOUT,
+          "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
+      ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+               "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
+               "buffer: %s",
+               buffer_status.GetErrorMessage().c_str());
       return;
     }
+    auto buffer_consumer = buffer_status.take();
 
-    // Save buffer index, associated with the buffer id so that it can be looked
-    // up later.
-    int buffer_id = buffer_consumer->id();
-    if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
-      buffer_id_to_index_[buffer_id] = allocated_buffer_index_;
-      ++allocated_buffer_index_;
-    }
-
-    if (!IsVisible()) {
+    if (!visible()) {
       ATRACE_NAME("DropFrameOnInvisibleSurface");
       ALOGD_IF(TRACE,
-               "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
-               "on invisible surface.",
+               "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
+               "buffer_id=%d on invisible surface.",
                buffer_consumer->id());
       buffer_consumer->Discard();
       continue;
@@ -125,34 +346,34 @@
 
     if (acquired_buffers_.IsFull()) {
       ALOGE(
-          "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
+          "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
           "overwriting.");
       acquired_buffers_.PopBack();
     }
 
     acquired_buffers_.Append(
-        AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
+        AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
   }
 }
 
-AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
+AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
   std::lock_guard<std::mutex> autolock(lock_);
   DequeueBuffersLocked();
 
   if (acquired_buffers_.IsEmpty()) {
     ALOGE(
-        "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
-        "none are posted.");
+        "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
+        "when none are posted.");
     return AcquiredBuffer();
   }
   AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
   acquired_buffers_.PopFront();
-  ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
+  ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p",
            buffer.buffer().get());
   return buffer;
 }
 
-AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
+AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
     AcquiredBuffer* skipped_buffer) {
   std::lock_guard<std::mutex> autolock(lock_);
   DequeueBuffersLocked();
@@ -175,23 +396,13 @@
     if (frames == 2)
       break;
   }
-  ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
+  ALOGD_IF(TRACE,
+           "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
            buffer.buffer().get());
   return buffer;
 }
 
-uint32_t DisplaySurface::GetRenderBufferIndex(int buffer_id) {
-  std::lock_guard<std::mutex> autolock(lock_);
-
-  if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
-    ALOGW("DisplaySurface::GetRenderBufferIndex: unknown buffer_id %d.",
-          buffer_id);
-    return 0;
-  }
-  return buffer_id_to_index_[buffer_id];
-}
-
-bool DisplaySurface::IsBufferAvailable() {
+bool DirectDisplaySurface::IsBufferAvailable() {
   std::lock_guard<std::mutex> autolock(lock_);
   DequeueBuffersLocked();
 
@@ -199,158 +410,48 @@
          acquired_buffers_.Front().IsAvailable();
 }
 
-bool DisplaySurface::IsBufferPosted() {
+bool DirectDisplaySurface::IsBufferPosted() {
   std::lock_guard<std::mutex> autolock(lock_);
   DequeueBuffersLocked();
 
   return !acquired_buffers_.IsEmpty();
 }
 
-pdx::Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
-  switch (message.GetOp()) {
-    case DisplayRPC::SetAttributes::Opcode:
-      DispatchRemoteMethod<DisplayRPC::SetAttributes>(
-          *this, &DisplaySurface::OnClientSetAttributes, message);
-      break;
-
-    case DisplayRPC::CreateBufferQueue::Opcode:
-      DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
-          *this, &DisplaySurface::OnCreateBufferQueue, message);
-      break;
-
-    case DisplayRPC::CreateVideoMeshSurface::Opcode:
-      DispatchRemoteMethod<DisplayRPC::CreateVideoMeshSurface>(
-          *this, &DisplaySurface::OnCreateVideoMeshSurface, message);
-      break;
-
-    default:
-      return SurfaceChannel::HandleMessage(message);
-  }
-
-  return {};
-}
-
-int DisplaySurface::OnClientSetAttributes(
-    pdx::Message& /*message*/, const DisplaySurfaceAttributes& attributes) {
-  for (const auto& attribute : attributes) {
-    const auto& key = attribute.first;
-    const auto* variant = &attribute.second;
-    bool invalid_value = false;
-    switch (key) {
-      case DisplaySurfaceAttributeEnum::ZOrder:
-        invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
-            variant, [this](const auto& value) {
-              DisplaySurface::ClientSetZOrder(value);
-            });
-        break;
-      case DisplaySurfaceAttributeEnum::Visible:
-        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
-            variant, [this](const auto& value) {
-              DisplaySurface::ClientSetVisible(value);
-            });
-        break;
-      case DisplaySurfaceAttributeEnum::ExcludeFromBlur:
-        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
-            variant, [this](const auto& value) {
-              DisplaySurface::ClientSetExcludeFromBlur(value);
-            });
-        break;
-      case DisplaySurfaceAttributeEnum::BlurBehind:
-        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
-            variant, [this](const auto& value) {
-              DisplaySurface::ClientSetBlurBehind(value);
-            });
-        break;
-      default:
-        ALOGW(
-            "DisplaySurface::OnClientSetAttributes: Unrecognized attribute %d "
-            "surface_id=%d",
-            key, surface_id());
-        break;
-    }
-
-    if (invalid_value) {
-      ALOGW(
-          "DisplaySurface::OnClientSetAttributes: Failed to set display "
-          "surface attribute '%s' because of incompatible type: %d",
-          DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index());
+Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
+    DisplayService* service, int surface_id, int process_id, int user_id,
+    const display::SurfaceAttributes& attributes) {
+  bool direct = false;
+  auto search = attributes.find(display::SurfaceAttribute::Direct);
+  if (search != attributes.end()) {
+    if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
+                                                     &direct)) {
+      ALOGE(
+          "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
+      return ErrorStatus(EINVAL);
     }
   }
 
-  service()->NotifyDisplayConfigurationUpdate();
-  return 0;
-}
+  ALOGD_IF(TRACE,
+           "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
+           "direct=%d",
+           surface_id, process_id, user_id, direct);
 
-LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
-  ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
-
-  if (consumer_queue_ != nullptr) {
-    ALOGE(
-        "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
-        "created and transported to DisplayClient.");
-    REPLY_ERROR_RETURN(message, EALREADY, {});
-  }
-
-  auto producer = ProducerQueue::Create<uint64_t>();
-  consumer_queue_ = producer->CreateConsumerQueue();
-
-  return std::move(producer->GetChannelHandle());
-}
-
-RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
-    pdx::Message& message) {
-  if (flags_ & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) {
-    ALOGE(
-        "DisplaySurface::OnCreateVideoMeshSurface: system distortion is "
-        "disabled on this display surface, cannot create VideoMeshSurface on "
-        "top of it.");
-    REPLY_ERROR_RETURN(message, EINVAL, {});
-  }
-
-  int channel_id;
-  auto status = message.PushChannel(0, nullptr, &channel_id);
-  if (!status) {
-    ALOGE(
-        "DisplaySurface::OnCreateVideoMeshSurface: failed to push channel: %s",
-        status.GetErrorMessage().c_str());
-    REPLY_ERROR_RETURN(message, status.error(), {});
-  }
-
-  auto surface = std::make_shared<VideoMeshSurface>(service(), channel_id);
-  auto channel_status = service()->SetChannel(channel_id, surface);
-  if (!channel_status) {
-    ALOGE(
-        "DisplaySurface::OnCreateVideoMeshSurface: failed to set new video "
-        "mesh surface channel: %s",
-        channel_status.GetErrorMessage().c_str());
-    REPLY_ERROR_RETURN(message, channel_status.error(), {});
-  }
-
-  {
-    std::lock_guard<std::mutex> autolock(lock_);
-    pending_video_mesh_surfaces_.push_back(surface);
-    video_mesh_surfaces_updated_ = true;
-  }
-
-  return status.take();
-}
-
-std::vector<std::shared_ptr<VideoMeshSurface>>
-DisplaySurface::GetVideoMeshSurfaces() {
-  std::lock_guard<std::mutex> autolock(lock_);
-  std::vector<std::shared_ptr<VideoMeshSurface>> surfaces;
-
-  for (auto& surface : pending_video_mesh_surfaces_) {
-    if (auto video_surface = surface.lock()) {
-      surfaces.push_back(video_surface);
+  if (direct) {
+    const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+    if (trusted) {
+      return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
+          service, surface_id, process_id, user_id, attributes)}};
     } else {
-      ALOGE("Unable to lock video mesh surface.");
+      ALOGE(
+          "DisplaySurface::Create: Direct surfaces may only be created by "
+          "trusted UIDs: user_id=%d",
+          user_id);
+      return ErrorStatus(EPERM);
     }
+  } else {
+    return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
+        service, surface_id, process_id, user_id, attributes)}};
   }
-
-  pending_video_mesh_surfaces_.clear();
-  video_mesh_surfaces_updated_ = false;
-  return surfaces;
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index 2e4cf75..47a07f0 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -3,7 +3,9 @@
 
 #include <pdx/file_handle.h>
 #include <pdx/service.h>
-#include <private/dvr/display_rpc.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>
@@ -13,54 +15,136 @@
 #include <vector>
 
 #include "acquired_buffer.h"
-#include "surface_channel.h"
-#include "video_mesh_surface.h"
 
 namespace android {
 namespace dvr {
 
 class DisplayService;
 
-// DisplaySurface is the service-side notion of a client display context. It is
-// responsible for managing display buffer format, geometry, and state, and
-// maintains the buffer consumers connected to the client.
-class DisplaySurface : public SurfaceChannel {
+enum class SurfaceType {
+  Direct,
+  Application,
+};
+
+class DisplaySurface : public pdx::Channel {
  public:
-  DisplaySurface(DisplayService* service, int surface_id, int process_id,
-                 int width, int height, int format, int usage, int flags);
+  static pdx::Status<std::shared_ptr<DisplaySurface>> Create(
+      DisplayService* service, int surface_id, int process_id, int user_id,
+      const display::SurfaceAttributes& attributes);
+
   ~DisplaySurface() override;
 
+  DisplayService* service() const { return service_; }
+  SurfaceType surface_type() const { return surface_type_; }
+  int surface_id() const { return surface_id_; }
   int process_id() const { return process_id_; }
-  int width() const { return width_; }
-  int height() const { return height_; }
-  int format() const { return format_; }
-  int usage() const { return usage_; }
-  int flags() const { return flags_; }
+  int user_id() const { return user_id_; }
 
-  bool client_visible() const { return client_visible_; }
-  int client_z_order() const { return client_z_order_; }
-  bool client_exclude_from_blur() const { return client_exclude_from_blur_; }
-  bool client_blur_behind() const { return client_blur_behind_; }
+  bool visible() const { return visible_; }
+  int z_order() const { return z_order_; }
 
-  bool manager_visible() const { return manager_visible_; }
-  int manager_z_order() const { return manager_z_order_; }
-  float manager_blur() const { return manager_blur_; }
+  const display::SurfaceAttributes& attributes() const { return attributes_; }
+  display::SurfaceUpdateFlags update_flags() const { return update_flags_; }
 
-  bool video_mesh_surfaces_updated() const {
-    return video_mesh_surfaces_updated_;
+  virtual std::vector<int32_t> GetQueueIds() const { return {}; }
+
+  bool IsUpdatePending() const {
+    return update_flags_.value() != display::SurfaceUpdateFlags::None;
   }
 
-  volatile const DisplaySurfaceMetadata* GetMetadataBufferPtr() {
-    if (EnsureMetadataBuffer()) {
-      void* addr = nullptr;
-      metadata_buffer_->GetBlobReadWritePointer(metadata_size(), &addr);
-      return static_cast<const volatile DisplaySurfaceMetadata*>(addr);
-    } else {
-      return nullptr;
-    }
+ protected:
+  DisplaySurface(DisplayService* service, SurfaceType surface_type,
+                 int surface_id, int process_id, int user_id,
+                 const display::SurfaceAttributes& attributes);
+
+  // Utility to retrieve a shared pointer to this channel as the desired derived
+  // type.
+  template <
+      typename T = DisplaySurface,
+      typename = std::enable_if_t<std::is_base_of<DisplaySurface, T>::value>>
+  std::shared_ptr<T> Self() {
+    return std::static_pointer_cast<T>(shared_from_this());
   }
 
-  uint32_t GetRenderBufferIndex(int buffer_id);
+  virtual pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+      pdx::Message& message, size_t meta_size_bytes) = 0;
+
+  // Registers a consumer queue with the event dispatcher in DisplayService. The
+  // OnQueueEvent callback below is called to handle queue events.
+  pdx::Status<void> RegisterQueue(
+      const std::shared_ptr<ConsumerQueue>& consumer_queue);
+  pdx::Status<void> UnregisterQueue(
+      const std::shared_ptr<ConsumerQueue>& consumer_queue);
+
+  // Called by the event dispatcher in DisplayService when a registered queue
+  // event triggers. Executes on the event dispatcher thread.
+  virtual void OnQueueEvent(
+      const std::shared_ptr<ConsumerQueue>& consumer_queue, int events);
+
+  void SurfaceUpdated(display::SurfaceUpdateFlags update_flags);
+  void ClearUpdate();
+
+  // Synchronizes access to mutable state below between message dispatch thread
+  // and frame post thread.
+  mutable std::mutex lock_;
+
+ private:
+  friend class DisplayService;
+  friend class DisplayManagerService;
+
+  // Dispatches display surface messages to the appropriate handlers. This
+  // handler runs on the VrFlinger message dispatch thread.
+  pdx::Status<void> HandleMessage(pdx::Message& message);
+
+  pdx::Status<void> OnSetAttributes(
+      pdx::Message& message, const display::SurfaceAttributes& attributes);
+  pdx::Status<display::SurfaceInfo> OnGetSurfaceInfo(pdx::Message& message);
+
+  DisplayService* service_;
+  SurfaceType surface_type_;
+  int surface_id_;
+  int process_id_;
+  int user_id_;
+
+  display::SurfaceAttributes attributes_;
+  display::SurfaceUpdateFlags update_flags_ = display::SurfaceUpdateFlags::None;
+
+  // Subset of attributes that may be interpreted by the display service.
+  bool visible_ = false;
+  int z_order_ = 0;
+
+  DisplaySurface(const DisplaySurface&) = delete;
+  void operator=(const DisplaySurface&) = delete;
+};
+
+class ApplicationDisplaySurface : public DisplaySurface {
+ public:
+  ApplicationDisplaySurface(DisplayService* service, int surface_id,
+                            int process_id, int user_id,
+                            const display::SurfaceAttributes& attributes)
+      : DisplaySurface(service, SurfaceType::Application, surface_id,
+                       process_id, user_id, attributes) {}
+
+  std::shared_ptr<ConsumerQueue> GetQueue(int32_t queue_id);
+  std::vector<int32_t> GetQueueIds() const override;
+
+ private:
+  pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+      pdx::Message& message, size_t meta_size_bytes) override;
+  void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
+                    int events) override;
+
+  std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_;
+};
+
+class DirectDisplaySurface : public DisplaySurface {
+ public:
+  DirectDisplaySurface(DisplayService* service, int surface_id, int process_id,
+                       int user_id,
+                       const display::SurfaceAttributes& attributes)
+      : DisplaySurface(service, SurfaceType::Direct, surface_id, process_id,
+                       user_id, attributes),
+        acquired_buffers_(kMaxPostedBuffers) {}
   bool IsBufferAvailable();
   bool IsBufferPosted();
   AcquiredBuffer AcquireCurrentBuffer();
@@ -69,31 +153,11 @@
   // skipped, it will be stored in skipped_buffer if non null.
   AcquiredBuffer AcquireNewestAvailableBuffer(AcquiredBuffer* skipped_buffer);
 
-  // Display manager interface to control visibility and z order.
-  void ManagerSetVisible(bool visible);
-  void ManagerSetZOrder(int z_order);
-  void ManagerSetBlur(float blur);
-
-  // A surface must be set visible by both the client and the display manager to
-  // be visible on screen.
-  bool IsVisible() const { return client_visible_ && manager_visible_; }
-
-  // A surface is blurred if the display manager requests it.
-  bool IsBlurred() const { return manager_blur_ > 0.0f; }
-
-  // Set by HardwareComposer to the current logical layer order of this surface.
-  void SetLayerOrder(int layer_order) { layer_order_ = layer_order; }
-  // Gets the unique z-order index of this surface among other visible surfaces.
-  // This is not the same as the hardware layer index, as not all display
-  // surfaces map directly to hardware layers. Lower layer orders should be
-  // composited underneath higher layer orders.
-  int layer_order() const { return layer_order_; }
-
-  // Lock all video mesh surfaces so that VideoMeshCompositor can access them.
-  std::vector<std::shared_ptr<VideoMeshSurface>> GetVideoMeshSurfaces();
-
  private:
-  friend class DisplayService;
+  pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+      pdx::Message& message, size_t meta_size_bytes) override;
+  void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
+                    int events) override;
 
   // 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
@@ -104,75 +168,14 @@
   // Returns whether a frame is available without locking the mutex.
   bool IsFrameAvailableNoLock() const;
 
-  // Dispatches display surface messages to the appropriate handlers. This
-  // handler runs on the displayd message dispatch thread.
-  pdx::Status<void> HandleMessage(pdx::Message& message) override;
-
-  // Sets display surface's client-controlled attributes.
-  int OnClientSetAttributes(pdx::Message& message,
-                            const DisplaySurfaceAttributes& attributes);
-
-  // Creates a BufferHubQueue associated with this surface and returns the PDX
-  // handle of its producer side to the client.
-  pdx::LocalChannelHandle OnCreateBufferQueue(pdx::Message& message);
-
-  // Creates a video mesh surface associated with this surface and returns its
-  // PDX handle to the client.
-  pdx::RemoteChannelHandle OnCreateVideoMeshSurface(pdx::Message& message);
-
-  // Client interface (called through IPC) to set visibility and z order.
-  void ClientSetVisible(bool visible);
-  void ClientSetZOrder(int z_order);
-  void ClientSetExcludeFromBlur(bool exclude_from_blur);
-  void ClientSetBlurBehind(bool blur_behind);
-
   // Dequeue all available buffers from the consumer queue.
   void DequeueBuffersLocked();
 
-  DisplaySurface(const DisplaySurface&) = delete;
-  void operator=(const DisplaySurface&) = delete;
-
-  int process_id_;
-
-  // Synchronizes access to mutable state below between message dispatch thread,
-  // epoll event thread, and frame post thread.
-  mutable std::mutex lock_;
-
-  // The consumer end of a BufferHubQueue. VrFlinger allocates and controls the
-  // buffer queue and pass producer end to the app and the consumer end to
-  // compositor.
-  // TODO(jwcai) Add support for multiple buffer queues per display surface.
-  std::shared_ptr<ConsumerQueue> consumer_queue_;
-
   // In a triple-buffered surface, up to kMaxPostedBuffers buffers may be
   // posted and pending.
   RingBuffer<AcquiredBuffer> acquired_buffers_;
 
-  // Provides access to VideoMeshSurface. Here we don't want to increase
-  // the reference count immediately on allocation, will leave it into
-  // compositor's hand.
-  std::vector<std::weak_ptr<VideoMeshSurface>> pending_video_mesh_surfaces_;
-  volatile bool video_mesh_surfaces_updated_;
-
-  // Surface parameters.
-  int width_;
-  int height_;
-  int format_;
-  int usage_;
-  int flags_;
-  bool client_visible_;
-  int client_z_order_;
-  bool client_exclude_from_blur_;
-  bool client_blur_behind_;
-  bool manager_visible_;
-  int manager_z_order_;
-  float manager_blur_;
-  int layer_order_;
-
-  // The monotonically increasing index for allocated buffers in this surface.
-  uint32_t allocated_buffer_index_;
-  // Maps from the buffer id to the corresponding allocated buffer index.
-  std::unordered_map<int, uint32_t> buffer_id_to_index_;
+  std::shared_ptr<ConsumerQueue> direct_queue_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
new file mode 100644
index 0000000..06b69bb
--- /dev/null
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
@@ -0,0 +1,142 @@
+#include "epoll_event_dispatcher.h"
+
+#include <log/log.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <sys/prctl.h>
+
+#include <dvr/performance_client_api.h>
+
+namespace android {
+namespace dvr {
+
+EpollEventDispatcher::EpollEventDispatcher() {
+  epoll_fd_.Reset(epoll_create(64));
+  if (!epoll_fd_) {
+    ALOGE("Failed to create epoll fd: %s", strerror(errno));
+    return;
+  }
+
+  event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+  if (!event_fd_) {
+    ALOGE("Failed to create event for epolling: %s", strerror(errno));
+    return;
+  }
+
+  // Add watch for eventfd. This should only watch for EPOLLIN, which gets set
+  // when eventfd_write occurs. Use "this" as a unique sentinal value to
+  // identify events from the event fd.
+  epoll_event event = {.events = EPOLLIN, .data = {.ptr = this}};
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, event_fd_.Get(), &event) < 0) {
+    ALOGE("Failed to add eventfd to epoll set because: %s", strerror(errno));
+    return;
+  }
+
+  thread_ = std::thread(&EpollEventDispatcher::EventThread, this);
+}
+
+EpollEventDispatcher::~EpollEventDispatcher() { Stop(); }
+
+void EpollEventDispatcher::Stop() {
+  exit_thread_.store(true);
+  eventfd_write(event_fd_.Get(), 1);
+}
+
+pdx::Status<void> EpollEventDispatcher::AddEventHandler(int fd, int event_mask,
+                                                        Handler handler) {
+  std::lock_guard<std::mutex> lock(lock_);
+
+  epoll_event event;
+  event.events = event_mask;
+  event.data.ptr = &(handlers_[fd] = handler);
+
+  ALOGD_IF(
+      TRACE,
+      "EpollEventDispatcher::AddEventHandler: fd=%d event_mask=0x%x handler=%p",
+      fd, event_mask, event.data.ptr);
+
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd, &event) < 0) {
+    const int error = errno;
+    ALOGE("Failed to add fd to epoll set because: %s", strerror(error));
+    return pdx::ErrorStatus(error);
+  } else {
+    return {};
+  }
+}
+
+pdx::Status<void> EpollEventDispatcher::RemoveEventHandler(int fd) {
+  ALOGD_IF(TRACE, "EpollEventDispatcher::RemoveEventHandler: fd=%d", fd);
+  std::lock_guard<std::mutex> lock(lock_);
+
+  epoll_event dummy;  // See BUGS in man 2 epoll_ctl.
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, fd, &dummy) < 0) {
+    const int error = errno;
+    ALOGE("Failed to remove fd from epoll set because: %s", strerror(error));
+    return pdx::ErrorStatus(error);
+  }
+
+  // If the fd was valid above, add it to the list of ids to remove.
+  removed_handlers_.push_back(fd);
+
+  // Wake up the event thread to clean up.
+  eventfd_write(event_fd_.Get(), 1);
+
+  return {};
+}
+
+void EpollEventDispatcher::EventThread() {
+  prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrEvent"), 0, 0, 0);
+
+  const int error = dvrSetSchedulerClass(0, "graphics");
+  LOG_ALWAYS_FATAL_IF(
+      error < 0,
+      "EpollEventDispatcher::EventThread: Failed to set scheduler class: %s",
+      strerror(-error));
+
+  const size_t kMaxNumEvents = 128;
+  epoll_event events[kMaxNumEvents];
+
+  while (!exit_thread_.load()) {
+    const int num_events = epoll_wait(epoll_fd_.Get(), events, kMaxNumEvents, -1);
+    if (num_events < 0 && errno != EINTR)
+      break;
+
+    ALOGD_IF(TRACE, "EpollEventDispatcher::EventThread: num_events=%d",
+             num_events);
+
+    for (int i = 0; i < num_events; i++) {
+      ALOGD_IF(
+          TRACE,
+          "EpollEventDispatcher::EventThread: event %d: handler=%p events=0x%x",
+          i, events[i].data.ptr, events[i].events);
+
+      if (events[i].data.ptr == this) {
+        // Clear pending event on event_fd_. Serialize the read with respect to
+        // writes from other threads.
+        std::lock_guard<std::mutex> lock(lock_);
+        eventfd_t value;
+        eventfd_read(event_fd_.Get(), &value);
+      } else {
+        auto handler = reinterpret_cast<Handler*>(events[i].data.ptr);
+        if (handler)
+          (*handler)(events[i].events);
+      }
+    }
+
+    // Remove any handlers that have been posted for removal. This is done here
+    // instead of in RemoveEventHandler() to prevent races between the dispatch
+    // thread and the code requesting the removal. Handlers are guaranteed to
+    // stay alive between exiting epoll_wait() and the dispatch loop above.
+    std::lock_guard<std::mutex> lock(lock_);
+    for (auto handler_fd : removed_handlers_) {
+      ALOGD_IF(TRACE,
+               "EpollEventDispatcher::EventThread: removing handler: fd=%d",
+               handler_fd);
+      handlers_.erase(handler_fd);
+    }
+    removed_handlers_.clear();
+  }
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.h b/libs/vr/libvrflinger/epoll_event_dispatcher.h
new file mode 100644
index 0000000..eb687f4
--- /dev/null
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.h
@@ -0,0 +1,63 @@
+#ifndef ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
+#define ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
+
+#include <sys/epoll.h>
+
+#include <atomic>
+#include <functional>
+#include <mutex>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+#include <pdx/file_handle.h>
+#include <pdx/status.h>
+
+namespace android {
+namespace dvr {
+
+class EpollEventDispatcher {
+ public:
+  // Function type for event handlers. The handler receives a bitmask of the
+  // epoll events that occurred on the file descriptor associated with the
+  // handler.
+  using Handler = std::function<void(int)>;
+
+  EpollEventDispatcher();
+  ~EpollEventDispatcher();
+
+  // |handler| is called on the internal dispatch thread when |fd| is signaled
+  // by events in |event_mask|.
+  pdx::Status<void> AddEventHandler(int fd, int event_mask, Handler handler);
+  pdx::Status<void> RemoveEventHandler(int fd);
+
+  void Stop();
+
+ private:
+  void EventThread();
+
+  std::thread thread_;
+  std::atomic<bool> exit_thread_{false};
+
+  // Protects handlers_ and removed_handlers_ and serializes operations on
+  // epoll_fd_ and event_fd_.
+  std::mutex lock_;
+
+  // Maintains a map of fds to event handlers. This is primarily to keep any
+  // references alive that may be bound in the std::function instances. It is
+  // not used at dispatch time to avoid performance problems with different
+  // versions of std::unordered_map.
+  std::unordered_map<int, Handler> handlers_;
+
+  // List of fds to be removed from the map. The actual removal is performed
+  // by the event dispatch thread to avoid races.
+  std::vector<int> removed_handlers_;
+
+  pdx::LocalHandle epoll_fd_;
+  pdx::LocalHandle event_fd_;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index bac9872..4c08284 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1,9 +1,9 @@
 #include "hardware_composer.h"
 
-#include <log/log.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
 #include <fcntl.h>
+#include <log/log.h>
 #include <poll.h>
 #include <sync/sync.h>
 #include <sys/eventfd.h>
@@ -11,23 +11,27 @@
 #include <sys/resource.h>
 #include <sys/system_properties.h>
 #include <sys/timerfd.h>
+#include <time.h>
 #include <unistd.h>
 #include <utils/Trace.h>
 
 #include <algorithm>
+#include <chrono>
 #include <functional>
 #include <map>
 
+#include <dvr/dvr_display_types.h>
 #include <dvr/performance_client_api.h>
 #include <private/dvr/clock_ns.h>
-#include <private/dvr/display_types.h>
+#include <private/dvr/ion_buffer.h>
 #include <private/dvr/pose_client_internal.h>
 #include <private/dvr/sync_util.h>
 
-#include "debug_hud_data.h"
-#include "screenshot_service.h"
-
 using android::pdx::LocalHandle;
+using android::pdx::rpc::EmptyVariant;
+using android::pdx::rpc::IfAnyOf;
+
+using namespace std::chrono_literals;
 
 namespace android {
 namespace dvr {
@@ -42,17 +46,8 @@
 // display and the EDS timing coincides with zero pending fences, so this is 0.
 constexpr int kAllowedPendingFenceCount = 0;
 
-// If we think we're going to miss vsync by more than this amount, skip the
-// frame.
-constexpr int64_t kFrameSkipThresholdNs = 4000000;  // 4ms
-
-// Counter PostLayers() deficiency by requiring apps to produce a frame at least
-// 2.5ms before vsync. See b/28881672.
-constexpr int64_t kFrameTimeEstimateMin = 2500000;  // 2.5ms
-
-constexpr size_t kDefaultDisplayConfigCount = 32;
-
-constexpr float kMetersPerInch = 0.0254f;
+// Offset before vsync to submit frames to hardware composer.
+constexpr int64_t kFramePostOffsetNs = 4000000;  // 4ms
 
 const char kBacklightBrightnessSysFile[] =
     "/sys/class/leds/lcd-backlight/brightness";
@@ -66,23 +61,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.
@@ -93,44 +71,52 @@
   return (vsync_period_ns * 150) / 100;
 }
 
+// Attempts to set the scheduler class and partiton for the current thread.
+// Returns true on success or false on failure.
+bool SetThreadPolicy(const std::string& scheduler_class,
+                     const std::string& partition) {
+  int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
+  if (error < 0) {
+    ALOGE(
+        "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
+        "thread_id=%d: %s",
+        scheduler_class.c_str(), gettid(), strerror(-error));
+    return false;
+  }
+  error = dvrSetCpuPartition(0, partition.c_str());
+  if (error < 0) {
+    ALOGE(
+        "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
+        "%s",
+        partition.c_str(), gettid(), strerror(-error));
+    return false;
+  }
+  return true;
+}
+
 }  // anonymous namespace
 
-HardwareComposer::HardwareComposer()
-  : HardwareComposer(nullptr) {
-}
+// Layer static data.
+Hwc2::Composer* Layer::hwc2_hidl_;
+const HWCDisplayMetrics* Layer::display_metrics_;
 
-HardwareComposer::HardwareComposer(Hwc2::Composer* hwc2_hidl)
+// HardwareComposer static data;
+constexpr size_t HardwareComposer::kMaxHardwareLayers;
+
+HardwareComposer::HardwareComposer()
+    : HardwareComposer(nullptr, RequestDisplayCallback()) {}
+
+HardwareComposer::HardwareComposer(
+    Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
     : initialized_(false),
       hwc2_hidl_(hwc2_hidl),
-      display_transform_(HWC_TRANSFORM_NONE),
-      active_surfaces_updated_(false),
-      active_layer_count_(0),
-      gpu_layer_(nullptr),
-      post_thread_enabled_(false),
-      post_thread_running_(false),
-      post_thread_quit_requested_(false),
-      post_thread_interrupt_event_fd_(-1),
-      backlight_brightness_fd_(-1),
-      primary_display_vsync_event_fd_(-1),
-      primary_display_wait_pp_fd_(-1),
-      vsync_sleep_timer_fd_(-1),
-      last_vsync_timestamp_(0),
-      vsync_count_(0),
-      frame_skip_count_(0),
-      pose_client_(nullptr) {
-  std::transform(layer_storage_.begin(), layer_storage_.end(), layers_.begin(),
-                 [](auto& layer) { return &layer; });
-
-  callbacks_ = new ComposerCallback;
-}
+      request_display_callback_(request_display_callback),
+      callbacks_(new ComposerCallback) {}
 
 HardwareComposer::~HardwareComposer(void) {
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  if (post_thread_.joinable()) {
-    post_thread_quit_requested_ = true;
-    post_thread_cond_var_.notify_all();
+  UpdatePostThreadState(PostThreadState::Quit, true);
+  if (post_thread_.joinable())
     post_thread_.join();
-  }
 }
 
 bool HardwareComposer::Initialize() {
@@ -139,25 +125,25 @@
     return false;
   }
 
-  int32_t ret = HWC2_ERROR_NONE;
+  HWC::Error error = HWC::Error::None;
 
   Hwc2::Config config;
-  ret = (int32_t)hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+  error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
 
-  if (ret != HWC2_ERROR_NONE) {
+  if (error != HWC::Error::None) {
     ALOGE("HardwareComposer: Failed to get current display config : %d",
           config);
     return false;
   }
 
-  ret =
+  error =
       GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
 
-  if (ret != HWC2_ERROR_NONE) {
+  if (error != HWC::Error::None) {
     ALOGE(
         "HardwareComposer: Failed to get display attributes for current "
         "configuration : %d",
-        ret);
+        error.value);
     return false;
   }
 
@@ -173,10 +159,12 @@
   display_transform_ = HWC_TRANSFORM_NONE;
   display_metrics_ = native_display_metrics_;
 
-  post_thread_interrupt_event_fd_.Reset(
-      eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+  // Pass hwc instance and metrics to setup globals for Layer.
+  Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
+
+  post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
   LOG_ALWAYS_FATAL_IF(
-      !post_thread_interrupt_event_fd_,
+      !post_thread_event_fd_,
       "HardwareComposer: Failed to create interrupt event fd : %s",
       strerror(errno));
 
@@ -188,61 +176,63 @@
 }
 
 void HardwareComposer::Enable() {
-  std::lock_guard<std::mutex> lock(post_thread_mutex_);
-  post_thread_enabled_ = true;
-  post_thread_cond_var_.notify_all();
+  UpdatePostThreadState(PostThreadState::Suspended, false);
 }
 
 void HardwareComposer::Disable() {
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  post_thread_enabled_ = false;
-  if (post_thread_running_) {
-    // Write to the interrupt fd to get fast interrupt of the post thread
-    int error = eventfd_write(post_thread_interrupt_event_fd_.Get(), 1);
-    ALOGW_IF(error,
-             "HardwareComposer::Disable: could not write post "
-             "thread interrupt event fd : %s",
-             strerror(errno));
-
-    post_thread_cond_var_.wait(lock, [this] { return !post_thread_running_; });
-
-    // Read the interrupt fd to clear its state
-    uint64_t interrupt_count= 0;
-    error = eventfd_read(post_thread_interrupt_event_fd_.Get(),
-                         &interrupt_count);
-    ALOGW_IF(error,
-             "HardwareComposer::Disable: could not read post "
-             "thread interrupt event fd : %s",
-             strerror(errno));
-  }
+  UpdatePostThreadState(PostThreadState::Suspended, true);
 }
 
-bool HardwareComposer::PostThreadHasWork() {
-  return !display_surfaces_.empty() ||
-      (active_surfaces_updated_ && !active_surfaces_.empty());
+// Update the post thread quiescent state based on idle and suspended inputs.
+void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
+                                             bool suspend) {
+  std::unique_lock<std::mutex> lock(post_thread_mutex_);
+
+  // Update the votes in the state variable before evaluating the effective
+  // quiescent state. Any bits set in post_thread_state_ indicate that the post
+  // thread should be suspended.
+  if (suspend) {
+    post_thread_state_ |= state;
+  } else {
+    post_thread_state_ &= ~state;
+  }
+
+  const bool quit = post_thread_state_ & PostThreadState::Quit;
+  const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
+  if (quit) {
+    post_thread_quiescent_ = true;
+    eventfd_write(post_thread_event_fd_.Get(), 1);
+    post_thread_wait_.notify_one();
+  } else if (effective_suspend && !post_thread_quiescent_) {
+    post_thread_quiescent_ = true;
+    eventfd_write(post_thread_event_fd_.Get(), 1);
+  } else if (!effective_suspend && post_thread_quiescent_) {
+    post_thread_quiescent_ = false;
+    eventfd_t value;
+    eventfd_read(post_thread_event_fd_.Get(), &value);
+    post_thread_wait_.notify_one();
+  }
+
+  // Wait until the post thread is in the requested state.
+  post_thread_ready_.wait(lock, [this, effective_suspend] {
+    return effective_suspend != post_thread_resumed_;
+  });
 }
 
 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();
 
-  // Associate each Layer instance with a hardware composer layer.
-  for (auto layer : layers_) {
-    layer->Initialize(hwc2_hidl_.get(), &native_display_metrics_);
-  }
-
   // Connect to pose service.
   pose_client_ = dvrPoseCreate();
   ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
 
+  // HIDL HWC seems to have an internal race condition. If we submit a frame too
+  // soon after turning on VSync we don't get any VSync signals. Give poor HWC
+  // implementations a chance to enable VSync before we continue.
+  EnableVsync(false);
+  std::this_thread::sleep_for(100ms);
   EnableVsync(true);
+  std::this_thread::sleep_for(100ms);
 
   // TODO(skiazyk): We need to do something about accessing this directly,
   // supposedly there is a backlight service on the way.
@@ -251,33 +241,18 @@
   // control of the display back to surface flinger?
   SetBacklightBrightness(255);
 
-  // Initialize the GPU compositor.
-  LOG_ALWAYS_FATAL_IF(!compositor_.Initialize(GetHmdDisplayMetrics()),
-                      "Failed to initialize the compositor");
-
   // Trigger target-specific performance mode change.
   property_set(kDvrPerformanceProperty, "performance");
 }
 
 void HardwareComposer::OnPostThreadPaused() {
   retire_fence_fds_.clear();
-  gpu_layer_ = nullptr;
-
-  // We have to destroy the layers to fully clear hwc device state before
-  // handing off back to surface flinger
-  for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
-    layers_[i]->Reset();
-  }
-
-  active_layer_count_ = 0;
-
-  framebuffer_target_.reset();
-
   display_surfaces_.clear();
-  compositor_surfaces_.clear();
 
-  // Since we're clearing display_surfaces_ we'll need an update.
-  active_surfaces_updated_ = true;
+  for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
+    layers_[i].Reset();
+  }
+  active_layer_count_ = 0;
 
   if (pose_client_) {
     dvrPoseDestroy(pose_client_);
@@ -286,50 +261,24 @@
 
   EnableVsync(false);
 
-  frame_time_history_.ResetWithSeed(GuessFrameTime(0));
-  frame_time_backlog_.clear();
-
-  compositor_.Shutdown();
-
   hwc2_hidl_->resetCommands();
 
   // Trigger target-specific performance mode change.
   property_set(kDvrPerformanceProperty, "idle");
 }
 
-DisplayMetrics HardwareComposer::GetHmdDisplayMetrics() const {
-  vec2i screen_size(display_metrics_.width, display_metrics_.height);
-  DisplayOrientation orientation =
-      (display_metrics_.width > display_metrics_.height
-           ? DisplayOrientation::kLandscape
-           : DisplayOrientation::kPortrait);
-  float dpi_x = static_cast<float>(display_metrics_.dpi.x) / 1000.0f;
-  float dpi_y = static_cast<float>(display_metrics_.dpi.y) / 1000.0f;
-  float meters_per_pixel_x = kMetersPerInch / dpi_x;
-  float meters_per_pixel_y = kMetersPerInch / dpi_y;
-  vec2 meters_per_pixel(meters_per_pixel_x, meters_per_pixel_y);
-  double frame_duration_s =
-      static_cast<double>(display_metrics_.vsync_period_ns) / 1000000000.0;
-  // TODO(hendrikw): Hard coding to 3mm.  The Pixel is actually 4mm, but it
-  //                 seems that their tray to lens distance is wrong too, which
-  //                 offsets this, at least for the pixel.
-  float border_size = 0.003f;
-  return DisplayMetrics(screen_size, meters_per_pixel, border_size,
-                        static_cast<float>(frame_duration_s), orientation);
-}
-
-int32_t HardwareComposer::Validate(hwc2_display_t display) {
+HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
   uint32_t num_types;
   uint32_t num_requests;
-  int32_t error =
-      (int32_t)hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
+  HWC::Error error =
+      hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
 
   if (error == HWC2_ERROR_HAS_CHANGES) {
     // TODO(skiazyk): We might need to inspect the requested changes first, but
     // so far it seems like we shouldn't ever hit a bad state.
     // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
     //                                               display);
-    error = (int32_t)hwc2_hidl_->acceptDisplayChanges(display);
+    error = hwc2_hidl_->acceptDisplayChanges(display);
   }
 
   return error;
@@ -342,13 +291,13 @@
                                              : HWC2_VSYNC_DISABLE));
 }
 
-int32_t HardwareComposer::Present(hwc2_display_t display) {
+HWC::Error HardwareComposer::Present(hwc2_display_t display) {
   int32_t present_fence;
-  int32_t error = (int32_t)hwc2_hidl_->presentDisplay(display, &present_fence);
+  HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
 
   // According to the documentation, this fence is signaled at the time of
   // vsync/DMA for physical displays.
-  if (error == HWC2_ERROR_NONE) {
+  if (error == HWC::Error::None) {
     ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
     retire_fence_fds_.emplace_back(present_fence);
   } else {
@@ -358,82 +307,81 @@
   return error;
 }
 
-int32_t HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
-                                              hwc2_config_t config,
-                                              hwc2_attribute_t attribute,
-                                              int32_t* out_value) const {
-  return (int32_t)hwc2_hidl_->getDisplayAttribute(
+HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
+                                                 hwc2_config_t config,
+                                                 hwc2_attribute_t attribute,
+                                                 int32_t* out_value) const {
+  return hwc2_hidl_->getDisplayAttribute(
       display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
 }
 
-int32_t HardwareComposer::GetDisplayMetrics(
+HWC::Error HardwareComposer::GetDisplayMetrics(
     hwc2_display_t display, hwc2_config_t config,
     HWCDisplayMetrics* out_metrics) const {
-  int32_t ret = HWC2_ERROR_NONE;
+  HWC::Error error;
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
-                            &out_metrics->width);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display width");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
+                              &out_metrics->width);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
-                            &out_metrics->height);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display height");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
+                              &out_metrics->height);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
-                            &out_metrics->vsync_period_ns);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display height");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+                              &out_metrics->vsync_period_ns);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
-                            &out_metrics->dpi.x);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display DPI X");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
+                              &out_metrics->dpi.x);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
-                            &out_metrics->dpi.y);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display DPI Y");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
+                              &out_metrics->dpi.y);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  return HWC2_ERROR_NONE;
+  return HWC::Error::None;
 }
 
-void HardwareComposer::Dump(char* buffer, uint32_t* out_size) {
-  std::string debug_str = hwc2_hidl_->dumpDebugInfo();
-  ALOGI("%s", debug_str.c_str());
+std::string HardwareComposer::Dump() { return hwc2_hidl_->dumpDebugInfo(); }
 
-  if (buffer == nullptr) {
-    *out_size = debug_str.size();
-  } else {
-    std::copy(debug_str.begin(), debug_str.begin() + *out_size, buffer);
-  }
-}
-
-// TODO(skiazyk): Figure out what to do with `is_geometry_changed`. There does
-// not seem to be any equivalent in the HWC2 API, but that doesn't mean its not
-// there.
-void HardwareComposer::PostLayers(bool /*is_geometry_changed*/) {
+void HardwareComposer::PostLayers() {
   ATRACE_NAME("HardwareComposer::PostLayers");
 
   // Setup the hardware composer layers with current buffers.
   for (size_t i = 0; i < active_layer_count_; i++) {
-    layers_[i]->Prepare();
+    layers_[i].Prepare();
   }
 
-  int32_t ret = Validate(HWC_DISPLAY_PRIMARY);
-  if (ret) {
-    ALOGE("HardwareComposer::Validate failed; ret=%d", ret);
+  HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
+  if (error != HWC::Error::None) {
+    ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
+          error.to_string().c_str());
     return;
   }
 
@@ -462,7 +410,7 @@
              retire_fence_fds_.size());
 
     for (size_t i = 0; i < active_layer_count_; i++) {
-      layers_[i]->Drop();
+      layers_[i].Drop();
     }
     return;
   } else {
@@ -473,55 +421,71 @@
 
 #if TRACE
   for (size_t i = 0; i < active_layer_count_; i++)
-    ALOGI("HardwareComposer::PostLayers: dl[%zu] ctype=0x%08x", i,
-          layers_[i]->GetCompositionType());
+    ALOGI("HardwareComposer::PostLayers: layer=%zu composition=%s", i,
+          layers_[i].GetCompositionType().to_string().c_str());
 #endif
 
-  ret = Present(HWC_DISPLAY_PRIMARY);
-  if (ret) {
-    ALOGE("HardwareComposer::Present failed; ret=%d", ret);
+  error = Present(HWC_DISPLAY_PRIMARY);
+  if (error != HWC::Error::None) {
+    ALOGE("HardwareComposer::PostLayers: Present failed: %s",
+          error.to_string().c_str());
     return;
   }
 
   std::vector<Hwc2::Layer> out_layers;
   std::vector<int> out_fences;
-  ret = (int32_t)hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
-                                              &out_fences);
-  uint32_t num_elements = out_layers.size();
-
-  ALOGE_IF(ret, "HardwareComposer: GetReleaseFences failed; ret=%d", ret);
+  error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+                                       &out_fences);
+  ALOGE_IF(error != HWC::Error::None,
+           "HardwareComposer::PostLayers: Failed to get release fences: %s",
+           error.to_string().c_str());
 
   // Perform post-frame bookkeeping. Unused layers are a no-op.
+  uint32_t num_elements = out_layers.size();
   for (size_t i = 0; i < num_elements; ++i) {
     for (size_t j = 0; j < active_layer_count_; ++j) {
-      if (layers_[j]->GetLayerHandle() == out_layers[i]) {
-        layers_[j]->Finish(out_fences[i]);
+      if (layers_[j].GetLayerHandle() == out_layers[i]) {
+        layers_[j].Finish(out_fences[i]);
       }
     }
   }
 }
 
 void HardwareComposer::SetDisplaySurfaces(
-    std::vector<std::shared_ptr<DisplaySurface>> surfaces) {
+    std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
   ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
         surfaces.size());
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  active_surfaces_ = std::move(surfaces);
-  active_surfaces_updated_ = true;
-  if (post_thread_enabled_)
-    post_thread_cond_var_.notify_all();
+  const bool display_idle = surfaces.size() == 0;
+  {
+    std::unique_lock<std::mutex> lock(post_thread_mutex_);
+    pending_surfaces_ = std::move(surfaces);
+  }
+
+  // Set idle state based on whether there are any surfaces to handle.
+  UpdatePostThreadState(PostThreadState::Idle, display_idle);
+
+  // XXX: TEMPORARY
+  // Request control of the display based on whether there are any surfaces to
+  // handle. This callback sets the post thread active state once the transition
+  // is complete in SurfaceFlinger.
+  // TODO(eieio): Unify the control signal used to move SurfaceFlinger into VR
+  // mode. Currently this is hooked up to persistent VR mode, but perhaps this
+  // makes more sense to control it from VrCore, which could in turn base its
+  // decision on persistent VR mode.
+  if (request_display_callback_)
+    request_display_callback_(!display_idle);
 }
 
-int HardwareComposer::PostThreadPollInterruptible(int event_fd,
-                                                  int requested_events) {
+int HardwareComposer::PostThreadPollInterruptible(
+    const pdx::LocalHandle& event_fd, int requested_events) {
   pollfd pfd[2] = {
       {
-          .fd = event_fd,
+          .fd = event_fd.Get(),
           .events = static_cast<short>(requested_events),
           .revents = 0,
       },
       {
-          .fd = post_thread_interrupt_event_fd_.Get(),
+          .fd = post_thread_event_fd_.Get(),
           .events = POLLPRI | POLLIN,
           .revents = 0,
       },
@@ -642,9 +606,8 @@
 // TODO(eieio): This is pretty driver specific, this should be moved to a
 // separate class eventually.
 int HardwareComposer::BlockUntilVSync() {
-  return PostThreadPollInterruptible(primary_display_vsync_event_fd_.Get(),
-                                     // There will be a POLLPRI event on vsync
-                                     POLLPRI);
+  // Vsync is signaled by POLLPRI on the fb vsync node.
+  return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
 }
 
 // Waits for the next vsync and returns the timestamp of the vsync event. If
@@ -683,7 +646,7 @@
     // See how close we are to the next expected vsync. If we're within 1ms,
     // sleep for 1ms and try again.
     const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
-    const int64_t threshold_ns = 1000000;
+    const int64_t threshold_ns = 1000000;  // 1ms
 
     const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
     const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
@@ -695,7 +658,7 @@
         return error;
     } else {
       // Sleep for a short time (1 millisecond) before retrying.
-      error = SleepUntil(GetSystemClockNs() + 1000000);
+      error = SleepUntil(GetSystemClockNs() + threshold_ns);
       if (error < 0 || error == kPostThreadInterrupted)
         return error;
     }
@@ -717,24 +680,18 @@
     return -error;
   }
 
-  return PostThreadPollInterruptible(timer_fd, POLLIN);
+  return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
 }
 
 void HardwareComposer::PostThread() {
   // NOLINTNEXTLINE(runtime/int)
   prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
 
-  // Set the scheduler to SCHED_FIFO with high priority.
-  int error = dvrSetSchedulerClass(0, "graphics:high");
-  LOG_ALWAYS_FATAL_IF(
-      error < 0,
-      "HardwareComposer::PostThread: Failed to set scheduler class: %s",
-      strerror(-error));
-  error = dvrSetCpuPartition(0, "/system/performance");
-  LOG_ALWAYS_FATAL_IF(
-      error < 0,
-      "HardwareComposer::PostThread: Failed to set cpu partition: %s",
-      strerror(-error));
+  // Set the scheduler to SCHED_FIFO with high priority. If this fails here
+  // there may have been a startup timing issue between this thread and
+  // performanced. Try again later when this thread becomes active.
+  bool thread_policy_setup =
+      SetThreadPolicy("graphics:high", "/system/performance");
 
 #if ENABLE_BACKLIGHT_BRIGHTNESS
   // TODO(hendrikw): This isn't required at the moment. It's possible that there
@@ -744,7 +701,7 @@
   ALOGW_IF(!backlight_brightness_fd_,
            "HardwareComposer: Failed to open backlight brightness control: %s",
            strerror(errno));
-#endif // ENABLE_BACKLIGHT_BRIGHTNESS
+#endif  // ENABLE_BACKLIGHT_BRIGHTNESS
 
   // Open the vsync event node for the primary display.
   // TODO(eieio): Move this into a platform-specific class.
@@ -783,11 +740,6 @@
   right_eye_photon_offset_ns =
       property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
 
-  compositor_surfaces_.reserve(2);
-
-  constexpr int kFrameTimeBacklogMax = 2;
-  frame_time_backlog_.reserve(kFrameTimeBacklogMax);
-
   // Storage for retrieving fence info.
   FenceInfoBuffer fence_info_buffer;
 
@@ -796,35 +748,42 @@
   while (1) {
     ATRACE_NAME("HardwareComposer::PostThread");
 
-    {
+    while (post_thread_quiescent_) {
       std::unique_lock<std::mutex> lock(post_thread_mutex_);
-      while (!post_thread_enabled_ || post_thread_quit_requested_ ||
-             !PostThreadHasWork()) {
-        if (was_running) {
-          const char* pause_reason = "unknown";
-          if (!post_thread_enabled_)
-            pause_reason = "disabled";
-          else if (post_thread_quit_requested_)
-            pause_reason = "quit requested";
-          else if (!PostThreadHasWork())
-            pause_reason = "no work";
-          ALOGI("VrHwcPost thread paused. Reason: %s.", pause_reason);
-          OnPostThreadPaused();
-          was_running = false;
-        }
-        post_thread_running_ = false;
-        post_thread_cond_var_.notify_all();
-        if (post_thread_quit_requested_)
-          return;
-        post_thread_cond_var_.wait(lock);
+      ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
+
+      // Tear down resources.
+      OnPostThreadPaused();
+
+      was_running = false;
+      post_thread_resumed_ = false;
+      post_thread_ready_.notify_all();
+
+      if (post_thread_state_ & PostThreadState::Quit) {
+        ALOGI("HardwareComposer::PostThread: Quitting.");
+        return;
       }
-      post_thread_running_ = true;
+
+      post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
+
+      post_thread_resumed_ = true;
+      post_thread_ready_.notify_all();
+
+      ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
     }
 
     if (!was_running) {
-      ALOGI("VrHwcPost thread resumed");
+      // Setup resources.
       OnPostThreadResumed();
       was_running = true;
+
+      // Try to setup the scheduler policy if it failed during startup. Only
+      // attempt to do this on transitions from inactive to active to avoid
+      // spamming the system with RPCs and log messages.
+      if (!thread_policy_setup) {
+        thread_policy_setup =
+            SetThreadPolicy("graphics:high", "/system/performance");
+      }
     }
 
     int64_t vsync_timestamp = 0;
@@ -834,7 +793,7 @@
                vsync_count_ + 1);
       ATRACE_NAME(buf.data());
 
-      error = WaitForVSync(&vsync_timestamp);
+      const int error = WaitForVSync(&vsync_timestamp);
       ALOGE_IF(
           error < 0,
           "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
@@ -854,74 +813,27 @@
                                 ns_per_frame, right_eye_photon_offset_ns);
     }
 
-    bool layer_config_changed = UpdateLayerConfig();
-
-    if (!was_running || layer_config_changed) {
-      frame_time_history_.ResetWithSeed(
-          GuessFrameTime(compositor_surfaces_.size()));
-      frame_time_backlog_.clear();
-    } else {
-      UpdateFrameTimeHistory(&frame_time_backlog_, kFrameTimeBacklogMax,
-                             &fence_info_buffer, &frame_time_history_);
-    }
-
-    // Get our current best estimate at how long the next frame will take to
-    // render, based on how long previous frames took to render. Use this
-    // estimate to decide when to wake up for EDS.
-    int64_t frame_time_estimate =
-        frame_time_history_.GetSampleCount() == 0
-            ? GuessFrameTime(compositor_surfaces_.size())
-            : frame_time_history_.GetAverage();
-    frame_time_estimate = std::max(frame_time_estimate, kFrameTimeEstimateMin);
-    DebugHudData::data.hwc_latency = frame_time_estimate;
+    const bool layer_config_changed = UpdateLayerConfig();
 
     // Signal all of the vsync clients. Because absolute time is used for the
     // wakeup time below, this can take a little time if necessary.
     if (vsync_callback_)
-      vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp, frame_time_estimate,
-                      vsync_count_);
+      vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
+                      /*frame_time_estimate*/ 0, vsync_count_);
 
     {
-      // Sleep until async EDS wakeup time.
+      // Sleep until shortly before vsync.
       ATRACE_NAME("sleep");
 
-      int64_t display_time_est = vsync_timestamp + ns_per_frame;
-      int64_t now = GetSystemClockNs();
-      int64_t frame_finish_time_est = now + frame_time_estimate;
-      int64_t sleep_time_ns = display_time_est - now - frame_time_estimate;
+      const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
+      const int64_t now_ns = GetSystemClockNs();
+      const int64_t sleep_time_ns =
+          display_time_est_ns - now_ns - kFramePostOffsetNs;
+      const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
 
       ATRACE_INT64("sleep_time_ns", sleep_time_ns);
-      if (frame_finish_time_est - display_time_est >= kFrameSkipThresholdNs) {
-        ATRACE_INT("frame_skip_count", ++frame_skip_count_);
-        ALOGE(
-            "HardwareComposer::PostThread: Missed frame schedule, drop "
-            "frame. Expected frame miss: %.1fms",
-            static_cast<double>(frame_finish_time_est - display_time_est) /
-                1000000);
-
-        // There are several reasons we might skip a frame, but one possibility
-        // is we mispredicted the frame time. Clear out the frame time history.
-        frame_time_history_.ResetWithSeed(
-            GuessFrameTime(compositor_surfaces_.size()));
-        frame_time_backlog_.clear();
-        DebugHudData::data.hwc_frame_stats.SkipFrame();
-
-        if (layer_config_changed) {
-          // If the layer config changed we need to validateDisplay() even if
-          // we're going to drop the frame, to flush the Composer object's
-          // internal command buffer and apply our layer changes.
-          Validate(HWC_DISPLAY_PRIMARY);
-        }
-
-        continue;
-      } else {
-        // Make the transition more obvious in systrace when the frame skip
-        // happens above.
-        ATRACE_INT("frame_skip_count", 0);
-      }
-
       if (sleep_time_ns > 0) {
-        error = SleepUntil(display_time_est - frame_time_estimate);
+        int error = SleepUntil(wakeup_time_ns);
         ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
                  strerror(-error));
         if (error == kPostThreadInterrupted) {
@@ -936,314 +848,58 @@
       }
     }
 
-    DebugHudData::data.hwc_frame_stats.AddFrame();
-
-    int64_t frame_start_time = GetSystemClockNs();
-
-    // Setup the output buffer for the compositor. This needs to happen before
-    // you draw with the compositor.
-    if (gpu_layer_ != nullptr) {
-      gpu_layer_->UpdateDirectBuffer(compositor_.GetBuffer());
-    }
-
-    // Call PostLayers now before performing the GL code for the compositor to
-    // avoid missing the deadline that can cause the lower-level hwc to get
-    // permanently backed up.
-    PostLayers(layer_config_changed);
-
-    PostCompositorBuffers();
-
-    if (gpu_layer_ != nullptr) {
-      // Note, with scanline racing, this draw is timed along with the post
-      // layers to finish just in time.
-      LocalHandle frame_fence_fd;
-      compositor_.DrawFrame(vsync_count_ + 1, &frame_fence_fd);
-      if (frame_fence_fd) {
-        LOG_ALWAYS_FATAL_IF(frame_time_backlog_.size() >= kFrameTimeBacklogMax,
-                            "Frame time backlog exceeds capacity");
-        frame_time_backlog_.push_back(
-            {frame_start_time, std::move(frame_fence_fd)});
-      }
-    } else if (!layer_config_changed) {
-      frame_time_history_.AddSample(GetSystemClockNs() - frame_start_time);
-    }
-
-    HandlePendingScreenshots();
+    PostLayers();
   }
 }
 
+// Checks for changes in the surface stack and updates the layer config to
+// accomodate the new stack.
 bool HardwareComposer::UpdateLayerConfig() {
-  std::vector<std::shared_ptr<DisplaySurface>> old_display_surfaces;
+  std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
   {
-    std::lock_guard<std::mutex> lock(post_thread_mutex_);
-    if (!active_surfaces_updated_)
+    std::unique_lock<std::mutex> lock(post_thread_mutex_);
+    if (pending_surfaces_.empty())
       return false;
-    old_display_surfaces = display_surfaces_;
-    display_surfaces_ = active_surfaces_;
-    active_surfaces_updated_ = false;
+
+    surfaces = std::move(pending_surfaces_);
   }
 
-  DebugHudData::data.ResetLayers();
-
-  // Figure out whether we need to update hardware layers. If this surface
-  // change does not add or remove hardware layers we can avoid display hiccups
-  // by gracefully updating only the GPU compositor layers.
-  int old_gpu_layer_count = 0;
-  int new_gpu_layer_count = 0;
-  bool hardware_layers_need_update = false;
-  // Look for new hardware layers and count new GPU layers.
-  for (const auto& surface : display_surfaces_) {
-    if (!(surface->flags() &
-          DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
-      ++new_gpu_layer_count;
-    else if (std::find(old_display_surfaces.begin(), old_display_surfaces.end(),
-                       surface) == old_display_surfaces.end())
-      // This is a new hardware layer, we need to update.
-      hardware_layers_need_update = true;
-  }
-  // Look for deleted hardware layers or compositor layers.
-  for (const auto& surface : old_display_surfaces) {
-    if (!(surface->flags() &
-          DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
-      ++old_gpu_layer_count;
-    else if (std::find(display_surfaces_.begin(), display_surfaces_.end(),
-                       surface) == display_surfaces_.end())
-      // This is a deleted hardware layer, we need to update.
-      hardware_layers_need_update = true;
-  }
-  // Check for compositor hardware layer transition.
-  if ((!old_gpu_layer_count && new_gpu_layer_count) ||
-      (old_gpu_layer_count && !new_gpu_layer_count))
-    hardware_layers_need_update = true;
-
-  // Set the chosen layer order for all surfaces.
-  for (size_t i = 0; i < display_surfaces_.size(); ++i) {
-    display_surfaces_[i]->SetLayerOrder(static_cast<int>(i));
-  }
-
-  // Update compositor layers.
-  {
-    ATRACE_NAME("UpdateLayerConfig_GpuLayers");
-    compositor_.UpdateSurfaces(display_surfaces_);
-    compositor_surfaces_.clear();
-    for (size_t i = 0; i < display_surfaces_.size(); ++i) {
-      const auto& surface = display_surfaces_[i];
-      if (!(surface->flags() &
-            DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION)) {
-        compositor_surfaces_.push_back(surface);
-      }
-    }
-  }
-
-  if (!hardware_layers_need_update)
-    return true;
-
-  // Update hardware layers.
-
   ATRACE_NAME("UpdateLayerConfig_HwLayers");
 
-  // Update the display layers in a non-destructive fashion.
+  display_surfaces_.clear();
 
-  // Create a map from surface id to hardware layer
-  std::map<int, Layer*> display_surface_layers;
-
-  for (size_t i = 0; i < active_layer_count_; ++i) {
-    auto layer = layers_[i];
-    int surface_id = layer->GetSurfaceId();
-
-    auto found =
-        std::find_if(display_surfaces_.begin(), display_surfaces_.end(),
-                     [surface_id](const auto& surface) {
-                       return surface->surface_id() == surface_id;
-                     });
-
-    if (found != display_surfaces_.end()) {
-      display_surface_layers[surface_id] = layer;
-    }
+  Layer* target_layer;
+  size_t layer_index;
+  for (layer_index = 0;
+       layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
+       layer_index++) {
+    // The bottom layer is opaque, other layers blend.
+    HWC::BlendMode blending =
+        layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
+    layers_[layer_index].Setup(surfaces[layer_index], blending,
+                               display_transform_, HWC::Composition::Device,
+                               layer_index);
+    display_surfaces_.push_back(surfaces[layer_index]);
   }
 
-  bool has_gpu_layer = std::any_of(
-      display_surfaces_.begin(), display_surfaces_.end(),
-      [](const auto& surface) {
-        return !(surface->flags() &
-                 DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION);
-      });
+  // Clear unused layers.
+  for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
+    layers_[i].Reset();
 
-  if (!has_gpu_layer) {
-    gpu_layer_ = nullptr;
-  }
-
-  auto is_layer_active = [&display_surface_layers, has_gpu_layer](auto layer) {
-    int surface_id = layer->GetSurfaceId();
-    if (surface_id >= 0) {
-      return display_surface_layers.count(surface_id) > 0;
-    } else {
-      return has_gpu_layer;
-    }
-  };
-
-  // Compress the in-use layers to the top of the list
-  auto part = std::partition(
-      layers_.begin(), layers_.begin() + active_layer_count_, is_layer_active);
-
-  size_t new_active_layer_count = part - layers_.begin();
-
-  // Clear any unused layers
-  for (size_t i = new_active_layer_count; i < active_layer_count_; ++i) {
-    layers_[i]->Reset();
-  }
-
-  active_layer_count_ = new_active_layer_count;
-
-  bool gpu_layer_applied = false;
-
-  // Create/update all of the hardware layers
-  for (size_t i = 0; i < display_surfaces_.size(); ++i) {
-    const auto& surface = display_surfaces_[i];
-    bool is_hw_surface =
-        surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION;
-    hwc2_blend_mode_t blending =
-        i == 0 ? HWC2_BLEND_MODE_NONE : HWC2_BLEND_MODE_COVERAGE;
-
-    DebugHudData::data.SetLayerInfo(
-        i, surface->width(), surface->height(),
-        !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2));
-
-    if (!is_hw_surface && gpu_layer_applied) {
-      continue;
-    }
-
-    Layer* target_layer;
-    bool existing_layer = false;
-
-    if (is_hw_surface) {
-      auto it = display_surface_layers.find(surface->surface_id());
-
-      if (it != display_surface_layers.end()) {
-        target_layer = it->second;
-        existing_layer = true;
-      }
-    } else if (gpu_layer_ != nullptr) {
-      target_layer = gpu_layer_;
-      existing_layer = true;
-    }
-
-    if (!existing_layer) {
-      if (active_layer_count_ >= kMaxHardwareLayers) {
-        ALOGI("HardwareComposer: More than %d hardware layers requested.",
-              kMaxHardwareLayers);
-        break;
-      } else {
-        target_layer = layers_[active_layer_count_];
-        ++active_layer_count_;
-      }
-
-      ALOGD_IF(TRACE,
-               "HardwareComposer::UpdateLayerConfig: (new) surface_id=%d -> "
-               "layer=%zd",
-               surface->surface_id(), i);
-
-      if (is_hw_surface) {
-        target_layer->Setup(surface, blending, display_transform_,
-                            HWC2_COMPOSITION_DEVICE, i);
-      } else {
-        gpu_layer_ = target_layer;
-        target_layer->Setup(compositor_.GetBuffer(), blending,
-                            display_transform_, HWC2_COMPOSITION_DEVICE, i);
-      }
-    } else {
-      ALOGD_IF(TRACE,
-               "HardwareComposer::UpdateLayerConfig: (retained) surface_id=%d "
-               "-> layer=%zd",
-               surface->surface_id(), i);
-
-      target_layer->SetBlending(blending);
-      target_layer->SetZOrderIndex(i);
-      target_layer->UpdateLayerSettings();
-    }
-
-    gpu_layer_applied = !is_hw_surface;
-  }
-
+  active_layer_count_ = layer_index;
   ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
            active_layer_count_);
 
+  // Any surfaces left over could not be assigned a hardware layer and will
+  // not be displayed.
+  ALOGW_IF(surfaces.size() != display_surfaces_.size(),
+           "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
+           "pending_surfaces=%zu display_surfaces=%zu",
+           surfaces.size(), display_surfaces_.size());
+
   return true;
 }
 
-void HardwareComposer::PostCompositorBuffers() {
-  ATRACE_NAME("PostCompositorBuffers");
-  for (const auto& surface : compositor_surfaces_) {
-    compositor_.PostBuffer(surface);
-  }
-}
-
-void HardwareComposer::UpdateFrameTimeHistory(
-    std::vector<FrameTimeMeasurementRecord>* backlog, int backlog_max,
-    FenceInfoBuffer* fence_info_buffer, FrameTimeHistory* history) {
-  while (!backlog->empty()) {
-    const auto& frame_time_record = backlog->front();
-    int64_t end_time = 0;
-    bool frame_finished = CheckFrameFinished(frame_time_record.fence.Get(),
-                                             fence_info_buffer, &end_time);
-    if (frame_finished) {
-      int64_t frame_duration = end_time - frame_time_record.start_time;
-      history->AddSample(frame_duration);
-      // Our backlog is tiny (2 elements), so erasing from the front is ok
-      backlog->erase(backlog->begin());
-    } else {
-      break;
-    }
-  }
-
-  if (backlog->size() == static_cast<size_t>(backlog_max)) {
-    // Yikes, something must've gone wrong if our oldest frame hasn't finished
-    // yet. Give up on waiting for it.
-    const auto& stale_frame_time_record = backlog->front();
-    int64_t frame_duration =
-        GetSystemClockNs() - stale_frame_time_record.start_time;
-    backlog->erase(backlog->begin());
-    history->AddSample(frame_duration);
-    ALOGW("Frame didn't finish after %.1fms",
-          static_cast<double>(frame_duration) / 1000000);
-  }
-}
-
-bool HardwareComposer::CheckFrameFinished(int frame_fence_fd,
-                                          FenceInfoBuffer* fence_info_buffer,
-                                          int64_t* timestamp) {
-  int result = -1;
-  int sync_result = sync_wait(frame_fence_fd, 0);
-  if (sync_result == 0) {
-    result =
-        GetFenceSignaledTimestamp(frame_fence_fd, fence_info_buffer, timestamp);
-    if (result < 0) {
-      ALOGE("Failed getting signaled timestamp from fence");
-    }
-  } else if (errno != ETIME) {
-    ALOGE("sync_wait on frame fence failed");
-  }
-  return result >= 0;
-}
-
-void HardwareComposer::HandlePendingScreenshots() {
-  // Take a screenshot of the requested layer, if available.
-  // TODO(eieio): Look into using virtual displays to composite the layer stack
-  // into a single output buffer that can be returned to the screenshot clients.
-  if (active_layer_count_ > 0) {
-    if (auto screenshot_service = ScreenshotService::GetInstance()) {
-      if (screenshot_service->IsScreenshotRequestPending()) {
-        ATRACE_NAME("screenshot");
-        screenshot_service->TakeIfNeeded(layers_, compositor_);
-      }
-    } else {
-      ALOGW(
-          "HardwareComposer::HandlePendingScreenshots: Failed to get "
-          "screenshot service!");
-    }
-  }
-}
-
 void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
   vsync_callback_ = callback;
 }
@@ -1280,145 +936,133 @@
   }
 }
 
-Layer::Layer()
-    : hwc2_hidl_(nullptr),
-      surface_index_(-1),
-      hardware_composer_layer_(0),
-      display_metrics_(nullptr),
-      blending_(HWC2_BLEND_MODE_NONE),
-      transform_(HWC_TRANSFORM_NONE),
-      composition_type_(HWC2_COMPOSITION_DEVICE),
-      surface_rect_functions_applied_(false) {}
-
-void Layer::Initialize(Hwc2::Composer* hwc2_hidl, HWCDisplayMetrics* metrics) {
+void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
+                              const HWCDisplayMetrics* metrics) {
   hwc2_hidl_ = hwc2_hidl;
   display_metrics_ = metrics;
 }
 
 void Layer::Reset() {
-  const int ret = acquired_buffer_.Release(std::move(release_fence_));
-  ALOGE_IF(ret < 0, "Layer::Reset: failed to release buffer: %s",
-           strerror(-ret));
-
   if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
     hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
     hardware_composer_layer_ = 0;
   }
 
-  surface_index_ = static_cast<size_t>(-1);
-  blending_ = HWC2_BLEND_MODE_NONE;
-  transform_ = HWC_TRANSFORM_NONE;
-  composition_type_ = HWC2_COMPOSITION_DEVICE;
-  direct_buffer_ = nullptr;
-  surface_ = nullptr;
-  acquire_fence_fd_.Close();
+  z_order_ = 0;
+  blending_ = HWC::BlendMode::None;
+  transform_ = HWC::Transform::None;
+  composition_type_ = HWC::Composition::Invalid;
+  target_composition_type_ = composition_type_;
+  source_ = EmptyVariant{};
+  acquire_fence_.Close();
   surface_rect_functions_applied_ = false;
 }
 
-void Layer::Setup(const std::shared_ptr<DisplaySurface>& surface,
-                  hwc2_blend_mode_t blending, hwc_transform_t transform,
-                  hwc2_composition_t composition_type, size_t index) {
+void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+                  HWC::BlendMode blending, HWC::Transform transform,
+                  HWC::Composition composition_type, size_t z_order) {
   Reset();
-  surface_index_ = index;
-  surface_ = surface;
+  z_order_ = z_order;
   blending_ = blending;
   transform_ = transform;
-  composition_type_ = composition_type;
+  composition_type_ = HWC::Composition::Invalid;
+  target_composition_type_ = composition_type;
+  source_ = SourceSurface{surface};
   CommonLayerSetup();
 }
 
 void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
-                  hwc2_blend_mode_t blending, hwc_transform_t transform,
-                  hwc2_composition_t composition_type, size_t z_order) {
+                  HWC::BlendMode blending, HWC::Transform transform,
+                  HWC::Composition composition_type, size_t z_order) {
   Reset();
-  surface_index_ = z_order;
-  direct_buffer_ = buffer;
+  z_order_ = z_order;
   blending_ = blending;
   transform_ = transform;
-  composition_type_ = composition_type;
+  composition_type_ = HWC::Composition::Invalid;
+  target_composition_type_ = composition_type;
+  source_ = SourceBuffer{buffer};
   CommonLayerSetup();
 }
 
-void Layer::UpdateDirectBuffer(const std::shared_ptr<IonBuffer>& buffer) {
-  direct_buffer_ = buffer;
+void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
+  if (source_.is<SourceBuffer>())
+    std::get<SourceBuffer>(source_) = {buffer};
 }
 
-void Layer::SetBlending(hwc2_blend_mode_t blending) { blending_ = blending; }
-
-void Layer::SetZOrderIndex(int z_index) { surface_index_ = z_index; }
+void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
+void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
 
 IonBuffer* Layer::GetBuffer() {
-  if (direct_buffer_)
-    return direct_buffer_.get();
-  else if (acquired_buffer_.IsAvailable())
-    return acquired_buffer_.buffer()->buffer();
-  else
-    return nullptr;
+  struct Visitor {
+    IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
+    IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
+    IonBuffer* operator()(EmptyVariant) { return nullptr; }
+  };
+  return source_.Visit(Visitor{});
 }
 
 void Layer::UpdateLayerSettings() {
   if (!IsLayerSetup()) {
-    ALOGE("HardwareComposer: Trying to update layers data on an unused layer.");
+    ALOGE(
+        "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
+        "unused Layer!");
     return;
   }
 
-  int32_t ret = HWC2_ERROR_NONE;
-
+  HWC::Error error;
   hwc2_display_t display = HWC_DISPLAY_PRIMARY;
 
-  ret = (int32_t)hwc2_hidl_->setLayerCompositionType(
+  error = hwc2_hidl_->setLayerCompositionType(
       display, hardware_composer_layer_,
-      (Hwc2::IComposerClient::Composition)composition_type_);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer composition type : %d",
-           ret);
-  // ret = (int32_t) hwc2_hidl_->setLayerTransform(display,
-  // hardware_composer_layer_,
-  //                                    (Hwc2::IComposerClient::Transform)
-  //                                    transform_);
-  // ALOGE_IF(ret, "HardwareComposer: Error setting layer transform : %d", ret);
+      composition_type_.cast<Hwc2::IComposerClient::Composition>());
+  ALOGE_IF(
+      error != HWC::Error::None,
+      "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
+      error.to_string().c_str());
 
-  // ret = hwc2_funcs_->set_layer_blend_mode_fn_(
-  //    hardware_composer_device_, display, hardware_composer_layer_,
-  //    blending_);
-  ret = (int32_t)hwc2_hidl_->setLayerBlendMode(
+  error = hwc2_hidl_->setLayerBlendMode(
       display, hardware_composer_layer_,
-      (Hwc2::IComposerClient::BlendMode)blending_);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer blend mode : %d", ret);
+      blending_.cast<Hwc2::IComposerClient::BlendMode>());
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
+           error.to_string().c_str());
 
-  Hwc2::IComposerClient::Rect display_frame;
-  display_frame.left = 0;
-  display_frame.top = 0;
-  display_frame.right = display_metrics_->width;
-  display_frame.bottom = display_metrics_->height;
-  ret = (int32_t)hwc2_hidl_->setLayerDisplayFrame(
-      display, hardware_composer_layer_, display_frame);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer display frame : %d",
-           ret);
+  // TODO(eieio): Use surface attributes or some other mechanism to control
+  // the layer display frame.
+  error = hwc2_hidl_->setLayerDisplayFrame(
+      display, hardware_composer_layer_,
+      {0, 0, display_metrics_->width, display_metrics_->height});
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
+           error.to_string().c_str());
 
-  std::vector<Hwc2::IComposerClient::Rect> visible_region(1);
-  visible_region[0] = display_frame;
-  ret = (int32_t)hwc2_hidl_->setLayerVisibleRegion(
-      display, hardware_composer_layer_, visible_region);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer visible region : %d",
-           ret);
+  error = hwc2_hidl_->setLayerVisibleRegion(
+      display, hardware_composer_layer_,
+      {{0, 0, display_metrics_->width, display_metrics_->height}});
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
+           error.to_string().c_str());
 
-  ret = (int32_t)hwc2_hidl_->setLayerPlaneAlpha(display,
-                                                hardware_composer_layer_, 1.0f);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer plane alpha : %d", ret);
+  error =
+      hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
+           error.to_string().c_str());
 
-  ret = (int32_t)hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_,
-                                            surface_index_);
-  ALOGE_IF(ret, "HardwareComposer: Error, setting z order index : %d", ret);
+  error =
+      hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting z_ order: %s",
+           error.to_string().c_str());
 }
 
 void Layer::CommonLayerSetup() {
-  int32_t ret = (int32_t)hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY,
-                                                 &hardware_composer_layer_);
-
-  ALOGE_IF(ret,
-           "HardwareComposer: Failed to create layer on primary display : %d",
-           ret);
-
+  HWC::Error error =
+      hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+  ALOGE_IF(
+      error != HWC::Error::None,
+      "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
+      error.to_string().c_str());
   UpdateLayerSettings();
 }
 
@@ -1426,114 +1070,69 @@
   int right, bottom;
   sp<GraphicBuffer> handle;
 
-  if (surface_) {
-    // Only update the acquired buffer when one is either available or this is
-    // the first time through.
-    if (surface_->IsBufferAvailable()) {
-      // If we previously set this to a solid color layer to stall for time,
-      // revert it to a device layer.
-      if (acquired_buffer_.IsEmpty() &&
-          composition_type_ != HWC2_COMPOSITION_DEVICE) {
-        composition_type_ = HWC2_COMPOSITION_DEVICE;
-        hwc2_hidl_->setLayerCompositionType(
-            HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
-            (Hwc2::IComposerClient::Composition)HWC2_COMPOSITION_DEVICE);
-      }
+  // Acquire the next buffer according to the type of source.
+  IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
+    std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
+  });
 
-      DebugHudData::data.AddLayerFrame(surface_index_);
-      acquired_buffer_.Release(std::move(release_fence_));
-      acquired_buffer_ = surface_->AcquireCurrentBuffer();
-
-      // Basic latency stopgap for when the application misses a frame:
-      // If the application recovers on the 2nd or 3rd (etc) frame after
-      // missing, this code will skip a frame to catch up by checking if
-      // the next frame is also available.
-      if (surface_->IsBufferAvailable()) {
-        DebugHudData::data.SkipLayerFrame(surface_index_);
-        ATRACE_NAME("DropToCatchUp");
-        ATRACE_ASYNC_END("BufferPost", acquired_buffer_.buffer()->id());
-        acquired_buffer_ = surface_->AcquireCurrentBuffer();
-      }
-      ATRACE_ASYNC_END("BufferPost", acquired_buffer_.buffer()->id());
-    } else if (acquired_buffer_.IsEmpty()) {
-      // While we are waiting for a buffer, set this to be an empty layer
-      if (composition_type_ != HWC2_COMPOSITION_SOLID_COLOR) {
-        composition_type_ = HWC2_COMPOSITION_SOLID_COLOR;
-        hwc2_hidl_->setLayerCompositionType(
-            HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
-            (Hwc2::IComposerClient::Composition)HWC2_COMPOSITION_SOLID_COLOR);
-
-        Hwc2::IComposerClient::Color layer_color = {
-            0, 0, 0, 0,
-        };
-        hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
-                                  layer_color);
-      }
-      return;
+  // When a layer is first setup there may be some time before the first buffer
+  // arrives. Setup the HWC layer as a solid color to stall for time until the
+  // first buffer arrives. Once the first buffer arrives there will always be a
+  // buffer for the frame even if it is old.
+  if (!handle.get()) {
+    if (composition_type_ == HWC::Composition::Invalid) {
+      composition_type_ = HWC::Composition::SolidColor;
+      hwc2_hidl_->setLayerCompositionType(
+          HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+          composition_type_.cast<Hwc2::IComposerClient::Composition>());
+      Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
+      hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+                                layer_color);
+    } else {
+      // The composition type is already set. Nothing else to do until a
+      // buffer arrives.
     }
-    right = acquired_buffer_.buffer()->width();
-    bottom = acquired_buffer_.buffer()->height();
-    handle = acquired_buffer_.buffer()->buffer()->buffer();
-    acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release());
   } else {
-    // TODO(jwcai) Note: this is the GPU compositor's layer, and we need the
-    // mechanism to accept distorted layers from VrCore.
-    right = direct_buffer_->width();
-    bottom = direct_buffer_->height();
-    handle = direct_buffer_->buffer();
-    acquire_fence_fd_.Close();
-  }
+    if (composition_type_ != target_composition_type_) {
+      composition_type_ = target_composition_type_;
+      hwc2_hidl_->setLayerCompositionType(
+          HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+          composition_type_.cast<Hwc2::IComposerClient::Composition>());
+    }
 
-  int32_t ret = HWC2_ERROR_NONE;
+    HWC::Error error{HWC::Error::None};
+    error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
+                                       hardware_composer_layer_, 0, handle,
+                                       acquire_fence_.Get());
 
-  if (composition_type_ == HWC2_COMPOSITION_DEVICE) {
-    ret = (int32_t)hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
-                                              hardware_composer_layer_, 0,
-                                              handle,
-                                              acquire_fence_fd_.Get());
+    ALOGE_IF(error != HWC::Error::None,
+             "Layer::Prepare: Error setting layer buffer: %s",
+             error.to_string().c_str());
 
-    ALOGE_IF(ret, "HardwareComposer: Error setting layer buffer : %d", ret);
-  }
+    if (!surface_rect_functions_applied_) {
+      const float float_right = right;
+      const float float_bottom = bottom;
+      error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+                                             hardware_composer_layer_,
+                                             {0, 0, float_right, float_bottom});
 
-  if (!surface_rect_functions_applied_) {
-    Hwc2::IComposerClient::FRect crop_rect = {
-        0, 0, static_cast<float>(right), static_cast<float>(bottom),
-    };
-    hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
-                                   hardware_composer_layer_, crop_rect);
+      ALOGE_IF(error != HWC::Error::None,
+               "Layer::Prepare: Error setting layer source crop: %s",
+               error.to_string().c_str());
 
-    ALOGE_IF(ret, "HardwareComposer: Error setting layer source crop : %d",
-             ret);
-
-// TODO(skiazyk): why is this ifdef'd out. Is if a driver-specific issue where
-// it must/cannot be called?
-#ifdef QCOM_BSP
-    hwc_rect_t damage_rect = {
-        0, 0, right, bottom,
-    };
-    hwc_region_t damage = {
-        1, &damage_rect,
-    };
-    // ret = hwc2_funcs_->set_layer_surface_damage(
-    //    hardware_composer_device_, HWC_DISPLAY_PRIMARY,
-    //    hardware_composer_layer_, damage);
-    // uses a std::vector as the listing
-    // hwc2_hidl_->setLayerSurfaceDamage(HWC_DISPLAY_PRIMARY,
-    // hardware_composer_layer_, vector here);
-
-    ALOGE_IF(ret, "HardwareComposer: Error settings layer surface damage : %d",
-             ret);
-#endif
-
-    surface_rect_functions_applied_ = true;
+      surface_rect_functions_applied_ = true;
+    }
   }
 }
 
 void Layer::Finish(int release_fence_fd) {
-  release_fence_.Reset(release_fence_fd);
+  IfAnyOf<SourceSurface, SourceBuffer>::Call(
+      &source_, [release_fence_fd](auto& source) {
+        source.Finish(LocalHandle(release_fence_fd));
+      });
 }
 
-void Layer::Drop() { acquire_fence_fd_.Close(); }
+void Layer::Drop() { acquire_fence_.Close(); }
 
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index e570cb6..20327a3 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -1,13 +1,12 @@
 #ifndef ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_
 #define ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_
 
-#include <log/log.h>
-#include <hardware/gralloc.h>
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer2.h>
+#include <ui/GraphicBuffer.h>
+#include "DisplayHardware/ComposerHal.h"
+#include "hwc_types.h"
 
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/sync_util.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
 
 #include <array>
 #include <condition_variable>
@@ -17,17 +16,16 @@
 #include <tuple>
 #include <vector>
 
+#include <dvr/pose_client.h>
 #include <pdx/file_handle.h>
+#include <pdx/rpc/variant.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/frame_time_history.h>
 #include <private/dvr/sync_util.h>
 
 #include "acquired_buffer.h"
-#include "compositor.h"
 #include "display_surface.h"
 
-#include "DisplayHardware/ComposerHal.h"
-
 // Hardware composer HAL doesn't define HWC_TRANSFORM_NONE as of this writing.
 #ifndef HWC_TRANSFORM_NONE
 #define HWC_TRANSFORM_NONE static_cast<hwc_transform_t>(0)
@@ -53,29 +51,28 @@
 // source supplying buffers for the layer's contents.
 class Layer {
  public:
-  Layer();
+  Layer() {}
 
-  // Sets the hardware composer layer and display metrics that this Layer should
-  // use each Prepare cycle. This class does not own either of these pointers,
-  // which MUST remain valid for its lifetime. This method MUST be called once
-  // in the life of the instance before any other method is valid to call.
-  void Initialize(Hwc2::Composer* hwc2_hidl, HWCDisplayMetrics* metrics);
+  // Sets up the global state used by all Layer instances. This must be called
+  // before using any Layer methods.
+  static void InitializeGlobals(Hwc2::Composer* hwc2_hidl,
+                                const HWCDisplayMetrics* metrics);
 
   // Releases any shared pointers and fence handles held by this instance.
   void Reset();
 
   // Sets up the layer to use a display surface as its content source. The Layer
-  // will automatically handle ACQUIRE/RELEASE phases for the surface's buffer
-  // train every frame.
+  // automatically handles ACQUIRE/RELEASE phases for the surface's buffer train
+  // every frame.
   //
   // |blending| receives HWC_BLENDING_* values.
   // |transform| receives HWC_TRANSFORM_* values.
   // |composition_type| receives either HWC_FRAMEBUFFER for most layers or
   // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
-  // |index| is the index of this surface in the DisplaySurface array.
-  void Setup(const std::shared_ptr<DisplaySurface>& surface,
-             hwc2_blend_mode_t blending, hwc_transform_t transform,
-             hwc2_composition_t composition_type, size_t index);
+  // |index| is the index of this surface in the DirectDisplaySurface array.
+  void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+             HWC::BlendMode blending, HWC::Transform transform,
+             HWC::Composition composition_type, size_t z_roder);
 
   // Sets up the layer to use a direct buffer as its content source. No special
   // handling of the buffer is performed; responsibility for updating or
@@ -85,13 +82,13 @@
   // |transform| receives HWC_TRANSFORM_* values.
   // |composition_type| receives either HWC_FRAMEBUFFER for most layers or
   // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
-  void Setup(const std::shared_ptr<IonBuffer>& buffer,
-             hwc2_blend_mode_t blending, hwc_transform_t transform,
-             hwc2_composition_t composition_type, size_t z_order);
+  void Setup(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+             HWC::Transform transform, HWC::Composition composition_type,
+             size_t z_order);
 
   // Layers that use a direct IonBuffer should call this each frame to update
   // which buffer will be used for the next PostLayers.
-  void UpdateDirectBuffer(const std::shared_ptr<IonBuffer>& buffer);
+  void UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer);
 
   // Sets up the hardware composer layer for the next frame. When the layer is
   // associated with a display surface, this method automatically ACQUIRES a new
@@ -107,10 +104,10 @@
   void Finish(int release_fence_fd);
 
   // Sets the blending for the layer. |blending| receives HWC_BLENDING_* values.
-  void SetBlending(hwc2_blend_mode_t blending);
+  void SetBlending(HWC::BlendMode blending);
 
-  // Sets the Z-order of this layer
-  void SetZOrderIndex(int surface_index);
+  // Sets the z-order of this layer
+  void SetZOrder(size_t z_order);
 
   // Gets the current IonBuffer associated with this layer. Ownership of the
   // buffer DOES NOT pass to the caller and the pointer is not guaranteed to
@@ -118,57 +115,111 @@
   // Layer::Reset(). YOU HAVE BEEN WARNED.
   IonBuffer* GetBuffer();
 
-  hwc2_composition_t GetCompositionType() const { return composition_type_; }
-
-  hwc2_layer_t GetLayerHandle() const { return hardware_composer_layer_; }
-
-  bool UsesDirectBuffer() const { return direct_buffer_ != nullptr; }
-
-  bool IsLayerSetup() const {
-    return direct_buffer_ != nullptr || surface_ != nullptr;
-  }
+  HWC::Composition GetCompositionType() const { return composition_type_; }
+  HWC::Layer GetLayerHandle() const { return hardware_composer_layer_; }
+  bool IsLayerSetup() const { return !source_.empty(); }
 
   // Applies all of the settings to this layer using the hwc functions
   void UpdateLayerSettings();
 
   int GetSurfaceId() const {
-    if (surface_ != nullptr) {
-      return surface_->surface_id();
-    } else {
-      return -1;
-    }
+    int surface_id = -1;
+    pdx::rpc::IfAnyOf<SourceSurface>::Call(
+        &source_, [&surface_id](const SourceSurface& surface_source) {
+          surface_id = surface_source.surface->surface_id();
+        });
+    return surface_id;
   }
 
  private:
   void CommonLayerSetup();
 
-  Hwc2::Composer* hwc2_hidl_;
-
-  // Original display surface array index for tracking purposes.
-  size_t surface_index_;
+  static Hwc2::Composer* hwc2_hidl_;
+  static const HWCDisplayMetrics* display_metrics_;
 
   // The hardware composer layer and metrics to use during the prepare cycle.
-  hwc2_layer_t hardware_composer_layer_;
-  HWCDisplayMetrics* display_metrics_;
+  hwc2_layer_t hardware_composer_layer_ = 0;
 
   // Layer properties used to setup the hardware composer layer during the
   // Prepare phase.
-  hwc2_blend_mode_t blending_;
-  hwc_transform_t transform_;
-  hwc2_composition_t composition_type_;
+  size_t z_order_ = 0;
+  HWC::BlendMode blending_ = HWC::BlendMode::None;
+  HWC::Transform transform_ = HWC::Transform::None;
+  HWC::Composition composition_type_ = HWC::Composition::Invalid;
+  HWC::Composition target_composition_type_ = HWC::Composition::Device;
 
-  // These two members are mutually exclusive. When direct_buffer_ is set the
-  // Layer gets its contents directly from that buffer; when surface_ is set the
-  // Layer gets it contents from the surface's buffer train.
-  std::shared_ptr<IonBuffer> direct_buffer_;
-  std::shared_ptr<DisplaySurface> surface_;
+  // State when the layer is connected to a surface. Provides the same interface
+  // as SourceBuffer to simplify internal use by Layer.
+  struct SourceSurface {
+    std::shared_ptr<DirectDisplaySurface> surface;
+    AcquiredBuffer acquired_buffer;
+    pdx::LocalHandle release_fence;
 
-  // State when associated with a display surface.
-  AcquiredBuffer acquired_buffer_;
-  pdx::LocalHandle release_fence_;
+    SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
+        : surface(surface) {}
 
-  pdx::LocalHandle acquire_fence_fd_;
-  bool surface_rect_functions_applied_;
+    // Attempts to acquire a new buffer from the surface and return a tuple with
+    // width, height, buffer handle, and fence. If a new buffer is not available
+    // the previous buffer is returned or an empty value if no buffer has ever
+    // been posted. When a new buffer is acquired the previous buffer's release
+    // fence is passed out automatically.
+    std::tuple<int, int, sp<GraphicBuffer>, pdx::LocalHandle> Acquire() {
+      if (surface->IsBufferAvailable()) {
+        acquired_buffer.Release(std::move(release_fence));
+        acquired_buffer = surface->AcquireCurrentBuffer();
+        ATRACE_ASYNC_END("BufferPost", acquired_buffer.buffer()->id());
+      }
+      if (!acquired_buffer.IsEmpty()) {
+        return std::make_tuple(acquired_buffer.buffer()->width(),
+                               acquired_buffer.buffer()->height(),
+                               acquired_buffer.buffer()->buffer()->buffer(),
+                               acquired_buffer.ClaimAcquireFence());
+      } else {
+        return std::make_tuple(0, 0, nullptr, pdx::LocalHandle{});
+      }
+    }
+
+    void Finish(pdx::LocalHandle fence) { release_fence = std::move(fence); }
+
+    // Gets a pointer to the current acquired buffer or returns nullptr if there
+    // isn't one.
+    IonBuffer* GetBuffer() {
+      if (acquired_buffer.IsAvailable())
+        return acquired_buffer.buffer()->buffer();
+      else
+        return nullptr;
+    }
+
+    // Returns the surface id of the surface.
+    int GetSurfaceId() { return surface->surface_id(); }
+  };
+
+  // State when the layer is connected to a buffer. Provides the same interface
+  // as SourceSurface to simplify internal use by Layer.
+  struct SourceBuffer {
+    std::shared_ptr<IonBuffer> buffer;
+
+    std::tuple<int, int, sp<GraphicBuffer>, pdx::LocalHandle> Acquire() {
+      if (buffer)
+        return std::make_tuple(buffer->width(), buffer->height(),
+                               buffer->buffer(), pdx::LocalHandle{});
+      else
+        return std::make_tuple(0, 0, nullptr, pdx::LocalHandle{});
+    }
+
+    void Finish(pdx::LocalHandle /*fence*/) {}
+
+    IonBuffer* GetBuffer() { return buffer.get(); }
+
+    int GetSurfaceId() const { return -1; }
+  };
+
+  // The underlying hardware composer layer is supplied buffers either from a
+  // surface buffer train or from a buffer directly.
+  pdx::rpc::Variant<SourceSurface, SourceBuffer> source_;
+
+  pdx::LocalHandle acquire_fence_;
+  bool surface_rect_functions_applied_ = false;
 
   Layer(const Layer&) = delete;
   void operator=(const Layer&) = delete;
@@ -186,13 +237,15 @@
  public:
   // Type for vsync callback.
   using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>;
+  using RequestDisplayCallback = std::function<void(bool)>;
 
   // Since there is no universal way to query the number of hardware layers,
   // just set it to 4 for now.
-  static constexpr int kMaxHardwareLayers = 4;
+  static constexpr size_t kMaxHardwareLayers = 4;
 
   HardwareComposer();
-  HardwareComposer(Hwc2::Composer* hidl);
+  HardwareComposer(Hwc2::Composer* hidl,
+                   RequestDisplayCallback request_display_callback);
   ~HardwareComposer();
 
   bool Initialize();
@@ -207,14 +260,14 @@
   void Disable();
 
   // Get the HMD display metrics for the current display.
-  DisplayMetrics GetHmdDisplayMetrics() const;
+  display::Metrics GetHmdDisplayMetrics() const;
 
-  int32_t GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
-                              hwc2_attribute_t attributes,
-                              int32_t* out_value) const;
-  int32_t GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
-                            HWCDisplayMetrics* out_metrics) const;
-  void Dump(char* buffer, uint32_t* out_size);
+  HWC::Error GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
+                                 hwc2_attribute_t attributes,
+                                 int32_t* out_value) const;
+  HWC::Error GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
+                               HWCDisplayMetrics* out_metrics) const;
+  std::string Dump();
 
   void SetVSyncCallback(VSyncCallback callback);
 
@@ -229,11 +282,9 @@
     return native_display_metrics_;
   }
 
-  // Set the display surface stack to compose to the display each frame.
+  // Sets the display surfaces to compose the hardware layer stack.
   void SetDisplaySurfaces(
-      std::vector<std::shared_ptr<DisplaySurface>> surfaces);
-
-  Compositor* GetCompositor() { return &compositor_; }
+      std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces);
 
   void OnHardwareComposerRefresh();
 
@@ -265,23 +316,36 @@
     }
   };
 
-  int32_t Validate(hwc2_display_t display);
-  int32_t Present(hwc2_display_t display);
+  HWC::Error Validate(hwc2_display_t display);
+  HWC::Error Present(hwc2_display_t display);
 
   void SetBacklightBrightness(int brightness);
 
-  void PostLayers(bool is_geometry_changed);
+  void PostLayers();
   void PostThread();
 
-  // Check to see if we have a value written to post_thread_interrupt_event_fd_,
-  // indicating a control thread interrupted the post thread. This clears the
-  // post_thread_interrupt_event_fd_ state in the process. Returns true if an
-  // interrupt was requested.
-  bool CheckPostThreadInterruptEventFd();
+  // The post thread has two controlling states:
+  // 1. Idle: no work to do (no visible surfaces).
+  // 2. Suspended: explicitly halted (system is not in VR mode).
+  // When either #1 or #2 is true then the post thread is quiescent, otherwise
+  // it is active.
+  using PostThreadStateType = uint32_t;
+  struct PostThreadState {
+    enum : PostThreadStateType {
+      Active = 0,
+      Idle = (1 << 0),
+      Suspended = (1 << 1),
+      Quit = (1 << 2),
+    };
+  };
+
+  void UpdatePostThreadState(uint32_t state, bool suspend);
+
   // Blocks until either event_fd becomes readable, or we're interrupted by a
   // control thread. Any errors are returned as negative errno values. If we're
   // interrupted, kPostThreadInterrupted will be returned.
-  int PostThreadPollInterruptible(int event_fd, int requested_events);
+  int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
+                                  int requested_events);
 
   // BlockUntilVSync, WaitForVSync, and SleepUntil are all blocking calls made
   // on the post thread that can be interrupted by a control thread. If
@@ -294,49 +358,21 @@
 
   bool IsFramePendingInDriver() { return ReadWaitPPState() == 1; }
 
-  // Returns true if the layer config changed, false otherwise
+  // Reconfigures the layer stack if the display surfaces changed since the last
+  // frame. Called only from the post thread.
   bool UpdateLayerConfig();
-  void PostCompositorBuffers();
-
-  // Return true if the post thread has work to do (i.e. there are visible
-  // surfaces to post to the screen). Must be called with post_thread_mutex_
-  // locked. Called only from the post thread.
-  bool PostThreadHasWork();
 
   // Called on the post thread when the post thread is resumed.
   void OnPostThreadResumed();
   // Called on the post thread when the post thread is paused or quits.
   void OnPostThreadPaused();
 
-  struct FrameTimeMeasurementRecord {
-    int64_t start_time;
-    pdx::LocalHandle fence;
-
-    FrameTimeMeasurementRecord(FrameTimeMeasurementRecord&&) = default;
-    FrameTimeMeasurementRecord& operator=(FrameTimeMeasurementRecord&&) =
-        default;
-    FrameTimeMeasurementRecord(const FrameTimeMeasurementRecord&) = delete;
-    FrameTimeMeasurementRecord& operator=(const FrameTimeMeasurementRecord&) =
-        delete;
-  };
-
-  void UpdateFrameTimeHistory(std::vector<FrameTimeMeasurementRecord>* backlog,
-                              int backlog_max,
-                              FenceInfoBuffer* fence_info_buffer,
-                              FrameTimeHistory* history);
-
-  // Returns true if the frame finished rendering, false otherwise. If the frame
-  // finished the frame end time is stored in timestamp. Doesn't block.
-  bool CheckFrameFinished(int frame_fence_fd,
-                          FenceInfoBuffer* fence_info_buffer,
-                          int64_t* timestamp);
-
-  void HandlePendingScreenshots();
-
   bool initialized_;
 
-  // Hardware composer HAL device.
-  std::unique_ptr<Hwc2::Composer> hwc2_hidl_;
+  // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own
+  // this pointer.
+  Hwc2::Composer* hwc2_hidl_;
+  RequestDisplayCallback request_display_callback_;
   sp<ComposerCallback> callbacks_;
 
   // Display metrics of the physical display.
@@ -345,69 +381,36 @@
   // landscape.
   HWCDisplayMetrics display_metrics_;
   // Transform required to get from native to logical display orientation.
-  hwc_transform_t display_transform_;
+  HWC::Transform display_transform_ = HWC::Transform::None;
 
-  // Buffer for the background layer required by hardware composer.
-  std::shared_ptr<IonBuffer> framebuffer_target_;
-
-  // Protects access to variables used by the post thread and one of the control
-  // threads (either the vr flinger dispatcher thread or the surface flinger
-  // main thread). This includes active_surfaces_, active_surfaces_updated_,
-  // post_thread_enabled_, post_thread_running_, and
-  // post_thread_quit_requested_.
-  std::mutex post_thread_mutex_;
-
-  // Surfaces configured by the display manager. Written by the vr flinger
-  // dispatcher thread, read by the post thread.
-  std::vector<std::shared_ptr<DisplaySurface>> active_surfaces_;
-  // active_surfaces_updated_ is set to true by the vr flinger dispatcher thread
-  // when the list of active surfaces changes. active_surfaces_updated_ will be
-  // set back to false by the post thread when it processes the update.
-  bool active_surfaces_updated_;
+  // 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.
+  std::vector<std::shared_ptr<DirectDisplaySurface>> pending_surfaces_;
 
   // The surfaces displayed by the post thread. Used exclusively by the post
   // thread.
-  std::vector<std::shared_ptr<DisplaySurface>> display_surfaces_;
-
-  // The surfaces rendered by the compositor. Used exclusively by the post
-  // thread.
-  std::vector<std::shared_ptr<DisplaySurface>> compositor_surfaces_;
+  std::vector<std::shared_ptr<DirectDisplaySurface>> display_surfaces_;
 
   // Layer array for handling buffer flow into hardware composer layers.
-  // Note that the first array is the actual storage for the layer objects,
-  // and the latter is an array of pointers, which can be freely re-arranged
-  // without messing up the underlying objects.
-  std::array<Layer, kMaxHardwareLayers> layer_storage_;
-  std::array<Layer*, kMaxHardwareLayers> layers_;
-  size_t active_layer_count_;
-
-  // Set by the Post thread to the index of the GPU compositing output
-  // buffer in the layers_ array.
-  Layer* gpu_layer_;
+  std::array<Layer, kMaxHardwareLayers> layers_;
+  size_t active_layer_count_ = 0;
 
   // Handler to hook vsync events outside of this class.
   VSyncCallback vsync_callback_;
 
   // The layer posting thread. This thread wakes up a short time before vsync to
-  // hand buffers to post processing and the results to hardware composer.
+  // hand buffers to hardware composer.
   std::thread post_thread_;
 
-  // Set to true if the post thread is allowed to run. Surface flinger and vr
-  // flinger share access to the display, and vr flinger shouldn't use the
-  // display while surface flinger is using it. While surface flinger owns the
-  // display, post_thread_enabled_ will be set to false to indicate the post
-  // thread shouldn't run.
-  bool post_thread_enabled_;
-  // Set to true by the post thread if it's currently running.
-  bool post_thread_running_;
-  // Set to true if the post thread should quit. Only set when destroying the
-  // HardwareComposer instance.
-  bool post_thread_quit_requested_;
-  // Used to wake the post thread up while it's waiting for vsync or sleeping
-  // until EDS preemption, for faster transition to the paused state.
-  pdx::LocalHandle post_thread_interrupt_event_fd_;
-  // Used to communicate between the control thread and the post thread.
-  std::condition_variable post_thread_cond_var_;
+  // Post thread state machine and synchronization primitives.
+  PostThreadStateType post_thread_state_{PostThreadState::Idle};
+  std::atomic<bool> post_thread_quiescent_{true};
+  bool post_thread_resumed_{false};
+  pdx::LocalHandle post_thread_event_fd_;
+  std::mutex post_thread_mutex_;
+  std::condition_variable post_thread_wait_;
+  std::condition_variable post_thread_ready_;
 
   // Backlight LED brightness sysfs node.
   pdx::LocalHandle backlight_brightness_fd_;
@@ -422,16 +425,13 @@
   pdx::LocalHandle vsync_sleep_timer_fd_;
 
   // The timestamp of the last vsync.
-  int64_t last_vsync_timestamp_;
+  int64_t last_vsync_timestamp_ = 0;
 
   // Vsync count since display on.
-  uint32_t vsync_count_;
+  uint32_t vsync_count_ = 0;
 
   // Counter tracking the number of skipped frames.
-  int frame_skip_count_;
-
-  // After construction, only accessed on post_thread_.
-  Compositor compositor_;
+  int frame_skip_count_ = 0;
 
   // Fd array for tracking retire fences that are returned by hwc. This allows
   // us to detect when the display driver begins queuing frames.
@@ -439,16 +439,7 @@
 
   // Pose client for frame count notifications. Pose client predicts poses
   // out to display frame boundaries, so we need to tell it about vsyncs.
-  DvrPose* pose_client_;
-
-  // Our history of frame times. This is used to get a better estimate of how
-  // long the next frame will take, to set a schedule for EDS.
-  FrameTimeHistory frame_time_history_;
-
-  // The backlog is used to allow us to start rendering the next frame before
-  // the previous frame has finished, and still get an accurate measurement of
-  // frame duration.
-  std::vector<FrameTimeMeasurementRecord> frame_time_backlog_;
+  DvrPose* pose_client_ = nullptr;
 
   static constexpr int kPostThreadInterrupted = 1;
 
diff --git a/libs/vr/libvrflinger/hwc_types.h b/libs/vr/libvrflinger/hwc_types.h
new file mode 100644
index 0000000..cbf636c
--- /dev/null
+++ b/libs/vr/libvrflinger/hwc_types.h
@@ -0,0 +1,300 @@
+#ifndef ANDROID_LIBVRFLINGER_HWCTYPES_H
+#define ANDROID_LIBVRFLINGER_HWCTYPES_H
+
+// General HWC type support. Hardware composer type support is a bit of a mess
+// between HWC1, HWC2 C/C++11, and HIDL types. Particularly bothersome is the
+// use of enum classes, which make analogous types between versions much
+// harder to deal with in a uniform way.
+//
+// These utilities help address some of these pains by providing a type-safe,
+// flexible interface to translate between different type spaces.
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include <string>
+#include <type_traits>
+
+namespace HWC {
+
+// Value types derived from HWC HAL types. Some of these are stand-alone,
+// while others are also wrapped in translator classes below.
+using ColorMode = int32_t;  // android_color_mode_t;
+using Config = hwc2_config_t;
+using ColorTransform =
+    std::underlying_type<android_color_transform_t>::type;          // int32_t;
+using Dataspace = std::underlying_type<android_dataspace_t>::type;  // int32_t;
+using DisplayId = hwc2_display_t;
+using DisplayRequest = std::underlying_type<HWC2::DisplayRequest>::type;
+using Hdr = std::underlying_type<android_hdr_t>::type;  // int32_t;
+using Layer = hwc2_layer_t;
+using PixelFormat =
+    std::underlying_type<android_pixel_format_t>::type;  // int32_t;
+
+// Type traits and casting utilities.
+
+// SFINAE utility to evaluate type expressions.
+template <typename...>
+using TestTypeExpression = void;
+
+// Traits type to determine the underlying type of an enum, integer,
+// or wrapper class.
+template <typename T, typename = typename std::is_enum<T>::type,
+          typename = typename std::is_integral<T>::type, typename = void>
+struct UnderlyingType {
+  using Type = T;
+};
+// Partial specialization that matches enum types. Captures the underlying type
+// of the enum in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::true_type, std::false_type> {
+  using Type = typename std::underlying_type<T>::type;
+};
+// Partial specialization that matches integral types. Captures the type of the
+// integer in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::false_type, std::true_type> {
+  using Type = T;
+};
+// Partial specialization that matches the wrapper types below. Captures
+// wrapper member type ValueType in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::false_type, std::false_type,
+                      TestTypeExpression<typename T::ValueType>> {
+  using Type = typename T::ValueType;
+};
+
+// Enable if T is an enum with underlying type U.
+template <typename T, typename U, typename ReturnType = void>
+using EnableIfMatchingEnum = typename std::enable_if<
+    std::is_enum<T>::value &&
+        std::is_same<U, typename UnderlyingType<T>::Type>::value,
+    ReturnType>::type;
+
+// Enable if T and U are the same size/alignment and have the same underlying
+// type. Handles enum, integral, and wrapper classes below.
+template <typename T, typename U, typename Return = void>
+using EnableIfSafeCast = typename std::enable_if<
+    sizeof(T) == sizeof(U) && alignof(T) == alignof(U) &&
+        std::is_same<typename UnderlyingType<T>::Type,
+                     typename UnderlyingType<U>::Type>::value,
+    Return>::type;
+
+// Safely cast between std::vectors of matching enum/integer/wraper types.
+// Normally this is not possible with pendantic compiler type checks. However,
+// given the same size, alignment, and underlying type this is safe due to
+// allocator requirements and array-like element access guarantees.
+template <typename T, typename U>
+EnableIfSafeCast<T, U, std::vector<T>*> VectorCast(std::vector<U>* in) {
+  return reinterpret_cast<std::vector<T>*>(in);
+}
+
+// Translator classes that wrap specific HWC types to make translating
+// between different types (especially enum class) in code cleaner.
+
+// Base type for the enum wrappers below. This type provides type definitions
+// and implicit conversion logic common to each wrapper type.
+template <typename EnumType>
+struct Wrapper {
+  // Alias type of this instantiantion of Wrapper. Useful for inheriting
+  // constructors in subclasses via "using Base::Base;" statements.
+  using Base = Wrapper<EnumType>;
+
+  // The enum type wrapped by this instantiation of Wrapper.
+  using BaseType = EnumType;
+
+  // The underlying type of the base enum type.
+  using ValueType = typename UnderlyingType<BaseType>::Type;
+
+  // A default constructor is not defined here. Subclasses should define one
+  // as appropriate to define the correct inital value for the enum type.
+
+  // Default copy constructor.
+  Wrapper(const Wrapper&) = default;
+
+  // Implicit conversion from ValueType.
+  Wrapper(ValueType value) : value(value) {}
+
+  // Implicit conversion from BaseType.
+  Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {}
+
+  // Implicit conversion from an enum type of the same underlying type.
+  template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+  Wrapper(const T& value) : value(static_cast<ValueType>(value)) {}
+
+  // Implicit conversion to BaseType.
+  operator BaseType() const { return static_cast<BaseType>(value); }
+
+  // Implicit conversion to ValueType.
+  operator ValueType() const { return value; }
+
+  template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+  T cast() const {
+    return static_cast<T>(value);
+  }
+
+  // Converts to string using HWC2 stringification of BaseType.
+  std::string to_string() const {
+    return HWC2::to_string(static_cast<BaseType>(value));
+  }
+
+  bool operator!=(const Wrapper& other) const { return value != other.value; }
+  bool operator!=(ValueType other_value) const { return value != other_value; }
+  bool operator!=(BaseType other_value) const {
+    return static_cast<BaseType>(value) != other_value;
+  }
+  bool operator==(const Wrapper& other) const { return value == other.value; }
+  bool operator==(ValueType other_value) const { return value == other_value; }
+  bool operator==(BaseType other_value) const {
+    return static_cast<BaseType>(value) == other_value;
+  }
+
+  ValueType value;
+};
+
+struct Attribute final : public Wrapper<HWC2::Attribute> {
+  enum : ValueType {
+    Invalid = HWC2_ATTRIBUTE_INVALID,
+    Width = HWC2_ATTRIBUTE_WIDTH,
+    Height = HWC2_ATTRIBUTE_HEIGHT,
+    VsyncPeriod = HWC2_ATTRIBUTE_VSYNC_PERIOD,
+    DpiX = HWC2_ATTRIBUTE_DPI_X,
+    DpiY = HWC2_ATTRIBUTE_DPI_Y,
+  };
+
+  Attribute() : Base(Invalid) {}
+  using Base::Base;
+};
+
+struct BlendMode final : public Wrapper<HWC2::BlendMode> {
+  enum : ValueType {
+    Invalid = HWC2_BLEND_MODE_INVALID,
+    None = HWC2_BLEND_MODE_NONE,
+    Premultiplied = HWC2_BLEND_MODE_PREMULTIPLIED,
+    Coverage = HWC2_BLEND_MODE_COVERAGE,
+  };
+
+  BlendMode() : Base(Invalid) {}
+  using Base::Base;
+};
+
+struct Composition final : public Wrapper<HWC2::Composition> {
+  enum : ValueType {
+    Invalid = HWC2_COMPOSITION_INVALID,
+    Client = HWC2_COMPOSITION_CLIENT,
+    Device = HWC2_COMPOSITION_DEVICE,
+    SolidColor = HWC2_COMPOSITION_SOLID_COLOR,
+    Cursor = HWC2_COMPOSITION_CURSOR,
+    Sideband = HWC2_COMPOSITION_SIDEBAND,
+  };
+
+  Composition() : Base(Invalid) {}
+  using Base::Base;
+};
+
+struct DisplayType final : public Wrapper<HWC2::DisplayType> {
+  enum : ValueType {
+    Invalid = HWC2_DISPLAY_TYPE_INVALID,
+    Physical = HWC2_DISPLAY_TYPE_PHYSICAL,
+    Virtual = HWC2_DISPLAY_TYPE_VIRTUAL,
+  };
+
+  DisplayType() : Base(Invalid) {}
+  using Base::Base;
+};
+
+struct Error final : public Wrapper<HWC2::Error> {
+  enum : ValueType {
+    None = HWC2_ERROR_NONE,
+    BadConfig = HWC2_ERROR_BAD_CONFIG,
+    BadDisplay = HWC2_ERROR_BAD_DISPLAY,
+    BadLayer = HWC2_ERROR_BAD_LAYER,
+    BadParameter = HWC2_ERROR_BAD_PARAMETER,
+    HasChanges = HWC2_ERROR_HAS_CHANGES,
+    NoResources = HWC2_ERROR_NO_RESOURCES,
+    NotValidated = HWC2_ERROR_NOT_VALIDATED,
+    Unsupported = HWC2_ERROR_UNSUPPORTED,
+  };
+
+  Error() : Base(None) {}
+  using Base::Base;
+};
+
+struct LayerRequest final : public Wrapper<HWC2::LayerRequest> {
+  enum : ValueType {
+    ClearClientTarget = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET,
+  };
+
+  LayerRequest() : Base(0) {}
+  using Base::Base;
+};
+
+struct PowerMode final : public Wrapper<HWC2::PowerMode> {
+  enum : ValueType {
+    Off = HWC2_POWER_MODE_OFF,
+    DozeSuspend = HWC2_POWER_MODE_DOZE_SUSPEND,
+    Doze = HWC2_POWER_MODE_DOZE,
+    On = HWC2_POWER_MODE_ON,
+  };
+
+  PowerMode() : Base(Off) {}
+  using Base::Base;
+};
+
+struct Transform final : public Wrapper<HWC2::Transform> {
+  enum : ValueType {
+    None = 0,
+    FlipH = HWC_TRANSFORM_FLIP_H,
+    FlipV = HWC_TRANSFORM_FLIP_V,
+    Rotate90 = HWC_TRANSFORM_ROT_90,
+    Rotate180 = HWC_TRANSFORM_ROT_180,
+    Rotate270 = HWC_TRANSFORM_ROT_270,
+    FlipHRotate90 = HWC_TRANSFORM_FLIP_H_ROT_90,
+    FlipVRotate90 = HWC_TRANSFORM_FLIP_V_ROT_90,
+  };
+
+  Transform() : Base(None) {}
+  using Base::Base;
+};
+
+struct Vsync final : public Wrapper<HWC2::Vsync> {
+  enum : ValueType {
+    Invalid = HWC2_VSYNC_INVALID,
+    Enable = HWC2_VSYNC_ENABLE,
+    Disable = HWC2_VSYNC_DISABLE,
+  };
+
+  Vsync() : Base(Invalid) {}
+  using Base::Base;
+};
+
+// Utility color type.
+struct Color final {
+  Color(const Color&) = default;
+  Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
+  Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
+
+  operator hwc_color_t() const { return {r, g, b, a}; }
+
+  uint8_t r __attribute__((aligned(1)));
+  uint8_t g __attribute__((aligned(1)));
+  uint8_t b __attribute__((aligned(1)));
+  uint8_t a __attribute__((aligned(1)));
+};
+
+// Utility rectangle type.
+struct Rect final {
+  // TODO(eieio): Implicit conversion to/from Android rect types.
+
+  int32_t left __attribute__((aligned(4)));
+  int32_t top __attribute__((aligned(4)));
+  int32_t right __attribute__((aligned(4)));
+  int32_t bottom __attribute__((aligned(4)));
+};
+
+}  // namespace HWC
+
+#endif  // ANDROID_LIBVRFLINGER_HWCTYPES_H
diff --git a/libs/vr/libvrflinger/screenshot_service.cpp b/libs/vr/libvrflinger/screenshot_service.cpp
deleted file mode 100644
index d14d588..0000000
--- a/libs/vr/libvrflinger/screenshot_service.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "screenshot_service.h"
-
-#include <utils/Trace.h>
-
-#include <pdx/default_transport/service_endpoint.h>
-#include <private/android_filesystem_config.h>
-#include <private/dvr/display_types.h>
-#include <private/dvr/trusted_uids.h>
-
-using android::pdx::Message;
-using android::pdx::MessageInfo;
-using android::pdx::default_transport::Endpoint;
-using android::pdx::rpc::DispatchRemoteMethod;
-using android::pdx::rpc::RemoteMethodError;
-using android::pdx::rpc::RemoteMethodReturn;
-
-namespace android {
-namespace dvr {
-
-ScreenshotService::~ScreenshotService() { instance_ = nullptr; }
-
-pdx::Status<void> ScreenshotService::HandleMessage(pdx::Message& message) {
-  switch (message.GetOp()) {
-    case DisplayScreenshotRPC::GetFormat::Opcode:
-      DispatchRemoteMethod<DisplayScreenshotRPC::GetFormat>(
-          *this, &ScreenshotService::OnGetFormat, message);
-      return {};
-
-    case DisplayScreenshotRPC::TakeScreenshot::Opcode:
-      DispatchRemoteMethod<DisplayScreenshotRPC::TakeScreenshot>(
-          *this, &ScreenshotService::OnTakeScreenshot, message);
-      return {};
-
-    default:
-      return Service::HandleMessage(message);
-  }
-}
-
-int ScreenshotService::OnGetFormat(pdx::Message&) {
-  return HAL_PIXEL_FORMAT_RGB_888;
-}
-
-ScreenshotData ScreenshotService::OnTakeScreenshot(pdx::Message& message,
-                                                   int layer_index) {
-  // Also allow AID_SHELL to support vrscreencap commands.
-  if (message.GetEffectiveUserId() != AID_SHELL &&
-      !IsTrustedUid(message.GetEffectiveUserId())) {
-    REPLY_ERROR_RETURN(message, EACCES, {});
-  }
-
-  AddWaiter(std::move(message), layer_index);
-  return {};
-}
-
-void ScreenshotService::AddWaiter(pdx::Message&& message, int layer_index) {
-  std::lock_guard<std::mutex> lock(mutex_);
-  waiters_.emplace_back(std::move(message), layer_index);
-}
-
-void ScreenshotService::TakeIfNeeded(
-    std::array<Layer*, HardwareComposer::kMaxHardwareLayers>& hw_layers,
-    Compositor& compositor) {
-  std::lock_guard<std::mutex> lock(mutex_);
-
-  // Send the buffer contents to all of our waiting clients.
-  for (auto& waiter : waiters_) {
-    if (waiter.IsDone())
-      continue;
-
-    if (waiter.layer_index() == 0) {
-      ALOGE(
-          "ScreenshotService::TakeIfNeeded: Capturing the composited display "
-          "output is not yet supported.");
-
-      waiter.Error(EINVAL);
-      continue;
-    }
-
-    if (waiter.layer_index() > 0) {
-      // Check for hardware layer screenshot requests.
-      // Hardware layers are requested with positive indices starting at 1.
-      const size_t layer_index = static_cast<size_t>(waiter.layer_index() - 1);
-
-      if (layer_index >= hw_layers.size()) {
-        waiter.Error(EINVAL);
-        continue;
-      }
-
-      auto buffer = hw_layers[layer_index]->GetBuffer();
-      if (!buffer) {
-        waiter.Error(ENOBUFS);
-        continue;
-      }
-
-      auto data = compositor.ReadBufferPixels(buffer);
-      if (data.empty()) {
-        waiter.Error(ENOBUFS);
-        continue;
-      }
-
-      Take(&waiter, data.data(), buffer->width(), buffer->height(),
-           buffer->width());
-    } else {
-      // Check for compositor input layer screenshot requests.
-      // Prewarp surfaces are requested with negative indices starting at -1.
-      const size_t layer_index = static_cast<size_t>(-waiter.layer_index() - 1);
-
-      if (layer_index >= compositor.GetLayerCount()) {
-        waiter.Error(EINVAL);
-        continue;
-      }
-
-      int width = 0;
-      int height = 0;
-      auto data = compositor.ReadLayerPixels(layer_index, &width, &height);
-      if (data.empty()) {
-        waiter.Error(ENOBUFS);
-        continue;
-      }
-
-      Take(&waiter, data.data(), width, height, width);
-    }
-  }
-
-  // Reply with error to requests that did not match up with a source layer.
-  for (auto& waiter : waiters_) {
-    if (!waiter.IsDone())
-      waiter.Error(EAGAIN);
-  }
-  waiters_.clear();
-}
-
-void ScreenshotWaiter::Reply(const ScreenshotData& screenshot) {
-  ALOGI("Returning screenshot: size=%zu recv_size=%zu",
-        screenshot.buffer.size(), message_.GetReceiveLength());
-  RemoteMethodReturn<DisplayScreenshotRPC::TakeScreenshot>(message_,
-                                                           screenshot);
-}
-
-void ScreenshotWaiter::Error(int error) { RemoteMethodError(message_, error); }
-
-void ScreenshotService::Take(ScreenshotWaiter* waiter, const void* rgba_data,
-                             int32_t width, int32_t height, int buffer_stride) {
-  ATRACE_NAME(__PRETTY_FUNCTION__);
-
-  bool is_portrait = height > width;
-  if (is_portrait) {
-    std::swap(width, height);
-  }
-  int response_stride = width;
-
-  // Convert from RGBA to RGB and if in portrait, rotates to landscape; store
-  // the result in the response buffer.
-  ScreenshotData screenshot{width, height,
-                            std::vector<uint8_t>(width * height * 3)};
-
-  const auto rgba_bytes = static_cast<const uint8_t*>(rgba_data);
-  for (int j = 0; j < height; ++j) {
-    for (int i = 0; i < width; ++i) {
-      // If the screenshot is in portrait mode, rotate into landscape mode.
-      const int response_index = is_portrait
-                                     ? (height - j - 1) * response_stride + i
-                                     : j * response_stride + i;
-      const int buffer_index =
-          is_portrait ? i * buffer_stride + j : j * buffer_stride + i;
-      screenshot.buffer[response_index * 3 + 0] =
-          rgba_bytes[buffer_index * 4 + 0];
-      screenshot.buffer[response_index * 3 + 1] =
-          rgba_bytes[buffer_index * 4 + 1];
-      screenshot.buffer[response_index * 3 + 2] =
-          rgba_bytes[buffer_index * 4 + 2];
-    }
-  }
-
-  waiter->Reply(screenshot);
-}
-
-ScreenshotService::ScreenshotService()
-    : BASE("ScreenshotService",
-           Endpoint::Create(DisplayScreenshotRPC::kClientPath)) {
-  instance_ = this;
-}
-
-ScreenshotService* ScreenshotService::GetInstance() { return instance_; }
-
-ScreenshotService* ScreenshotService::instance_ = nullptr;
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/screenshot_service.h b/libs/vr/libvrflinger/screenshot_service.h
deleted file mode 100644
index f59e872..0000000
--- a/libs/vr/libvrflinger/screenshot_service.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
-
-#include <pdx/rpc/pointer_wrapper.h>
-#include <pdx/service.h>
-#include <private/dvr/ion_buffer.h>
-
-#include <mutex>
-#include <vector>
-
-#include "hardware_composer.h"
-
-namespace android {
-namespace dvr {
-
-class ScreenshotWaiter {
- public:
-  explicit ScreenshotWaiter(pdx::Message&& message, int layer_index)
-      : message_(std::move(message)), layer_index_(layer_index) {}
-  ScreenshotWaiter(ScreenshotWaiter&&) = default;
-
-  void Reply(const ScreenshotData& screenshot);
-  void Error(int error);
-
-  bool IsDone() const { return message_.replied(); }
-  int layer_index() const { return layer_index_; }
-
- private:
-  pdx::Message message_;
-  int layer_index_;
-
-  ScreenshotWaiter(const ScreenshotWaiter&) = delete;
-  void operator=(const ScreenshotWaiter&) = delete;
-};
-
-// The screenshot service allows clients to obtain screenshots from displayd.
-class ScreenshotService : public pdx::ServiceBase<ScreenshotService> {
- public:
-  ~ScreenshotService();
-
-  pdx::Status<void> HandleMessage(pdx::Message& message) override;
-
-  // Returns true if there is a pending screenshot request.
-  bool IsScreenshotRequestPending() const {
-    std::lock_guard<std::mutex> lock(mutex_);
-    return !waiters_.empty();
-  }
-
-  // If any clients are currently waiting for a screenshot, read back the
-  // contents of requested layers and send the resulting
-  // image to the clients.
-  void TakeIfNeeded(
-      std::array<Layer*, HardwareComposer::kMaxHardwareLayers>& hw_layers,
-      Compositor& compositor);
-
-  static ScreenshotService* GetInstance();
-
- private:
-  friend BASE;
-
-  ScreenshotService();
-
-  void AddWaiter(pdx::Message&& message, int layer_index);
-
-  ScreenshotData OnTakeScreenshot(pdx::Message& message, int index);
-  int OnGetFormat(pdx::Message& message);
-
-  // Copy the given screenshot data into the message reply.
-  void Take(ScreenshotWaiter* waiter, const void* rgba_data, int32_t width,
-            int32_t height, int buffer_stride);
-
-  static ScreenshotService* instance_;
-
-  // Protects access to subsequent member variables.
-  mutable std::mutex mutex_;
-  std::vector<ScreenshotWaiter> waiters_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
diff --git a/libs/vr/libvrflinger/surface_channel.cpp b/libs/vr/libvrflinger/surface_channel.cpp
deleted file mode 100644
index 263b382..0000000
--- a/libs/vr/libvrflinger/surface_channel.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "surface_channel.h"
-
-using android::pdx::BorrowedChannelHandle;
-using android::pdx::Message;
-using android::pdx::rpc::DispatchRemoteMethod;
-
-namespace android {
-namespace dvr {
-
-pdx::Status<void> SurfaceChannel::HandleMessage(Message& message) {
-  switch (message.GetOp()) {
-    case DisplayRPC::GetMetadataBuffer::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetMetadataBuffer>(
-          *this, &SurfaceChannel::OnGetMetadataBuffer, message);
-      break;
-  }
-
-  return {};
-}
-
-BorrowedChannelHandle SurfaceChannel::OnGetMetadataBuffer(Message& message) {
-  if (EnsureMetadataBuffer()) {
-    return metadata_buffer_->GetChannelHandle().Borrow();
-  } else {
-    REPLY_ERROR_RETURN(message, -ENOMEM, {});
-  }
-}
-
-bool SurfaceChannel::EnsureMetadataBuffer() {
-  if (!metadata_buffer_) {
-    metadata_buffer_ =
-        BufferProducer::CreateUncachedBlob(metadata_size());
-    if (!metadata_buffer_) {
-      ALOGE(
-          "DisplaySurface::EnsureMetadataBuffer: could not allocate metadata "
-          "buffer");
-      return false;
-    }
-  }
-  return true;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/surface_channel.h b/libs/vr/libvrflinger/surface_channel.h
deleted file mode 100644
index bb6b1c5..0000000
--- a/libs/vr/libvrflinger/surface_channel.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
-
-#include <pdx/service.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/display_rpc.h>
-
-namespace android {
-namespace dvr {
-
-class DisplayService;
-
-class SurfaceChannel : public pdx::Channel {
- public:
-  SurfaceChannel(DisplayService* service, int channel_id, SurfaceType type,
-                 size_t metadata_size)
-      : service_(service),
-        surface_id_(channel_id),
-        type_(type),
-        metadata_size_(metadata_size) {}
-
-  ~SurfaceChannel() override = default;
-
-  DisplayService* service() const { return service_; }
-  int surface_id() const { return surface_id_; }
-  SurfaceType type() const { return type_; }
-  size_t metadata_size() const { return metadata_size_; }
-
-  pdx::LocalHandle GetMetadataBufferFd() {
-    return EnsureMetadataBuffer() ? metadata_buffer_->GetBlobFd()
-                                  : pdx::LocalHandle{};
-  }
-
-  // Dispatches surface channel messages to the appropriate handlers. This
-  // handler runs on the displayd message dispatch thread.
-  virtual pdx::Status<void> HandleMessage(pdx::Message& message);
-
- protected:
-  // Contains the surface metadata.
-  std::shared_ptr<BufferProducer> metadata_buffer_;
-
-  // Returns the metadata buffer for this surface. The first call allocates the
-  // buffer, while subsequent calls return the same buffer.
-  pdx::BorrowedChannelHandle OnGetMetadataBuffer(pdx::Message& message);
-
-  // Allocates the single metadata buffer for this surface unless it is already
-  // allocated. Idempotent when called multiple times.
-  bool EnsureMetadataBuffer();
-
- private:
-  DisplayService* service_;
-  int surface_id_;
-  SurfaceType type_;
-  size_t metadata_size_;
-
-  SurfaceChannel(const SurfaceChannel&) = delete;
-  void operator=(const SurfaceChannel&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
diff --git a/libs/vr/libvrflinger/video_compositor.cpp b/libs/vr/libvrflinger/video_compositor.cpp
deleted file mode 100644
index c5a5b64..0000000
--- a/libs/vr/libvrflinger/video_compositor.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-#include "video_compositor.h"
-
-#include <EGL/eglext.h>
-#include <GLES2/gl2ext.h>
-
-#include <private/dvr/debug.h>
-#include <private/dvr/display_rpc.h>
-
-namespace android {
-namespace dvr {
-
-VideoCompositor::Texture::Texture(
-    EGLDisplay display, const std::shared_ptr<BufferConsumer>& buffer_consumer)
-    : display_(display),
-      image_(EGL_NO_IMAGE_KHR),
-      texture_id_(0),
-      buffer_consumer_(buffer_consumer) {}
-
-VideoCompositor::Texture::~Texture() {
-  if (image_ != EGL_NO_IMAGE_KHR)
-    eglDestroyImageKHR(display_, image_);
-  if (texture_id_ != 0)
-    glDeleteTextures(1, &texture_id_);
-}
-
-GLuint VideoCompositor::Texture::EnsureTextureReady() {
-  if (!image_) {
-    native_buffer_ = new NativeBuffer(buffer_consumer_);
-    CHECK_GL();
-
-    image_ = eglCreateImageKHR(
-        display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-        static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
-    if (!image_) {
-      ALOGE("Failed to create EGLImage.");
-      return 0;
-    }
-
-    glGenTextures(1, &texture_id_);
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image_);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
-                    GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
-                    GL_CLAMP_TO_EDGE);
-    CHECK_GL();
-  }
-
-  return texture_id_;
-}
-
-void VideoCompositor::Texture::Release() {
-  const int ret = buffer_consumer_->Release({});
-  if (ret < 0) {
-    ALOGE(
-        "VideoCompositor::Texture::Release: Failed to release buffer, error: "
-        "%s",
-        strerror(-ret));
-  }
-}
-
-VideoCompositor::VideoCompositor(
-    const std::shared_ptr<VideoMeshSurface>& surface,
-    const volatile DisplaySurfaceMetadata* display_surface_metadata)
-    : surface_(surface),
-      consumer_queue_(surface->GetConsumerQueue()),
-      transform_metadata_(display_surface_metadata),
-      active_texture_slot_(-1) {}
-
-GLuint VideoCompositor::GetActiveTextureId(EGLDisplay display) {
-  size_t slot;
-  BufferHubQueueCore::NativeBufferMetadata metadata;
-
-  while (true) {
-    // A native way to pick the active texture: always dequeue all buffers from
-    // the queue until it's empty. This works well as long as video frames are
-    // queued in order from the producer side.
-    // TODO(jwcai) Use |metadata.timestamp_ns| to schedule video frames
-    // accurately.
-    LocalHandle acquire_fence;
-    auto buffer_consumer =
-        consumer_queue_->Dequeue(0, &slot, &metadata, &acquire_fence);
-
-    if (buffer_consumer) {
-      // Create a new texture if it hasn't been created yet, or the same slot
-      // has a new |buffer_consumer|.
-      if (textures_[slot] == nullptr ||
-          textures_[slot]->event_fd() != buffer_consumer->event_fd()) {
-        textures_[slot] =
-            std::unique_ptr<Texture>(new Texture(display, buffer_consumer));
-      }
-
-      if (active_texture_slot_ != static_cast<int>(slot)) {
-        if (active_texture_slot_ >= 0) {
-          // Release the last active texture and move on to use the new one.
-          textures_[active_texture_slot_]->Release();
-        }
-        active_texture_slot_ = slot;
-      }
-    } else {
-      break;
-    }
-  }
-
-  if (active_texture_slot_ < 0) {
-    // No texture is active yet.
-    return 0;
-  }
-
-  return textures_[active_texture_slot_]->EnsureTextureReady();
-}
-
-mat4 VideoCompositor::GetTransform(int eye, size_t render_buffer_index) {
-  volatile const VideoMeshSurfaceMetadata* transform_metadata =
-      surface_->GetMetadataBufferPtr();
-
-  mat4 screen_transform;
-  for (int i = 0; i < 4; ++i) {
-    for (int j = 0; j < 4; ++j) {
-      screen_transform(i, j) =
-          transform_metadata->transform[render_buffer_index][eye].val[i][j];
-    }
-  }
-
-  return screen_transform;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/video_compositor.h b/libs/vr/libvrflinger/video_compositor.h
deleted file mode 100644
index d0e72e1..0000000
--- a/libs/vr/libvrflinger/video_compositor.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
-
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <private/dvr/buffer_hub_queue_core.h>
-#include <private/dvr/types.h>
-
-#include <vector>
-
-#include "display_surface.h"
-#include "video_mesh_surface.h"
-
-namespace android {
-namespace dvr {
-
-using pdx::LocalHandle;
-
-// Manages video buffer consumers, texture mapping, and playback timing.
-class VideoCompositor {
- public:
-  VideoCompositor(
-      const std::shared_ptr<VideoMeshSurface>& surface,
-      const volatile DisplaySurfaceMetadata* display_surface_metadata);
-
-  int surface_id() const { return surface_ ? surface_->surface_id() : -1; }
-
-  // Returns a GL texture id that should be composited by displayd during the
-  // current rendering loop. Note that this function must be called in
-  // displayd's GL context.
-  GLuint GetActiveTextureId(EGLDisplay display);
-
-  // Returns a basic video mesh tranform.
-  mat4 GetTransform(int eye, size_t render_buffer_index);
-
- private:
-  class Texture {
-   public:
-    Texture(EGLDisplay display,
-            const std::shared_ptr<BufferConsumer>& buffer_consumer);
-    ~Texture();
-
-    // Returns the |event_fd| of the underlying buffer consumer. Caller can use
-    // this to decided whether the Texture need to be recreated for a different
-    // buffer consumer.
-    int event_fd() const { return buffer_consumer_->event_fd(); }
-
-    // Method to map a dvr::BufferConsumer to a GL texture within the current GL
-    // context. If the current Texture object's |image_| hasn't been
-    // initialized, the method will do so based on the |buffer_consumer| and a
-    // new GL texture will be generated, cached, and returned. Otherwise, the
-    // cached |texture_id_| will be returned directly.
-    GLuint EnsureTextureReady();
-
-    // Signal bufferhub that the texture is done rendering so that the buffer
-    // can be re-gained by the producer for future use.
-    void Release();
-
-   private:
-    using NativeBuffer = BufferHubQueueCore::NativeBuffer;
-
-    EGLDisplay display_;
-    EGLImageKHR image_;
-    GLuint texture_id_;
-    sp<NativeBuffer> native_buffer_;
-    std::shared_ptr<BufferConsumer> buffer_consumer_;
-  };
-
-  std::shared_ptr<VideoMeshSurface> surface_;
-  std::shared_ptr<ConsumerQueue> consumer_queue_;
-  std::array<std::unique_ptr<Texture>, BufferHubQueue::kMaxQueueCapacity>
-      textures_;
-
-  const volatile DisplaySurfaceMetadata* transform_metadata_;
-  int active_texture_slot_;
-
-  VideoCompositor(const VideoCompositor&) = delete;
-  void operator=(const VideoCompositor&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
diff --git a/libs/vr/libvrflinger/video_mesh_surface.cpp b/libs/vr/libvrflinger/video_mesh_surface.cpp
deleted file mode 100644
index ce0dfca..0000000
--- a/libs/vr/libvrflinger/video_mesh_surface.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "video_mesh_surface.h"
-
-#include <private/dvr/buffer_hub_queue_core.h>
-#include <private/dvr/display_rpc.h>
-
-using android::pdx::LocalChannelHandle;
-using android::pdx::rpc::DispatchRemoteMethod;
-
-namespace android {
-namespace dvr {
-
-VideoMeshSurface::VideoMeshSurface(DisplayService* service, int surface_id)
-    : SurfaceChannel(service, surface_id, SurfaceTypeEnum::VideoMesh,
-                     sizeof(VideoMeshSurfaceMetadata)) {}
-
-VideoMeshSurface::~VideoMeshSurface() {}
-
-pdx::Status<void> VideoMeshSurface::HandleMessage(Message& message) {
-  ATRACE_NAME("VideoMeshSurface::HandleMessage");
-
-  switch (message.GetOp()) {
-    case DisplayRPC::VideoMeshSurfaceCreateProducerQueue::Opcode:
-      DispatchRemoteMethod<DisplayRPC::VideoMeshSurfaceCreateProducerQueue>(
-          *this, &VideoMeshSurface::OnCreateProducerQueue, message);
-      break;
-
-    default:
-      return SurfaceChannel::HandleMessage(message);
-  }
-
-  return {};
-}
-
-std::shared_ptr<ConsumerQueue> VideoMeshSurface::GetConsumerQueue() {
-  if (!consumer_queue_) {
-    ALOGE(
-        "VideoMeshSurface::GetConsumerQueue: consumer_queue is uninitialized.");
-  }
-
-  return consumer_queue_;
-}
-
-LocalChannelHandle VideoMeshSurface::OnCreateProducerQueue(Message& message) {
-  ATRACE_NAME("VideoMeshSurface::OnCreateProducerQueue");
-
-  if (consumer_queue_ != nullptr) {
-    ALOGE(
-        "VideoMeshSurface::OnCreateProducerQueue: A ProdcuerQueue has already "
-        "been created and transported to VideoMeshSurfaceClient.");
-    REPLY_ERROR_RETURN(message, EALREADY, {});
-  }
-
-  auto producer =
-      ProducerQueue::Create<BufferHubQueueCore::NativeBufferMetadata>();
-  consumer_queue_ = producer->CreateConsumerQueue();
-
-  return std::move(producer->GetChannelHandle());
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/video_mesh_surface.h b/libs/vr/libvrflinger/video_mesh_surface.h
deleted file mode 100644
index 2c9f3e8..0000000
--- a/libs/vr/libvrflinger/video_mesh_surface.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
-
-#include <private/dvr/buffer_hub_queue_client.h>
-
-#include "surface_channel.h"
-
-namespace android {
-namespace dvr {
-
-class DisplayService;
-
-// VideoMeshSurface takes three inputs: 1) buffers filled by Android system
-// components (e.g. MediaCodec or camera stack) other than applications' GL
-// context; 2) a 3D mesh chosen by application to define the shape of the
-// surface; 3) a transformation matrix from application to define the rotation,
-// position, and scaling of the video surface.
-class VideoMeshSurface : public SurfaceChannel {
- public:
-  using Message = pdx::Message;
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-
-  VideoMeshSurface(DisplayService* service, int channel_id);
-  ~VideoMeshSurface() override;
-
-  volatile const VideoMeshSurfaceMetadata* GetMetadataBufferPtr() {
-    if (EnsureMetadataBuffer()) {
-      void* addr = nullptr;
-      metadata_buffer_->GetBlobReadWritePointer(metadata_size(), &addr);
-      return static_cast<const volatile VideoMeshSurfaceMetadata*>(addr);
-    } else {
-      return nullptr;
-    }
-  }
-
-  pdx::Status<void> HandleMessage(Message& message) override;
-
-  std::shared_ptr<ConsumerQueue> GetConsumerQueue();
-
- private:
-  LocalChannelHandle OnCreateProducerQueue(Message& message);
-
-  std::shared_ptr<ConsumerQueue> consumer_queue_;
-
-  VideoMeshSurface(const VideoMeshSurface&) = delete;
-  void operator=(const VideoMeshSurface&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 21226db..b2dc1d8 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -11,9 +11,9 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
-#include <log/log.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
+#include <log/log.h>
 #include <private/dvr/display_client.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
@@ -25,7 +25,6 @@
 #include "DisplayHardware/ComposerHal.h"
 #include "display_manager_service.h"
 #include "display_service.h"
-#include "screenshot_service.h"
 #include "vsync_service.h"
 
 namespace android {
@@ -77,11 +76,11 @@
 
   request_display_callback_ = request_display_callback;
 
-  dispatcher_ =
-      android::pdx::default_transport::ServiceDispatcher::Create();
+  dispatcher_ = android::pdx::default_transport::ServiceDispatcher::Create();
   CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
 
-  display_service_ = android::dvr::DisplayService::Create(hidl);
+  display_service_ =
+      android::dvr::DisplayService::Create(hidl, request_display_callback);
   CHECK_ERROR(!display_service_, error, "Failed to create display service.");
   dispatcher_->AddService(display_service_);
 
@@ -89,10 +88,6 @@
   CHECK_ERROR(!service, error, "Failed to create display manager service.");
   dispatcher_->AddService(service);
 
-  service = android::dvr::ScreenshotService::Create();
-  CHECK_ERROR(!service, error, "Failed to create screenshot service.");
-  dispatcher_->AddService(service);
-
   service = android::dvr::VSyncService::Create();
   CHECK_ERROR(!service, error, "Failed to create vsync service.");
   dispatcher_->AddService(service);
@@ -147,7 +142,9 @@
 void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged(
     bool enabled) {
   ALOGV("Notified persistent vr mode is %s", enabled ? "on" : "off");
-  request_display_callback_(enabled);
+  // TODO(eieio): Determine the correct signal to request display control.
+  // Persistent VR mode is not enough.
+  // request_display_callback_(enabled);
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp
index 612b9b2..2a83933 100644
--- a/libs/vr/libvrflinger/vsync_service.cpp
+++ b/libs/vr/libvrflinger/vsync_service.cpp
@@ -1,17 +1,19 @@
 #include "vsync_service.h"
 
-#include <log/log.h>
 #include <hardware/hwcomposer.h>
+#include <log/log.h>
 #include <poll.h>
 #include <sys/prctl.h>
 #include <time.h>
 #include <utils/Trace.h>
 
+#include <dvr/dvr_display_types.h>
 #include <pdx/default_transport/service_endpoint.h>
 #include <private/dvr/clock_ns.h>
-#include <private/dvr/display_rpc.h>
-#include <private/dvr/display_types.h>
+#include <private/dvr/display_protocol.h>
 
+using android::dvr::display::VSyncProtocol;
+using android::dvr::display::VSyncSchedInfo;
 using android::pdx::Channel;
 using android::pdx::Message;
 using android::pdx::MessageInfo;
@@ -22,7 +24,7 @@
 namespace dvr {
 
 VSyncService::VSyncService()
-    : BASE("VSyncService", Endpoint::Create(DisplayVSyncRPC::kClientPath)),
+    : BASE("VSyncService", Endpoint::Create(VSyncProtocol::kClientPath)),
       last_vsync_(0),
       current_vsync_(0),
       compositor_time_ns_(0),
@@ -109,22 +111,22 @@
 
 pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
   switch (message.GetOp()) {
-    case DisplayVSyncRPC::Wait::Opcode:
+    case VSyncProtocol::Wait::Opcode:
       AddWaiter(message);
       return {};
 
-    case DisplayVSyncRPC::GetLastTimestamp::Opcode:
-      DispatchRemoteMethod<DisplayVSyncRPC::GetLastTimestamp>(
+    case VSyncProtocol::GetLastTimestamp::Opcode:
+      DispatchRemoteMethod<VSyncProtocol::GetLastTimestamp>(
           *this, &VSyncService::OnGetLastTimestamp, message);
       return {};
 
-    case DisplayVSyncRPC::GetSchedInfo::Opcode:
-      DispatchRemoteMethod<DisplayVSyncRPC::GetSchedInfo>(
+    case VSyncProtocol::GetSchedInfo::Opcode:
+      DispatchRemoteMethod<VSyncProtocol::GetSchedInfo>(
           *this, &VSyncService::OnGetSchedInfo, message);
       return {};
 
-    case DisplayVSyncRPC::Acknowledge::Opcode:
-      DispatchRemoteMethod<DisplayVSyncRPC::Acknowledge>(
+    case VSyncProtocol::Acknowledge::Opcode:
+      DispatchRemoteMethod<VSyncProtocol::Acknowledge>(
           *this, &VSyncService::OnAcknowledge, message);
       return {};
 
@@ -133,16 +135,17 @@
   }
 }
 
-int64_t VSyncService::OnGetLastTimestamp(pdx::Message& message) {
+pdx::Status<int64_t> VSyncService::OnGetLastTimestamp(pdx::Message& message) {
   auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
   std::lock_guard<std::mutex> autolock(mutex_);
 
   // Getting the timestamp has the side effect of ACKing.
   client->Ack();
-  return current_vsync_;
+  return {current_vsync_};
 }
 
-VSyncSchedInfo VSyncService::OnGetSchedInfo(pdx::Message& message) {
+pdx::Status<VSyncSchedInfo> VSyncService::OnGetSchedInfo(
+    pdx::Message& message) {
   auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
   std::lock_guard<std::mutex> autolock(mutex_);
 
@@ -176,23 +179,25 @@
     }
   }
 
-  return {vsync_period_ns, next_warp, next_vsync_count};
+  return {{vsync_period_ns, next_warp, next_vsync_count}};
 }
 
-int VSyncService::OnAcknowledge(pdx::Message& message) {
+pdx::Status<void> VSyncService::OnAcknowledge(pdx::Message& message) {
   auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
   std::lock_guard<std::mutex> autolock(mutex_);
   client->Ack();
-  return 0;
+  return {};
 }
 
 void VSyncWaiter::Notify(int64_t timestamp) {
   timestamp_ = timestamp;
-  DispatchRemoteMethod<DisplayVSyncRPC::Wait>(*this, &VSyncWaiter::OnWait,
-                                              message_);
+  DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait,
+                                            message_);
 }
 
-int64_t VSyncWaiter::OnWait(pdx::Message& /*message*/) { return timestamp_; }
+pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) {
+  return {timestamp_};
+}
 
 void VSyncChannel::Ack() {
   ALOGD_IF(TRACE, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
diff --git a/libs/vr/libvrflinger/vsync_service.h b/libs/vr/libvrflinger/vsync_service.h
index 1c86d42..215948e 100644
--- a/libs/vr/libvrflinger/vsync_service.h
+++ b/libs/vr/libvrflinger/vsync_service.h
@@ -23,7 +23,7 @@
   void Notify(int64_t timestamp);
 
  private:
-  int64_t OnWait(pdx::Message& message);
+  pdx::Status<int64_t> OnWait(pdx::Message& message);
 
   pdx::Message message_;
   int64_t timestamp_ = 0;
@@ -62,10 +62,9 @@
   void OnChannelClose(pdx::Message& message,
                       const std::shared_ptr<pdx::Channel>& channel) override;
 
-  // Called by the hardware composer HAL, or similar,
-  // whenever a vsync event occurs.
-  // |compositor_time_ns| is the number of ns before the next vsync when the
-  // compositor will preempt the GPU to do EDS and lens warp.
+  // Called by the hardware composer HAL, or similar, whenever a vsync event
+  // occurs. |compositor_time_ns| is the number of ns before the next vsync when
+  // the compositor will preempt the GPU to do EDS and lens warp.
   void VSyncEvent(int display, int64_t timestamp_ns, int64_t compositor_time_ns,
                   uint32_t vsync_count);
 
@@ -74,9 +73,9 @@
 
   VSyncService();
 
-  int64_t OnGetLastTimestamp(pdx::Message& message);
-  VSyncSchedInfo OnGetSchedInfo(pdx::Message& message);
-  int OnAcknowledge(pdx::Message& message);
+  pdx::Status<int64_t> OnGetLastTimestamp(pdx::Message& message);
+  pdx::Status<display::VSyncSchedInfo> OnGetSchedInfo(pdx::Message& message);
+  pdx::Status<void> OnAcknowledge(pdx::Message& message);
 
   void NotifierThreadFunction();
 
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index d59182e..3588b5e 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -66,7 +66,6 @@
         "libgmock_main",
         "libgmock",
         "libdisplay",
-        "libeds",
         "libvrsensor",
         "libdvrgraphics",
     ] + staticLibraries,
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 9de15d0..10f4e66 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -829,6 +829,42 @@
             egl_tls_t::setContext(EGL_NO_CONTEXT);
         }
     } else {
+        // 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);
+
+        if (cur_c == NULL) {
+            restore_result = dp->makeCurrent(c, cur_c,
+                    EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT,
+                    EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        } else {
+            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/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 22a4616..2efb340 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -1172,10 +1172,11 @@
     bool wrongDevice = false;
     if (newGesture) {
         bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
-        if (switchedDevice && mTempTouchState.down && !down) {
+        if (switchedDevice && mTempTouchState.down && !down && !isHoverAction) {
 #if DEBUG_FOCUS
             ALOGD("Dropping event because a pointer for a different device is already down.");
 #endif
+            // TODO: test multiple simultaneous input streams.
             injectionResult = INPUT_EVENT_INJECTION_FAILED;
             switchedDevice = false;
             wrongDevice = true;
@@ -1187,6 +1188,15 @@
         mTempTouchState.source = entry->source;
         mTempTouchState.displayId = displayId;
         isSplit = false;
+    } else if (switchedDevice && maskedAction == AMOTION_EVENT_ACTION_MOVE) {
+#if DEBUG_FOCUS
+        ALOGI("Dropping move event because a pointer for a different device is already active.");
+#endif
+        // TODO: test multiple simultaneous input streams.
+        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+        switchedDevice = false;
+        wrongDevice = true;
+        goto Failed;
     }
 
     if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index cd1d1b0..d60768c 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1070,7 +1070,7 @@
     for (sensors_event_t* i = event; i < event + 3; i++) {
         *i = (sensors_event_t) {
             .version = sizeof(sensors_event_t),
-            .sensor = 0,
+            .sensor = SENSORS_HANDLE_BASE - 1, // sensor that never exists
             .type = SENSOR_TYPE_ADDITIONAL_INFO,
             .timestamp = timestamp++,
             .additional_info = (additional_info_event_t) {
@@ -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/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 406debf..d33d370 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1033,7 +1033,7 @@
         // figure out if there is something below us
         Region under;
         bool finished = false;
-        mFlinger->mDrawingState.layersSortedByZ.traverseInZOrder([&](Layer* layer) {
+        mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) {
             if (finished || layer == static_cast<Layer const*>(this)) {
                 finished = true;
                 return;
@@ -2519,7 +2519,7 @@
 }
 
 bool Layer::detachChildren() {
-    traverseInZOrder([this](Layer* child) {
+    traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) {
         if (child == this) {
             return;
         }
@@ -2553,20 +2553,26 @@
     return mDrawingState.z;
 }
 
-LayerVector Layer::makeTraversalList() {
-    if (mDrawingState.zOrderRelatives.size() == 0) {
-        return mDrawingChildren;
+LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) {
+    LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid,
+                        "makeTraversalList received invalid stateSet");
+    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+    const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
+
+    if (state.zOrderRelatives.size() == 0) {
+        return children;
     }
     LayerVector traverse;
 
-    for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+    for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
         sp<Layer> strongRelative = weakRelative.promote();
         if (strongRelative != nullptr) {
             traverse.add(strongRelative);
         }
     }
 
-    for (const sp<Layer>& child : mDrawingChildren) {
+    for (const sp<Layer>& child : children) {
         traverse.add(child);
     }
 
@@ -2576,8 +2582,8 @@
 /**
  * Negatively signed relatives are before 'this' in Z-order.
  */
-void Layer::traverseInZOrder(const std::function<void(Layer*)>& exec) {
-    LayerVector list = makeTraversalList();
+void Layer::traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) {
+    LayerVector list = makeTraversalList(stateSet);
 
     size_t i = 0;
     for (; i < list.size(); i++) {
@@ -2585,20 +2591,21 @@
         if (relative->getZ() >= 0) {
             break;
         }
-        relative->traverseInZOrder(exec);
+        relative->traverseInZOrder(stateSet, visitor);
     }
-    exec(this);
+    visitor(this);
     for (; i < list.size(); i++) {
         const auto& relative = list[i];
-        relative->traverseInZOrder(exec);
+        relative->traverseInZOrder(stateSet, visitor);
     }
 }
 
 /**
  * Positively signed relatives are before 'this' in reverse Z-order.
  */
-void Layer::traverseInReverseZOrder(const std::function<void(Layer*)>& exec) {
-    LayerVector list = makeTraversalList();
+void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet,
+                                    const LayerVector::Visitor& visitor) {
+    LayerVector list = makeTraversalList(stateSet);
 
     int32_t i = 0;
     for (i = list.size()-1; i>=0; i--) {
@@ -2606,12 +2613,12 @@
         if (relative->getZ() < 0) {
             break;
         }
-        relative->traverseInReverseZOrder(exec);
+        relative->traverseInReverseZOrder(stateSet, visitor);
     }
-    exec(this);
+    visitor(this);
     for (; i>=0; i--) {
         const auto& relative = list[i];
-        relative->traverseInReverseZOrder(exec);
+        relative->traverseInReverseZOrder(stateSet, visitor);
     }
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a5224ec..9f45435 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -476,8 +476,9 @@
     uint8_t getAlpha() const;
 #endif
 
-    void traverseInReverseZOrder(const std::function<void(Layer*)>& exec);
-    void traverseInZOrder(const std::function<void(Layer*)>& exec);
+    void traverseInReverseZOrder(LayerVector::StateSet stateSet,
+                                 const LayerVector::Visitor& visitor);
+    void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor);
 
     void addChild(const sp<Layer>& layer);
     // Returns index if removed, or negative value otherwise
@@ -557,7 +558,7 @@
 
     void setParent(const sp<Layer>& layer);
 
-    LayerVector makeTraversalList();
+    LayerVector makeTraversalList(LayerVector::StateSet stateSet);
     void addZOrderRelative(const wp<Layer>& relative);
     void removeZOrderRelative(const wp<Layer>& relative);
 
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 90e6395..2233e78 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -18,9 +18,14 @@
 #include "Layer.h"
 
 namespace android {
+
+LayerVector::LayerVector() = default;
+
 LayerVector::LayerVector(const LayerVector& rhs) : SortedVector<sp<Layer>>(rhs) {
 }
 
+LayerVector::~LayerVector() = default;
+
 int LayerVector::do_compare(const void* lhs, const void* rhs) const
 {
     // sort layers per layer-stack, then by z-order and finally by sequence
@@ -40,23 +45,27 @@
     return l->sequence - r->sequence;
 }
 
-void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const {
+void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const {
     for (size_t i = 0; i < size(); i++) {
         const auto& layer = (*this)[i];
-        if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+        auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
+                                                      : layer->getDrawingState();
+        if (state.zOrderRelativeOf != nullptr) {
             continue;
         }
-        layer->traverseInZOrder(consume);
+        layer->traverseInZOrder(stateSet, visitor);
     }
 }
 
-void LayerVector::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const {
+void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const {
     for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
         const auto& layer = (*this)[i];
-        if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+        auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
+                                                      : layer->getDrawingState();
+        if (state.zOrderRelativeOf != nullptr) {
             continue;
         }
-        layer->traverseInReverseZOrder(consume);
+        layer->traverseInReverseZOrder(stateSet, visitor);
      }
 }
 } // namespace android
diff --git a/services/surfaceflinger/LayerVector.h b/services/surfaceflinger/LayerVector.h
index 7dfa4a0..a9adb41 100644
--- a/services/surfaceflinger/LayerVector.h
+++ b/services/surfaceflinger/LayerVector.h
@@ -32,13 +32,22 @@
  */
 class LayerVector : public SortedVector<sp<Layer>> {
 public:
-    LayerVector() = default;
+    LayerVector();
     LayerVector(const LayerVector& rhs);
+    ~LayerVector() override;
+
+    enum class StateSet {
+        Invalid,
+        Current,
+        Drawing,
+    };
+
     // Sorts layer by layer-stack, Z order, and finally creation order (sequence).
     int do_compare(const void* lhs, const void* rhs) const override;
 
-    void traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const;
-    void traverseInZOrder(const std::function<void(Layer*)>& consume) const;
+    using Visitor = std::function<void(Layer*)>;
+    void traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const;
+    void traverseInZOrder(StateSet stateSet, const Visitor& visitor) const;
 };
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9cd1214..fec1f1e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -548,12 +548,15 @@
         mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
         mEventQueue.setEventThread(mSFEventThread);
 
-        // set SFEventThread to SCHED_FIFO to minimize jitter
+        // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
         struct sched_param param = {0};
         param.sched_priority = 2;
         if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
             ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
         }
+        if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
+            ALOGE("Couldn't set SCHED_FIFO for EventThread");
+        }
 
         // Get a RenderEngine for the given display / config (can't fail)
         mRenderEngine = RenderEngine::create(mEGLDisplay,
@@ -581,6 +584,7 @@
 
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
+            ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
             mVrFlingerRequestsDisplay = requestDisplay;
             signalTransaction();
         };
@@ -1258,7 +1262,6 @@
         }
     }
     mDisplays.clear();
-    initializeDisplays();
 }
 
 void SurfaceFlinger::updateVrFlinger() {
@@ -1305,6 +1308,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);
 }
@@ -4195,7 +4204,7 @@
         if (state.z < minLayerZ || state.z > maxLayerZ) {
             continue;
         }
-        layer->traverseInZOrder([&](Layer* layer) {
+        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
             if (!layer->isVisible()) {
                 return;
             }
@@ -4243,7 +4252,7 @@
                 (state.z < minLayerZ || state.z > maxLayerZ)) {
             continue;
         }
-        layer->traverseInZOrder([&](Layer *layer) {
+        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) {
             secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() &&
                     layer->isSecure());
         });
@@ -4391,7 +4400,7 @@
             const Layer::State& state(layer->getDrawingState());
             if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ &&
                     state.z <= maxLayerZ) {
-                layer->traverseInZOrder([&](Layer* layer) {
+                layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
                     ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
                             layer->isVisible() ? '+' : '-',
                             i, layer->getName().string(), layer->getLayerStack(), state.z,
@@ -4405,12 +4414,12 @@
 
 // ---------------------------------------------------------------------------
 
-void SurfaceFlinger::State::traverseInZOrder(const std::function<void(Layer*)>& consume) const {
-    layersSortedByZ.traverseInZOrder(consume);
+void SurfaceFlinger::State::traverseInZOrder(const LayerVector::Visitor& visitor) const {
+    layersSortedByZ.traverseInZOrder(stateSet, visitor);
 }
 
-void SurfaceFlinger::State::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const {
-    layersSortedByZ.traverseInReverseZOrder(consume);
+void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& visitor) const {
+    layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
 }
 
 }; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c01f701..1bc689d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -238,11 +238,21 @@
 
     class State {
     public:
+        explicit State(LayerVector::StateSet set) : stateSet(set) {}
+        State& operator=(const State& other) {
+            // We explicitly don't copy stateSet so that, e.g., mDrawingState
+            // always uses the Drawing StateSet.
+            layersSortedByZ = other.layersSortedByZ;
+            displays = other.displays;
+            return *this;
+        }
+
+        const LayerVector::StateSet stateSet = LayerVector::StateSet::Invalid;
         LayerVector layersSortedByZ;
         DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
 
-        void traverseInZOrder(const std::function<void(Layer*)>& consume) const;
-        void traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const;
+        void traverseInZOrder(const LayerVector::Visitor& visitor) const;
+        void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
     };
 
     /* ------------------------------------------------------------------------
@@ -577,7 +587,7 @@
 
     // access must be protected by mStateLock
     mutable Mutex mStateLock;
-    State mCurrentState;
+    State mCurrentState{LayerVector::StateSet::Current};
     volatile int32_t mTransactionFlags;
     Condition mTransactionCV;
     bool mTransactionPending;
@@ -617,7 +627,7 @@
 
     // Can only accessed from the main thread, these members
     // don't need synchronization
-    State mDrawingState;
+    State mDrawingState{LayerVector::StateSet::Drawing};
     bool mVisibleRegionsDirty;
 #ifndef USE_HWC2
     bool mHwWorkListDirty;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 02923ae..7070b97 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -520,13 +520,15 @@
     mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
     mEventQueue.setEventThread(mSFEventThread);
 
-    // set SFEventThread to SCHED_FIFO to minimize jitter
+    // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
     struct sched_param param = {0};
     param.sched_priority = 2;
     if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
         ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
     }
-
+    if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for EventThread");
+    }
 
     // Initialize the H/W composer object.  There may or may not be an
     // actual hardware composer underneath.
@@ -3808,7 +3810,7 @@
         if (state.z < minLayerZ || state.z > maxLayerZ) {
             continue;
         }
-        layer->traverseInZOrder([&](Layer* layer) {
+        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
             if (!layer->isVisible()) {
                 return;
             }
@@ -3858,7 +3860,7 @@
                 (state.z < minLayerZ || state.z > maxLayerZ)) {
             continue;
         }
-        layer->traverseInZOrder([&](Layer *layer) {
+        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) {
             secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() &&
                     layer->isSecure());
         });
@@ -3997,7 +3999,7 @@
             const Layer::State& state(layer->getDrawingState());
             if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ &&
                     state.z <= maxLayerZ) {
-                layer->traverseInZOrder([&](Layer* layer) {
+                layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
                     ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x",
                             layer->isVisible() ? '+' : '-',
                             i, layer->getName().string(), layer->getLayerStack(), state.z,
@@ -4011,12 +4013,12 @@
 
 // ---------------------------------------------------------------------------
 
-void SurfaceFlinger::State::traverseInZOrder(const std::function<void(Layer*)>& consume) const {
-    layersSortedByZ.traverseInZOrder(consume);
+void SurfaceFlinger::State::traverseInZOrder(const LayerVector::Visitor& visitor) const {
+    layersSortedByZ.traverseInZOrder(stateSet, visitor);
 }
 
-void SurfaceFlinger::State::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const {
-    layersSortedByZ.traverseInReverseZOrder(consume);
+void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& visitor) const {
+    layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
 }
 
 }; // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 026fe80..db489b2 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -80,7 +80,7 @@
 void SurfaceInterceptor::saveExistingSurfacesLocked(const SortedVector<sp<Layer>>& layers) {
     ATRACE_CALL();
     for (const auto& l : layers) {
-        l->traverseInZOrder([this](Layer* layer) {
+        l->traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* layer) {
             addSurfaceCreationLocked(createTraceIncrementLocked(), layer);
             addInitialSurfaceStateLocked(createTraceIncrementLocked(), layer);
         });
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index 1c0427d..ff6be81 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -6,5 +6,4 @@
     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/screenshot stream 0660 system graphics
     socket pdx/system/vr/display/vsync stream 0666 system graphics
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 5474fda..1b17e55 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -977,4 +977,35 @@
     }
 }
 
+TEST_F(ChildLayerTest, Bug36858924) {
+    // Destroy the child layer
+    mChild.clear();
+
+    // Now recreate it as hidden
+    mChild = mComposerClient->createSurface(String8("Child surface"), 10, 10,
+                                            PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eHidden,
+                                            mFGSurfaceControl.get());
+
+    // Show the child layer in a deferred transaction
+    SurfaceComposerClient::openGlobalTransaction();
+    mChild->deferTransactionUntil(mFGSurfaceControl->getHandle(),
+                                  mFGSurfaceControl->getSurface()->getNextFrameNumber());
+    mChild->show();
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    // Render the foreground surface a few times
+    //
+    // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the third
+    // frame because SurfaceFlinger would never process the deferred transaction and would therefore
+    // never acquire/release the first buffer
+    ALOGI("Filling 1");
+    fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
+    ALOGI("Filling 2");
+    fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255);
+    ALOGI("Filling 3");
+    fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0);
+    ALOGI("Filling 4");
+    fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
+}
+
 }
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 4b1a522..d27f274 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -53,7 +53,7 @@
   stream << " ";
   stream << std::setw(6) << "Format";
   stream << " ";
-  stream << std::setw(21) << "Usage";
+  stream << std::setw(11) << "Usage";
   stream << " ";
   stream << "Name";
   stream << std::endl;
@@ -73,16 +73,14 @@
       } 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 << " ";
       stream << std::setw(6) << info.format;
       stream << " ";
       stream << "0x" << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.producer_usage;
-      stream << "0x";
-      stream << std::setw(8) << info.consumer_usage;
+      stream << std::setw(8) << info.usage;
       stream << std::dec << std::setfill(' ');
       stream << " ";
       stream << info.name;
@@ -122,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 << " ";
@@ -134,16 +132,12 @@
   stream << std::endl;
   stream << "Active Producer Queues:\n";
   stream << std::right << std::setw(6) << "Id";
-  stream << std::right << std::setw(12) << " Allocated";
+  stream << std::right << std::setw(12) << " Capacity";
   stream << std::right << std::setw(12) << " Consumers";
   stream << " UsageSetMask";
   stream << " UsageClearMask";
   stream << " UsageDenySetMask";
   stream << " UsageDenyClearMask";
-  stream << " UsageSetMask";
-  stream << " UsageClearMask";
-  stream << " UsageDenySetMask";
-  stream << " UsageDenyClearMask";
   stream << " ";
   stream << std::endl;
 
@@ -157,28 +151,16 @@
       stream << std::right << std::setw(12) << info.consumer_count;
       stream << std::setw(5) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_policy.producer_set_mask;
+      stream << std::setw(8) << info.usage_policy.usage_set_mask;
       stream << std::setw(7) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_policy.producer_clear_mask;
+      stream << std::setw(8) << info.usage_policy.usage_clear_mask;
       stream << std::setw(9) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_policy.producer_deny_set_mask;
+      stream << std::setw(8) << info.usage_policy.usage_deny_set_mask;
       stream << std::setw(11) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_policy.producer_deny_clear_mask;
-      stream << std::setw(5) << std::setfill(' ') << "0x";
-      stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_policy.consumer_set_mask;
-      stream << std::setw(7) << std::setfill(' ') << "0x";
-      stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_policy.consumer_clear_mask;
-      stream << std::setw(9) << std::setfill(' ') << "0x";
-      stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_policy.consumer_deny_set_mask;
-      stream << std::setw(11) << std::setfill(' ') << "0x";
-      stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_policy.consumer_deny_clear_mask;
+      stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask;
       stream << std::hex << std::setfill('0');
       stream << std::endl;
     }
@@ -259,18 +241,14 @@
 
 Status<void> BufferHubService::OnCreateBuffer(Message& message, 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 usage,
+                                              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 producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
-           " meta_size_bytes=%zu slice_count=%zu",
-           buffer_id, width, height, format, producer_usage, consumer_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>()) {
@@ -278,10 +256,10 @@
           buffer_id);
     return ErrorStatus(EALREADY);
   }
-
-  auto status = ProducerChannel::Create(this, buffer_id, width, height, format,
-                                        producer_usage, consumer_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 {};
@@ -294,16 +272,16 @@
 
 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 producer_usage,
-    uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count) {
+    uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
+    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 "
-           "producer_usage=%" PRIx64 " consumer_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,
-           producer_usage, consumer_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>()) {
@@ -324,9 +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, producer_usage,
-                                        consumer_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",
@@ -344,9 +321,9 @@
       return {};
     }
   } else {
-    auto status = ProducerChannel::Create(
-        this, channel_id, width, height, format, producer_usage, consumer_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 4cb1eb9..3bc2635 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -50,29 +50,25 @@
     // Data field for buffer producer.
     uint32_t width = 0;
     uint32_t height = 0;
+    uint32_t layer_count = 0;
     uint32_t format = 0;
-    uint64_t producer_usage = 0;
-    uint64_t consumer_usage = 0;
-    size_t slice_count = 0;
+    uint64_t usage = 0;
     std::string name;
 
     // Data filed for producer queue.
     size_t capacity = 0;
-    UsagePolicy usage_policy{0, 0, 0, 0, 0, 0, 0, 0};
+    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 producer_usage,
-               uint64_t consumer_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),
-          producer_usage(producer_usage),
-          consumer_usage(consumer_usage),
-          slice_count(slice_count),
+          usage(usage),
           name(name) {}
 
     BufferInfo(int id, size_t consumer_count, size_t capacity,
@@ -159,16 +155,17 @@
   std::unordered_map<std::string, std::shared_ptr<ProducerChannel>>
       named_buffers_;
 
-  pdx::Status<void> OnCreateBuffer(pdx::Message& message, 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);
-  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 producer_usage, uint64_t consumer_usage,
-                               size_t meta_size_bytes, size_t slice_count);
-  pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
+  pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width,
+                                   uint32_t height, uint32_t format,
+                                   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,
                                                size_t meta_size_bytes,
                                                const UsagePolicy& usage_policy);
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/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index 7422751..f447e00 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -8,6 +8,7 @@
 using android::pdx::RemoteChannelHandle;
 using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
+using android::pdx::rpc::RemoteMethodError;
 
 namespace android {
 namespace dvr {
@@ -33,8 +34,10 @@
 bool ConsumerQueueChannel::HandleMessage(Message& message) {
   ATRACE_NAME("ConsumerQueueChannel::HandleMessage");
   auto producer = GetProducer();
-  if (!producer)
-    REPLY_ERROR_RETURN(message, EPIPE, true);
+  if (!producer) {
+    RemoteMethodError(message, EPIPE);
+    return true;
+  }
 
   switch (message.GetOp()) {
     case BufferHubRPC::CreateConsumerQueue::Opcode:
@@ -79,6 +82,9 @@
 
 void ConsumerQueueChannel::RegisterNewBuffer(
     const std::shared_ptr<ProducerChannel>& producer_channel, size_t slot) {
+  ALOGD_IF(TRACE,
+           "ConsumerQueueChannel::RegisterNewBuffer: buffer_id=%d slot=%zu",
+           producer_channel->buffer_id(), slot);
   pending_buffer_slots_.emplace(producer_channel, slot);
 
   // Signal the client that there is new buffer available throught POLLIN.
@@ -89,7 +95,8 @@
 ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) {
   std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
   ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers");
-  ALOGD(
+  ALOGD_IF(
+      TRACE,
       "ConsumerQueueChannel::OnConsumerQueueImportBuffers number of buffers to "
       "import: %zu",
       pending_buffer_slots_.size());
@@ -134,5 +141,12 @@
   return {std::move(buffer_handles)};
 }
 
+void ConsumerQueueChannel::OnProducerClosed() {
+  ALOGD_IF(TRACE, "ConsumerQueueChannel::OnProducerClosed: queue_id=%d",
+           buffer_id());
+  producer_.reset();
+  Hangup();
+}
+
 }  // namespace dvr
 }  // namespace android
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index e1005e4..aa3f531 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -39,6 +39,8 @@
   pdx::Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
   OnConsumerQueueImportBuffers(Message& message);
 
+  void OnProducerClosed();
+
  private:
   std::shared_ptr<ProducerQueueChannel> GetProducer() const;
 
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index c946a8d..b9984a0 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -26,25 +26,20 @@
 
 ProducerChannel::ProducerChannel(BufferHubService* service, int channel_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,
+                                 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, producer_usage, consumer_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.
@@ -53,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 producer_usage, uint64_t consumer_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, producer_usage,
-      consumer_usage, meta_size_bytes, slice_count, &error));
+  std::shared_ptr<ProducerChannel> producer(
+      new ProducerChannel(service, channel_id, width, height, layer_count,
+                          format, usage, meta_size_bytes, &error));
   if (error < 0)
     return ErrorStatus(-error);
   else
@@ -74,10 +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].producer_usage(), slices_[0].consumer_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) {
@@ -97,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);
@@ -133,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) {
@@ -202,10 +177,15 @@
     return ErrorStatus(EBUSY);
   }
 
-  if (meta_size_bytes_ != metadata.size())
+  if (meta_size_bytes_ != metadata.size()) {
+    ALOGD_IF(TRACE,
+             "ProducerChannel::OnProducerPost: Expected meta_size_bytes=%zu "
+             "got size=%zu",
+             meta_size_bytes_, metadata.size());
     return ErrorStatus(EINVAL);
-  std::copy(metadata.begin(), metadata.end(), meta_.get());
+  }
 
+  std::copy(metadata.begin(), metadata.end(), meta_.get());
   post_fence_ = std::move(acquire_fence);
   producer_owns_ = false;
 
@@ -369,15 +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 producer_usage,
-                                      uint64_t consumer_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].producer_usage() == producer_usage &&
-         slices_[0].consumer_usage() == consumer_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 f04c8a5..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 producer_usage,
-      uint64_t consumer_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 producer_usage, uint64_t consumer_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,9 +91,8 @@
   std::string name_;
 
   ProducerChannel(BufferHubService* service, int channel, 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, 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 dc2a47e..886e621 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -26,7 +26,12 @@
   *error = 0;
 }
 
-ProducerQueueChannel::~ProducerQueueChannel() {}
+ProducerQueueChannel::~ProducerQueueChannel() {
+  ALOGD_IF(TRACE, "ProducerQueueChannel::~ProducerQueueChannel: queue_id=%d",
+           buffer_id());
+  for (auto* consumer : consumer_channels_)
+    consumer->OnProducerClosed();
+}
 
 /* static */
 Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
@@ -34,19 +39,12 @@
     const UsagePolicy& usage_policy) {
   // Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
   // should be mutually exclusive.
-  if ((usage_policy.producer_deny_set_mask &
-       usage_policy.producer_deny_clear_mask) ||
-      (usage_policy.consumer_deny_set_mask &
-       usage_policy.consumer_deny_clear_mask)) {
+  if ((usage_policy.usage_deny_set_mask & usage_policy.usage_deny_clear_mask)) {
     ALOGE(
         "BufferHubService::OnCreateProducerQueue: illegal usage mask "
-        "configuration: producer_deny_set_mask=%" PRIx64
-        " producer_deny_clear_mask=%" PRIx64 " consumer_deny_set_mask=%" PRIx64
-        " consumer_deny_clear_mask=%" PRIx64,
-        usage_policy.producer_deny_set_mask,
-        usage_policy.producer_deny_clear_mask,
-        usage_policy.consumer_deny_set_mask,
-        usage_policy.consumer_deny_clear_mask);
+        "configuration: usage_deny_set_mask=%" PRIx64
+        " usage_deny_clear_mask=%" PRIx64,
+        usage_policy.usage_deny_set_mask, usage_policy.usage_deny_clear_mask);
     return ErrorStatus(EINVAL);
   }
 
@@ -113,13 +111,21 @@
     return ErrorStatus(ENOMEM);
   }
 
-  const auto channel_status = service()->SetChannel(
-      channel_id, std::make_shared<ConsumerQueueChannel>(
-                      service(), buffer_id(), channel_id, shared_from_this()));
+  auto consumer_queue_channel = std::make_shared<ConsumerQueueChannel>(
+      service(), buffer_id(), channel_id, shared_from_this());
+
+  // Register the existing buffers with the new consumer queue.
+  for (size_t slot = 0; slot < BufferHubRPC::kMaxQueueCapacity; slot++) {
+    if (auto buffer = buffers_[slot].lock())
+      consumer_queue_channel->RegisterNewBuffer(buffer, slot);
+  }
+
+  const auto channel_status =
+      service()->SetChannel(channel_id, consumer_queue_channel);
   if (!channel_status) {
     ALOGE(
-        "ProducerQueueChannel::OnCreateConsumerQueue: failed to set new "
-        "consumer channel: %s",
+        "ProducerQueueChannel::OnCreateConsumerQueue: Failed to set channel: "
+        "%s",
         channel_status.GetErrorMessage().c_str());
     return ErrorStatus(ENOMEM);
   }
@@ -133,9 +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 producer_usage, uint64_t consumer_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: "
@@ -145,58 +150,32 @@
   std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
 
   // Deny buffer allocation violating preset rules.
-  if (producer_usage & usage_policy_.producer_deny_set_mask) {
+  if (usage & usage_policy_.usage_deny_set_mask) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
-        "%" PRIx64
-        " is not permitted. Violating producer_deny_set_mask, the following "
-        "bits shall not be set: %" PRIx64 ".",
-        producer_usage, usage_policy_.producer_deny_set_mask);
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %" PRIx64
+        " is not permitted. Violating usage_deny_set_mask, the following  bits "
+        "shall not be set: %" PRIx64 ".",
+        usage, usage_policy_.usage_deny_set_mask);
     return ErrorStatus(EINVAL);
   }
 
-  if (consumer_usage & usage_policy_.consumer_deny_set_mask) {
+  if (~usage & usage_policy_.usage_deny_clear_mask) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
-        "%" PRIx64
-        " is not permitted. Violating consumer_deny_set_mask, the following "
-        "bits shall not be set: %" PRIx64 ".",
-        consumer_usage, usage_policy_.consumer_deny_set_mask);
-    return ErrorStatus(EINVAL);
-  }
-
-  if (~producer_usage & usage_policy_.producer_deny_clear_mask) {
-    ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
-        "%" PRIx64
-        " is not permitted. Violating producer_deny_clear_mask, the following "
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %" PRIx64
+        " is not permitted. Violating usage_deny_clear_mask, the following "
         "bits must be set: %" PRIx64 ".",
-        producer_usage, usage_policy_.producer_deny_clear_mask);
+        usage, usage_policy_.usage_deny_clear_mask);
     return ErrorStatus(EINVAL);
   }
 
-  if (~consumer_usage & usage_policy_.consumer_deny_clear_mask) {
-    ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
-        "%" PRIx64
-        " is not permitted. Violating consumer_deny_clear_mask, the following "
-        "bits must be set: %" PRIx64 ".",
-        consumer_usage, usage_policy_.consumer_deny_clear_mask);
-    return ErrorStatus(EINVAL);
-  }
-  // Force set mask and clear mask. Note that |usage_policy_.X_set_mask_| takes
-  // precedence and will overwrite |usage_policy_.X_clear_mask|.
-  uint64_t effective_producer_usage =
-      (producer_usage & ~usage_policy_.producer_clear_mask) |
-      usage_policy_.producer_set_mask;
-  uint64_t effective_consumer_usage =
-      (consumer_usage & ~usage_policy_.consumer_clear_mask) |
-      usage_policy_.consumer_set_mask;
+  // Force set mask and clear mask. Note that |usage_policy_.usage_set_mask_|
+  // takes precedence and will overwrite |usage_policy_.usage_clear_mask|.
+  uint64_t effective_usage =
+      (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_producer_usage,
-                       effective_consumer_usage, slice_count);
+    auto status = AllocateBuffer(message, width, height, layer_count, format,
+                                 effective_usage);
     if (!status) {
       ALOGE(
           "ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to "
@@ -211,10 +190,8 @@
 
 Status<std::pair<RemoteChannelHandle, size_t>>
 ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width,
-                                     uint32_t height, uint32_t format,
-                                     uint64_t producer_usage,
-                                     uint64_t consumer_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",
@@ -239,15 +216,13 @@
 
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%u "
-           "height=%u format=%u producer_usage=%" PRIx64
-           " consumer_usage=%" PRIx64 " slice_count=%zu",
-           buffer_id, width, height, format, producer_usage, consumer_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, producer_usage,
-      consumer_usage, meta_size_bytes_, slice_count);
+  auto producer_channel_status =
+      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 "
@@ -290,7 +265,7 @@
   capacity_++;
 
   // Notify each consumer channel about the new buffer.
-  for (auto consumer_channel : consumer_channels_) {
+  for (auto* consumer_channel : consumer_channels_) {
     ALOGD(
         "ProducerQueueChannel::AllocateBuffer: Notified consumer with new "
         "buffer, buffer_id=%d",
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index 09b0243..28c74cd 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -34,9 +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 producer_usage,
-                                 uint64_t consumer_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
@@ -58,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 producer_usage, uint64_t consumer_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/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index 504b26f..5d51827 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -60,24 +60,22 @@
   *height = 1920;
 
   int error = 0;
-  auto display_client = DisplayClient::Create(&error);
-  SystemDisplayMetrics metrics;
-
-  if (error) {
+  auto display_client = display::DisplayClient::Create(&error);
+  if (!display_client) {
     ALOGE("Could not connect to display service : %s(%d)", strerror(error),
           error);
     return;
   }
 
-  error = display_client->GetDisplayMetrics(&metrics);
-  if (error) {
+  auto status = display_client->GetDisplayMetrics();
+  if (!status) {
     ALOGE("Could not get display metrics from display service : %s(%d)",
-          strerror(error), error);
+          status.GetErrorMessage().c_str(), status.error());
     return;
   }
 
-  *width = metrics.display_native_width;
-  *height = metrics.display_native_height;
+  *width = status.get().display_width;
+  *height = status.get().display_height;
 }
 
 }  // namespace
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/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 2b53cd6..0000000
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ /dev/null
@@ -1,529 +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_ = 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.
-  bool vr_running = display_client_->IsVrAppRunning();
-
-  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 d90e833..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<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..0005a90 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -887,6 +887,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)