Merge "Dump EGL Extension list" into oc-dev
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index 69ed416..6c5869a 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -18,4 +18,10 @@
     ],
 
     init_rc: ["atrace.rc"],
+
+    product_variables: {
+        debuggable: {
+            init_rc: ["atrace_userdebug.rc"],
+        },
+    },
 }
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 05e1615..6cfbed9 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -552,7 +552,13 @@
                 // ignore
                 continue;
             }
+
             sp<IBase> interface = interfaceRet;
+            if (interface == nullptr) {
+                // ignore
+                continue;
+            }
+
             auto notifyRet = interface->notifySyspropsChanged();
             if (!notifyRet.isOk()) {
                 // ignore
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
new file mode 100644
index 0000000..5fd28e2
--- /dev/null
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -0,0 +1,47 @@
+## Permissions to allow additional system-wide tracing to the kernel trace buffer.
+## The default list of permissions is set in frameworks/native/cmds/atrace/atrace.rc
+
+# Allow the shell group to enable kernel tracepoints:
+
+on post-fs
+    chown root shell /sys/kernel/debug/tracing/events/sync/enable
+    chown root shell /sys/kernel/debug/tracing/events/workqueue/enable
+    chown root shell /sys/kernel/debug/tracing/events/regulator/enable
+    chown root shell /sys/kernel/debug/tracing/events/pagecache/enable
+
+    # irq
+    chown root shell /sys/kernel/debug/tracing/events/irq/enable
+    chown root shell /sys/kernel/debug/tracing/events/ipi/enable
+
+    # disk
+    chown root shell /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
+    chown root shell /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
+    chown root shell /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
+    chown root shell /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
+    chown root shell /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
+    chown root shell /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
+    chown root shell /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
+    chown root shell /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
+    chown root shell /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
+    chown root shell /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
+
+    chmod 0664 /sys/kernel/debug/tracing/events/sync/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/workqueue/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/regulator/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/pagecache/enable
+
+    # irq
+    chmod 0664 /sys/kernel/debug/tracing/events/irq/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/ipi/enable
+
+    # disk
+    chmod 0664 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index f5dca47..f649a5e 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -94,6 +94,7 @@
         "android.hardware.audio@2.0::IDevicesFactory",
         "android.hardware.bluetooth@1.0::IBluetoothHci",
         "android.hardware.camera.provider@2.4::ICameraProvider",
+        "android.hardware.graphics.composer@2.1::IComposer",
         "android.hardware.vr@1.0::IVr",
         "android.hardware.media.omx@1.0::IOmx",
         NULL,
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 5c04f6c..dfc3e58 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -25,7 +25,6 @@
  namespace android {
 
 GLHelper::GLHelper() :
-    mGraphicBufferAlloc(new GraphicBufferAlloc()),
     mDisplay(EGL_NO_DISPLAY),
     mContext(EGL_NO_CONTEXT),
     mDummySurface(EGL_NO_SURFACE),
@@ -203,7 +202,7 @@
         sp<GLConsumer>* glConsumer, EGLSurface* surface) {
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
-    BufferQueue::createBufferQueue(&producer, &consumer, mGraphicBufferAlloc);
+    BufferQueue::createBufferQueue(&producer, &consumer);
     sp<GLConsumer> glc = new GLConsumer(consumer, name,
             GL_TEXTURE_EXTERNAL_OES, false, true);
     glc->setDefaultBufferSize(w, h);
diff --git a/cmds/flatland/GLHelper.h b/cmds/flatland/GLHelper.h
index 7a9e9e3..d09463a 100644
--- a/cmds/flatland/GLHelper.h
+++ b/cmds/flatland/GLHelper.h
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <gui/GraphicBufferAlloc.h>
 #include <gui/GLConsumer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceControl.h>
@@ -75,8 +74,6 @@
 
     bool setUpShaders(const ShaderDesc* shaderDescs, size_t numShaders);
 
-    sp<GraphicBufferAlloc> mGraphicBufferAlloc;
-
     EGLDisplay mDisplay;
     EGLContext mContext;
     EGLSurface mDummySurface;
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index c47b0c8..ec1e543 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -16,7 +16,6 @@
 
 #define ATRACE_TAG ATRACE_TAG_ALWAYS
 
-#include <gui/GraphicBufferAlloc.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceControl.h>
 #include <gui/GLConsumer.h>
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index be1a434..1d21b3c 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
 
 LOCAL_SRC_FILES := otapreopt.cpp globals.cpp utils.cpp dexopt.cpp
+LOCAL_HEADER_LIBRARIES := dex2oat_headers
 LOCAL_SHARED_LIBRARIES := \
     libbase \
     libcutils \
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index e9a135c..70acb07 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -395,7 +395,9 @@
         }
 
         // Consider restorecon over contents if label changed
-        if (restorecon_app_data_lazy(path, seInfo, uid, existing)) {
+        if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
+                restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
+                restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
             return error("Failed to restorecon " + path);
         }
 
@@ -617,11 +619,9 @@
         ATRACE_BEGIN("fixup user");
         FTS* fts;
         FTSENT* p;
-        char *argv[] = {
-                (char*) create_data_user_ce_path(uuid_, user).c_str(),
-                (char*) create_data_user_de_path(uuid_, user).c_str(),
-                nullptr
-        };
+        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 };
         if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
             return error("Failed to fts_open");
         }
@@ -950,11 +950,9 @@
         for (auto user : get_known_users(uuid_)) {
             FTS *fts;
             FTSENT *p;
-            char *argv[] = {
-                    (char*) create_data_user_ce_path(uuid_, user).c_str(),
-                    (char*) create_data_user_de_path(uuid_, user).c_str(),
-                    nullptr
-            };
+            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 };
             if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
                 return error("Failed to fts_open");
             }
@@ -1124,61 +1122,81 @@
 
     struct dqblk dq;
 
-    uid_t uid = multiuser_get_uid(userId, appId);
-    if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
-            reinterpret_cast<char*>(&dq)) != 0) {
-        if (errno != ESRCH) {
-            PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
-        }
-    } else {
-#if MEASURE_DEBUG
-        LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
-#endif
-        stats->dataSize += dq.dqb_curspace;
-    }
-
-    int cacheGid = multiuser_get_cache_gid(userId, appId);
-    if (cacheGid != -1) {
-        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid,
+    if (stats != nullptr) {
+        uid_t uid = multiuser_get_uid(userId, appId);
+        if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
                 reinterpret_cast<char*>(&dq)) != 0) {
             if (errno != ESRCH) {
-                PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid;
+                PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
             }
         } else {
 #if MEASURE_DEBUG
-            LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace;
+            LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
 #endif
-            stats->cacheSize += dq.dqb_curspace;
+            stats->dataSize += dq.dqb_curspace;
+        }
+
+        int cacheGid = multiuser_get_cache_gid(userId, appId);
+        if (cacheGid != -1) {
+            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid,
+                    reinterpret_cast<char*>(&dq)) != 0) {
+                if (errno != ESRCH) {
+                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid;
+                }
+            } else {
+#if MEASURE_DEBUG
+                LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace;
+#endif
+                stats->cacheSize += dq.dqb_curspace;
+            }
+        }
+
+        int sharedGid = multiuser_get_shared_gid(0, appId);
+        if (sharedGid != -1) {
+            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
+                    reinterpret_cast<char*>(&dq)) != 0) {
+                if (errno != ESRCH) {
+                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
+                }
+            } else {
+#if MEASURE_DEBUG
+                LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
+#endif
+                stats->codeSize += dq.dqb_curspace;
+            }
         }
     }
 
-    int extGid = multiuser_get_ext_gid(userId, appId);
-    if (extGid != -1) {
-        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
-                reinterpret_cast<char*>(&dq)) != 0) {
-            if (errno != ESRCH) {
-                PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid;
-            }
-        } else {
+    if (extStats != nullptr) {
+        int extGid = multiuser_get_ext_gid(userId, appId);
+        if (extGid != -1) {
+            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
+                    reinterpret_cast<char*>(&dq)) != 0) {
+                if (errno != ESRCH) {
+                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid;
+                }
+            } else {
 #if MEASURE_DEBUG
-            LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace;
+                LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace;
 #endif
-            extStats->dataSize += dq.dqb_curspace;
+                extStats->dataSize += dq.dqb_curspace;
+            }
         }
-    }
 
-    int sharedGid = multiuser_get_shared_gid(userId, appId);
-    if (sharedGid != -1) {
-        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
-                reinterpret_cast<char*>(&dq)) != 0) {
-            if (errno != ESRCH) {
-                PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
-            }
-        } else {
+        int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
+        if (extCacheGid != -1) {
+            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extCacheGid,
+                    reinterpret_cast<char*>(&dq)) != 0) {
+                if (errno != ESRCH) {
+                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extCacheGid;
+                }
+            } else {
 #if MEASURE_DEBUG
-            LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
+                LOG(DEBUG) << "quotactl() for GID " << extCacheGid << " " << dq.dqb_curspace;
 #endif
-            stats->codeSize += dq.dqb_curspace;
+                extStats->dataSize += dq.dqb_curspace;
+                extStats->cacheSize += dq.dqb_curspace;
+            }
         }
     }
 }
@@ -1254,9 +1272,10 @@
             if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) != 0) {
                 continue;
             }
+            int32_t user_uid = multiuser_get_app_id(s.st_uid);
             if (!strcmp(name, ".") || !strcmp(name, "..")) {
                 continue;
-            } else if (exclude_apps && (s.st_uid >= AID_APP_START && s.st_uid <= AID_APP_END)) {
+            } else if (exclude_apps && (user_uid >= AID_APP_START && user_uid <= AID_APP_END)) {
                 continue;
             } else {
                 collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats);
@@ -1355,14 +1374,13 @@
         ATRACE_BEGIN("code");
         for (auto codePath : codePaths) {
             calculate_tree_size(codePath, &stats.codeSize, -1,
-                    multiuser_get_shared_gid(userId, appId));
+                    multiuser_get_shared_gid(0, appId));
         }
         ATRACE_END();
 
         ATRACE_BEGIN("quota");
         collectQuotaStats(device, userId, appId, &stats, &extStats);
         ATRACE_END();
-
     } else {
         ATRACE_BEGIN("code");
         for (auto codePath : codePaths) {
@@ -1380,12 +1398,16 @@
             collectManualStats(dePath, &stats);
             ATRACE_END();
 
-            ATRACE_BEGIN("profiles");
-            auto userProfilePath = create_primary_current_profile_package_dir_path(userId, pkgname);
-            calculate_tree_size(userProfilePath, &stats.dataSize);
-            auto refProfilePath = create_primary_reference_profile_package_dir_path(pkgname);
-            calculate_tree_size(refProfilePath, &stats.codeSize);
-            ATRACE_END();
+            if (!uuid) {
+                ATRACE_BEGIN("profiles");
+                calculate_tree_size(
+                        create_primary_current_profile_package_dir_path(userId, pkgname),
+                        &stats.dataSize);
+                calculate_tree_size(
+                        create_primary_reference_profile_package_dir_path(pkgname),
+                        &stats.codeSize);
+                ATRACE_END();
+            }
 
             ATRACE_BEGIN("external");
             auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
@@ -1395,15 +1417,15 @@
             ATRACE_END();
         }
 
-        ATRACE_BEGIN("dalvik");
-        int32_t sharedGid = multiuser_get_shared_gid(userId, appId);
-        if (sharedGid != -1) {
-            calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
-                    sharedGid, -1);
+        if (!uuid) {
+            ATRACE_BEGIN("dalvik");
+            int32_t sharedGid = multiuser_get_shared_gid(0, appId);
+            if (sharedGid != -1) {
+                calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
+                        sharedGid, -1);
+            }
+            ATRACE_END();
         }
-        calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
-                multiuser_get_uid(userId, appId), -1);
-        ATRACE_END();
     }
 
     std::vector<int64_t> ret;
@@ -1475,12 +1497,14 @@
         collectManualStatsForUser(dePath, &stats, true);
         ATRACE_END();
 
-        ATRACE_BEGIN("profile");
-        auto userProfilePath = create_primary_cur_profile_dir_path(userId);
-        calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
-        auto refProfilePath = create_primary_ref_profile_dir_path();
-        calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
-        ATRACE_END();
+        if (!uuid) {
+            ATRACE_BEGIN("profile");
+            auto userProfilePath = create_primary_cur_profile_dir_path(userId);
+            calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
+            auto refProfilePath = create_primary_ref_profile_dir_path();
+            calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
+            ATRACE_END();
+        }
 
         ATRACE_BEGIN("external");
         uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
@@ -1497,23 +1521,28 @@
         }
         ATRACE_END();
 
-        ATRACE_BEGIN("dalvik");
-        calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
-                -1, -1, true);
-        calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
-                -1, -1, true);
-        ATRACE_END();
+        if (!uuid) {
+            ATRACE_BEGIN("dalvik");
+            calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
+                    -1, -1, true);
+            calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
+                    -1, -1, true);
+            ATRACE_END();
+        }
 
         ATRACE_BEGIN("quota");
+        int64_t dataSize = extStats.dataSize;
         for (auto appId : appIds) {
             if (appId >= AID_APP_START) {
                 collectQuotaStats(device, userId, appId, &stats, &extStats);
+
 #if MEASURE_DEBUG
                 // Sleep to make sure we don't lose logs
                 usleep(1);
 #endif
             }
         }
+        extStats.dataSize = dataSize;
         ATRACE_END();
     } else {
         ATRACE_BEGIN("obb");
@@ -1532,12 +1561,14 @@
         collectManualStatsForUser(dePath, &stats);
         ATRACE_END();
 
-        ATRACE_BEGIN("profile");
-        auto userProfilePath = create_primary_cur_profile_dir_path(userId);
-        calculate_tree_size(userProfilePath, &stats.dataSize);
-        auto refProfilePath = create_primary_ref_profile_dir_path();
-        calculate_tree_size(refProfilePath, &stats.codeSize);
-        ATRACE_END();
+        if (!uuid) {
+            ATRACE_BEGIN("profile");
+            auto userProfilePath = create_primary_cur_profile_dir_path(userId);
+            calculate_tree_size(userProfilePath, &stats.dataSize);
+            auto refProfilePath = create_primary_ref_profile_dir_path();
+            calculate_tree_size(refProfilePath, &stats.codeSize);
+            ATRACE_END();
+        }
 
         ATRACE_BEGIN("external");
         auto dataMediaPath = create_data_media_path(uuid_, userId);
@@ -1548,10 +1579,12 @@
 #endif
         ATRACE_END();
 
-        ATRACE_BEGIN("dalvik");
-        calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
-        calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize);
-        ATRACE_END();
+        if (!uuid) {
+            ATRACE_BEGIN("dalvik");
+            calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
+            calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize);
+            ATRACE_END();
+        }
     }
 
     std::vector<int64_t> ret;
@@ -1569,7 +1602,8 @@
 }
 
 binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std::string>& uuid,
-        int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return) {
+        int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
+        std::vector<int64_t>* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     // NOTE: Locking is relaxed on this method, since it's limited to
@@ -1588,6 +1622,7 @@
     int64_t audioSize = 0;
     int64_t videoSize = 0;
     int64_t imageSize = 0;
+    int64_t appSize = 0;
 
     auto device = findQuotaDeviceForUuid(uuid);
     if (device.empty()) {
@@ -1597,6 +1632,7 @@
     if (flags & FLAG_USE_QUOTA) {
         struct dqblk dq;
 
+        ATRACE_BEGIN("quota");
         uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
         if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
                 reinterpret_cast<char*>(&dq)) != 0) {
@@ -1605,7 +1641,7 @@
             }
         } else {
 #if MEASURE_DEBUG
-        LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
+            LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
 #endif
             totalSize = dq.dqb_curspace;
         }
@@ -1614,7 +1650,7 @@
         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid,
                 reinterpret_cast<char*>(&dq)) == 0) {
 #if MEASURE_DEBUG
-        LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace;
+            LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace;
 #endif
             audioSize = dq.dqb_curspace;
         }
@@ -1622,7 +1658,7 @@
         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid,
                 reinterpret_cast<char*>(&dq)) == 0) {
 #if MEASURE_DEBUG
-        LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace;
+            LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace;
 #endif
             videoSize = dq.dqb_curspace;
         }
@@ -1630,11 +1666,24 @@
         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid,
                 reinterpret_cast<char*>(&dq)) == 0) {
 #if MEASURE_DEBUG
-        LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace;
+            LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace;
 #endif
             imageSize = dq.dqb_curspace;
         }
+        ATRACE_END();
+
+        ATRACE_BEGIN("apps");
+        struct stats extStats;
+        memset(&extStats, 0, sizeof(extStats));
+        for (auto appId : appIds) {
+            if (appId >= AID_APP_START) {
+                collectQuotaStats(device, userId, appId, nullptr, &extStats);
+            }
+        }
+        appSize = extStats.dataSize + extStats.cacheSize;
+        ATRACE_END();
     } else {
+        ATRACE_BEGIN("manual");
         FTS *fts;
         FTSENT *p;
         auto path = create_data_media_path(uuid_, userId);
@@ -1668,11 +1717,15 @@
             case FTS_DEFAULT:
             case FTS_SL:
             case FTS_SLNONE:
+                if (p->fts_parent->fts_number == 1) {
+                    appSize += size;
+                }
                 totalSize += size;
                 break;
             }
         }
         fts_close(fts);
+        ATRACE_END();
     }
 
     std::vector<int64_t> ret;
@@ -1680,6 +1733,7 @@
     ret.push_back(audioSize);
     ret.push_back(videoSize);
     ret.push_back(imageSize);
+    ret.push_back(appSize);
 #if MEASURE_DEBUG
     LOG(DEBUG) << "Final result " << toString(ret);
 #endif
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index fe8aa14..7f73c2a 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -68,7 +68,8 @@
             int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
             std::vector<int64_t>* _aidl_return);
     binder::Status getExternalSize(const std::unique_ptr<std::string>& uuid,
-            int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return);
+            int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
+            std::vector<int64_t>* _aidl_return);
 
     binder::Status setAppQuota(const std::unique_ptr<std::string>& uuid,
             int32_t userId, int32_t appId, int64_t cacheQuota);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index e738b81..6b99c1d 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -38,7 +38,7 @@
             int userId, int flags, int appId, in long[] ceDataInodes,
             in @utf8InCpp String[] codePaths);
     long[] getUserSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds);
-    long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags);
+    long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds);
 
     void setAppQuota(@nullable @utf8InCpp String uuid, int userId, int appId, long cacheQuota);
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 63afdcd..e9d06d1 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -67,14 +67,6 @@
     return unique_fd(-1);
 }
 
-static const char* parse_null(const char* arg) {
-    if (strcmp(arg, "!") == 0) {
-        return nullptr;
-    } else {
-        return arg;
-    }
-}
-
 static bool clear_profile(const std::string& profile) {
     unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
     if (ufd.get() < 0) {
@@ -185,9 +177,20 @@
   return count;
 }
 
+static const char* get_location_from_path(const char* path) {
+    static constexpr char kLocationSeparator = '/';
+    const char *location = strrchr(path, kLocationSeparator);
+    if (location == NULL) {
+        return path;
+    } else {
+        // Skip the separator character.
+        return location + 1;
+    }
+}
+
 static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
         const char* input_file_name, const char* output_file_name, int swap_fd,
-        const char *instruction_set, const char* compiler_filter, bool vm_safe_mode,
+        const char* instruction_set, const char* compiler_filter, bool vm_safe_mode,
         bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
@@ -197,6 +200,9 @@
         return;
     }
 
+    // Get the relative path to the input file.
+    const char* relative_input_file_name = get_location_from_path(input_file_name);
+
     char dex2oat_Xms_flag[kPropertyValueMax];
     bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
 
@@ -287,7 +293,7 @@
     char dex2oat_image_fd[arraysize("--app-image-fd=") + MAX_INT_LEN];
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
-    sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
+    sprintf(zip_location_arg, "--zip-location=%s", relative_input_file_name);
     sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
     sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
     sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
@@ -349,8 +355,18 @@
         sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
     }
 
+    // Get the directory of the apk to pass as a base classpath directory.
+    char base_dir[arraysize("--classpath-dir=") + PKG_PATH_MAX];
+    std::string apk_dir(input_file_name);
+    unsigned long dir_index = apk_dir.rfind('/');
+    bool has_base_dir = dir_index != std::string::npos;
+    if (has_base_dir) {
+        apk_dir = apk_dir.substr(0, dir_index);
+        sprintf(base_dir, "--classpath-dir=%s", apk_dir.c_str());
+    }
 
-    ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
+
+    ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, relative_input_file_name, output_file_name);
 
     const char* argv[9  // program name, mandatory arguments and the final NULL
                      + (have_dex2oat_isa_variant ? 1 : 0)
@@ -368,6 +384,7 @@
                      + dex2oat_flags_count
                      + (profile_fd == -1 ? 0 : 1)
                      + (shared_libraries != nullptr ? 4 : 0)
+                     + (has_base_dir ? 1 : 0)
                      + (have_dex2oat_large_app_threshold ? 1 : 0)];
     int i = 0;
     argv[i++] = DEX2OAT_BIN;
@@ -432,6 +449,9 @@
         argv[i++] = RUNTIME_ARG;
         argv[i++] = shared_libraries;
     }
+    if (has_base_dir) {
+        argv[i++] = base_dir;
+    }
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -769,17 +789,6 @@
     exit(68);   /* only get here on exec failure */
 }
 
-static const char* get_location_from_path(const char* path) {
-    static constexpr char kLocationSeparator = '/';
-    const char *location = strrchr(path, kLocationSeparator);
-    if (location == NULL) {
-        return path;
-    } else {
-        // Skip the separator character.
-        return location + 1;
-    }
-}
-
 bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
     std::vector<unique_fd> profile_fds;
     unique_fd reference_profile_fd;
@@ -1556,14 +1565,12 @@
             _exit(67);
         }
 
-        // Pass dex2oat the relative path to the input file.
-        const char *input_file_name = get_location_from_path(dex_path);
         run_dex2oat(input_fd.get(),
                     out_oat_fd.get(),
                     in_vdex_fd.get(),
                     out_vdex_fd.get(),
                     image_fd.get(),
-                    input_file_name,
+                    dex_path,
                     out_oat_path,
                     swap_fd.get(),
                     instruction_set,
@@ -1863,20 +1870,5 @@
     return return_value_oat && return_value_art;
 }
 
-int dexopt(const char* const params[DEXOPT_PARAM_COUNT]) {
-    return dexopt(params[0],                    // apk_path
-                  atoi(params[1]),              // uid
-                  params[2],                    // pkgname
-                  params[3],                    // instruction_set
-                  atoi(params[4]),              // dexopt_needed
-                  params[5],                    // oat_dir
-                  atoi(params[6]),              // dexopt_flags
-                  params[7],                    // compiler_filter
-                  parse_null(params[8]),        // volume_uuid
-                  parse_null(params[9]),        // shared_libraries
-                  parse_null(params[10]));       // se_info
-    static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param count");
-}
-
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 88144b7..355adb1 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -62,12 +62,6 @@
         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
         const char* volume_uuid, const char* shared_libraries, const char* se_info);
 
-static constexpr size_t DEXOPT_PARAM_COUNT = 11U;
-static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param size");
-
-// Helper for the above, converting arguments.
-int dexopt(const char* const params[DEXOPT_PARAM_COUNT]);
-
 }  // namespace installd
 }  // namespace android
 
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 82b8cc2..ff838ce 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -16,6 +16,7 @@
 
 #include <algorithm>
 #include <inttypes.h>
+#include <limits>
 #include <random>
 #include <regex>
 #include <selinux/android.h>
@@ -33,12 +34,14 @@
 #include <android-base/strings.h>
 #include <cutils/fs.h>
 #include <cutils/properties.h>
+#include <dex2oat_return_codes.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 
 #include "dexopt.h"
 #include "file_parsing.h"
 #include "globals.h"
+#include "installd_constants.h"
 #include "installd_deps.h"  // Need to fill in requirements of commands.
 #include "otapreopt_utils.h"
 #include "system_properties.h"
@@ -144,6 +147,20 @@
 
 private:
 
+    struct Parameters {
+        const char *apk_path;
+        uid_t uid;
+        const char *pkgName;
+        const char *instruction_set;
+        int dexopt_needed;
+        const char* oat_dir;
+        int dexopt_flags;
+        const char* compiler_filter;
+        const char* volume_uuid;
+        const char* shared_libraries;
+        const char* se_info;
+    };
+
     bool ReadSystemProperties() {
         static constexpr const char* kPropertyFiles[] = {
                 "/default.prop", "/system/build.prop"
@@ -245,15 +262,23 @@
         return true;
     }
 
-    bool ReadArguments(int argc ATTRIBUTE_UNUSED, char** argv) {
-        // Expected command line:
-        //   target-slot dexopt {DEXOPT_PARAMETERS}
-        // The DEXOPT_PARAMETERS are passed on to dexopt(), so we expect DEXOPT_PARAM_COUNT
-        // of them. We store them in package_parameters_ (size checks are done when
-        // parsing the special parameters and when copying into package_parameters_.
+    bool ParseUInt(const char* in, uint32_t* out) {
+        char* end;
+        long long int result = strtoll(in, &end, 0);
+        if (in == end || *end != '\0') {
+            return false;
+        }
+        if (result < std::numeric_limits<uint32_t>::min() ||
+                std::numeric_limits<uint32_t>::max() < result) {
+            return false;
+        }
+        *out = static_cast<uint32_t>(result);
+        return true;
+    }
 
-        static_assert(DEXOPT_PARAM_COUNT == ARRAY_SIZE(package_parameters_),
-                      "Unexpected dexopt param count");
+    bool ReadArguments(int argc, char** argv) {
+        // Expected command line:
+        //   target-slot [version] dexopt {DEXOPT_PARAMETERS}
 
         const char* target_slot_arg = argv[1];
         if (target_slot_arg == nullptr) {
@@ -267,28 +292,229 @@
             return false;
         }
 
-        // Check for "dexopt" next.
+        // Check for version or "dexopt" next.
+        if (argv[2] == nullptr) {
+            LOG(ERROR) << "Missing parameters";
+            return false;
+        }
+
+        if (std::string("dexopt").compare(argv[2]) == 0) {
+            // This is version 1 (N) or pre-versioning version 2.
+            constexpr int kV2ArgCount =   1   // "otapreopt"
+                                        + 1   // slot
+                                        + 1   // "dexopt"
+                                        + 1   // apk_path
+                                        + 1   // uid
+                                        + 1   // pkg
+                                        + 1   // isa
+                                        + 1   // dexopt_needed
+                                        + 1   // oat_dir
+                                        + 1   // dexopt_flags
+                                        + 1   // filter
+                                        + 1   // volume
+                                        + 1   // libs
+                                        + 1;  // seinfo
+            if (argc == kV2ArgCount) {
+                return ReadArgumentsV2(argc, argv, false);
+            } else {
+                return ReadArgumentsV1(argc, argv);
+            }
+        }
+
+        uint32_t version;
+        if (!ParseUInt(argv[2], &version)) {
+            LOG(ERROR) << "Could not parse version: " << argv[2];
+            return false;
+        }
+
+        switch (version) {
+            case 2:
+                return ReadArgumentsV2(argc, argv, true);
+
+            default:
+                LOG(ERROR) << "Unsupported version " << version;
+                return false;
+        }
+    }
+
+    bool ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, char** argv, bool versioned) {
+        size_t dexopt_index = versioned ? 3 : 2;
+
+        // Check for "dexopt".
+        if (argv[dexopt_index] == nullptr) {
+            LOG(ERROR) << "Missing parameters";
+            return false;
+        }
+        if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
+            LOG(ERROR) << "Expected \"dexopt\"";
+            return false;
+        }
+
+        size_t param_index = 0;
+        for (;; ++param_index) {
+            const char* param = argv[dexopt_index + 1 + param_index];
+            if (param == nullptr) {
+                break;
+            }
+
+            switch (param_index) {
+                case 0:
+                    package_parameters_.apk_path = param;
+                    break;
+
+                case 1:
+                    package_parameters_.uid = atoi(param);
+                    break;
+
+                case 2:
+                    package_parameters_.pkgName = param;
+                    break;
+
+                case 3:
+                    package_parameters_.instruction_set = param;
+                    break;
+
+                case 4:
+                    package_parameters_.dexopt_needed = atoi(param);
+                    break;
+
+                case 5:
+                    package_parameters_.oat_dir = param;
+                    break;
+
+                case 6:
+                    package_parameters_.dexopt_flags = atoi(param);
+                    break;
+
+                case 7:
+                    package_parameters_.compiler_filter = param;
+                    break;
+
+                case 8:
+                    package_parameters_.volume_uuid = ParseNull(param);
+                    break;
+
+                case 9:
+                    package_parameters_.shared_libraries = ParseNull(param);
+                    break;
+
+                case 10:
+                    package_parameters_.se_info = ParseNull(param);
+                    break;
+
+                default:
+                    LOG(ERROR) << "Too many arguments, got " << param;
+                    return false;
+            }
+        }
+
+        if (param_index != 11) {
+            LOG(ERROR) << "Not enough parameters";
+            return false;
+        }
+
+        return true;
+    }
+
+    static int ReplaceMask(int input, int old_mask, int new_mask) {
+        return (input & old_mask) != 0 ? new_mask : 0;
+    }
+
+    bool ReadArgumentsV1(int argc ATTRIBUTE_UNUSED, char** argv) {
+        // Check for "dexopt".
         if (argv[2] == nullptr) {
             LOG(ERROR) << "Missing parameters";
             return false;
         }
         if (std::string("dexopt").compare(argv[2]) != 0) {
-            LOG(ERROR) << "Second parameter not dexopt: " << argv[2];
+            LOG(ERROR) << "Expected \"dexopt\"";
             return false;
         }
 
-        // Copy the rest into package_parameters_, but be careful about over- and underflow.
-        size_t index = 0;
-        while (index < DEXOPT_PARAM_COUNT &&
-                argv[index + 3] != nullptr) {
-            package_parameters_[index] = argv[index + 3];
-            index++;
+        size_t param_index = 0;
+        for (;; ++param_index) {
+            const char* param = argv[3 + param_index];
+            if (param == nullptr) {
+                break;
+            }
+
+            switch (param_index) {
+                case 0:
+                    package_parameters_.apk_path = param;
+                    break;
+
+                case 1:
+                    package_parameters_.uid = atoi(param);
+                    break;
+
+                case 2:
+                    package_parameters_.pkgName = param;
+                    break;
+
+                case 3:
+                    package_parameters_.instruction_set = param;
+                    break;
+
+                case 4: {
+                    // Version 1 had:
+                    //   DEXOPT_DEX2OAT_NEEDED       = 1
+                    //   DEXOPT_PATCHOAT_NEEDED      = 2
+                    //   DEXOPT_SELF_PATCHOAT_NEEDED = 3
+                    // We will simply use DEX2OAT_FROM_SCRATCH.
+                    package_parameters_.dexopt_needed = DEX2OAT_FROM_SCRATCH;
+                    break;
+                }
+
+                case 5:
+                    package_parameters_.oat_dir = param;
+                    break;
+
+                case 6: {
+                    // Version 1 had:
+                    constexpr int OLD_DEXOPT_PUBLIC         = 1 << 1;
+                    constexpr int OLD_DEXOPT_SAFEMODE       = 1 << 2;
+                    constexpr int OLD_DEXOPT_DEBUGGABLE     = 1 << 3;
+                    constexpr int OLD_DEXOPT_BOOTCOMPLETE   = 1 << 4;
+                    constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
+                    constexpr int OLD_DEXOPT_OTA            = 1 << 6;
+                    int input = atoi(param);
+                    package_parameters_.dexopt_flags =
+                            ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
+                            ReplaceMask(input, OLD_DEXOPT_SAFEMODE, DEXOPT_SAFEMODE) |
+                            ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
+                            ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
+                            ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
+                            ReplaceMask(input, OLD_DEXOPT_OTA, 0);
+                    break;
+                }
+
+                case 7:
+                    package_parameters_.compiler_filter = param;
+                    break;
+
+                case 8:
+                    package_parameters_.volume_uuid = ParseNull(param);
+                    break;
+
+                case 9:
+                    package_parameters_.shared_libraries = ParseNull(param);
+                    break;
+
+                default:
+                    LOG(ERROR) << "Too many arguments, got " << param;
+                    return false;
+            }
         }
-        if (index != ARRAY_SIZE(package_parameters_) || argv[index + 3] != nullptr) {
-            LOG(ERROR) << "Wrong number of parameters";
+
+        if (param_index != 10) {
+            LOG(ERROR) << "Not enough parameters";
             return false;
         }
 
+        // Set se_info to null. It is only relevant for secondary dex files, which we won't
+        // receive from a v1 A side.
+        package_parameters_.se_info = nullptr;
+
         return true;
     }
 
@@ -305,11 +531,11 @@
     // Ensure that we have the right boot image. The first time any app is
     // compiled, we'll try to generate it.
     bool PrepareBootImage(bool force) const {
-        if (package_parameters_[kISAIndex] == nullptr) {
+        if (package_parameters_.instruction_set == nullptr) {
             LOG(ERROR) << "Instruction set missing.";
             return false;
         }
-        const char* isa = package_parameters_[kISAIndex];
+        const char* isa = package_parameters_.instruction_set;
 
         // Check whether the file exists where expected.
         std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
@@ -535,14 +761,12 @@
         //       (This is ugly as it's the only thing where we need to understand the contents
         //        of package_parameters_, but it beats postponing the decision or using the call-
         //        backs to do weird things.)
-        constexpr size_t kApkPathIndex = 0;
-        CHECK_GT(DEXOPT_PARAM_COUNT, kApkPathIndex);
-        CHECK(package_parameters_[kApkPathIndex] != nullptr);
-        if (StartsWith(package_parameters_[kApkPathIndex], android_root_.c_str())) {
-            const char* last_slash = strrchr(package_parameters_[kApkPathIndex], '/');
+        const char* apk_path = package_parameters_.apk_path;
+        CHECK(apk_path != nullptr);
+        if (StartsWith(apk_path, android_root_.c_str())) {
+            const char* last_slash = strrchr(apk_path, '/');
             if (last_slash != nullptr) {
-                std::string path(package_parameters_[kApkPathIndex],
-                                 last_slash - package_parameters_[kApkPathIndex] + 1);
+                std::string path(apk_path, last_slash - apk_path + 1);
                 CHECK(EndsWith(path, "/"));
                 path = path + "oat";
                 if (access(path.c_str(), F_OK) == 0) {
@@ -556,36 +780,64 @@
         // partition will not be available and fail to build. This is problematic, as
         // this tool will wipe the OTA artifact cache and try again (for robustness after
         // a failed OTA with remaining cache artifacts).
-        if (access(package_parameters_[kApkPathIndex], F_OK) != 0) {
-            LOG(WARNING) << "Skipping preopt of non-existing package "
-                         << package_parameters_[kApkPathIndex];
+        if (access(apk_path, F_OK) != 0) {
+            LOG(WARNING) << "Skipping preopt of non-existing package " << apk_path;
             return true;
         }
 
         return false;
     }
 
+    // Run dexopt with the parameters of package_parameters_.
+    int Dexopt() {
+        return dexopt(package_parameters_.apk_path,
+                      package_parameters_.uid,
+                      package_parameters_.pkgName,
+                      package_parameters_.instruction_set,
+                      package_parameters_.dexopt_needed,
+                      package_parameters_.oat_dir,
+                      package_parameters_.dexopt_flags,
+                      package_parameters_.compiler_filter,
+                      package_parameters_.volume_uuid,
+                      package_parameters_.shared_libraries,
+                      package_parameters_.se_info);
+    }
+
     int RunPreopt() {
         if (ShouldSkipPreopt()) {
             return 0;
         }
 
-        int dexopt_result = dexopt(package_parameters_);
+        int dexopt_result = Dexopt();
         if (dexopt_result == 0) {
             return 0;
         }
 
         // If the dexopt failed, we may have a stale boot image from a previous OTA run.
-        // Try to delete and retry.
+        // Then regenerate and retry.
+        if (WEXITSTATUS(dexopt_result) ==
+                static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
+            if (!PrepareBootImage(/* force */ true)) {
+                LOG(ERROR) << "Forced boot image creating failed. Original error return was "
+                        << dexopt_result;
+                return dexopt_result;
+            }
 
-        if (!PrepareBootImage(/* force */ true)) {
-            LOG(ERROR) << "Forced boot image creating failed. Original error return was "
-                         << dexopt_result;
+            int dexopt_result_boot_image_retry = Dexopt();
+            if (dexopt_result_boot_image_retry == 0) {
+                return 0;
+            }
+        }
+
+        // If this was a profile-guided run, we may have profile version issues. Try to downgrade,
+        // if possible.
+        if ((package_parameters_.dexopt_flags & DEXOPT_PROFILE_GUIDED) == 0) {
             return dexopt_result;
         }
 
-        LOG(WARNING) << "Original dexopt failed, re-trying after boot image was regenerated.";
-        return dexopt(package_parameters_);
+        LOG(WARNING) << "Downgrading compiler filter in an attempt to progress compilation";
+        package_parameters_.dexopt_flags &= ~DEXOPT_PROFILE_GUIDED;
+        return Dexopt();
     }
 
     ////////////////////////////////////
@@ -715,7 +967,7 @@
     std::string boot_classpath_;
     std::string asec_mountpoint_;
 
-    const char* package_parameters_[DEXOPT_PARAM_COUNT];
+    Parameters package_parameters_;
 
     // Store environment values we need to set.
     std::vector<std::string> environ_;
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index cec8f68..2030997 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -27,7 +27,6 @@
 
 #include "installd_constants.h"
 #include "otapreopt_utils.h"
-#include "dexopt.h"
 
 #ifndef LOG_TAG
 #define LOG_TAG "otapreopt"
@@ -137,44 +136,18 @@
 
     // Now go on and run otapreopt.
 
-    // Incoming:  cmd + status-fd + target-slot + "dexopt" + dexopt-params + null
-    // Outgoing:  cmd             + target-slot + "dexopt" + dexopt-params + null
-    constexpr size_t kInArguments =   1                       // Binary name.
-                                    + 1                       // status file descriptor.
-                                    + 1                       // target-slot.
-                                    + 1                       // "dexopt."
-                                    + DEXOPT_PARAM_COUNT      // dexopt parameters.
-                                    + 1;                      // null termination.
-    constexpr size_t kOutArguments =   1                       // Binary name.
-                                     + 1                       // target-slot.
-                                     + 1                       // "dexopt."
-                                     + DEXOPT_PARAM_COUNT      // dexopt parameters.
-                                     + 1;                      // null termination.
-    const char* argv[kOutArguments];
-    if (static_cast<size_t>(argc) !=  kInArguments - 1 /* null termination */) {
-        LOG(ERROR) << "Unexpected argument size "
-                   << argc
-                   << " vs "
-                   << (kInArguments - 1);
-        for (size_t i = 0; i < static_cast<size_t>(argc); ++i) {
-            if (arg[i] == nullptr) {
-                LOG(ERROR) << "(null)";
-            } else {
-                LOG(ERROR) << "\"" << arg[i] << "\"";
-            }
-        }
-        exit(206);
-    }
+    // Incoming:  cmd + status-fd + target-slot + cmd... + null      | Incoming | = argc + 1
+    // Outgoing:  cmd             + target-slot + cmd... + null      | Outgoing | = argc
+    const char** argv = new const char*[argc];
+
     argv[0] = "/system/bin/otapreopt";
 
     // The first parameter is the status file descriptor, skip.
-
-    for (size_t i = 1; i <= kOutArguments - 2 /* cmd + null */; ++i) {
-        argv[i] = arg[i + 1];
+    for (size_t i = 2; i <= static_cast<size_t>(argc); ++i) {
+        argv[i - 1] = arg[i];
     }
-    argv[kOutArguments - 1] = nullptr;
 
-    execv(argv[0], (char * const *)argv);
+    execv(argv[0], static_cast<char * const *>(const_cast<char**>(argv)));
     PLOG(ERROR) << "execv(OTAPREOPT) failed.";
     exit(99);
 }
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 49605be..dab3236 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -547,7 +547,7 @@
 
 TEST_F(UtilsTest, CreatePrimaryCurrentProfile) {
     std::string expected =
-        create_primary_current_profile_package_dir_path(1, "com.example") + "/primary.prof";
+        create_primary_current_profile_package_dir_path(0, "com.example") + "/primary.prof";
     EXPECT_EQ(expected,
             create_current_profile_path(/*user*/0, "com.example", /*is_secondary*/false));
 }
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 4c57361..33bc43c 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -296,7 +296,7 @@
                 continue;
             }
 
-            vintf::ManifestHal *hal = manifest.getHal(fqName.package());
+            vintf::ManifestHal *hal = manifest.getAnyHal(fqName.package());
             if (hal == nullptr) {
                 if (!manifest.add(vintf::ManifestHal{
                     .format = vintf::HalFormat::HIDL,
@@ -306,7 +306,7 @@
                     mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
                     continue;
                 }
-                hal = manifest.getHal(fqName.package());
+                hal = manifest.getAnyHal(fqName.package());
             }
             if (hal == nullptr) {
                 mErr << "Warning: cannot get hal '" << fqInstanceName
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 68d39db..39d92a7 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -38,7 +38,7 @@
 cc_binary {
     name: "vndservicemanager",
     defaults: ["servicemanager_flags"],
-    proprietary: true,
+    vendor: true,
     srcs: [
         "service_manager.c",
         "binder.c",
@@ -46,6 +46,7 @@
     cflags: [
         "-DVENDORSERVICEMANAGER=1",
     ],
-    shared_libs: ["libcutils", "libselinux"],
+    shared_libs: ["libcutils"],
+    static_libs: ["libselinux"],
     init_rc: ["vndservicemanager.rc"],
 }
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 1f56a47..45bb1d0 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -65,11 +65,7 @@
 static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
 {
     char *sctx = NULL;
-#ifdef VENDORSERVICEMANAGER
-    const char *class = "vndservice_manager";
-#else
     const char *class = "service_manager";
-#endif
     bool allowed;
     struct audit_data ad;
 
diff --git a/cmds/vr/vrscreencap/Android.mk b/cmds/vr/vrscreencap/Android.mk
index bd0b224..804afc9 100644
--- a/cmds/vr/vrscreencap/Android.mk
+++ b/cmds/vr/vrscreencap/Android.mk
@@ -6,6 +6,7 @@
 	vrscreencap.cpp
 
 LOCAL_STATIC_LIBRARIES := \
+	libbufferhub \
 	libdisplay \
 	libimageio \
 	libpdx_default_transport \
@@ -14,7 +15,8 @@
 	libcutils \
 	liblog \
 	libpng \
-	libsync
+	libsync \
+	libui \
 
 LOCAL_MODULE := vrscreencap
 
diff --git a/data/etc/android.hardware.nfc.hce.xml b/data/etc/android.hardware.nfc.hce.xml
index 10b96b1..95da181 100644
--- a/data/etc/android.hardware.nfc.hce.xml
+++ b/data/etc/android.hardware.nfc.hce.xml
@@ -18,4 +18,5 @@
      NFC card emulation -->
 <permissions>
     <feature name="android.hardware.nfc.hce" />
+    <feature name="android.hardware.nfc.any" />
 </permissions>
diff --git a/data/etc/android.hardware.nfc.hcef.xml b/data/etc/android.hardware.nfc.hcef.xml
index 0d03023..b86890d 100644
--- a/data/etc/android.hardware.nfc.hcef.xml
+++ b/data/etc/android.hardware.nfc.hcef.xml
@@ -18,4 +18,5 @@
      NFC-F card emulation -->
 <permissions>
     <feature name="android.hardware.nfc.hcef" />
+    <feature name="android.hardware.nfc.any" />
 </permissions>
diff --git a/data/etc/android.hardware.nfc.xml b/data/etc/android.hardware.nfc.xml
index 81c4a84..5201fa2 100644
--- a/data/etc/android.hardware.nfc.xml
+++ b/data/etc/android.hardware.nfc.xml
@@ -18,4 +18,5 @@
      using Near-Field Communications (NFC). -->
 <permissions>
     <feature name="android.hardware.nfc" />
+    <feature name="android.hardware.nfc.any" />
 </permissions>
diff --git a/data/etc/android.software.autofill.xml b/data/etc/android.software.autofill.xml
new file mode 100644
index 0000000..c510d0c
--- /dev/null
+++ b/data/etc/android.software.autofill.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<permissions>
+    <feature name="android.software.autofill" />
+</permissions>
diff --git a/data/etc/android.software.cts.xml b/data/etc/android.software.cts.xml
new file mode 100644
index 0000000..0414c9a
--- /dev/null
+++ b/data/etc/android.software.cts.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<permissions>
+    <!-- This is Android and fully CTS compatible.  Basically this is for CTS tests to use. -->
+    <feature name="android.software.cts" />
+</permissions>
diff --git a/data/etc/android.software.preview_sdk.xml b/data/etc/android.software.preview_sdk.xml
new file mode 100644
index 0000000..928b4b3
--- /dev/null
+++ b/data/etc/android.software.preview_sdk.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<permissions>
+    <!-- The device is running a preview (i.e. unofficial) API version. -->
+    <feature name="android.software.preview_sdk" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 9229f82..0d5d206 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -49,6 +49,7 @@
     <feature name="android.software.activities_on_secondary_displays" />
     <feature name="android.software.print" />
     <feature name="android.software.companion_device_setup" />
+    <feature name="android.software.autofill" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
     <feature name="android.software.device_admin" />
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 64e32ff..9b88648 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -49,6 +49,7 @@
     <feature name="android.software.activities_on_secondary_displays" />
     <feature name="android.software.print" />
     <feature name="android.software.companion_device_setup" />
+    <feature name="android.software.autofill" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
     <feature name="android.software.device_admin" />
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 186f62c..cdb3fff 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -484,8 +484,9 @@
  *
  * Configure sensor direct report on a direct channel: set rate to value other than
  * {@link ASENSOR_DIRECT_RATE_STOP} so that sensor event can be directly
- * written into the shared memory region used for creating the buffer; set rate to
- * {@link ASENSOR_DIRECT_RATE_STOP} will stop the sensor direct report.
+ * written into the shared memory region used for creating the buffer. It returns a positive token
+ * which can be used for identify sensor events from different sensors on success. Calling with rate
+ * {@link ASENSOR_DIRECT_RATE_STOP} will stop direct report of the sensor specified in the channel.
  *
  * To stop all active sensor direct report configured to a channel, set sensor to NULL and rate to
  * {@link ASENSOR_DIRECT_RATE_STOP}.
@@ -513,7 +514,7 @@
  *                  {@link ASensorManager_createSharedMemoryDirectChannel} or
  *                  {@link ASensorManager_createHardwareBufferDirectChannel}.
  *
- * \return 0 for success or negative integer for failure.
+ * \return positive token for success or negative error code.
  */
 int ASensorManager_configureDirectReport(
         ASensorManager* manager, ASensor const* sensor, int channelId, int rate);
diff --git a/include/binder b/include/binder
new file mode 120000
index 0000000..35a022a
--- /dev/null
+++ b/include/binder
@@ -0,0 +1 @@
+../libs/binder/include/binder/
\ No newline at end of file
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index c95c535..bd62d85 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -23,10 +23,6 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/IConsumerListener.h>
 
-// These are only required to keep other parts of the framework with incomplete
-// dependencies building successfully
-#include <gui/IGraphicBufferAlloc.h>
-
 namespace android {
 
 class BufferQueue {
@@ -81,11 +77,9 @@
     // needed gralloc buffers.
     static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
             sp<IGraphicBufferConsumer>* outConsumer,
-            const sp<IGraphicBufferAlloc>& allocator = NULL,
             bool consumerIsSurfaceFlinger = false);
 
-private:
-    BufferQueue(); // Create through createBufferQueue
+    BufferQueue() = delete; // Create through createBufferQueue
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index da574ec..1e22d28 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -110,7 +110,7 @@
     virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
 
     // setConsumerName sets the name used in logging
-    virtual void setConsumerName(const String8& name);
+    status_t setConsumerName(const String8& name) override;
 
     // setDefaultBufferFormat allows the BufferQueue to create
     // GraphicBuffers of a defaultFormat if no format is specified
@@ -135,7 +135,7 @@
     virtual status_t setTransformHint(uint32_t hint);
 
     // Retrieve the sideband buffer stream, if any.
-    virtual sp<NativeHandle> getSidebandStream() const;
+    status_t getSidebandStream(sp<NativeHandle>* outStream) const override;
 
     // See IGraphicBufferConsumer::getOccupancyHistory
     virtual status_t getOccupancyHistory(bool forceFlush,
@@ -145,7 +145,7 @@
     virtual status_t discardFreeBuffers() override;
 
     // dump our state in a String
-    virtual void dumpState(String8& result, const char* prefix) const;
+    status_t dumpState(const String8& prefix, String8* outResult) const override;
 
     // Functions required for backwards compatibility.
     // These will be modified/renamed in IGraphicBufferConsumer and will be
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index b1c730a..cfe716f 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -51,7 +51,6 @@
 namespace android {
 
 class IConsumerListener;
-class IGraphicBufferAlloc;
 class IProducerListener;
 
 class BufferQueueCore : public virtual RefBase {
@@ -79,14 +78,13 @@
     typedef Vector<BufferItem> Fifo;
 
     // BufferQueueCore manages a pool of gralloc memory slots to be used by
-    // producers and consumers. allocator is used to allocate all the needed
-    // gralloc buffers.
-    BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator = NULL);
+    // producers and consumers.
+    BufferQueueCore();
     virtual ~BufferQueueCore();
 
 private:
     // Dump our state in a string
-    void dumpState(String8& result, const char* prefix) const;
+    void dumpState(const String8& prefix, String8* outResult) const;
 
     // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
     // that must remain in a state other than DEQUEUED. The async parameter
@@ -143,10 +141,6 @@
     void validateConsistencyLocked() const;
 #endif
 
-    // mAllocator is the connection to SurfaceFlinger that is used to allocate
-    // new GraphicBuffer objects.
-    sp<IGraphicBufferAlloc> mAllocator;
-
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of BufferQueueCore objects. It must be locked whenever any
     // member variable is accessed.
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 92251ed..9716be4 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -54,8 +54,7 @@
     static constexpr auto EVENT_COUNT =
             static_cast<size_t>(FrameEvent::EVENT_COUNT);
     static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");
-    static constexpr nsecs_t TIMESTAMP_PENDING =
-            std::numeric_limits<nsecs_t>::max();
+    static constexpr nsecs_t TIMESTAMP_PENDING = -2;
 
     static inline bool isValidTimestamp(nsecs_t time) {
         return time != TIMESTAMP_PENDING;
diff --git a/include/gui/GraphicBufferAlloc.h b/include/gui/GraphicBufferAlloc.h
deleted file mode 100644
index 54c9829..0000000
--- a/include/gui/GraphicBufferAlloc.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
-#define ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <ui/PixelFormat.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class GraphicBuffer;
-
-/*
- * Concrete implementation of the IGraphicBufferAlloc interface.
- *
- * This can create GraphicBuffer instance across processes. This is mainly used
- * by surfaceflinger.
- */
-
-class GraphicBufferAlloc : public BnGraphicBufferAlloc {
-public:
-    GraphicBufferAlloc();
-    virtual ~GraphicBufferAlloc();
-    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
-            uint32_t height, PixelFormat format, uint32_t layerCount,
-            uint64_t producerUsage, uint64_t consumerUsage,
-            std::string requestorName, status_t* error) override;
-};
-
-
-} // namespace android
-
-#endif // ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
diff --git a/include/gui/IGraphicBufferAlloc.h b/include/gui/IGraphicBufferAlloc.h
deleted file mode 100644
index 1e578cc..0000000
--- a/include/gui/IGraphicBufferAlloc.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GUI_IGRAPHIC_BUFFER_ALLOC_H
-#define ANDROID_GUI_IGRAPHIC_BUFFER_ALLOC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/IInterface.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/PixelFormat.h>
-#include <utils/RefBase.h>
-
-#include <string>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class IGraphicBufferAlloc : public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(GraphicBufferAlloc)
-
-    /* Create a new GraphicBuffer for the client to use.
-     */
-    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
-            uint64_t consumerUsage, std::string requestorName,
-            status_t* error) = 0;
-
-    sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t layerCount, uint32_t usage,
-            status_t* error) {
-        return createGraphicBuffer(w, h, format, layerCount, usage,
-                usage, "<Unknown>", error);
-    }
-
-    sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t layerCount, uint32_t usage,
-            std::string requestorName, status_t* error) {
-        return createGraphicBuffer(w, h, format, layerCount, usage,
-                usage, requestorName, error);
-    }
-
-    sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
-            uint64_t consumerUsage, status_t* error) {
-        return createGraphicBuffer(w, h, format, layerCount, producerUsage,
-                consumerUsage, "<Unknown>", error);
-    }
-};
-
-// ----------------------------------------------------------------------------
-
-class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
-{
-public:
-    virtual status_t onTransact(uint32_t code,
-                                const Parcel& data,
-                                Parcel* reply,
-                                uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_GUI_IGRAPHIC_BUFFER_ALLOC_H
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 60b7d24..63254ed 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -14,27 +14,21 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_GUI_IGRAPHICBUFFERCONSUMER_H
-#define ANDROID_GUI_IGRAPHICBUFFERCONSUMER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-
-#include <binder/IInterface.h>
-
-#include <ui/PixelFormat.h>
+#pragma once
 
 #include <gui/OccupancyTracker.h>
 
+#include <binder/IInterface.h>
+#include <binder/SafeInterface.h>
+
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
+#include <ui/PixelFormat.h>
+
+#include <utils/Errors.h>
+
 namespace android {
-// ----------------------------------------------------------------------------
 
 class BufferItem;
 class Fence;
@@ -43,11 +37,12 @@
 class NativeHandle;
 
 class IGraphicBufferConsumer : public IInterface {
-
 public:
+    DECLARE_META_INTERFACE(GraphicBufferConsumer)
+
     enum {
-        // Returned by releaseBuffer, after which the consumer must
-        // free any references to the just-released buffer that it might have.
+        // Returned by releaseBuffer, after which the consumer must free any references to the
+        // just-released buffer that it might have.
         STALE_BUFFER_SLOT = 1,
         // Returned by dequeueBuffer if there are no pending buffers available.
         NO_BUFFER_AVAILABLE,
@@ -55,88 +50,79 @@
         PRESENT_LATER,
     };
 
-    // acquireBuffer attempts to acquire ownership of the next pending buffer in
-    // the BufferQueue.  If no buffer is pending then it returns
-    // NO_BUFFER_AVAILABLE.  If a buffer is successfully acquired, the
-    // information about the buffer is returned in BufferItem.
+    // acquireBuffer attempts to acquire ownership of the next pending buffer in the BufferQueue.
+    // If no buffer is pending then it returns NO_BUFFER_AVAILABLE. If a buffer is successfully
+    // acquired, the information about the buffer is returned in BufferItem.
     //
-    // If the buffer returned had previously been
-    // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
-    // NULL and it is assumed that the consumer still holds a reference to the
+    // If the buffer returned had previously been acquired then the BufferItem::mGraphicBuffer field
+    // of buffer is set to NULL and it is assumed that the consumer still holds a reference to the
     // buffer.
     //
-    // If presentWhen is non-zero, it indicates the time when the buffer will
-    // be displayed on screen.  If the buffer's timestamp is farther in the
-    // future, the buffer won't be acquired, and PRESENT_LATER will be
-    // returned.  The presentation time is in nanoseconds, and the time base
+    // If presentWhen is non-zero, it indicates the time when the buffer will be displayed on
+    // screen. If the buffer's timestamp is farther in the future, the buffer won't be acquired, and
+    // PRESENT_LATER will be returned. The presentation time is in nanoseconds, and the time base
     // is CLOCK_MONOTONIC.
     //
-    // If maxFrameNumber is non-zero, it indicates that acquireBuffer should
-    // only return a buffer with a frame number less than or equal to
-    // maxFrameNumber. If no such frame is available (such as when a buffer has
-    // been replaced but the consumer has not received the onFrameReplaced
-    // callback), then PRESENT_LATER will be returned.
+    // If maxFrameNumber is non-zero, it indicates that acquireBuffer should only return a buffer
+    // with a frame number less than or equal to maxFrameNumber. If no such frame is available
+    // (such as when a buffer has been replaced but the consumer has not received the
+    // onFrameReplaced callback), then PRESENT_LATER will be returned.
     //
     // Return of NO_ERROR means the operation completed as normal.
     //
-    // Return of a positive value means the operation could not be completed
-    //    at this time, but the user should try again later:
+    // Return of a positive value means the operation could not be completed at this time, but the
+    // user should try again later:
     // * NO_BUFFER_AVAILABLE - no buffer is pending (nothing queued by producer)
     // * PRESENT_LATER - the buffer's timestamp is farther in the future
     //
     // Return of a negative value means an error has occurred:
     // * INVALID_OPERATION - too many buffers have been acquired
     virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
-            uint64_t maxFrameNumber = 0) = 0;
+                                   uint64_t maxFrameNumber = 0) = 0;
 
-    // detachBuffer attempts to remove all ownership of the buffer in the given
-    // slot from the buffer queue. If this call succeeds, the slot will be
-    // freed, and there will be no way to obtain the buffer from this interface.
-    // The freed slot will remain unallocated until either it is selected to
-    // hold a freshly allocated buffer in dequeueBuffer or a buffer is attached
-    // to the slot. The buffer must have already been acquired.
+    // detachBuffer attempts to remove all ownership of the buffer in the given slot from the buffer
+    // queue. If this call succeeds, the slot will be freed, and there will be no way to obtain the
+    // buffer from this interface. The freed slot will remain unallocated until either it is
+    // selected to hold a freshly allocated buffer in dequeueBuffer or a buffer is attached to the
+    // slot. The buffer must have already been acquired.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * BAD_VALUE - the given slot number is invalid, either because it is
-    //               out of the range [0, NUM_BUFFER_SLOTS) or because the slot
-    //               it refers to is not currently acquired.
+    // * BAD_VALUE - the given slot number is invalid, either because it is out of the range
+    //               [0, NUM_BUFFER_SLOTS) or because the slot it refers to is not
+    //               currently acquired.
     virtual status_t detachBuffer(int slot) = 0;
 
-    // attachBuffer attempts to transfer ownership of a buffer to the buffer
-    // queue. If this call succeeds, it will be as if this buffer was acquired
-    // from the returned slot number. As such, this call will fail if attaching
-    // this buffer would cause too many buffers to be simultaneously acquired.
+    // attachBuffer attempts to transfer ownership of a buffer to the BufferQueue. If this call
+    // succeeds, it will be as if this buffer was acquired from the returned slot number. As such,
+    // this call will fail if attaching this buffer would cause too many buffers to be
+    // simultaneously acquired.
     //
-    // If the buffer is successfully attached, its frameNumber is initialized
-    // to 0. This must be passed into the releaseBuffer call or else the buffer
-    // will be deallocated as stale.
+    // If the buffer is successfully attached, its frameNumber is initialized to 0. This must be
+    // passed into the releaseBuffer call or else the buffer will be deallocated as stale.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * BAD_VALUE - outSlot or buffer were NULL, or the generation number of
-    //               the buffer did not match the buffer queue.
-    // * INVALID_OPERATION - cannot attach the buffer because it would cause too
-    //                       many buffers to be acquired.
+    // * BAD_VALUE - outSlot or buffer were NULL, or the generation number of the buffer did not
+    //               match the BufferQueue.
+    // * INVALID_OPERATION - cannot attach the buffer because it would cause too many buffers
+    //                       to be acquired.
     // * NO_MEMORY - no free slots available
-    virtual status_t attachBuffer(int *outSlot,
-            const sp<GraphicBuffer>& buffer) = 0;
+    virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) = 0;
 
-    // releaseBuffer releases a buffer slot from the consumer back to the
-    // BufferQueue.  This may be done while the buffer's contents are still
-    // being accessed.  The fence will signal when the buffer is no longer
-    // in use. frameNumber is used to indentify the exact buffer returned.
+    // releaseBuffer releases a buffer slot from the consumer back to the BufferQueue. This may be
+    // done while the buffer's contents are still being accessed. The fence will signal when the
+    // buffer is no longer in use. frameNumber is used to identify the exact buffer returned.
     //
-    // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
-    // any references to the just-released buffer that it might have, as if it
-    // had received a onBuffersReleased() call with a mask set for the released
-    // buffer.
+    // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free any references to the
+    // just-released buffer that it might have, as if it had received a onBuffersReleased() call
+    // with a mask set for the released buffer.
     //
-    // Note that the dependencies on EGL will be removed once we switch to using
-    // the Android HW Sync HAL.
+    // Note that the dependencies on EGL will be removed once we switch to using the Android HW
+    // Sync HAL.
     //
     // Return of NO_ERROR means the operation completed as normal.
     //
-    // Return of a positive value means the operation could not be completed
-    //    at this time, but the user should try again later:
+    // Return of a positive value means the operation could not be completed at this time, but the
+    // user should try again later:
     // * STALE_BUFFER_SLOT - see above (second paragraph)
     //
     // Return of a negative value means an error has occurred:
@@ -144,159 +130,157 @@
     //               * the buffer slot was invalid
     //               * the fence was NULL
     //               * the buffer slot specified is not in the acquired state
-    virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
-            EGLDisplay display, EGLSyncKHR fence,
-            const sp<Fence>& releaseFence) = 0;
+    virtual status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display,
+                                   EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0;
 
-    // consumerConnect connects a consumer to the BufferQueue.  Only one
-    // consumer may be connected, and when that consumer disconnects the
-    // BufferQueue is placed into the "abandoned" state, causing most
-    // interactions with the BufferQueue by the producer to fail.
-    // controlledByApp indicates whether the consumer is controlled by
-    // the application.
+    status_t releaseHelper(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) {
+        return releaseBuffer(buf, frameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
+    }
+    // This is explicitly *not* the actual signature of IGBC::releaseBuffer, but:
+    //     1) We have no easy way to send the EGL objects across Binder
+    //     2) This has always been broken, probably because
+    //     3) IGBC is rarely remoted
+    // For now, we will choose to bury our heads in the sand and ignore this problem until such time
+    // as we can finally finish converting away from EGL sync to native Android sync
+    using ReleaseBuffer = decltype(&IGraphicBufferConsumer::releaseHelper);
+
+    // consumerConnect connects a consumer to the BufferQueue. Only one consumer may be connected,
+    // and when that consumer disconnects the BufferQueue is placed into the "abandoned" state,
+    // causing most interactions with the BufferQueue by the producer to fail. controlledByApp
+    // indicates whether the consumer is controlled by the application.
     //
     // consumer may not be NULL.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned
+    // * NO_INIT - the BufferQueue has been abandoned
     // * BAD_VALUE - a NULL consumer was provided
-    virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0;
+    virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
+                                     bool controlledByApp) = 0;
 
-    // consumerDisconnect disconnects a consumer from the BufferQueue. All
-    // buffers will be freed and the BufferQueue is placed in the "abandoned"
-    // state, causing most interactions with the BufferQueue by the producer to
-    // fail.
+    // consumerDisconnect disconnects a consumer from the BufferQueue. All buffers will be freed and
+    // the BufferQueue is placed in the "abandoned" state, causing most interactions with the
+    // BufferQueue by the producer to fail.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
     // * BAD_VALUE - no consumer is currently connected
     virtual status_t consumerDisconnect() = 0;
 
-    // getReleasedBuffers sets the value pointed to by slotMask to a bit set.
-    // Each bit index with a 1 corresponds to a released buffer slot with that
-    // index value.  In particular, a released buffer is one that has
-    // been released by the BufferQueue but have not yet been released by the consumer.
+    // getReleasedBuffers sets the value pointed to by slotMask to a bit set. Each bit index with a
+    // 1 corresponds to a released buffer slot with that index value. In particular, a released
+    // buffer is one that has been released by the BufferQueue but has not yet been released by
+    // the consumer.
     //
     // This should be called from the onBuffersReleased() callback.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the BufferQueue has been abandoned.
     virtual status_t getReleasedBuffers(uint64_t* slotMask) = 0;
 
-    // setDefaultBufferSize is used to set the size of buffers returned by
-    // dequeueBuffer when a width and height of zero is requested.  Default
-    // is 1x1.
+    // setDefaultBufferSize is used to set the size of buffers returned by dequeueBuffer when a
+    // width and height of zero is requested. Default is 1x1.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
     // * BAD_VALUE - either w or h was zero
     virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
 
-    // setMaxBufferCount sets the maximum value for the number of buffers used
-    // in the buffer queue (the initial default is NUM_BUFFER_SLOTS). If a call
-    // to setMaxAcquiredBufferCount (by the consumer), or a call to setAsyncMode
-    // or setMaxDequeuedBufferCount (by the producer), would cause this value to
-    // be exceeded then that call will fail. This call will fail if a producer
+    // setMaxBufferCount sets the maximum value for the number of buffers used in the BufferQueue
+    // (the initial default is NUM_BUFFER_SLOTS). If a call to setMaxAcquiredBufferCount (by the
+    // consumer), or a call to setAsyncMode or setMaxDequeuedBufferCount (by the producer), would
+    // cause this value to be exceeded then that call will fail. This call will fail if a producer
     // is connected to the BufferQueue.
     //
-    // The count must be between 1 and NUM_BUFFER_SLOTS, inclusive. The count
-    // cannot be less than maxAcquiredBufferCount.
+    // The count must be between 1 and NUM_BUFFER_SLOTS, inclusive. The count cannot be less than
+    // maxAcquiredBufferCount.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
     // * BAD_VALUE - one of the below conditions occurred:
-    //             * bufferCount was out of range (see above).
-    //             * failure to adjust the number of available slots.
+    //               * bufferCount was out of range (see above).
+    //               * failure to adjust the number of available slots.
     // * INVALID_OPERATION - attempting to call this after a producer connected.
     virtual status_t setMaxBufferCount(int bufferCount) = 0;
 
-    // setMaxAcquiredBufferCount sets the maximum number of buffers that can
-    // be acquired by the consumer at one time (default 1). If this method
-    // succeeds, any new buffer slots will be both unallocated and owned by the
-    // BufferQueue object (i.e. they are not owned by the producer or consumer).
-    // Calling this may also cause some buffer slots to be emptied.
+    // setMaxAcquiredBufferCount sets the maximum number of buffers that can be acquired by the
+    // consumer at one time (default 1). If this method succeeds, any new buffer slots will be both
+    // unallocated and owned by the BufferQueue object (i.e. they are not owned by the producer or
+    // consumer). Calling this may also cause some buffer slots to be emptied.
     //
-    // This function should not be called with a value of maxAcquiredBuffers
-    // that is less than the number of currently acquired buffer slots. Doing so
-    // will result in a BAD_VALUE error.
+    // This function should not be called with a value of maxAcquiredBuffers that is less than the
+    // number of currently acquired buffer slots. Doing so will result in a BAD_VALUE error.
     //
-    // maxAcquiredBuffers must be (inclusive) between 1 and
-    // MAX_MAX_ACQUIRED_BUFFERS. It also cannot cause the maxBufferCount value
-    // to be exceeded.
+    // maxAcquiredBuffers must be (inclusive) between 1 and MAX_MAX_ACQUIRED_BUFFERS. It also cannot
+    // cause the maxBufferCount value to be exceeded.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned
+    // * NO_INIT - the BufferQueue has been abandoned
     // * BAD_VALUE - one of the below conditions occurred:
-    //             * maxAcquiredBuffers was out of range (see above).
-    //             * failure to adjust the number of available slots.
-    //             * client would have more than the requested number of
-    //               acquired buffers after this call
+    //               * maxAcquiredBuffers was out of range (see above).
+    //               * failure to adjust the number of available slots.
+    //               * client would have more than the requested number of acquired buffers after
+    //                 this call
     // * INVALID_OPERATION - attempting to call this after a producer connected.
     virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0;
 
     // setConsumerName sets the name used in logging
-    virtual void setConsumerName(const String8& name) = 0;
+    virtual status_t setConsumerName(const String8& name) = 0;
 
-    // setDefaultBufferFormat allows the BufferQueue to create
-    // GraphicBuffers of a defaultFormat if no format is specified
-    // in dequeueBuffer.
-    // The initial default is PIXEL_FORMAT_RGBA_8888.
+    // setDefaultBufferFormat allows the BufferQueue to create GraphicBuffers of a defaultFormat if
+    // no format is specified in dequeueBuffer. The initial default is PIXEL_FORMAT_RGBA_8888.
     //
     // Return of a value other than NO_ERROR means an unknown error has occurred.
     virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) = 0;
 
-    // setDefaultBufferDataSpace is a request to the producer to provide buffers
-    // of the indicated dataSpace. The producer may ignore this request.
-    // The initial default is HAL_DATASPACE_UNKNOWN.
+    // setDefaultBufferDataSpace is a request to the producer to provide buffers of the indicated
+    // dataSpace. The producer may ignore this request. The initial default is
+    // HAL_DATASPACE_UNKNOWN.
     //
     // Return of a value other than NO_ERROR means an unknown error has occurred.
-    virtual status_t setDefaultBufferDataSpace(
-            android_dataspace defaultDataSpace) = 0;
+    virtual status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) = 0;
 
-    // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
-    // These are merged with the bits passed to dequeueBuffer.  The values are
-    // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
+    // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer. These are merged
+    // with the bits passed to dequeueBuffer. The values are enumerated in gralloc.h,
+    // e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
     //
     // Return of a value other than NO_ERROR means an unknown error has occurred.
     virtual status_t setConsumerUsageBits(uint32_t usage) = 0;
 
-    // setTransformHint bakes in rotation to buffers so overlays can be used.
-    // The values are enumerated in window.h, e.g.
-    // NATIVE_WINDOW_TRANSFORM_ROT_90.  The default is 0 (no transform).
+    // setTransformHint bakes in rotation to buffers so overlays can be used. The values are
+    // enumerated in window.h, e.g. NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0
+    // (no transform).
     //
     // Return of a value other than NO_ERROR means an unknown error has occurred.
     virtual status_t setTransformHint(uint32_t hint) = 0;
 
     // Retrieve the sideband buffer stream, if any.
-    virtual sp<NativeHandle> getSidebandStream() const = 0;
+    virtual status_t getSidebandStream(sp<NativeHandle>* outStream) const = 0;
 
-    // Retrieves any stored segments of the occupancy history of this
-    // BufferQueue and clears them. Optionally closes out the pending segment if
-    // forceFlush is true.
+    // Retrieves any stored segments of the occupancy history of this BufferQueue and clears them.
+    // Optionally closes out the pending segment if forceFlush is true.
     virtual status_t getOccupancyHistory(bool forceFlush,
-            std::vector<OccupancyTracker::Segment>* outHistory) = 0;
+                                         std::vector<OccupancyTracker::Segment>* outHistory) = 0;
 
-    // discardFreeBuffers releases all currently-free buffers held by the queue,
-    // in order to reduce the memory consumption of the queue to the minimum
-    // possible without discarding data.
+    // discardFreeBuffers releases all currently-free buffers held by the BufferQueue, in order to
+    // reduce the memory consumption of the BufferQueue to the minimum possible without
+    // discarding data.
     virtual status_t discardFreeBuffers() = 0;
 
     // dump state into a string
-    virtual void dumpState(String8& result, const char* prefix) const = 0;
+    virtual status_t dumpState(const String8& prefix, String8* outResult) const = 0;
 
-public:
-    DECLARE_META_INTERFACE(GraphicBufferConsumer)
+    // Provide backwards source compatibility
+    void dumpState(String8& result, const char* prefix) {
+        String8 returned;
+        dumpState(String8(prefix), &returned);
+        result.append(returned);
+    }
 };
 
-// ----------------------------------------------------------------------------
-
-class BnGraphicBufferConsumer : public BnInterface<IGraphicBufferConsumer>
-{
+class BnGraphicBufferConsumer : public SafeBnInterface<IGraphicBufferConsumer> {
 public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
+    BnGraphicBufferConsumer()
+          : SafeBnInterface<IGraphicBufferConsumer>("BnGraphicBufferConsumer") {}
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                        uint32_t flags = 0) override;
 };
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_IGRAPHICBUFFERCONSUMER_H
+} // namespace android
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 5810335..9250806 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -487,6 +487,7 @@
     // is considered a no-op.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
+    // * NO_INIT - the producer is not connected
     // * BAD_VALUE - one of the following has occurred:
     //             * the api specified does not match the one that was connected
     //             * api was out of range (see above).
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 2fbe07a..1112973 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -41,7 +41,6 @@
 struct DisplayStatInfo;
 class HdrCapabilities;
 class IDisplayEventConnection;
-class IGraphicBufferAlloc;
 class IGraphicBufferProducer;
 class ISurfaceComposerClient;
 class Rect;
@@ -89,10 +88,6 @@
     virtual sp<ISurfaceComposerClient> createScopedConnection(
             const sp<IGraphicBufferProducer>& parent) = 0;
 
-    /* create a graphic buffer allocator
-     */
-    virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
-
     /* return an IDisplayEventConnection */
     virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
 
@@ -126,6 +121,11 @@
     virtual bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& surface) const = 0;
 
+    /* Returns the frame timestamps supported by SurfaceFlinger.
+     */
+    virtual status_t getSupportedFrameTimestamps(
+            std::vector<FrameEvent>* outSupported) const = 0;
+
     /* set display power mode. depending on the mode, it can either trigger
      * screen on, off or low power mode and wait for it to complete.
      * requires ACCESS_SURFACE_FLINGER permission.
@@ -200,7 +200,7 @@
         // Java by ActivityManagerService.
         BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
         CREATE_CONNECTION,
-        CREATE_GRAPHIC_BUFFER_ALLOC,
+        UNUSED, // formerly CREATE_GRAPHIC_BUFFER_ALLOC
         CREATE_DISPLAY_EVENT_CONNECTION,
         CREATE_DISPLAY,
         DESTROY_DISPLAY,
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 88ef010..8b1d106 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -426,6 +426,10 @@
     uint64_t mNextFrameNumber = 1;
     uint64_t mLastFrameNumber = 0;
 
+    // Mutable because ANativeWindow::query needs this class const.
+    mutable bool mQueriedSupportedTimestamps;
+    mutable bool mFrameTimestampsSupportsPresent;
+
     // A cached copy of the FrameEventHistory maintained by the consumer.
     bool mEnableFrameTimestamps = false;
     std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 394425a..ec310cf 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -146,6 +146,8 @@
     status_t    setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
     status_t    setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
     status_t    setLayer(const sp<IBinder>& id, int32_t layer);
+    status_t    setRelativeLayer(const sp<IBinder>& id,
+            const sp<IBinder>& relativeTo, int32_t layer);
     status_t    setAlpha(const sp<IBinder>& id, float alpha=1.0f);
     status_t    setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy);
     status_t    setPosition(const sp<IBinder>& id, float x, float y);
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 3cff7df..712a323 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -62,6 +62,27 @@
 
     status_t    setLayerStack(uint32_t layerStack);
     status_t    setLayer(int32_t layer);
+
+    // Sets a Z order relative to the Surface specified by "relativeTo" but
+    // without becoming a full child of the relative. Z-ordering works exactly
+    // as if it were a child however.
+    //
+    // As a nod to sanity, only non-child surfaces may have a relative Z-order.
+    //
+    // This overrides any previous and is overriden by any future calls
+    // to setLayer.
+    //
+    // If the relative dissapears, the Surface will have no layer and be
+    // invisible, until the next time set(Relative)Layer is called.
+    //
+    // TODO: This is probably a hack. Currently it exists only to work around
+    // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type
+    // which allows inserting a window between a SurfaceView and it's main application
+    // window. However, since we are using child windows for the SurfaceView, but not using
+    // child windows elsewhere in O, the WindowManager can't set the layer appropriately.
+    // This is only used by the "TvInputService" and following the port of ViewRootImpl
+    // to child surfaces, we can then port this and remove this method.
+    status_t    setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer);
     status_t    setPosition(float x, float y);
     status_t    setSize(uint32_t w, uint32_t h);
     status_t    hide();
diff --git a/include/media/cas/CasAPI.h b/include/media/cas/CasAPI.h
index 0e88019..67f4511 100644
--- a/include/media/cas/CasAPI.h
+++ b/include/media/cas/CasAPI.h
@@ -81,23 +81,12 @@
     virtual status_t setPrivateData(
             const CasData &privateData) = 0;
 
-    // Open a session for descrambling a program. The session will receive the
-    // ECM stream corresponding to the CA_PID for the program.
-    virtual status_t openSession(
-            uint16_t program_number,
-            CasSessionId *sessionId) = 0;
-
-    // Open a session for descrambling an elementary stream inside a program.
-    // The session will receive the ECM stream corresponding to the CA_PID for
-    // the stream.
-    virtual status_t openSession(
-            uint16_t program_number,
-            uint16_t elementary_PID,
-            CasSessionId *sessionId) = 0;
+    // Open a session for descrambling a program, or one or more elementary
+    // streams.
+    virtual status_t openSession(CasSessionId *sessionId) = 0;
 
     // Close a previously opened session.
-    virtual status_t closeSession(
-            const CasSessionId &sessionId) = 0;
+    virtual status_t closeSession(const CasSessionId &sessionId) = 0;
 
     // Provide the CA private data from a CA_descriptor in the program map
     // table to a CasPlugin.
diff --git a/include/private/binder b/include/private/binder
new file mode 120000
index 0000000..09e9076
--- /dev/null
+++ b/include/private/binder
@@ -0,0 +1 @@
+../../libs/binder/include/private/binder
\ No newline at end of file
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 20f51a5..307c764 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -58,7 +58,8 @@
         eOverrideScalingModeChanged = 0x00000800,
         eGeometryAppliesWithResize  = 0x00001000,
         eReparentChildren           = 0x00002000,
-        eDetachChildren             = 0x00004000
+        eDetachChildren             = 0x00004000,
+        eRelativeLayerChanged       = 0x00008000
     };
 
     layer_state_t()
@@ -104,6 +105,8 @@
 
             sp<IGraphicBufferProducer> barrierGbp;
 
+            sp<IBinder>     relativeLayerHandle;
+
             // non POD must be last. see write/read
             Region          transparentRegion;
 };
diff --git a/include/ui/Gralloc1.h b/include/ui/Gralloc1.h
deleted file mode 100644
index 90713b3..0000000
--- a/include/ui/Gralloc1.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_UI_GRALLOC1_H
-#define ANDROID_UI_GRALLOC1_H
-
-#define GRALLOC1_LOG_TAG "Gralloc1"
-
-#include <functional>
-#include <memory>
-#include <unordered_set>
-
-#include <log/log.h>
-
-#include <ui/Fence.h>
-
-#include <hardware/gralloc1.h>
-
-
-namespace std {
-    template <>
-    struct hash<gralloc1_capability_t> {
-        size_t operator()(gralloc1_capability_t capability) const {
-            return std::hash<int32_t>()(static_cast<int32_t>(capability));
-        }
-    };
-}
-
-namespace android {
-class GraphicBuffer;
-class Fence;
-class GraphicBuffer;
-class Gralloc1On0Adapter;
-} // namespace android
-
-
-// This is not an "official" capability (i.e., it is not found in gralloc1.h),
-// but we will use it to detect that we are running through the adapter, which
-// is capable of collaborating with GraphicBuffer such that queries on a
-// buffer_handle_t succeed
-static const auto GRALLOC1_CAPABILITY_ON_ADAPTER =
-        static_cast<gralloc1_capability_t>(GRALLOC1_LAST_CAPABILITY + 1);
-
-static const auto GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER =
-        static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 1);
-static const auto GRALLOC1_FUNCTION_ALLOCATE_WITH_ID =
-        static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 2);
-static const auto GRALLOC1_FUNCTION_LOCK_YCBCR =
-        static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 3);
-static const auto GRALLOC1_LAST_ADAPTER_FUNCTION = GRALLOC1_FUNCTION_LOCK_YCBCR;
-
-typedef gralloc1_error_t (*GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER)(
-        gralloc1_device_t* device, const android::GraphicBuffer* buffer);
-typedef gralloc1_error_t (*GRALLOC1_PFN_ALLOCATE_WITH_ID)(
-        gralloc1_device_t* device, gralloc1_buffer_descriptor_t descriptor,
-        gralloc1_backing_store_t id, buffer_handle_t* outBuffer);
-typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_LOCK_YCBCR)(
-        gralloc1_device_t* device, buffer_handle_t buffer,
-        uint64_t /*gralloc1_producer_usage_t*/ producerUsage,
-        uint64_t /*gralloc1_consumer_usage_t*/ consumerUsage,
-        const gralloc1_rect_t* accessRegion, struct android_ycbcr* outYCbCr,
-        int32_t acquireFence);
-
-
-namespace android {
-namespace Gralloc1 {
-
-class Device;
-
-class Descriptor {
-public:
-    Descriptor(Device& device, gralloc1_buffer_descriptor_t deviceId)
-      : mShimDevice(device),
-        mDeviceId(deviceId),
-        mWidth(0),
-        mHeight(0),
-        mFormat(static_cast<android_pixel_format_t>(0)),
-        mLayerCount(0),
-        mProducerUsage(GRALLOC1_PRODUCER_USAGE_NONE),
-        mConsumerUsage(GRALLOC1_CONSUMER_USAGE_NONE) {}
-
-    ~Descriptor();
-
-    gralloc1_buffer_descriptor_t getDeviceId() const { return mDeviceId; }
-
-    gralloc1_error_t setDimensions(uint32_t width, uint32_t height);
-    gralloc1_error_t setFormat(android_pixel_format_t format);
-    gralloc1_error_t setLayerCount(uint32_t layerCount);
-    gralloc1_error_t setProducerUsage(gralloc1_producer_usage_t usage);
-    gralloc1_error_t setConsumerUsage(gralloc1_consumer_usage_t usage);
-
-private:
-    Device& mShimDevice;
-    const gralloc1_buffer_descriptor_t mDeviceId;
-
-    uint32_t mWidth;
-    uint32_t mHeight;
-    android_pixel_format_t mFormat;
-    uint32_t mLayerCount;
-    gralloc1_producer_usage_t mProducerUsage;
-    gralloc1_consumer_usage_t mConsumerUsage;
-
-}; // Descriptor
-
-class Device {
-    friend class Gralloc1::Descriptor;
-
-public:
-    Device(gralloc1_device_t* device);
-
-    bool hasCapability(gralloc1_capability_t capability) const;
-
-    std::string dump();
-
-    std::shared_ptr<Descriptor> createDescriptor();
-
-    gralloc1_error_t allocate(
-            const std::vector<std::shared_ptr<const Descriptor>>& descriptors,
-            std::vector<buffer_handle_t>* outBuffers);
-    gralloc1_error_t allocate(
-            const std::shared_ptr<const Descriptor>& descriptor,
-            gralloc1_backing_store_t id, buffer_handle_t* outBuffer);
-
-    gralloc1_error_t retain(buffer_handle_t buffer);
-    gralloc1_error_t retain(const GraphicBuffer* buffer);
-
-    gralloc1_error_t release(buffer_handle_t buffer);
-
-    gralloc1_error_t getDimensions(buffer_handle_t buffer,
-            uint32_t* outWidth, uint32_t* outHeight);
-    gralloc1_error_t getFormat(buffer_handle_t buffer,
-            int32_t* outFormat);
-    gralloc1_error_t getLayerCount(buffer_handle_t buffer,
-            uint32_t* outLayerCount);
-    gralloc1_error_t getProducerUsage(buffer_handle_t buffer,
-            uint64_t* outProducerUsage);
-    gralloc1_error_t getConsumerUsage(buffer_handle_t buffer,
-            uint64_t* outConsumerUsage);
-    gralloc1_error_t getBackingStore(buffer_handle_t buffer,
-            uint64_t* outBackingStore);
-    gralloc1_error_t getStride(buffer_handle_t buffer, uint32_t* outStride);
-    gralloc1_error_t getNumFlexPlanes(buffer_handle_t buffer,
-            uint32_t* outNumPlanes);
-
-    gralloc1_error_t lock(buffer_handle_t buffer,
-            gralloc1_producer_usage_t producerUsage,
-            gralloc1_consumer_usage_t consumerUsage,
-            const gralloc1_rect_t* accessRegion, void** outData,
-            const sp<Fence>& acquireFence);
-    gralloc1_error_t lockFlex(buffer_handle_t buffer,
-            gralloc1_producer_usage_t producerUsage,
-            gralloc1_consumer_usage_t consumerUsage,
-            const gralloc1_rect_t* accessRegion,
-            struct android_flex_layout* outData, const sp<Fence>& acquireFence);
-    gralloc1_error_t lockYCbCr(buffer_handle_t buffer,
-            gralloc1_producer_usage_t producerUsage,
-            gralloc1_consumer_usage_t consumerUsage,
-            const gralloc1_rect_t* accessRegion, struct android_ycbcr* outData,
-            const sp<Fence>& acquireFence);
-
-    gralloc1_error_t unlock(buffer_handle_t buffer, sp<Fence>* outFence);
-
-private:
-    std::unordered_set<gralloc1_capability_t> loadCapabilities();
-
-    bool loadFunctions();
-
-    template <typename LockType, typename OutType>
-    gralloc1_error_t lockHelper(LockType pfn, buffer_handle_t buffer,
-            gralloc1_producer_usage_t producerUsage,
-            gralloc1_consumer_usage_t consumerUsage,
-            const gralloc1_rect_t* accessRegion, OutType* outData,
-            const sp<Fence>& acquireFence) {
-        int32_t intError = pfn(mDevice, buffer,
-                static_cast<uint64_t>(producerUsage),
-                static_cast<uint64_t>(consumerUsage), accessRegion, outData,
-                acquireFence->dup());
-        return static_cast<gralloc1_error_t>(intError);
-    }
-
-    gralloc1_device_t* const mDevice;
-
-    const std::unordered_set<gralloc1_capability_t> mCapabilities;
-
-    template <typename PFN, gralloc1_function_descriptor_t descriptor>
-    struct FunctionLoader {
-        FunctionLoader() : pfn(nullptr) {}
-
-        bool load(gralloc1_device_t* device, bool errorIfNull) {
-            gralloc1_function_pointer_t rawPointer =
-                    device->getFunction(device, descriptor);
-            pfn = reinterpret_cast<PFN>(rawPointer);
-            if (errorIfNull && !rawPointer) {
-                ALOG(LOG_ERROR, GRALLOC1_LOG_TAG,
-                        "Failed to load function pointer %d", descriptor);
-            }
-            return rawPointer != nullptr;
-        }
-
-        template <typename ...Args>
-        typename std::result_of<PFN(Args...)>::type operator()(Args... args) {
-            return pfn(args...);
-        }
-
-        PFN pfn;
-    };
-
-    // Function pointers
-    struct Functions {
-        FunctionLoader<GRALLOC1_PFN_DUMP, GRALLOC1_FUNCTION_DUMP> dump;
-        FunctionLoader<GRALLOC1_PFN_CREATE_DESCRIPTOR,
-                GRALLOC1_FUNCTION_CREATE_DESCRIPTOR> createDescriptor;
-        FunctionLoader<GRALLOC1_PFN_DESTROY_DESCRIPTOR,
-                GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR> destroyDescriptor;
-        FunctionLoader<GRALLOC1_PFN_SET_CONSUMER_USAGE,
-                GRALLOC1_FUNCTION_SET_CONSUMER_USAGE> setConsumerUsage;
-        FunctionLoader<GRALLOC1_PFN_SET_DIMENSIONS,
-                GRALLOC1_FUNCTION_SET_DIMENSIONS> setDimensions;
-        FunctionLoader<GRALLOC1_PFN_SET_FORMAT,
-                GRALLOC1_FUNCTION_SET_FORMAT> setFormat;
-        FunctionLoader<GRALLOC1_PFN_SET_LAYER_COUNT,
-                GRALLOC1_FUNCTION_SET_LAYER_COUNT> setLayerCount;
-        FunctionLoader<GRALLOC1_PFN_SET_PRODUCER_USAGE,
-                GRALLOC1_FUNCTION_SET_PRODUCER_USAGE> setProducerUsage;
-        FunctionLoader<GRALLOC1_PFN_GET_BACKING_STORE,
-                GRALLOC1_FUNCTION_GET_BACKING_STORE> getBackingStore;
-        FunctionLoader<GRALLOC1_PFN_GET_CONSUMER_USAGE,
-                GRALLOC1_FUNCTION_GET_CONSUMER_USAGE> getConsumerUsage;
-        FunctionLoader<GRALLOC1_PFN_GET_DIMENSIONS,
-                GRALLOC1_FUNCTION_GET_DIMENSIONS> getDimensions;
-        FunctionLoader<GRALLOC1_PFN_GET_FORMAT,
-                GRALLOC1_FUNCTION_GET_FORMAT> getFormat;
-        FunctionLoader<GRALLOC1_PFN_GET_LAYER_COUNT,
-                GRALLOC1_FUNCTION_GET_LAYER_COUNT> getLayerCount;
-        FunctionLoader<GRALLOC1_PFN_GET_PRODUCER_USAGE,
-                GRALLOC1_FUNCTION_GET_PRODUCER_USAGE> getProducerUsage;
-        FunctionLoader<GRALLOC1_PFN_GET_STRIDE,
-                GRALLOC1_FUNCTION_GET_STRIDE> getStride;
-        FunctionLoader<GRALLOC1_PFN_ALLOCATE,
-                GRALLOC1_FUNCTION_ALLOCATE> allocate;
-        FunctionLoader<GRALLOC1_PFN_RETAIN,
-                GRALLOC1_FUNCTION_RETAIN> retain;
-        FunctionLoader<GRALLOC1_PFN_RELEASE,
-                GRALLOC1_FUNCTION_RELEASE> release;
-        FunctionLoader<GRALLOC1_PFN_GET_NUM_FLEX_PLANES,
-                GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES> getNumFlexPlanes;
-        FunctionLoader<GRALLOC1_PFN_LOCK,
-                GRALLOC1_FUNCTION_LOCK> lock;
-        FunctionLoader<GRALLOC1_PFN_LOCK_FLEX,
-                GRALLOC1_FUNCTION_LOCK_FLEX> lockFlex;
-        FunctionLoader<GRALLOC1_PFN_LOCK_YCBCR,
-                GRALLOC1_FUNCTION_LOCK_YCBCR> lockYCbCr;
-        FunctionLoader<GRALLOC1_PFN_UNLOCK,
-                GRALLOC1_FUNCTION_UNLOCK> unlock;
-
-        // Adapter-only functions
-        FunctionLoader<GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER,
-                GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER> retainGraphicBuffer;
-        FunctionLoader<GRALLOC1_PFN_ALLOCATE_WITH_ID,
-                GRALLOC1_FUNCTION_ALLOCATE_WITH_ID> allocateWithId;
-    } mFunctions;
-
-}; // class android::Gralloc1::Device
-
-class Loader
-{
-public:
-    Loader();
-    ~Loader();
-
-    std::unique_ptr<Device> getDevice();
-
-private:
-    static std::unique_ptr<Gralloc1On0Adapter> mAdapter;
-    std::unique_ptr<Device> mDevice;
-};
-
-} // namespace android::Gralloc1
-
-} // namespace android
-
-#endif
diff --git a/include/ui/Gralloc1On0Adapter.h b/include/ui/Gralloc1On0Adapter.h
deleted file mode 100644
index 6379a08..0000000
--- a/include/ui/Gralloc1On0Adapter.h
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_UI_GRALLOC_1_ON_0_ADAPTER_H
-#define ANDROID_UI_GRALLOC_1_ON_0_ADAPTER_H
-
-#include <log/log.h>
-
-#include <ui/Fence.h>
-
-#include <hardware/gralloc.h>
-#include <hardware/gralloc1.h>
-
-#include <mutex>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-namespace android {
-class GraphicBuffer;
-} // namespace android
-
-struct gralloc_module_t;
-
-namespace android {
-
-class Gralloc1On0Adapter : public gralloc1_device_t
-{
-public:
-    Gralloc1On0Adapter(const hw_module_t* module);
-    ~Gralloc1On0Adapter();
-
-    gralloc1_device_t* getDevice() {
-        return static_cast<gralloc1_device_t*>(this);
-    }
-
-private:
-    static inline Gralloc1On0Adapter* getAdapter(gralloc1_device_t* device) {
-        return static_cast<Gralloc1On0Adapter*>(device);
-    }
-
-    // getCapabilities
-
-    void doGetCapabilities(uint32_t* outCount,
-            int32_t* /*gralloc1_capability_t*/ outCapabilities);
-    static void getCapabilitiesHook(gralloc1_device_t* device,
-            uint32_t* outCount,
-            int32_t* /*gralloc1_capability_t*/ outCapabilities) {
-        getAdapter(device)->doGetCapabilities(outCount, outCapabilities);
-    }
-
-    // getFunction
-
-    gralloc1_function_pointer_t doGetFunction(
-            int32_t /*gralloc1_function_descriptor_t*/ descriptor);
-    static gralloc1_function_pointer_t getFunctionHook(
-            gralloc1_device_t* device,
-            int32_t /*gralloc1_function_descriptor_t*/ descriptor) {
-        return getAdapter(device)->doGetFunction(descriptor);
-    }
-
-    // dump
-
-    void dump(uint32_t* outSize, char* outBuffer);
-    static void dumpHook(gralloc1_device_t* device, uint32_t* outSize,
-            char* outBuffer) {
-        return getAdapter(device)->dump(outSize, outBuffer);
-    }
-    std::string mCachedDump;
-
-    // Buffer descriptor lifecycle functions
-
-    struct Descriptor;
-
-    gralloc1_error_t createDescriptor(
-            gralloc1_buffer_descriptor_t* outDescriptor);
-    static int32_t createDescriptorHook(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t* outDescriptor) {
-        auto error = getAdapter(device)->createDescriptor(outDescriptor);
-        return static_cast<int32_t>(error);
-    }
-
-    gralloc1_error_t destroyDescriptor(gralloc1_buffer_descriptor_t descriptor);
-    static int32_t destroyDescriptorHook(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t descriptor) {
-        auto error = getAdapter(device)->destroyDescriptor(descriptor);
-        return static_cast<int32_t>(error);
-    }
-
-    // Buffer descriptor modification functions
-
-    struct Descriptor : public std::enable_shared_from_this<Descriptor> {
-        Descriptor(Gralloc1On0Adapter* _adapter,
-                gralloc1_buffer_descriptor_t _id)
-          : adapter(_adapter),
-            id(_id),
-            width(0),
-            height(0),
-            format(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
-            layerCount(1),
-            producerUsage(GRALLOC1_PRODUCER_USAGE_NONE),
-            consumerUsage(GRALLOC1_CONSUMER_USAGE_NONE) {}
-
-        gralloc1_error_t setDimensions(uint32_t w, uint32_t h) {
-            width = w;
-            height = h;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t setFormat(int32_t f) {
-            format = f;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t setLayerCount(uint32_t lc) {
-            layerCount = lc;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t setProducerUsage(gralloc1_producer_usage_t usage) {
-            producerUsage = usage;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t setConsumerUsage(gralloc1_consumer_usage_t usage) {
-            consumerUsage = usage;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        Gralloc1On0Adapter* const adapter;
-        const gralloc1_buffer_descriptor_t id;
-
-        uint32_t width;
-        uint32_t height;
-        int32_t format;
-        uint32_t layerCount;
-        gralloc1_producer_usage_t producerUsage;
-        gralloc1_consumer_usage_t consumerUsage;
-    };
-
-    template <typename ...Args>
-    static int32_t callDescriptorFunction(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t descriptorId,
-            gralloc1_error_t (Descriptor::*member)(Args...), Args... args) {
-        auto descriptor = getAdapter(device)->getDescriptor(descriptorId);
-        if (!descriptor) {
-            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_DESCRIPTOR);
-        }
-        auto error = ((*descriptor).*member)(std::forward<Args>(args)...);
-        return static_cast<int32_t>(error);
-    }
-
-    static int32_t setConsumerUsageHook(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) {
-        auto usage = static_cast<gralloc1_consumer_usage_t>(intUsage);
-        return callDescriptorFunction(device, descriptorId,
-                &Descriptor::setConsumerUsage, usage);
-    }
-
-    static int32_t setDimensionsHook(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t descriptorId, uint32_t width,
-            uint32_t height) {
-        return callDescriptorFunction(device, descriptorId,
-                &Descriptor::setDimensions, width, height);
-    }
-
-    static int32_t setFormatHook(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t descriptorId, int32_t format) {
-        return callDescriptorFunction(device, descriptorId,
-                &Descriptor::setFormat, format);
-    }
-
-    static int32_t setLayerCountHook(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t descriptorId, uint32_t layerCount) {
-        return callDescriptorFunction(device, descriptorId,
-                &Descriptor::setLayerCount, layerCount);
-    }
-
-    static int32_t setProducerUsageHook(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) {
-        auto usage = static_cast<gralloc1_producer_usage_t>(intUsage);
-        return callDescriptorFunction(device, descriptorId,
-                &Descriptor::setProducerUsage, usage);
-    }
-
-    // Buffer handle query functions
-
-    class Buffer {
-    public:
-        Buffer(buffer_handle_t handle, gralloc1_backing_store_t store,
-                const Descriptor& descriptor, uint32_t stride,
-                bool wasAllocated);
-
-        buffer_handle_t getHandle() const { return mHandle; }
-
-        void retain() { ++mReferenceCount; }
-
-        // Returns true if the reference count has dropped to 0, indicating that
-        // the buffer needs to be released
-        bool release() { return --mReferenceCount == 0; }
-
-        bool wasAllocated() const { return mWasAllocated; }
-
-        gralloc1_error_t getBackingStore(
-                gralloc1_backing_store_t* outStore) const {
-            *outStore = mStore;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t getConsumerUsage(
-                gralloc1_consumer_usage_t* outUsage) const {
-            *outUsage = mDescriptor.consumerUsage;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t getDimensions(uint32_t* outWidth,
-                uint32_t* outHeight) const {
-            *outWidth = mDescriptor.width;
-            *outHeight = mDescriptor.height;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t getFormat(int32_t* outFormat) const {
-            *outFormat = mDescriptor.format;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t getLayerCount(uint32_t* outLayerCount) const {
-            *outLayerCount = mDescriptor.layerCount;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t getNumFlexPlanes(uint32_t* outNumPlanes) const {
-            // TODO: This is conservative, and we could do better by examining
-            // the format, but it won't hurt anything for now
-            *outNumPlanes = 4;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t getProducerUsage(
-                gralloc1_producer_usage_t* outUsage) const {
-            *outUsage = mDescriptor.producerUsage;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-        gralloc1_error_t getStride(uint32_t* outStride) const {
-            *outStride = mStride;
-            return GRALLOC1_ERROR_NONE;
-        }
-
-    private:
-
-        const buffer_handle_t mHandle;
-        size_t mReferenceCount;
-
-        // Since we're adapting to gralloc0, there will always be a 1:1
-        // correspondence between buffer handles and backing stores, and the
-        // backing store ID will be the same as the GraphicBuffer unique ID
-        const gralloc1_backing_store_t mStore;
-
-        const Descriptor mDescriptor;
-        const uint32_t mStride;
-
-        // Whether this buffer allocated in this process (as opposed to just
-        // being retained here), which determines whether to free or unregister
-        // the buffer when this Buffer is released
-        const bool mWasAllocated;
-    };
-
-    template <typename ...Args>
-    static int32_t callBufferFunction(gralloc1_device_t* device,
-            buffer_handle_t bufferHandle,
-            gralloc1_error_t (Buffer::*member)(Args...) const, Args... args) {
-        auto buffer = getAdapter(device)->getBuffer(bufferHandle);
-        if (!buffer) {
-            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE);
-        }
-        auto error = ((*buffer).*member)(std::forward<Args>(args)...);
-        return static_cast<int32_t>(error);
-    }
-
-    template <typename MF, MF memFunc, typename ...Args>
-    static int32_t bufferHook(gralloc1_device_t* device,
-            buffer_handle_t bufferHandle, Args... args) {
-        return Gralloc1On0Adapter::callBufferFunction(device, bufferHandle,
-                memFunc, std::forward<Args>(args)...);
-    }
-
-    static int32_t getConsumerUsageHook(gralloc1_device_t* device,
-            buffer_handle_t bufferHandle, uint64_t* outUsage) {
-        auto usage = GRALLOC1_CONSUMER_USAGE_NONE;
-        auto error = callBufferFunction(device, bufferHandle,
-                &Buffer::getConsumerUsage, &usage);
-        if (error == GRALLOC1_ERROR_NONE) {
-            *outUsage = static_cast<uint64_t>(usage);
-        }
-        return error;
-    }
-
-    static int32_t getProducerUsageHook(gralloc1_device_t* device,
-            buffer_handle_t bufferHandle, uint64_t* outUsage) {
-        auto usage = GRALLOC1_PRODUCER_USAGE_NONE;
-        auto error = callBufferFunction(device, bufferHandle,
-                &Buffer::getProducerUsage, &usage);
-        if (error == GRALLOC1_ERROR_NONE) {
-            *outUsage = static_cast<uint64_t>(usage);
-        }
-        return error;
-    }
-
-    // Buffer management functions
-
-    // We don't provide GRALLOC1_FUNCTION_ALLOCATE, since this should always be
-    // called through GRALLOC1_FUNCTION_ALLOCATE_WITH_ID
-    gralloc1_error_t allocate(
-            const std::shared_ptr<Descriptor>& descriptor,
-            gralloc1_backing_store_t id,
-            buffer_handle_t* outBufferHandle);
-    static gralloc1_error_t allocateWithIdHook(gralloc1_device_t* device,
-            gralloc1_buffer_descriptor_t descriptors,
-            gralloc1_backing_store_t id, buffer_handle_t* outBuffer);
-
-    gralloc1_error_t retain(const std::shared_ptr<Buffer>& buffer);
-    gralloc1_error_t release(const std::shared_ptr<Buffer>& buffer);
-
-    // Member function pointer 'member' will either be retain or release
-    template <gralloc1_error_t (Gralloc1On0Adapter::*member)(
-            const std::shared_ptr<Buffer>& buffer)>
-    static int32_t managementHook(gralloc1_device_t* device,
-            buffer_handle_t bufferHandle) {
-        auto adapter = getAdapter(device);
-
-        auto buffer = adapter->getBuffer(bufferHandle);
-        if (!buffer) {
-            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE);
-        }
-
-        auto error = ((*adapter).*member)(buffer);
-        return static_cast<int32_t>(error);
-    }
-
-    gralloc1_error_t retain(const GraphicBuffer* buffer);
-    static gralloc1_error_t retainGraphicBufferHook(gralloc1_device_t* device,
-            const GraphicBuffer* buffer) {
-        auto adapter = getAdapter(device);
-        return adapter->retain(buffer);
-    }
-
-    // Buffer access functions
-
-    gralloc1_error_t lock(const std::shared_ptr<Buffer>& buffer,
-            gralloc1_producer_usage_t producerUsage,
-            gralloc1_consumer_usage_t consumerUsage,
-            const gralloc1_rect_t& accessRegion, void** outData,
-            const sp<Fence>& acquireFence);
-    gralloc1_error_t lockFlex(const std::shared_ptr<Buffer>& buffer,
-            gralloc1_producer_usage_t producerUsage,
-            gralloc1_consumer_usage_t consumerUsage,
-            const gralloc1_rect_t& accessRegion,
-            struct android_flex_layout* outFlex,
-            const sp<Fence>& acquireFence);
-    gralloc1_error_t lockYCbCr(const std::shared_ptr<Buffer>& buffer,
-            gralloc1_producer_usage_t producerUsage,
-            gralloc1_consumer_usage_t consumerUsage,
-            const gralloc1_rect_t& accessRegion,
-            struct android_ycbcr* outFlex,
-            const sp<Fence>& acquireFence);
-
-    template <typename OUT, gralloc1_error_t (Gralloc1On0Adapter::*member)(
-            const std::shared_ptr<Buffer>&, gralloc1_producer_usage_t,
-            gralloc1_consumer_usage_t, const gralloc1_rect_t&, OUT*,
-            const sp<Fence>&)>
-    static int32_t lockHook(gralloc1_device_t* device,
-            buffer_handle_t bufferHandle,
-            uint64_t /*gralloc1_producer_usage_t*/ uintProducerUsage,
-            uint64_t /*gralloc1_consumer_usage_t*/ uintConsumerUsage,
-            const gralloc1_rect_t* accessRegion, OUT* outData,
-            int32_t acquireFenceFd) {
-        auto adapter = getAdapter(device);
-
-        // Exactly one of producer and consumer usage must be *_USAGE_NONE,
-        // but we can't check this until the upper levels of the framework
-        // correctly distinguish between producer and consumer usage
-        /*
-        bool hasProducerUsage =
-                uintProducerUsage != GRALLOC1_PRODUCER_USAGE_NONE;
-        bool hasConsumerUsage =
-                uintConsumerUsage != GRALLOC1_CONSUMER_USAGE_NONE;
-        if (hasProducerUsage && hasConsumerUsage ||
-                !hasProducerUsage && !hasConsumerUsage) {
-            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE);
-        }
-        */
-
-        auto producerUsage =
-                static_cast<gralloc1_producer_usage_t>(uintProducerUsage);
-        auto consumerUsage =
-                static_cast<gralloc1_consumer_usage_t>(uintConsumerUsage);
-
-        if (!outData) {
-            const auto producerCpuUsage = GRALLOC1_PRODUCER_USAGE_CPU_READ |
-                    GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
-            if ((producerUsage & producerCpuUsage) != 0) {
-                return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE);
-            }
-            if ((consumerUsage & GRALLOC1_CONSUMER_USAGE_CPU_READ) != 0) {
-                return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE);
-            }
-        }
-
-        auto buffer = adapter->getBuffer(bufferHandle);
-        if (!buffer) {
-            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE);
-        }
-
-        if (!accessRegion) {
-            ALOGE("accessRegion is null");
-            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE);
-        }
-
-        sp<Fence> acquireFence{new Fence(acquireFenceFd)};
-        auto error = ((*adapter).*member)(buffer, producerUsage, consumerUsage,
-                *accessRegion, outData, acquireFence);
-        return static_cast<int32_t>(error);
-    }
-
-    gralloc1_error_t unlock(const std::shared_ptr<Buffer>& buffer,
-            sp<Fence>* outReleaseFence);
-    static int32_t unlockHook(gralloc1_device_t* device,
-            buffer_handle_t bufferHandle, int32_t* outReleaseFenceFd) {
-        auto adapter = getAdapter(device);
-
-        auto buffer = adapter->getBuffer(bufferHandle);
-        if (!buffer) {
-            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE);
-        }
-
-        sp<Fence> releaseFence = Fence::NO_FENCE;
-        auto error = adapter->unlock(buffer, &releaseFence);
-        if (error == GRALLOC1_ERROR_NONE) {
-            *outReleaseFenceFd = releaseFence->dup();
-        }
-        return static_cast<int32_t>(error);
-    }
-
-    // Adapter internals
-    const gralloc_module_t* mModule;
-    uint8_t mMinorVersion;
-    alloc_device_t* mDevice;
-
-    std::shared_ptr<Descriptor> getDescriptor(
-            gralloc1_buffer_descriptor_t descriptorId);
-    std::shared_ptr<Buffer> getBuffer(buffer_handle_t bufferHandle);
-
-    static std::atomic<gralloc1_buffer_descriptor_t> sNextBufferDescriptorId;
-    std::mutex mDescriptorMutex;
-    std::unordered_map<gralloc1_buffer_descriptor_t,
-            std::shared_ptr<Descriptor>> mDescriptors;
-    std::mutex mBufferMutex;
-    std::unordered_map<buffer_handle_t, std::shared_ptr<Buffer>> mBuffers;
-};
-
-} // namespace android
-
-#endif
diff --git a/include/ui/Gralloc2.h b/include/ui/Gralloc2.h
new file mode 100644
index 0000000..f826b92
--- /dev/null
+++ b/include/ui/Gralloc2.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_GRALLOC2_H
+#define ANDROID_UI_GRALLOC2_H
+
+#include <string>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <system/window.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+using hardware::graphics::allocator::V2_0::IAllocator;
+using hardware::graphics::common::V1_0::BufferUsage;
+using hardware::graphics::common::V1_0::PixelFormat;
+using hardware::graphics::mapper::V2_0::BufferDescriptor;
+using hardware::graphics::mapper::V2_0::Error;
+using hardware::graphics::mapper::V2_0::IMapper;
+using hardware::graphics::mapper::V2_0::YCbCrLayout;
+
+// A wrapper to IMapper
+class Mapper {
+public:
+    Mapper();
+
+    Error createDescriptor(
+            const IMapper::BufferDescriptorInfo& descriptorInfo,
+            BufferDescriptor* outDescriptor) const;
+
+    // Import a buffer that is from another HAL, another process, or is
+    // cloned.
+    //
+    // The returned handle must be freed with freeBuffer.
+    Error importBuffer(const hardware::hidl_handle& rawHandle,
+            buffer_handle_t* outBufferHandle) const;
+
+    void freeBuffer(buffer_handle_t bufferHandle) const;
+
+    // The ownership of acquireFence is always transferred to the callee, even
+    // on errors.
+    Error lock(buffer_handle_t bufferHandle, uint64_t usage,
+            const IMapper::Rect& accessRegion,
+            int acquireFence, void** outData) const;
+
+    // The ownership of acquireFence is always transferred to the callee, even
+    // on errors.
+    Error lock(buffer_handle_t bufferHandle, uint64_t usage,
+            const IMapper::Rect& accessRegion,
+            int acquireFence, YCbCrLayout* outLayout) const;
+
+    // unlock returns a fence sync object (or -1) and the fence sync object is
+    // owned by the caller
+    int unlock(buffer_handle_t bufferHandle) const;
+
+private:
+    sp<IMapper> mMapper;
+};
+
+// A wrapper to IAllocator
+class Allocator {
+public:
+    // An allocator relies on a mapper, and that mapper must be alive at all
+    // time.
+    Allocator(const Mapper& mapper);
+
+    std::string dumpDebugInfo() const;
+
+    /*
+     * The returned buffers are already imported and must not be imported
+     * again.  outBufferHandles must point to a space that can contain at
+     * least "count" buffer_handle_t.
+     */
+    Error allocate(BufferDescriptor descriptor, uint32_t count,
+            uint32_t* outStride, buffer_handle_t* outBufferHandles) const;
+
+    Error allocate(BufferDescriptor descriptor,
+            uint32_t* outStride, buffer_handle_t* outBufferHandle) const
+    {
+        return allocate(descriptor, 1, outStride, outBufferHandle);
+    }
+
+    Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t count,
+            uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+    {
+        BufferDescriptor descriptor;
+        Error error = mMapper.createDescriptor(descriptorInfo, &descriptor);
+        if (error == Error::NONE) {
+            error = allocate(descriptor, count, outStride, outBufferHandles);
+        }
+        return error;
+    }
+
+    Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+            uint32_t* outStride, buffer_handle_t* outBufferHandle) const
+    {
+        return allocate(descriptorInfo, 1, outStride, outBufferHandle);
+    }
+
+private:
+    const Mapper& mMapper;
+    sp<IAllocator> mAllocator;
+};
+
+} // namespace Gralloc2
+
+} // namespace android
+
+#endif // ANDROID_UI_GRALLOC2_H
diff --git a/include/ui/GrallocAllocator.h b/include/ui/GrallocAllocator.h
deleted file mode 100644
index dd0f9e0..0000000
--- a/include/ui/GrallocAllocator.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_UI_GRALLOC_ALLOCATOR_H
-#define ANDROID_UI_GRALLOC_ALLOCATOR_H
-
-#include <string>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::Error;
-using hardware::graphics::allocator::V2_0::ProducerUsage;
-using hardware::graphics::allocator::V2_0::ConsumerUsage;
-using hardware::graphics::allocator::V2_0::BufferDescriptor;
-using hardware::graphics::allocator::V2_0::Buffer;
-using hardware::graphics::allocator::V2_0::IAllocator;
-using hardware::graphics::allocator::V2_0::IAllocatorClient;
-using hardware::graphics::common::V1_0::PixelFormat;
-
-// Allocator is a wrapper to IAllocator, a proxy to server-side allocator.
-class Allocator {
-public:
-    Allocator();
-
-    // this will be removed and Allocator will be always valid
-    bool valid() const { return (mAllocator != nullptr); }
-
-    std::string dumpDebugInfo() const;
-
-    Error createBufferDescriptor(
-            const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-            BufferDescriptor* outDescriptor) const;
-    void destroyBufferDescriptor(BufferDescriptor descriptor) const;
-
-    Error allocate(BufferDescriptor descriptor, Buffer* outBuffer) const;
-    void free(Buffer buffer) const;
-
-    Error exportHandle(BufferDescriptor descriptor, Buffer buffer,
-            native_handle_t** outBufferHandle) const;
-
-private:
-    sp<IAllocator> mAllocator;
-    sp<IAllocatorClient> mClient;
-};
-
-} // namespace Gralloc2
-
-} // namespace android
-
-#endif // ANDROID_UI_GRALLOC_ALLOCATOR_H
diff --git a/include/ui/GrallocMapper.h b/include/ui/GrallocMapper.h
deleted file mode 100644
index 5a0d64b..0000000
--- a/include/ui/GrallocMapper.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_UI_GRALLOC_MAPPER_H
-#define ANDROID_UI_GRALLOC_MAPPER_H
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <system/window.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::Error;
-using hardware::graphics::allocator::V2_0::ProducerUsage;
-using hardware::graphics::allocator::V2_0::ConsumerUsage;
-using hardware::graphics::common::V1_0::PixelFormat;
-using hardware::graphics::mapper::V2_0::FlexLayout;
-using hardware::graphics::mapper::V2_0::BackingStore;
-using hardware::graphics::mapper::V2_0::IMapper;
-
-// Mapper is a wrapper to IMapper, a client-side graphics buffer mapper.
-class Mapper {
-public:
-    Mapper();
-
-    // this will be removed and Mapper will be always valid
-    bool valid() const { return (mMapper != nullptr); }
-
-    Error retain(buffer_handle_t handle) const;
-    void release(buffer_handle_t handle) const;
-
-    Error getDimensions(buffer_handle_t handle,
-            uint32_t* outWidth, uint32_t* outHeight) const;
-    Error getFormat(buffer_handle_t handle, int32_t* outFormat) const;
-    Error getLayerCount(buffer_handle_t handle, uint32_t* outLayerCount) const;
-    Error getProducerUsage(buffer_handle_t handle,
-            uint64_t* outProducerUsage) const;
-    Error getConsumerUsage(buffer_handle_t handle,
-            uint64_t* outConsumerUsage) const;
-    Error getBackingStore(buffer_handle_t handle,
-            uint64_t* outBackingStore) const;
-    Error getStride(buffer_handle_t handle, uint32_t* outStride) const;
-
-    Error lock(buffer_handle_t handle, uint64_t producerUsage,
-            uint64_t consumerUsage, const IMapper::Rect& accessRegion,
-            int acquireFence, void** outData) const;
-    Error lock(buffer_handle_t handle, uint64_t producerUsage,
-            uint64_t consumerUsage, const IMapper::Rect& accessRegion,
-            int acquireFence, FlexLayout* outLayout) const;
-    int unlock(buffer_handle_t handle) const;
-
-private:
-    sp<IMapper> mMapper;
-};
-
-} // namespace Gralloc2
-
-} // namespace android
-
-#endif // ANDROID_UI_GRALLOC_MAPPER_H
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index af1d8be..4b82cff 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -81,8 +81,8 @@
     // Create a GraphicBuffer by allocating and managing a buffer internally.
     // This function is privileged.  See reallocate for details.
     GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
-            uint32_t inLayerCount, uint64_t inProducerUsage,
-            uint64_t inConsumerUsage, std::string requestorName = "<Unknown>");
+            uint32_t inLayerCount, uint64_t inUsage,
+            std::string requestorName = "<Unknown>");
 
     // Create a GraphicBuffer from an existing handle.
     enum HandleWrapMethod : uint8_t {
@@ -120,16 +120,15 @@
     GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
             uint32_t width, uint32_t height,
             PixelFormat format, uint32_t layerCount,
-            uint64_t producerUsage, uint64_t consumerUsage, uint32_t stride);
+            uint64_t usage, uint32_t stride);
 
-    // These functions are deprecated because they do not distinguish producer
-    // and consumer usages.
+    // These functions are deprecated because they only take 32 bits of usage
     GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
             uint32_t width, uint32_t height,
             PixelFormat format, uint32_t layerCount,
             uint32_t usage, uint32_t stride)
         : GraphicBuffer(handle, method, width, height, format, layerCount,
-                usage, usage, stride) {}
+                static_cast<uint64_t>(usage), stride) {}
     GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
             uint32_t inLayerCount, uint32_t inUsage, uint32_t inStride,
             native_handle_t* inHandle, bool keepOwnership);
@@ -157,10 +156,10 @@
     // device or service, which usually involves adding suitable selinux
     // rules.
     status_t reallocate(uint32_t inWidth, uint32_t inHeight,
-            PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage);
+            PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage);
 
     bool needsReallocation(uint32_t inWidth, uint32_t inHeight,
-            PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage);
+            PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage);
 
     status_t lock(uint32_t inUsage, void** vaddr);
     status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr);
@@ -219,13 +218,12 @@
 
     status_t initWithSize(uint32_t inWidth, uint32_t inHeight,
             PixelFormat inFormat, uint32_t inLayerCount,
-            uint64_t inProducerUsage, uint64_t inConsumerUsage,
-            std::string requestorName);
+            uint64_t inUsage, std::string requestorName);
 
     status_t initWithHandle(const native_handle_t* handle,
             HandleWrapMethod method, uint32_t width, uint32_t height,
             PixelFormat format, uint32_t layerCount,
-            uint64_t producerUsage, uint64_t consumerUsage, uint32_t stride);
+            uint64_t usage, uint32_t stride);
 
     void free_handle();
 
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index e97122b..fe99de1 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -25,14 +25,15 @@
 
 #include <cutils/native_handle.h>
 
+#include <system/window.h>
+
+#include <ui/PixelFormat.h>
+
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/Mutex.h>
 #include <utils/Singleton.h>
 
-#include <ui/Gralloc1.h>
-#include <ui/PixelFormat.h>
-
 namespace android {
 
 namespace Gralloc2 {
@@ -45,29 +46,10 @@
 class GraphicBufferAllocator : public Singleton<GraphicBufferAllocator>
 {
 public:
-    enum {
-        USAGE_SW_READ_NEVER     = GRALLOC1_CONSUMER_USAGE_CPU_READ_NEVER,
-        USAGE_SW_READ_RARELY    = GRALLOC1_CONSUMER_USAGE_CPU_READ,
-        USAGE_SW_READ_OFTEN     = GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN,
-        USAGE_SW_READ_MASK      = GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN,
-
-        USAGE_SW_WRITE_NEVER    = GRALLOC1_PRODUCER_USAGE_CPU_WRITE_NEVER,
-        USAGE_SW_WRITE_RARELY   = GRALLOC1_PRODUCER_USAGE_CPU_WRITE,
-        USAGE_SW_WRITE_OFTEN    = GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,
-        USAGE_SW_WRITE_MASK     = GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,
-
-        USAGE_SOFTWARE_MASK     = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,
-
-        USAGE_HW_TEXTURE        = GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE,
-        USAGE_HW_RENDER         = GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET,
-        USAGE_HW_2D             = 0x00000400, // Deprecated
-        USAGE_HW_MASK           = 0x00071F00, // Deprecated
-    };
-
     static inline GraphicBufferAllocator& get() { return getInstance(); }
 
     status_t allocate(uint32_t w, uint32_t h, PixelFormat format,
-            uint32_t layerCount, uint64_t producerUsage, uint64_t consumerUsage,
+            uint32_t layerCount, uint64_t usage,
             buffer_handle_t* handle, uint32_t* stride, uint64_t graphicBufferId,
             std::string requestorName);
 
@@ -83,8 +65,7 @@
         uint32_t stride;
         PixelFormat format;
         uint32_t layerCount;
-        uint64_t producerUsage;
-        uint64_t consumerUsage;
+        uint64_t usage;
         size_t size;
         std::string requestorName;
     };
@@ -96,11 +77,8 @@
     GraphicBufferAllocator();
     ~GraphicBufferAllocator();
 
-    const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
     GraphicBufferMapper& mMapper;
-
-    std::unique_ptr<Gralloc1::Loader> mLoader;
-    std::unique_ptr<Gralloc1::Device> mDevice;
+    const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index b6d4021..e0702e9 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -22,8 +22,6 @@
 
 #include <memory>
 
-#include <ui/Gralloc1.h>
-
 #include <utils/Singleton.h>
 
 
@@ -47,31 +45,12 @@
 public:
     static inline GraphicBufferMapper& get() { return getInstance(); }
 
-    // This may NOT work on devices without a valid Gralloc2::Mapper.
-    status_t registerBuffer(buffer_handle_t handle);
+    // The imported outHandle must be freed with freeBuffer when no longer
+    // needed. rawHandle is owned by the caller.
+    status_t importBuffer(buffer_handle_t rawHandle,
+            buffer_handle_t* outHandle);
 
-    status_t registerBuffer(const GraphicBuffer* buffer);
-
-    status_t unregisterBuffer(buffer_handle_t handle);
-
-    status_t getDimensions(buffer_handle_t handle,
-            uint32_t* outWidth, uint32_t* outHeight) const;
-
-    status_t getFormat(buffer_handle_t handle, int32_t* outFormat) const;
-
-    status_t getLayerCount(buffer_handle_t handle,
-            uint32_t* outLayerCount) const;
-
-    status_t getProducerUsage(buffer_handle_t handle,
-            uint64_t* outProducerUsage) const;
-
-    status_t getConsumerUsage(buffer_handle_t handle,
-            uint64_t* outConsumerUsage) const;
-
-    status_t getBackingStore(buffer_handle_t handle,
-            uint64_t* outBackingStore) const;
-
-    status_t getStride(buffer_handle_t handle, uint32_t* outStride) const;
+    status_t freeBuffer(buffer_handle_t handle);
 
     status_t lock(buffer_handle_t handle,
             uint32_t usage, const Rect& bounds, void** vaddr);
@@ -105,9 +84,6 @@
     GraphicBufferMapper();
 
     const std::unique_ptr<const Gralloc2::Mapper> mMapper;
-
-    std::unique_ptr<Gralloc1::Loader> mLoader;
-    std::unique_ptr<Gralloc1::Device> mDevice;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index b225128..204fdb5 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -12,9 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+cc_library_headers {
+    name: "libbinder_headers",
+    export_include_dirs: ["include"],
+}
+
 cc_library {
     name: "libbinder",
 
+    // for vndbinder
+    vendor_available: true,
+
     srcs: [
         "AppOpsManager.cpp",
         "Binder.cpp",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 3aeff2e..c7a0f43 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -23,6 +23,7 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 #include <utils/SystemClock.h>
+#include <utils/CallStack.h>
 
 #include <private/binder/Static.h>
 
@@ -136,7 +137,12 @@
         unsigned n;
         for (n = 0; n < 5; n++){
             if (n > 0) {
-                ALOGI("Waiting for service %s...", String8(name).string());
+                if (!strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder")) {
+                    ALOGI("Waiting for vendor service %s...", String8(name).string());
+                    CallStack stack(LOG_TAG);
+                } else {
+                    ALOGI("Waiting for service %s...", String8(name).string());
+                }
                 sleep(1);
             }
             sp<IBinder> svc = checkService(name);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index da94305..39bb078 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -553,6 +553,14 @@
     return err;
 }
 
+int Parcel::compareData(const Parcel& other) {
+    size_t size = dataSize();
+    if (size != other.dataSize()) {
+        return size < other.dataSize() ? -1 : 1;
+    }
+    return memcmp(data(), other.data(), size);
+}
+
 bool Parcel::allowFds() const
 {
     return mAllowFds;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 5c4cfe2..add5e74 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -79,6 +79,11 @@
 {
     Mutex::Autolock _l(gProcessMutex);
     if (gProcess != NULL) {
+        // Allow for initWithDriver to be called repeatedly with the same
+        // driver.
+        if (!strcmp(gProcess->getDriverName().c_str(), driver)) {
+            return gProcess;
+        }
         LOG_ALWAYS_FATAL("ProcessState was already initialized.");
     }
     gProcess = new ProcessState(driver);
@@ -317,6 +322,10 @@
     androidSetThreadName( makeBinderThreadName().string() );
 }
 
+String8 ProcessState::getDriverName() {
+    return mDriverName;
+}
+
 static int open_driver(const char *driver)
 {
     int fd = open(driver, O_RDWR | O_CLOEXEC);
@@ -346,7 +355,8 @@
 }
 
 ProcessState::ProcessState(const char *driver)
-    : mDriverFD(open_driver(driver))
+    : mDriverName(String8(driver))
+    , mDriverFD(open_driver(driver))
     , mVMStart(MAP_FAILED)
     , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
     , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
@@ -367,6 +377,7 @@
             ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
             close(mDriverFD);
             mDriverFD = -1;
+            mDriverName.clear();
         }
     }
 
diff --git a/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
similarity index 100%
rename from include/binder/AppOpsManager.h
rename to libs/binder/include/binder/AppOpsManager.h
diff --git a/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
similarity index 100%
rename from include/binder/Binder.h
rename to libs/binder/include/binder/Binder.h
diff --git a/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
similarity index 100%
rename from include/binder/BinderService.h
rename to libs/binder/include/binder/BinderService.h
diff --git a/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
similarity index 100%
rename from include/binder/BpBinder.h
rename to libs/binder/include/binder/BpBinder.h
diff --git a/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
similarity index 100%
rename from include/binder/BufferedTextOutput.h
rename to libs/binder/include/binder/BufferedTextOutput.h
diff --git a/include/binder/Debug.h b/libs/binder/include/binder/Debug.h
similarity index 100%
rename from include/binder/Debug.h
rename to libs/binder/include/binder/Debug.h
diff --git a/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
similarity index 100%
rename from include/binder/IActivityManager.h
rename to libs/binder/include/binder/IActivityManager.h
diff --git a/include/binder/IAppOpsCallback.h b/libs/binder/include/binder/IAppOpsCallback.h
similarity index 100%
rename from include/binder/IAppOpsCallback.h
rename to libs/binder/include/binder/IAppOpsCallback.h
diff --git a/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
similarity index 100%
rename from include/binder/IAppOpsService.h
rename to libs/binder/include/binder/IAppOpsService.h
diff --git a/include/binder/IBatteryStats.h b/libs/binder/include/binder/IBatteryStats.h
similarity index 100%
rename from include/binder/IBatteryStats.h
rename to libs/binder/include/binder/IBatteryStats.h
diff --git a/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
similarity index 100%
rename from include/binder/IBinder.h
rename to libs/binder/include/binder/IBinder.h
diff --git a/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
similarity index 100%
rename from include/binder/IInterface.h
rename to libs/binder/include/binder/IInterface.h
diff --git a/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
similarity index 100%
rename from include/binder/IMediaResourceMonitor.h
rename to libs/binder/include/binder/IMediaResourceMonitor.h
diff --git a/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h
similarity index 100%
rename from include/binder/IMemory.h
rename to libs/binder/include/binder/IMemory.h
diff --git a/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
similarity index 100%
rename from include/binder/IPCThreadState.h
rename to libs/binder/include/binder/IPCThreadState.h
diff --git a/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
similarity index 100%
rename from include/binder/IPermissionController.h
rename to libs/binder/include/binder/IPermissionController.h
diff --git a/include/binder/IProcessInfoService.h b/libs/binder/include/binder/IProcessInfoService.h
similarity index 100%
rename from include/binder/IProcessInfoService.h
rename to libs/binder/include/binder/IProcessInfoService.h
diff --git a/include/binder/IResultReceiver.h b/libs/binder/include/binder/IResultReceiver.h
similarity index 100%
rename from include/binder/IResultReceiver.h
rename to libs/binder/include/binder/IResultReceiver.h
diff --git a/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
similarity index 100%
rename from include/binder/IServiceManager.h
rename to libs/binder/include/binder/IServiceManager.h
diff --git a/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
similarity index 100%
rename from include/binder/IShellCallback.h
rename to libs/binder/include/binder/IShellCallback.h
diff --git a/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
similarity index 100%
rename from include/binder/IpPrefix.h
rename to libs/binder/include/binder/IpPrefix.h
diff --git a/include/binder/Map.h b/libs/binder/include/binder/Map.h
similarity index 100%
rename from include/binder/Map.h
rename to libs/binder/include/binder/Map.h
diff --git a/include/binder/MemoryBase.h b/libs/binder/include/binder/MemoryBase.h
similarity index 100%
rename from include/binder/MemoryBase.h
rename to libs/binder/include/binder/MemoryBase.h
diff --git a/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
similarity index 100%
rename from include/binder/MemoryDealer.h
rename to libs/binder/include/binder/MemoryDealer.h
diff --git a/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
similarity index 100%
rename from include/binder/MemoryHeapBase.h
rename to libs/binder/include/binder/MemoryHeapBase.h
diff --git a/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
similarity index 99%
rename from include/binder/Parcel.h
rename to libs/binder/include/binder/Parcel.h
index cf2fa47..5d36526 100644
--- a/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -72,6 +72,8 @@
     status_t            appendFrom(const Parcel *parcel,
                                    size_t start, size_t len);
 
+    int                 compareData(const Parcel& other);
+
     bool                allowFds() const;
     bool                pushAllowFds(bool allowFds);
     void                restoreAllowFds(bool lastValue);
diff --git a/include/binder/Parcelable.h b/libs/binder/include/binder/Parcelable.h
similarity index 100%
rename from include/binder/Parcelable.h
rename to libs/binder/include/binder/Parcelable.h
diff --git a/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
similarity index 100%
rename from include/binder/PermissionCache.h
rename to libs/binder/include/binder/PermissionCache.h
diff --git a/include/binder/PersistableBundle.h b/libs/binder/include/binder/PersistableBundle.h
similarity index 100%
rename from include/binder/PersistableBundle.h
rename to libs/binder/include/binder/PersistableBundle.h
diff --git a/include/binder/ProcessInfoService.h b/libs/binder/include/binder/ProcessInfoService.h
similarity index 100%
rename from include/binder/ProcessInfoService.h
rename to libs/binder/include/binder/ProcessInfoService.h
diff --git a/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
similarity index 97%
rename from include/binder/ProcessState.h
rename to libs/binder/include/binder/ProcessState.h
index 05e9d09..1ef045d 100644
--- a/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -69,6 +69,8 @@
             status_t            setThreadPoolMaxThreadCount(size_t maxThreads);
             void                giveThreadPoolName();
 
+            String8             getDriverName();
+
 private:
     friend class IPCThreadState;
     
@@ -86,6 +88,7 @@
 
             handle_entry*       lookupHandleLocked(int32_t handle);
 
+            String8             mDriverName;
             int                 mDriverFD;
             void*               mVMStart;
 
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index 44c1352..3bfd462 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -26,6 +26,8 @@
 #include <utils/CallStack.h>
 #endif
 
+#include <utils/NativeHandle.h>
+
 #include <functional>
 #include <type_traits>
 
@@ -44,6 +46,19 @@
     status_t write(Parcel* parcel, bool b) const {
         return callParcel("writeBool", [&]() { return parcel->writeBool(b); });
     }
+    template <typename E>
+    typename std::enable_if<std::is_enum<E>::value, status_t>::type read(const Parcel& parcel,
+                                                                         E* e) const {
+        typename std::underlying_type<E>::type u{};
+        status_t result = read(parcel, &u);
+        *e = static_cast<E>(u);
+        return result;
+    }
+    template <typename E>
+    typename std::enable_if<std::is_enum<E>::value, status_t>::type write(Parcel* parcel,
+                                                                          E e) const {
+        return write(parcel, static_cast<typename std::underlying_type<E>::type>(e));
+    }
     template <typename T>
     typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
             const Parcel& parcel, T* t) const {
@@ -55,6 +70,17 @@
         return callParcel("write(Flattenable)", [&]() { return parcel->write(t); });
     }
     template <typename T>
+    typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
+            const Parcel& parcel, sp<T>* t) const {
+        *t = new T{};
+        return callParcel("read(sp<Flattenable>)", [&]() { return parcel.read(*(t->get())); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write(
+            Parcel* parcel, const sp<T>& t) const {
+        return callParcel("write(sp<Flattenable>)", [&]() { return parcel->write(*(t.get())); });
+    }
+    template <typename T>
     typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type read(
             const Parcel& parcel, T* t) const {
         return callParcel("read(LightFlattenable)", [&]() { return parcel.read(*t); });
@@ -64,6 +90,18 @@
             Parcel* parcel, const T& t) const {
         return callParcel("write(LightFlattenable)", [&]() { return parcel->write(t); });
     }
+    template <typename NH>
+    typename std::enable_if<std::is_same<NH, sp<NativeHandle>>::value, status_t>::type read(
+            const Parcel& parcel, NH* nh) {
+        *nh = NativeHandle::create(parcel.readNativeHandle(), true);
+        return NO_ERROR;
+    }
+    template <typename NH>
+    typename std::enable_if<std::is_same<NH, sp<NativeHandle>>::value, status_t>::type write(
+            Parcel* parcel, const NH& nh) {
+        return callParcel("write(sp<NativeHandle>)",
+                          [&]() { return parcel->writeNativeHandle(nh->handle()); });
+    }
     template <typename T>
     typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
             const Parcel& parcel, T* t) const {
@@ -81,7 +119,8 @@
         return callParcel("writeString8", [&]() { return parcel->writeString8(str); });
     }
     template <typename T>
-    status_t read(const Parcel& parcel, sp<T>* pointer) const {
+    typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type read(
+            const Parcel& parcel, sp<T>* pointer) const {
         return callParcel("readNullableStrongBinder",
                           [&]() { return parcel.readNullableStrongBinder(pointer); });
     }
@@ -92,10 +131,27 @@
                           [&]() { return parcel->writeStrongBinder(pointer); });
     }
     template <typename T>
+    typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type read(
+            const Parcel& parcel, sp<T>* pointer) const {
+        return callParcel("readNullableStrongBinder[IInterface]",
+                          [&]() { return parcel.readNullableStrongBinder(pointer); });
+    }
+    template <typename T>
     typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type write(
             Parcel* parcel, const sp<T>& interface) const {
         return write(parcel, IInterface::asBinder(interface));
     }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
+            const Parcel& parcel, std::vector<T>* v) const {
+        return callParcel("readParcelableVector", [&]() { return parcel.readParcelableVector(v); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type write(
+            Parcel* parcel, const std::vector<T>& v) const {
+        return callParcel("writeParcelableVector",
+                          [&]() { return parcel->writeParcelableVector(v); });
+    }
 
     // Templates to handle integral types. We use a struct template to require that the called
     // function exactly matches the signedness and size of the argument (e.g., the argument isn't
@@ -121,6 +177,24 @@
         }
     };
     template <typename I>
+    struct HandleInt<true, 8, I> {
+        static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
+            return handler.callParcel("readInt64", [&]() { return parcel.readInt64(i); });
+        }
+        static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
+            return handler.callParcel("writeInt64", [&]() { return parcel->writeInt64(i); });
+        }
+    };
+    template <typename I>
+    struct HandleInt<false, 8, I> {
+        static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
+            return handler.callParcel("readUint64", [&]() { return parcel.readUint64(i); });
+        }
+        static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
+            return handler.callParcel("writeUint64", [&]() { return parcel->writeUint64(i); });
+        }
+    };
+    template <typename I>
     typename std::enable_if<std::is_integral<I>::value, status_t>::type read(const Parcel& parcel,
                                                                              I* i) const {
         return HandleInt<std::is_signed<I>::value, sizeof(I), I>::read(*this, parcel, i);
diff --git a/include/binder/Status.h b/libs/binder/include/binder/Status.h
similarity index 100%
rename from include/binder/Status.h
rename to libs/binder/include/binder/Status.h
diff --git a/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
similarity index 100%
rename from include/binder/TextOutput.h
rename to libs/binder/include/binder/TextOutput.h
diff --git a/include/binder/Value.h b/libs/binder/include/binder/Value.h
similarity index 100%
rename from include/binder/Value.h
rename to libs/binder/include/binder/Value.h
diff --git a/include/private/binder/ParcelValTypes.h b/libs/binder/include/private/binder/ParcelValTypes.h
similarity index 100%
rename from include/private/binder/ParcelValTypes.h
rename to libs/binder/include/private/binder/ParcelValTypes.h
diff --git a/include/private/binder/Static.h b/libs/binder/include/private/binder/Static.h
similarity index 100%
rename from include/private/binder/Static.h
rename to libs/binder/include/private/binder/Static.h
diff --git a/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
similarity index 100%
rename from include/private/binder/binder_module.h
rename to libs/binder/include/private/binder/binder_module.h
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 1ee4b6f..853ca16 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -100,6 +100,7 @@
 
     shared_libs: [
         "libbinder",
+        "libcutils",
         "liblog",
         "libutils",
     ],
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index d1f63a7..6a16e24 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -28,13 +28,26 @@
 #include <gtest/gtest.h>
 #pragma clang diagnostic pop
 
+#include <utils/LightRefBase.h>
+#include <utils/NativeHandle.h>
+
+#include <cutils/native_handle.h>
+
 #include <optional>
 
+#include <sys/eventfd.h>
+
 using namespace std::chrono_literals; // NOLINT - google-build-using-namespace
 
 namespace android {
 namespace tests {
 
+enum class TestEnum : uint32_t {
+    INVALID = 0,
+    INITIAL = 1,
+    FINAL = 2,
+};
+
 // This class serves two purposes:
 //   1) It ensures that the implementation doesn't require copying or moving the data (for
 //      efficiency purposes)
@@ -90,6 +103,48 @@
     int32_t value = 0;
 };
 
+// It seems like this should be able to inherit from TestFlattenable (to avoid duplicating code),
+// but the SafeInterface logic can't easily be extended to find an indirect Flattenable<T>
+// base class
+class TestLightRefBaseFlattenable : public Flattenable<TestLightRefBaseFlattenable>,
+                                    public LightRefBase<TestLightRefBaseFlattenable> {
+public:
+    TestLightRefBaseFlattenable() = default;
+    explicit TestLightRefBaseFlattenable(int32_t v) : value(v) {}
+
+    // Flattenable protocol
+    size_t getFlattenedSize() const { return sizeof(value); }
+    size_t getFdCount() const { return 0; }
+    status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
+        FlattenableUtils::write(buffer, size, value);
+        return NO_ERROR;
+    }
+    status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
+        FlattenableUtils::read(buffer, size, value);
+        return NO_ERROR;
+    }
+
+    int32_t value = 0;
+};
+
+class TestParcelable : public Parcelable {
+public:
+    TestParcelable() = default;
+    explicit TestParcelable(int32_t value) : mValue(value) {}
+    TestParcelable(const TestParcelable& other) : TestParcelable(other.mValue) {}
+    TestParcelable(TestParcelable&& other) : TestParcelable(other.mValue) {}
+
+    // Parcelable interface
+    status_t writeToParcel(Parcel* parcel) const override { return parcel->writeInt32(mValue); }
+    status_t readFromParcel(const Parcel* parcel) override { return parcel->readInt32(&mValue); }
+
+    int32_t getValue() const { return mValue; }
+    void setValue(int32_t value) { mValue = value; }
+
+private:
+    int32_t mValue = 0;
+};
+
 class ExitOnDeath : public IBinder::DeathRecipient {
 public:
     ~ExitOnDeath() override = default;
@@ -161,13 +216,19 @@
         SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
         ReturnsNoMemory,
         LogicalNot,
+        ModifyEnum,
         IncrementFlattenable,
         IncrementLightFlattenable,
+        IncrementLightRefBaseFlattenable,
+        IncrementNativeHandle,
         IncrementNoCopyNoMove,
+        IncrementParcelableVector,
         ToUpper,
         CallMeBack,
         IncrementInt32,
         IncrementUint32,
+        IncrementInt64,
+        IncrementUint64,
         IncrementTwo,
         Last,
     };
@@ -181,15 +242,23 @@
 
     // These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
     virtual status_t logicalNot(bool a, bool* notA) const = 0;
+    virtual status_t modifyEnum(TestEnum a, TestEnum* b) const = 0;
     virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
     virtual status_t increment(const TestLightFlattenable& a,
                                TestLightFlattenable* aPlusOne) const = 0;
+    virtual status_t increment(const sp<TestLightRefBaseFlattenable>& a,
+                               sp<TestLightRefBaseFlattenable>* aPlusOne) const = 0;
+    virtual status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const = 0;
     virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
+    virtual status_t increment(const std::vector<TestParcelable>& a,
+                               std::vector<TestParcelable>* aPlusOne) const = 0;
     virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
     // As mentioned above, sp<IBinder> is already tested by setDeathToken
     virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
     virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
     virtual status_t increment(uint32_t a, uint32_t* aPlusOne) const = 0;
+    virtual status_t increment(int64_t a, int64_t* aPlusOne) const = 0;
+    virtual status_t increment(uint64_t a, uint64_t* aPlusOne) const = 0;
 
     // This tests that input/output parameter interleaving works correctly
     virtual status_t increment(int32_t a, int32_t* aPlusOne, int32_t b,
@@ -213,6 +282,10 @@
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
     }
+    status_t modifyEnum(TestEnum a, TestEnum* b) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemote<decltype(&ISafeInterfaceTest::modifyEnum)>(Tag::ModifyEnum, a, b);
+    }
     status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
         using Signature =
                 status_t (ISafeInterfaceTest::*)(const TestFlattenable&, TestFlattenable*) const;
@@ -226,12 +299,31 @@
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         return callRemote<Signature>(Tag::IncrementLightFlattenable, a, aPlusOne);
     }
+    status_t increment(const sp<TestLightRefBaseFlattenable>& a,
+                       sp<TestLightRefBaseFlattenable>* aPlusOne) const override {
+        using Signature = status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&,
+                                                           sp<TestLightRefBaseFlattenable>*) const;
+        return callRemote<Signature>(Tag::IncrementLightRefBaseFlattenable, a, aPlusOne);
+    }
+    status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        using Signature =
+                status_t (ISafeInterfaceTest::*)(const sp<NativeHandle>&, sp<NativeHandle>*) const;
+        return callRemote<Signature>(Tag::IncrementNativeHandle, a, aPlusOne);
+    }
     status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
                                                            NoCopyNoMove* aPlusOne) const;
         return callRemote<Signature>(Tag::IncrementNoCopyNoMove, a, aPlusOne);
     }
+    status_t increment(const std::vector<TestParcelable>& a,
+                       std::vector<TestParcelable>* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        using Signature = status_t (ISafeInterfaceTest::*)(const std::vector<TestParcelable>&,
+                                                           std::vector<TestParcelable>*);
+        return callRemote<Signature>(Tag::IncrementParcelableVector, a, aPlusOne);
+    }
     status_t toUpper(const String8& str, String8* upperStr) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
@@ -251,6 +343,16 @@
         using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
         return callRemote<Signature>(Tag::IncrementUint32, a, aPlusOne);
     }
+    status_t increment(int64_t a, int64_t* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        using Signature = status_t (ISafeInterfaceTest::*)(int64_t, int64_t*) const;
+        return callRemote<Signature>(Tag::IncrementInt64, a, aPlusOne);
+    }
+    status_t increment(uint64_t a, uint64_t* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
+        return callRemote<Signature>(Tag::IncrementUint64, a, aPlusOne);
+    }
     status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         using Signature =
@@ -290,6 +392,11 @@
         *notA = !a;
         return NO_ERROR;
     }
+    status_t modifyEnum(TestEnum a, TestEnum* b) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *b = (a == TestEnum::INITIAL) ? TestEnum::FINAL : TestEnum::INVALID;
+        return NO_ERROR;
+    }
     status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         aPlusOne->value = a.value + 1;
@@ -301,11 +408,42 @@
         aPlusOne->value = a.value + 1;
         return NO_ERROR;
     }
+    status_t increment(const sp<TestLightRefBaseFlattenable>& a,
+                       sp<TestLightRefBaseFlattenable>* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *aPlusOne = new TestLightRefBaseFlattenable(a->value + 1);
+        return NO_ERROR;
+    }
+    status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        native_handle* rawHandle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
+        if (rawHandle == nullptr) return NO_MEMORY;
+
+        // Copy the fd over directly
+        rawHandle->data[0] = dup(a->handle()->data[0]);
+
+        // Increment the int
+        rawHandle->data[1] = a->handle()->data[1] + 1;
+
+        // This cannot fail, as it is just the sp<NativeHandle> taking responsibility for closing
+        // the native_handle when it goes out of scope
+        *aPlusOne = NativeHandle::create(rawHandle, true);
+        return NO_ERROR;
+    }
     status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         aPlusOne->setValue(a.getValue() + 1);
         return NO_ERROR;
     }
+    status_t increment(const std::vector<TestParcelable>& a,
+                       std::vector<TestParcelable>* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        aPlusOne->resize(a.size());
+        for (size_t i = 0; i < a.size(); ++i) {
+            (*aPlusOne)[i].setValue(a[i].getValue() + 1);
+        }
+        return NO_ERROR;
+    }
     status_t toUpper(const String8& str, String8* upperStr) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         *upperStr = str;
@@ -326,6 +464,16 @@
         *aPlusOne = a + 1;
         return NO_ERROR;
     }
+    status_t increment(int64_t a, int64_t* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *aPlusOne = a + 1;
+        return NO_ERROR;
+    }
+    status_t increment(uint64_t a, uint64_t* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *aPlusOne = a + 1;
+        return NO_ERROR;
+    }
     status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         *aPlusOne = a + 1;
@@ -349,6 +497,9 @@
             case ISafeInterfaceTest::Tag::LogicalNot: {
                 return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
             }
+            case ISafeInterfaceTest::Tag::ModifyEnum: {
+                return callLocal(data, reply, &ISafeInterfaceTest::modifyEnum);
+            }
             case ISafeInterfaceTest::Tag::IncrementFlattenable: {
                 using Signature = status_t (ISafeInterfaceTest::*)(const TestFlattenable& a,
                                                                    TestFlattenable* aPlusOne) const;
@@ -360,11 +511,28 @@
                                                          TestLightFlattenable* aPlusOne) const;
                 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
             }
+            case ISafeInterfaceTest::Tag::IncrementLightRefBaseFlattenable: {
+                using Signature =
+                        status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&,
+                                                         sp<TestLightRefBaseFlattenable>*) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
+            case ISafeInterfaceTest::Tag::IncrementNativeHandle: {
+                using Signature = status_t (ISafeInterfaceTest::*)(const sp<NativeHandle>&,
+                                                                   sp<NativeHandle>*) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
             case ISafeInterfaceTest::Tag::IncrementNoCopyNoMove: {
                 using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
                                                                    NoCopyNoMove* aPlusOne) const;
                 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
             }
+            case ISafeInterfaceTest::Tag::IncrementParcelableVector: {
+                using Signature =
+                        status_t (ISafeInterfaceTest::*)(const std::vector<TestParcelable>&,
+                                                         std::vector<TestParcelable>*) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
             case ISafeInterfaceTest::Tag::ToUpper: {
                 return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
             }
@@ -379,6 +547,14 @@
                 using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
                 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
             }
+            case ISafeInterfaceTest::Tag::IncrementInt64: {
+                using Signature = status_t (ISafeInterfaceTest::*)(int64_t, int64_t*) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
+            case ISafeInterfaceTest::Tag::IncrementUint64: {
+                using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
             case ISafeInterfaceTest::Tag::IncrementTwo: {
                 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t,
                                                                    int32_t*) const;
@@ -465,6 +641,14 @@
     ASSERT_EQ(!b, notB);
 }
 
+TEST_F(SafeInterfaceTest, TestModifyEnum) {
+    const TestEnum a = TestEnum::INITIAL;
+    TestEnum b = TestEnum::INVALID;
+    status_t result = mSafeInterfaceTest->modifyEnum(a, &b);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(TestEnum::FINAL, b);
+}
+
 TEST_F(SafeInterfaceTest, TestIncrementFlattenable) {
     const TestFlattenable a{1};
     TestFlattenable aPlusOne{0};
@@ -481,6 +665,56 @@
     ASSERT_EQ(a.value + 1, aPlusOne.value);
 }
 
+TEST_F(SafeInterfaceTest, TestIncrementLightRefBaseFlattenable) {
+    sp<TestLightRefBaseFlattenable> a = new TestLightRefBaseFlattenable{1};
+    sp<TestLightRefBaseFlattenable> aPlusOne;
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_NE(nullptr, aPlusOne.get());
+    ASSERT_EQ(a->value + 1, aPlusOne->value);
+}
+
+namespace { // Anonymous namespace
+
+bool fdsAreEquivalent(int a, int b) {
+    struct stat statA {};
+    struct stat statB {};
+    if (fstat(a, &statA) != 0) return false;
+    if (fstat(b, &statB) != 0) return false;
+    return (statA.st_dev == statB.st_dev) && (statA.st_ino == statB.st_ino);
+}
+
+} // Anonymous namespace
+
+TEST_F(SafeInterfaceTest, TestIncrementNativeHandle) {
+    // Create an fd we can use to send and receive from the remote process
+    base::unique_fd eventFd{eventfd(0 /*initval*/, 0 /*flags*/)};
+    ASSERT_NE(-1, eventFd);
+
+    // Determine the maximum number of fds this process can have open
+    struct rlimit limit {};
+    ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &limit));
+    uint32_t maxFds = static_cast<uint32_t>(limit.rlim_cur);
+
+    // Perform this test enough times to rule out fd leaks
+    for (uint32_t iter = 0; iter < (2 * maxFds); ++iter) {
+        native_handle* handle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
+        ASSERT_NE(nullptr, handle);
+        handle->data[0] = dup(eventFd.get());
+        handle->data[1] = 1;
+
+        // This cannot fail, as it is just the sp<NativeHandle> taking responsibility for closing
+        // the native_handle when it goes out of scope
+        sp<NativeHandle> a = NativeHandle::create(handle, true);
+
+        sp<NativeHandle> aPlusOne;
+        status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+        ASSERT_EQ(NO_ERROR, result);
+        ASSERT_TRUE(fdsAreEquivalent(a->handle()->data[0], aPlusOne->handle()->data[0]));
+        ASSERT_EQ(a->handle()->data[1] + 1, aPlusOne->handle()->data[1]);
+    }
+}
+
 TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) {
     const NoCopyNoMove a{1};
     NoCopyNoMove aPlusOne{0};
@@ -489,6 +723,16 @@
     ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
 }
 
+TEST_F(SafeInterfaceTest, TestIncremementParcelableVector) {
+    const std::vector<TestParcelable> a{TestParcelable{1}, TestParcelable{2}};
+    std::vector<TestParcelable> aPlusOne;
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(a.size(), aPlusOne.size());
+    for (size_t i = 0; i < a.size(); ++i) {
+        ASSERT_EQ(a[i].getValue() + 1, aPlusOne[i].getValue());
+    }
+}
+
 TEST_F(SafeInterfaceTest, TestToUpper) {
     const String8 str{"Hello, world!"};
     String8 upperStr;
@@ -544,6 +788,22 @@
     ASSERT_EQ(a + 1, aPlusOne);
 }
 
+TEST_F(SafeInterfaceTest, TestIncrementInt64) {
+    const int64_t a = 1;
+    int64_t aPlusOne = 0;
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(a + 1, aPlusOne);
+}
+
+TEST_F(SafeInterfaceTest, TestIncrementUint64) {
+    const uint64_t a = 1;
+    uint64_t aPlusOne = 0;
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(a + 1, aPlusOne);
+}
+
 TEST_F(SafeInterfaceTest, TestIncrementTwo) {
     const int32_t a = 1;
     int32_t aPlusOne = 0;
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index fe9e05a..13f03b1 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -40,7 +40,7 @@
 // GOOD_SYNC_MIN is considered as good
 #define GOOD_SYNC_MIN (0.6)
 
-#define DUMP_PRICISION 3
+#define DUMP_PRESICION 2
 
 string trace_path = "/sys/kernel/debug/tracing";
 
@@ -246,10 +246,11 @@
     double worst = (double)m_worst / 1.0E6;
     double average = (double)m_total_time / m_transactions / 1.0E6;
     // FIXME: libjson?
-    cout << std::setprecision(DUMP_PRICISION) << "{ \"avg\":" << setw(5) << left
-         << average << ", \"wst\":" << setw(5) << left << worst
-         << ", \"bst\":" << setw(5) << left << best << ", \"miss\":" << setw(5)
-         << left << m_miss << ", \"meetR\":" << setw(3) << left
+    int W = DUMP_PRESICION + 2;
+    cout << setprecision(DUMP_PRESICION) << "{ \"avg\":" << setw(W) << left
+         << average << ",\"wst\":" << setw(W) << left << worst
+         << ",\"bst\":" << setw(W) << left << best << ",\"miss\":" << left
+         << m_miss << ",\"meetR\":" << left << setprecision(DUMP_PRESICION + 3)
          << (1.0 - (double)m_miss / m_transactions) << "}";
   }
 };
@@ -272,8 +273,15 @@
   }
 }
 
+typedef struct {
+  void* result;
+  int target;
+} thread_priv_t;
+
 static void* thread_start(void* p) {
-  Results* results_fifo = (Results*)p;
+  thread_priv_t* priv = (thread_priv_t*)p;
+  int target = priv->target;
+  Results* results_fifo = (Results*)priv->result;
   Parcel data, reply;
   Tick sta, end;
 
@@ -281,7 +289,7 @@
   thread_dump("fifo-caller");
 
   sta = tickNow();
-  status_t ret = workers[0]->transact(BINDER_NOP, data, &reply);
+  status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
   end = tickNow();
   results_fifo->add_time(tickNano(sta, end));
 
@@ -291,16 +299,19 @@
 }
 
 // create a fifo thread to transact and wait it to finished
-static void thread_transaction(Results* results_fifo) {
+static void thread_transaction(int target, Results* results_fifo) {
+  thread_priv_t thread_priv;
   void* dummy;
   pthread_t thread;
   pthread_attr_t attr;
   struct sched_param param;
+  thread_priv.target = target;
+  thread_priv.result = results_fifo;
   ASSERT(!pthread_attr_init(&attr));
   ASSERT(!pthread_attr_setschedpolicy(&attr, SCHED_FIFO));
   param.sched_priority = sched_get_priority_max(SCHED_FIFO);
   ASSERT(!pthread_attr_setschedparam(&attr, &param));
-  ASSERT(!pthread_create(&thread, &attr, &thread_start, results_fifo));
+  ASSERT(!pthread_create(&thread, &attr, &thread_start, &thread_priv));
   ASSERT(!pthread_join(thread, &dummy));
 }
 
@@ -316,7 +327,9 @@
   sp<IServiceManager> serviceMgr = defaultServiceManager();
   sp<BinderWorkerService> service = new BinderWorkerService;
   serviceMgr->addService(generateServiceName(num), service);
+  // init done
   p.signal();
+  // wait for kick-off
   p.wait();
 
   // If client/server pairs, then half the workers are
@@ -338,7 +351,7 @@
     int target = num % server_count;
 
     // 1. transaction by fifo thread
-    thread_transaction(&results_fifo);
+    thread_transaction(target, &results_fifo);
     parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
     thread_dump("other-caller");
 
@@ -356,6 +369,7 @@
   p.wait();
 
   p.send(&dummy);
+  // wait for kill
   p.wait();
   // Client for each pair dump here
   if (is_client(num)) {
@@ -367,10 +381,10 @@
          << "\"S\":" << (no_trans - no_sync) << ",\"I\":" << no_trans << ","
          << "\"R\":" << sync_ratio << "," << endl;
 
-    cout << "      \"other_ms\":";
+    cout << "  \"other_ms\":";
     results_other.dump();
     cout << "," << endl;
-    cout << "      \"fifo_ms\": ";
+    cout << "  \"fifo_ms\": ";
     results_fifo.dump();
     cout << endl;
     cout << "}," << endl;
@@ -463,12 +477,17 @@
   for (int i = 0; i < no_process; i++) {
     pipes.push_back(make_process(i, iterations, no_process, payload_size));
   }
+  // wait for init done
   wait_all(pipes);
+  // kick-off iterations
   signal_all(pipes);
+  // wait for completion
   wait_all(pipes);
+  // start to send result
   signal_all(pipes);
   for (int i = 0; i < no_process; i++) {
     int status;
+    // kill
     pipes[i].signal();
     wait(&status);
     // the exit status is number of transactions without priority inheritance
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 90ab286..5eafb2c 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -79,11 +79,9 @@
         "DisplayEventReceiver.cpp",
         "FrameTimestamps.cpp",
         "GLConsumer.cpp",
-        "GraphicBufferAlloc.cpp",
         "GuiConfig.cpp",
         "IDisplayEventConnection.cpp",
         "IConsumerListener.cpp",
-        "IGraphicBufferAlloc.cpp",
         "IGraphicBufferConsumer.cpp",
         "IGraphicBufferProducer.cpp",
         "IProducerListener.cpp",
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 13692eb..4151212 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -79,14 +79,13 @@
 
 void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
         sp<IGraphicBufferConsumer>* outConsumer,
-        const sp<IGraphicBufferAlloc>& allocator,
         bool consumerIsSurfaceFlinger) {
     LOG_ALWAYS_FATAL_IF(outProducer == NULL,
             "BufferQueue: outProducer must not be NULL");
     LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
             "BufferQueue: outConsumer must not be NULL");
 
-    sp<BufferQueueCore> core(new BufferQueueCore(allocator));
+    sp<BufferQueueCore> core(new BufferQueueCore());
     LOG_ALWAYS_FATAL_IF(core == NULL,
             "BufferQueue: failed to create BufferQueueCore");
 
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index d66aa1a..cd8e696 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -675,12 +675,13 @@
     return NO_ERROR;
 }
 
-void BufferQueueConsumer::setConsumerName(const String8& name) {
+status_t BufferQueueConsumer::setConsumerName(const String8& name) {
     ATRACE_CALL();
     BQ_LOGV("setConsumerName: '%s'", name.string());
     Mutex::Autolock lock(mCore->mMutex);
     mCore->mConsumerName = name;
     mConsumerName = name;
+    return NO_ERROR;
 }
 
 status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
@@ -716,9 +717,10 @@
     return NO_ERROR;
 }
 
-sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
+status_t BufferQueueConsumer::getSidebandStream(sp<NativeHandle>* outStream) const {
     Mutex::Autolock lock(mCore->mMutex);
-    return mCore->mSidebandStream;
+    *outStream = mCore->mSidebandStream;
+    return NO_ERROR;
 }
 
 status_t BufferQueueConsumer::getOccupancyHistory(bool forceFlush,
@@ -734,20 +736,22 @@
     return NO_ERROR;
 }
 
-void BufferQueueConsumer::dumpState(String8& result, const char* prefix) const {
+status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResult) const {
     const IPCThreadState* ipc = IPCThreadState::self();
     const pid_t pid = ipc->getCallingPid();
     const uid_t uid = ipc->getCallingUid();
     if ((uid != AID_SHELL)
             && !PermissionCache::checkPermission(String16(
             "android.permission.DUMP"), pid, uid)) {
-        result.appendFormat("Permission Denial: can't dump BufferQueueConsumer "
+        outResult->appendFormat("Permission Denial: can't dump BufferQueueConsumer "
                 "from pid=%d, uid=%d\n", pid, uid);
         android_errorWriteWithInfoLog(0x534e4554, "27046057",
                 static_cast<int32_t>(uid), NULL, 0);
-    } else {
-        mCore->dumpState(result, prefix);
+        return PERMISSION_DENIED;
     }
+
+    mCore->dumpState(prefix, outResult);
+    return NO_ERROR;
 }
 
 } // namespace android
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index d653db8..cd94253 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -33,9 +33,7 @@
 
 #include <gui/BufferItem.h>
 #include <gui/BufferQueueCore.h>
-#include <gui/GraphicBufferAlloc.h>
 #include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferAlloc.h>
 #include <gui/IProducerListener.h>
 #include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
@@ -54,8 +52,7 @@
     return id | counter++;
 }
 
-BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
-    mAllocator(allocator),
+BufferQueueCore::BufferQueueCore() :
     mMutex(),
     mIsAbandoned(false),
     mConsumerControlledByApp(false),
@@ -97,30 +94,6 @@
     mLastQueuedSlot(INVALID_BUFFER_SLOT),
     mUniqueId(getUniqueId())
 {
-    if (allocator == NULL) {
-
-#ifdef HAVE_NO_SURFACE_FLINGER
-        // Without a SurfaceFlinger, allocate in-process.  This only makes
-        // sense in systems with static SELinux configurations and no
-        // applications (since applications need dynamic SELinux policy).
-        mAllocator = new GraphicBufferAlloc();
-#else
-        // Run time check for headless, where we also allocate in-process.
-        char value[PROPERTY_VALUE_MAX];
-        property_get("config.headless", value, "0");
-        if (atoi(value) == 1) {
-            mAllocator = new GraphicBufferAlloc();
-        } else {
-            sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-            mAllocator = composer->createGraphicBufferAlloc();
-        }
-#endif  // HAVE_NO_SURFACE_FLINGER
-
-        if (mAllocator == NULL) {
-            BQ_LOGE("createGraphicBufferAlloc failed");
-        }
-    }
-
     int numStartingBuffers = getMaxBufferCountLocked();
     for (int s = 0; s < numStartingBuffers; s++) {
         mFreeSlots.insert(s);
@@ -133,7 +106,7 @@
 
 BufferQueueCore::~BufferQueueCore() {}
 
-void BufferQueueCore::dumpState(String8& result, const char* prefix) const {
+void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
     Mutex::Autolock lock(mMutex);
 
     String8 fifo;
@@ -148,10 +121,10 @@
         ++current;
     }
 
-    result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
+    outResult->appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
             "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
             "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
-            "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix,
+            "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix.string(),
             mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
             mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
             mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
@@ -161,28 +134,28 @@
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
         // A dequeued buffer might be null if it's still being allocated
         if (buffer.get()) {
-            result.appendFormat("%s%s[%02d:%p] state=%-8s, %p "
-                    "[%4ux%4u:%4u,%3X]\n", prefix,
+            outResult->appendFormat("%s%s[%02d:%p] state=%-8s, %p "
+                    "[%4ux%4u:%4u,%3X]\n", prefix.string(),
                     (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
                     buffer.get(), mSlots[s].mBufferState.string(),
                     buffer->handle, buffer->width, buffer->height,
                     buffer->stride, buffer->format);
         } else {
-            result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
+            outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
                     buffer.get(), mSlots[s].mBufferState.string());
         }
     }
     for (int s : mFreeBuffers) {
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
-        result.appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
-                prefix, s, buffer.get(), mSlots[s].mBufferState.string(),
+        outResult->appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
+                prefix.string(), s, buffer.get(), mSlots[s].mBufferState.string(),
                 buffer->handle, buffer->width, buffer->height, buffer->stride,
                 buffer->format);
     }
 
     for (int s : mFreeSlots) {
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
-        result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
+        outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
                 buffer.get(), mSlots[s].mBufferState.string());
     }
 }
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index aef231a..cddb1fd 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -34,7 +34,6 @@
 #include <gui/BufferQueueProducer.h>
 #include <gui/GLConsumer.h>
 #include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferAlloc.h>
 #include <gui/IProducerListener.h>
 
 #include <utils/Log.h>
@@ -454,8 +453,7 @@
         mSlots[found].mBufferState.dequeue();
 
         if ((buffer == NULL) ||
-                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT,
-                usage))
+                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage))
         {
             mSlots[found].mAcquireCalled = false;
             mSlots[found].mGraphicBuffer = NULL;
@@ -503,11 +501,13 @@
     } // Autolock scope
 
     if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
-        status_t error;
         BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
-        sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
+        sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
                 width, height, format, BQ_LAYER_COUNT, usage,
-                {mConsumerName.string(), mConsumerName.size()}, &error));
+                {mConsumerName.string(), mConsumerName.size()});
+
+        status_t error = graphicBuffer->initCheck();
+
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
 
@@ -1267,7 +1267,10 @@
                     mCore->mSidebandStream.clear();
                     mCore->mDequeueCondition.broadcast();
                     listener = mCore->mConsumerListener;
-                } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+                } else if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+                    BQ_LOGE("disconnect: not connected (req=%d)", api);
+                    status = NO_INIT;
+                } else {
                     BQ_LOGE("disconnect: still connected to another API "
                             "(cur=%d req=%d)", mCore->mConnectedApi, api);
                     status = BAD_VALUE;
@@ -1337,11 +1340,12 @@
 
         Vector<sp<GraphicBuffer>> buffers;
         for (size_t i = 0; i <  newBufferCount; ++i) {
-            status_t result = NO_ERROR;
-            sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
+            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
                     allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
-                    allocUsage, {mConsumerName.string(), mConsumerName.size()},
-                    &result));
+                    allocUsage, {mConsumerName.string(), mConsumerName.size()});
+
+            status_t result = graphicBuffer->initCheck();
+
             if (result != NO_ERROR) {
                 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
                         " %u, usage %u)", width, height, format, usage);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index d4e4dc3..5c6158c 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -30,7 +30,6 @@
 #include <cutils/atomic.h>
 
 #include <gui/BufferItem.h>
-#include <gui/IGraphicBufferAlloc.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/ConsumerBase.h>
@@ -270,7 +269,9 @@
     result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
 
     if (!mAbandoned) {
-        mConsumer->dumpState(result, prefix);
+        String8 consumerState;
+        mConsumer->dumpState(String8(prefix), &consumerState);
+        result.append(consumerState);
     }
 }
 
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 55e0d26..c654f08 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -31,7 +31,6 @@
 
 #include <gui/BufferItem.h>
 #include <gui/GLConsumer.h>
-#include <gui/IGraphicBufferAlloc.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
 
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
deleted file mode 100644
index cc7d403..0000000
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- **
- ** Copyright 2012 The Android Open Source Project
- **
- ** Licensed under the Apache License Version 2.0(the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- **     http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing software
- ** distributed under the License is distributed on an "AS IS" BASIS
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#include <gui/GraphicBufferAlloc.h>
-
-#include <log/log.h>
-
-
-namespace android {
-
-GraphicBufferAlloc::GraphicBufferAlloc() = default;
-GraphicBufferAlloc::~GraphicBufferAlloc() = default;
-
-sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
-        uint32_t height, PixelFormat format, uint32_t layerCount,
-        uint64_t producerUsage, uint64_t consumerUsage,
-        std::string requestorName, status_t* error) {
-    sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(
-            width, height, format, layerCount, producerUsage, consumerUsage,
-            std::move(requestorName)));
-    status_t err = graphicBuffer->initCheck();
-    *error = err;
-    if (err != 0 || graphicBuffer->handle == 0) {
-        if (err == NO_MEMORY) {
-            GraphicBuffer::dumpAllocationsToSystemLog();
-        }
-        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
-                width, height, layerCount, strerror(-err),
-                graphicBuffer->handle);
-        graphicBuffer.clear();
-    }
-    return graphicBuffer;
-}
-
-} // namespace android
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
deleted file mode 100644
index 21a0dd5..0000000
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-// tag as surfaceflinger
-#define LOG_TAG "SurfaceFlinger"
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-
-enum {
-    CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
-{
-public:
-    explicit BpGraphicBufferAlloc(const sp<IBinder>& impl)
-        : BpInterface<IGraphicBufferAlloc>(impl)
-    {
-    }
-
-    virtual ~BpGraphicBufferAlloc();
-
-    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
-            uint32_t height, PixelFormat format, uint32_t layerCount,
-            uint64_t producerUsage, uint64_t consumerUsage,
-            std::string requestorName, status_t* error) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
-        data.writeUint32(width);
-        data.writeUint32(height);
-        data.writeInt32(static_cast<int32_t>(format));
-        data.writeUint32(layerCount);
-        data.writeUint64(producerUsage);
-        data.writeUint64(consumerUsage);
-        if (requestorName.empty()) {
-            requestorName += "[PID ";
-            requestorName += std::to_string(getpid());
-            requestorName += ']';
-        }
-        data.writeUtf8AsUtf16(requestorName);
-        remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
-        sp<GraphicBuffer> graphicBuffer;
-        status_t result = reply.readInt32();
-        if (result == NO_ERROR) {
-            graphicBuffer = new GraphicBuffer();
-            result = reply.read(*graphicBuffer);
-            if (result != NO_ERROR) {
-                graphicBuffer.clear();
-            }
-            // reply.readStrongBinder();
-            // here we don't even have to read the BufferReference from
-            // the parcel, it'll die with the parcel.
-        }
-        *error = result;
-        return graphicBuffer;
-    }
-};
-
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpGraphicBufferAlloc::~BpGraphicBufferAlloc() {}
-
-IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
-
-// ----------------------------------------------------------------------
-
-status_t BnGraphicBufferAlloc::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    // codes that don't require permission check
-
-    // BufferReference just keeps a strong reference to a GraphicBuffer until it
-    // is destroyed (that is, until no local or remote process have a reference
-    // to it).
-    class BufferReference : public BBinder {
-        sp<GraphicBuffer> mBuffer;
-    public:
-        explicit BufferReference(const sp<GraphicBuffer>& buffer) : mBuffer(buffer) {}
-    };
-
-
-    switch (code) {
-        case CREATE_GRAPHIC_BUFFER: {
-            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
-            uint32_t width = data.readUint32();
-            uint32_t height = data.readUint32();
-            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
-            uint32_t layerCount = data.readUint32();
-            uint64_t producerUsage = data.readUint64();
-            uint64_t consumerUsage = data.readUint64();
-            status_t error = NO_ERROR;
-            std::string requestorName;
-            data.readUtf8FromUtf16(&requestorName);
-            sp<GraphicBuffer> result = createGraphicBuffer(width, height,
-                    format, layerCount, producerUsage, consumerUsage,
-                    requestorName, &error);
-            reply->writeInt32(error);
-            if (result != 0) {
-                reply->write(*result);
-                // We add a BufferReference to this parcel to make sure the
-                // buffer stays alive until the GraphicBuffer object on
-                // the other side has been created.
-                // This is needed so that the buffer handle can be
-                // registered before the buffer is destroyed on implementations
-                // that do not use file-descriptors to track their buffers.
-                reply->writeStrongBinder( new BufferReference(result) );
-            }
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}; // namespace android
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index ef770e8..568c318 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -14,28 +14,24 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/NativeHandle.h>
-#include <utils/String8.h>
-
-#include <binder/Parcel.h>
-#include <binder/IInterface.h>
+#include <gui/IGraphicBufferConsumer.h>
 
 #include <gui/BufferItem.h>
 #include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferConsumer.h>
 
-#include <ui/GraphicBuffer.h>
+#include <binder/Parcel.h>
+
 #include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
 
-#include <system/window.h>
+#include <utils/NativeHandle.h>
+#include <utils/String8.h>
 
 namespace android {
 
-enum {
+namespace { // Anonymous namespace
+
+enum class Tag : uint32_t {
     ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
     DETACH_BUFFER,
     ATTACH_BUFFER,
@@ -54,439 +50,173 @@
     GET_SIDEBAND_STREAM,
     GET_OCCUPANCY_HISTORY,
     DISCARD_FREE_BUFFERS,
-    DUMP,
+    DUMP_STATE,
+    LAST = DUMP_STATE,
 };
 
+} // Anonymous namespace
 
-class BpGraphicBufferConsumer : public BpInterface<IGraphicBufferConsumer>
-{
+class BpGraphicBufferConsumer : public SafeBpInterface<IGraphicBufferConsumer> {
 public:
     explicit BpGraphicBufferConsumer(const sp<IBinder>& impl)
-        : BpInterface<IGraphicBufferConsumer>(impl)
-    {
+          : SafeBpInterface<IGraphicBufferConsumer>(impl, "BpGraphicBufferConsumer") {}
+
+    ~BpGraphicBufferConsumer() override;
+
+    status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
+                           uint64_t maxFrameNumber) override {
+        using Signature = decltype(&IGraphicBufferConsumer::acquireBuffer);
+        return callRemote<Signature>(Tag::ACQUIRE_BUFFER, buffer, presentWhen, maxFrameNumber);
     }
 
-    virtual ~BpGraphicBufferConsumer();
-
-    virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen,
-            uint64_t maxFrameNumber) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeInt64(presentWhen);
-        data.writeUint64(maxFrameNumber);
-        status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        result = reply.read(*buffer);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t detachBuffer(int slot) override {
+        using Signature = decltype(&IGraphicBufferConsumer::detachBuffer);
+        return callRemote<Signature>(Tag::DETACH_BUFFER, slot);
     }
 
-    virtual status_t detachBuffer(int slot) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeInt32(slot);
-        status_t result = remote()->transact(DETACH_BUFFER, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        result = reply.readInt32();
-        return result;
+    status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) override {
+        using Signature = decltype(&IGraphicBufferConsumer::attachBuffer);
+        return callRemote<Signature>(Tag::ATTACH_BUFFER, slot, buffer);
     }
 
-    virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.write(*buffer.get());
-        status_t result = remote()->transact(ATTACH_BUFFER, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        *slot = reply.readInt32();
-        result = reply.readInt32();
-        return result;
+    status_t releaseBuffer(int buf, uint64_t frameNumber,
+                           EGLDisplay display __attribute__((unused)),
+                           EGLSyncKHR fence __attribute__((unused)),
+                           const sp<Fence>& releaseFence) override {
+        return callRemote<ReleaseBuffer>(Tag::RELEASE_BUFFER, buf, frameNumber, releaseFence);
     }
 
-    virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
-            EGLDisplay display __attribute__((unused)), EGLSyncKHR fence __attribute__((unused)),
-            const sp<Fence>& releaseFence) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeInt32(buf);
-        data.writeInt64(static_cast<int64_t>(frameNumber));
-        data.write(*releaseFence);
-        status_t result = remote()->transact(RELEASE_BUFFER, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) override {
+        using Signature = decltype(&IGraphicBufferConsumer::consumerConnect);
+        return callRemote<Signature>(Tag::CONSUMER_CONNECT, consumer, controlledByApp);
     }
 
-    virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(consumer));
-        data.writeInt32(controlledByApp);
-        status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t consumerDisconnect() override {
+        return callRemote<decltype(&IGraphicBufferConsumer::consumerDisconnect)>(
+                Tag::CONSUMER_DISCONNECT);
     }
 
-    virtual status_t consumerDisconnect() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        status_t result = remote()->transact(CONSUMER_DISCONNECT, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t getReleasedBuffers(uint64_t* slotMask) override {
+        using Signature = decltype(&IGraphicBufferConsumer::getReleasedBuffers);
+        return callRemote<Signature>(Tag::GET_RELEASED_BUFFERS, slotMask);
     }
 
-    virtual status_t getReleasedBuffers(uint64_t* slotMask) {
-        Parcel data, reply;
-        if (slotMask == NULL) {
-            ALOGE("getReleasedBuffers: slotMask must not be NULL");
-            return BAD_VALUE;
-        }
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        status_t result = remote()->transact(GET_RELEASED_BUFFERS, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        *slotMask = static_cast<uint64_t>(reply.readInt64());
-        return reply.readInt32();
+    status_t setDefaultBufferSize(uint32_t width, uint32_t height) override {
+        using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferSize);
+        return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_SIZE, width, height);
     }
 
-    virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeUint32(width);
-        data.writeUint32(height);
-        status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t setMaxBufferCount(int bufferCount) override {
+        using Signature = decltype(&IGraphicBufferConsumer::setMaxBufferCount);
+        return callRemote<Signature>(Tag::SET_MAX_BUFFER_COUNT, bufferCount);
     }
 
-    virtual status_t setMaxBufferCount(int bufferCount) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeInt32(bufferCount);
-        status_t result = remote()->transact(SET_MAX_BUFFER_COUNT, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) override {
+        using Signature = decltype(&IGraphicBufferConsumer::setMaxAcquiredBufferCount);
+        return callRemote<Signature>(Tag::SET_MAX_ACQUIRED_BUFFER_COUNT, maxAcquiredBuffers);
     }
 
-    virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeInt32(maxAcquiredBuffers);
-        status_t result = remote()->transact(SET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t setConsumerName(const String8& name) override {
+        using Signature = decltype(&IGraphicBufferConsumer::setConsumerName);
+        return callRemote<Signature>(Tag::SET_CONSUMER_NAME, name);
     }
 
-    virtual void setConsumerName(const String8& name) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeString8(name);
-        remote()->transact(SET_CONSUMER_NAME, data, &reply);
+    status_t setDefaultBufferFormat(PixelFormat defaultFormat) override {
+        using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferFormat);
+        return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_FORMAT, defaultFormat);
     }
 
-    virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(defaultFormat));
-        status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) override {
+        using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferDataSpace);
+        return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_DATA_SPACE, defaultDataSpace);
     }
 
-    virtual status_t setDefaultBufferDataSpace(
-            android_dataspace defaultDataSpace) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(defaultDataSpace));
-        status_t result = remote()->transact(SET_DEFAULT_BUFFER_DATA_SPACE,
-                data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t setConsumerUsageBits(uint32_t usage) override {
+        using Signature = decltype(&IGraphicBufferConsumer::setConsumerUsageBits);
+        return callRemote<Signature>(Tag::SET_CONSUMER_USAGE_BITS, usage);
     }
 
-    virtual status_t setConsumerUsageBits(uint32_t usage) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeUint32(usage);
-        status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t setTransformHint(uint32_t hint) override {
+        using Signature = decltype(&IGraphicBufferConsumer::setTransformHint);
+        return callRemote<Signature>(Tag::SET_TRANSFORM_HINT, hint);
     }
 
-    virtual status_t setTransformHint(uint32_t hint) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeUint32(hint);
-        status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
+    status_t getSidebandStream(sp<NativeHandle>* outStream) const override {
+        using Signature = decltype(&IGraphicBufferConsumer::getSidebandStream);
+        return callRemote<Signature>(Tag::GET_SIDEBAND_STREAM, outStream);
     }
 
-    virtual sp<NativeHandle> getSidebandStream() const {
-        Parcel data, reply;
-        status_t err;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        if ((err = remote()->transact(GET_SIDEBAND_STREAM, data, &reply)) != NO_ERROR) {
-            return NULL;
-        }
-        sp<NativeHandle> stream;
-        if (reply.readInt32()) {
-            stream = NativeHandle::create(reply.readNativeHandle(), true);
-        }
-        return stream;
+    status_t getOccupancyHistory(bool forceFlush,
+                                 std::vector<OccupancyTracker::Segment>* outHistory) override {
+        using Signature = decltype(&IGraphicBufferConsumer::getOccupancyHistory);
+        return callRemote<Signature>(Tag::GET_OCCUPANCY_HISTORY, forceFlush, outHistory);
     }
 
-    virtual status_t getOccupancyHistory(bool forceFlush,
-            std::vector<OccupancyTracker::Segment>* outHistory) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        status_t error = data.writeBool(forceFlush);
-        if (error != NO_ERROR) {
-            return error;
-        }
-        error = remote()->transact(GET_OCCUPANCY_HISTORY, data,
-                &reply);
-        if (error != NO_ERROR) {
-            return error;
-        }
-        error = reply.readParcelableVector(outHistory);
-        if (error != NO_ERROR) {
-            return error;
-        }
-        status_t result = NO_ERROR;
-        error = reply.readInt32(&result);
-        if (error != NO_ERROR) {
-            return error;
-        }
-        return result;
+    status_t discardFreeBuffers() override {
+        return callRemote<decltype(&IGraphicBufferConsumer::discardFreeBuffers)>(
+                Tag::DISCARD_FREE_BUFFERS);
     }
 
-    virtual status_t discardFreeBuffers() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        status_t error = remote()->transact(DISCARD_FREE_BUFFERS, data, &reply);
-        if (error != NO_ERROR) {
-            return error;
-        }
-        int32_t result = NO_ERROR;
-        error = reply.readInt32(&result);
-        if (error != NO_ERROR) {
-            return error;
-        }
-        return result;
-    }
-
-    virtual void dumpState(String8& result, const char* prefix) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        data.writeString8(result);
-        data.writeString8(String8(prefix ? prefix : ""));
-        remote()->transact(DUMP, data, &reply);
-        reply.readString8();
+    status_t dumpState(const String8& prefix, String8* outResult) const override {
+        using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
+        return callRemote<Signature>(Tag::DUMP_STATE, prefix, outResult);
     }
 };
 
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpGraphicBufferConsumer::~BpGraphicBufferConsumer() {}
+// Out-of-line virtual method definition to trigger vtable emission in this translation unit
+// (see clang warning -Wweak-vtables)
+BpGraphicBufferConsumer::~BpGraphicBufferConsumer() = default;
 
 IMPLEMENT_META_INTERFACE(GraphicBufferConsumer, "android.gui.IGraphicBufferConsumer");
 
-// ----------------------------------------------------------------------
-
-status_t BnGraphicBufferConsumer::onTransact(
-        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case ACQUIRE_BUFFER: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            BufferItem item;
-            int64_t presentWhen = data.readInt64();
-            uint64_t maxFrameNumber = data.readUint64();
-            status_t result = acquireBuffer(&item, presentWhen, maxFrameNumber);
-            status_t err = reply->write(item);
-            if (err) return err;
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case DETACH_BUFFER: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            int slot = data.readInt32();
-            int result = detachBuffer(slot);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case ATTACH_BUFFER: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            sp<GraphicBuffer> buffer = new GraphicBuffer();
-            data.read(*buffer.get());
-            int slot = -1;
-            int result = attachBuffer(&slot, buffer);
-            reply->writeInt32(slot);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case RELEASE_BUFFER: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            int buf = data.readInt32();
-            uint64_t frameNumber = static_cast<uint64_t>(data.readInt64());
-            sp<Fence> releaseFence = new Fence();
-            status_t err = data.read(*releaseFence);
-            if (err) return err;
-            status_t result = releaseBuffer(buf, frameNumber,
-                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case CONSUMER_CONNECT: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            sp<IConsumerListener> consumer = IConsumerListener::asInterface( data.readStrongBinder() );
-            bool controlledByApp = data.readInt32();
-            status_t result = consumerConnect(consumer, controlledByApp);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case CONSUMER_DISCONNECT: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            status_t result = consumerDisconnect();
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case GET_RELEASED_BUFFERS: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            uint64_t slotMask = 0;
-            status_t result = getReleasedBuffers(&slotMask);
-            reply->writeInt64(static_cast<int64_t>(slotMask));
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case SET_DEFAULT_BUFFER_SIZE: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            uint32_t width = data.readUint32();
-            uint32_t height = data.readUint32();
-            status_t result = setDefaultBufferSize(width, height);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case SET_MAX_BUFFER_COUNT: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            int bufferCount = data.readInt32();
-            status_t result = setMaxBufferCount(bufferCount);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case SET_MAX_ACQUIRED_BUFFER_COUNT: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            int maxAcquiredBuffers = data.readInt32();
-            status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case SET_CONSUMER_NAME: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            setConsumerName( data.readString8() );
-            return NO_ERROR;
-        }
-        case SET_DEFAULT_BUFFER_FORMAT: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            PixelFormat defaultFormat = static_cast<PixelFormat>(data.readInt32());
-            status_t result = setDefaultBufferFormat(defaultFormat);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case SET_DEFAULT_BUFFER_DATA_SPACE: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            android_dataspace defaultDataSpace =
-                    static_cast<android_dataspace>(data.readInt32());
-            status_t result = setDefaultBufferDataSpace(defaultDataSpace);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case SET_CONSUMER_USAGE_BITS: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            uint32_t usage = data.readUint32();
-            status_t result = setConsumerUsageBits(usage);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case SET_TRANSFORM_HINT: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            uint32_t hint = data.readUint32();
-            status_t result = setTransformHint(hint);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case GET_SIDEBAND_STREAM: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            sp<NativeHandle> stream = getSidebandStream();
-            reply->writeInt32(static_cast<int32_t>(stream != NULL));
-            if (stream != NULL) {
-                reply->writeNativeHandle(stream->handle());
-            }
-            return NO_ERROR;
-        }
-        case GET_OCCUPANCY_HISTORY: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            bool forceFlush = false;
-            status_t error = data.readBool(&forceFlush);
-            if (error != NO_ERROR) {
-                return error;
-            }
-            std::vector<OccupancyTracker::Segment> history;
-            status_t result = getOccupancyHistory(forceFlush, &history);
-            error = reply->writeParcelableVector(history);
-            if (error != NO_ERROR) {
-                return error;
-            }
-            error = reply->writeInt32(result);
-            if (error != NO_ERROR) {
-                return error;
-            }
-            return NO_ERROR;
-        }
-        case DISCARD_FREE_BUFFERS: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            status_t result = discardFreeBuffers();
-            status_t error = reply->writeInt32(result);
-            return error;
-        }
-        case DUMP: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            String8 result = data.readString8();
-            String8 prefix = data.readString8();
-            static_cast<IGraphicBufferConsumer*>(this)->dumpState(result, prefix);
-            reply->writeString8(result);
-            return NO_ERROR;
+status_t BnGraphicBufferConsumer::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                             uint32_t flags) {
+    if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+    auto tag = static_cast<Tag>(code);
+    switch (tag) {
+        case Tag::ACQUIRE_BUFFER:
+            return callLocal(data, reply, &IGraphicBufferConsumer::acquireBuffer);
+        case Tag::DETACH_BUFFER:
+            return callLocal(data, reply, &IGraphicBufferConsumer::detachBuffer);
+        case Tag::ATTACH_BUFFER:
+            return callLocal(data, reply, &IGraphicBufferConsumer::attachBuffer);
+        case Tag::RELEASE_BUFFER:
+            return callLocal(data, reply, &IGraphicBufferConsumer::releaseHelper);
+        case Tag::CONSUMER_CONNECT:
+            return callLocal(data, reply, &IGraphicBufferConsumer::consumerConnect);
+        case Tag::CONSUMER_DISCONNECT:
+            return callLocal(data, reply, &IGraphicBufferConsumer::consumerDisconnect);
+        case Tag::GET_RELEASED_BUFFERS:
+            return callLocal(data, reply, &IGraphicBufferConsumer::getReleasedBuffers);
+        case Tag::SET_DEFAULT_BUFFER_SIZE:
+            return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferSize);
+        case Tag::SET_MAX_BUFFER_COUNT:
+            return callLocal(data, reply, &IGraphicBufferConsumer::setMaxBufferCount);
+        case Tag::SET_MAX_ACQUIRED_BUFFER_COUNT:
+            return callLocal(data, reply, &IGraphicBufferConsumer::setMaxAcquiredBufferCount);
+        case Tag::SET_CONSUMER_NAME:
+            return callLocal(data, reply, &IGraphicBufferConsumer::setConsumerName);
+        case Tag::SET_DEFAULT_BUFFER_FORMAT:
+            return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferFormat);
+        case Tag::SET_DEFAULT_BUFFER_DATA_SPACE:
+            return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferDataSpace);
+        case Tag::SET_CONSUMER_USAGE_BITS:
+            return callLocal(data, reply, &IGraphicBufferConsumer::setConsumerUsageBits);
+        case Tag::SET_TRANSFORM_HINT:
+            return callLocal(data, reply, &IGraphicBufferConsumer::setTransformHint);
+        case Tag::GET_SIDEBAND_STREAM:
+            return callLocal(data, reply, &IGraphicBufferConsumer::getSidebandStream);
+        case Tag::GET_OCCUPANCY_HISTORY:
+            return callLocal(data, reply, &IGraphicBufferConsumer::getOccupancyHistory);
+        case Tag::DISCARD_FREE_BUFFERS:
+            return callLocal(data, reply, &IGraphicBufferConsumer::discardFreeBuffers);
+        case Tag::DUMP_STATE: {
+            using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
+            return callLocal<Signature>(data, reply, &IGraphicBufferConsumer::dumpState);
         }
     }
-    return BBinder::onTransact(code, data, reply, flags);
 }
 
-}; // namespace android
+} // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 5a32d05..2516fb8 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,7 +25,6 @@
 #include <binder/IServiceManager.h>
 
 #include <gui/IDisplayEventConnection.h>
-#include <gui/IGraphicBufferAlloc.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
@@ -72,14 +71,6 @@
         return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
     }
 
-    virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
-        return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
-    }
-
     virtual void setTransactionState(
             const Vector<ComposerState>& state,
             const Vector<DisplayState>& displays,
@@ -166,6 +157,50 @@
         return result != 0;
     }
 
+    virtual status_t getSupportedFrameTimestamps(
+            std::vector<FrameEvent>* outSupported) const {
+        if (!outSupported) {
+            return UNEXPECTED_NULL;
+        }
+        outSupported->clear();
+
+        Parcel data, reply;
+
+        status_t err = data.writeInterfaceToken(
+                ISurfaceComposer::getInterfaceDescriptor());
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        err = remote()->transact(
+                BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS,
+                data, &reply);
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        int32_t result = 0;
+        err = reply.readInt32(&result);
+        if (err != NO_ERROR) {
+            return err;
+        }
+        if (result != NO_ERROR) {
+            return result;
+        }
+
+        std::vector<int32_t> supported;
+        err = reply.readInt32Vector(&supported);
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        outSupported->reserve(supported.size());
+        for (int32_t s : supported) {
+            outSupported->push_back(static_cast<FrameEvent>(s));
+        }
+        return NO_ERROR;
+    }
+
     virtual sp<IDisplayEventConnection> createDisplayEventConnection()
     {
         Parcel data, reply;
@@ -461,12 +496,6 @@
             reply->writeStrongBinder(b);
             return NO_ERROR;
         }
-        case CREATE_GRAPHIC_BUFFER_ALLOC: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> b = IInterface::asBinder(createGraphicBufferAlloc());
-            reply->writeStrongBinder(b);
-            return NO_ERROR;
-        }
         case SET_TRANSACTION_STATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
 
@@ -536,6 +565,25 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case GET_SUPPORTED_FRAME_TIMESTAMPS: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            std::vector<FrameEvent> supportedTimestamps;
+            status_t result = getSupportedFrameTimestamps(&supportedTimestamps);
+            status_t err = reply->writeInt32(result);
+            if (err != NO_ERROR) {
+                return err;
+            }
+            if (result != NO_ERROR) {
+                return result;
+            }
+
+            std::vector<int32_t> supported;
+            supported.reserve(supportedTimestamps.size());
+            for (FrameEvent s : supportedTimestamps) {
+                supported.push_back(static_cast<int32_t>(s));
+            }
+            return reply->writeInt32Vector(supported);
+        }
         case CREATE_DISPLAY_EVENT_CONNECTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IDisplayEventConnection> connection(createDisplayEventConnection());
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 2461cba..9b06e63 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -44,6 +44,7 @@
     output.writeUint64(frameNumber);
     output.writeInt32(overrideScalingMode);
     output.writeStrongBinder(IInterface::asBinder(barrierGbp));
+    output.writeStrongBinder(relativeLayerHandle);
     output.write(transparentRegion);
     return NO_ERROR;
 }
@@ -75,6 +76,7 @@
     overrideScalingMode = input.readInt32();
     barrierGbp =
         interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
+    relativeLayerHandle = input.readStrongBinder();
     input.read(transparentRegion);
     return NO_ERROR;
 }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 1149b89..a6d9e66 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -52,6 +52,8 @@
       mAutoRefresh(false),
       mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
       mSharedBufferHasBeenQueued(false),
+      mQueriedSupportedTimestamps(false),
+      mFrameTimestampsSupportsPresent(false),
       mEnableFrameTimestamps(false),
       mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
 {
@@ -209,8 +211,8 @@
     bool checkForDisplayPresent = (outDisplayPresentTime != nullptr) &&
             !e->hasDisplayPresentInfo();
 
-    // LastRefreshStart, DequeueReady, and Release are never
-    // available for the last frame.
+    // LastRefreshStart, DequeueReady, and Release are never available for the
+    // last frame.
     bool checkForLastRefreshStart = (outLastRefreshStartTime != nullptr) &&
             !e->hasLastRefreshStartInfo() &&
             (e->frameNumber != lastFrameNumber);
@@ -227,14 +229,26 @@
 
 static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
     if (dst != nullptr) {
-        *dst = FrameEvents::isValidTimestamp(src) ? src : 0;
+        // We always get valid timestamps for these eventually.
+        *dst = (src == FrameEvents::TIMESTAMP_PENDING) ?
+                NATIVE_WINDOW_TIMESTAMP_PENDING : src;
     }
 }
 
-static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptr<FenceTime>& src) {
+static void getFrameTimestampFence(nsecs_t *dst,
+        const std::shared_ptr<FenceTime>& src, bool fenceShouldBeKnown) {
     if (dst != nullptr) {
+        if (!fenceShouldBeKnown) {
+            *dst = NATIVE_WINDOW_TIMESTAMP_PENDING;
+            return;
+        }
+
         nsecs_t signalTime = src->getSignalTime();
-        *dst = Fence::isValidTimestamp(signalTime) ? signalTime : 0;
+        *dst = (signalTime == Fence::SIGNAL_TIME_PENDING) ?
+                    NATIVE_WINDOW_TIMESTAMP_PENDING :
+                (signalTime == Fence::SIGNAL_TIME_INVALID) ?
+                    NATIVE_WINDOW_TIMESTAMP_INVALID :
+                signalTime;
     }
 }
 
@@ -252,6 +266,12 @@
         return INVALID_OPERATION;
     }
 
+    // Verify the requested timestamps are supported.
+    querySupportedTimestampsLocked();
+    if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) {
+        return BAD_VALUE;
+    }
+
     FrameEvents* events = mFrameEventHistory->getFrame(frameNumber);
     if (events == nullptr) {
         // If the entry isn't available in the producer, it's definitely not
@@ -282,12 +302,15 @@
     getFrameTimestamp(outLastRefreshStartTime, events->lastRefreshStartTime);
     getFrameTimestamp(outDequeueReadyTime, events->dequeueReadyTime);
 
-    getFrameTimestampFence(outAcquireTime, events->acquireFence);
-    getFrameTimestampFence(
-            outGpuCompositionDoneTime, events->gpuCompositionDoneFence);
-    getFrameTimestampFence(
-            outDisplayPresentTime, events->displayPresentFence);
-    getFrameTimestampFence(outReleaseTime, events->releaseFence);
+    getFrameTimestampFence(outAcquireTime, events->acquireFence,
+            events->hasAcquireInfo());
+    getFrameTimestampFence(outGpuCompositionDoneTime,
+            events->gpuCompositionDoneFence,
+            events->hasGpuCompositionDoneInfo());
+    getFrameTimestampFence(outDisplayPresentTime, events->displayPresentFence,
+            events->hasDisplayPresentInfo());
+    getFrameTimestampFence(outReleaseTime, events->releaseFence,
+            events->hasReleaseInfo());
 
     return NO_ERROR;
 }
@@ -739,6 +762,29 @@
     return err;
 }
 
+void Surface::querySupportedTimestampsLocked() const {
+    // mMutex must be locked when calling this method.
+
+    if (mQueriedSupportedTimestamps) {
+        return;
+    }
+    mQueriedSupportedTimestamps = true;
+
+    std::vector<FrameEvent> supportedFrameTimestamps;
+    status_t err = composerService()->getSupportedFrameTimestamps(
+            &supportedFrameTimestamps);
+
+    if (err != NO_ERROR) {
+        return;
+    }
+
+    for (auto sft : supportedFrameTimestamps) {
+        if (sft == FrameEvent::DISPLAY_PRESENT) {
+            mFrameTimestampsSupportsPresent = true;
+        }
+    }
+}
+
 int Surface::query(int what, int* value) const {
     ATRACE_CALL();
     ALOGV("Surface::query");
@@ -800,6 +846,11 @@
                         static_cast<int>(durationUs);
                 return NO_ERROR;
             }
+            case NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT: {
+                querySupportedTimestampsLocked();
+                *value = mFrameTimestampsSupportsPresent ? 1 : 0;
+                return NO_ERROR;
+            }
             case NATIVE_WINDOW_IS_VALID: {
                 *value = mGraphicBufferProducer != nullptr ? 1 : 0;
                 return NO_ERROR;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 56c7586..8c83843 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -149,6 +149,8 @@
             uint32_t w, uint32_t h);
     status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
             int32_t z);
+    status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+            const sp<IBinder>& relativeTo, int32_t z);
     status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
             uint32_t flags, uint32_t mask);
     status_t setTransparentRegionHint(
@@ -343,6 +345,20 @@
     return NO_ERROR;
 }
 
+status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client,
+        const sp<IBinder>& id, const sp<IBinder>& relativeTo,
+        int32_t z) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s) {
+        return BAD_INDEX;
+    }
+    s->what |= layer_state_t::eRelativeLayerChanged;
+    s->relativeLayerHandle = relativeTo;
+    s->z = z;
+    return NO_ERROR;
+}
+
 status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
         const sp<IBinder>& id, uint32_t flags,
         uint32_t mask) {
@@ -760,6 +776,11 @@
     return getComposer().setLayer(this, id, z);
 }
 
+status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id,
+        const sp<IBinder>& relativeTo, int32_t z) {
+    return getComposer().setRelativeLayer(this, id, relativeTo, z);
+}
+
 status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
     return getComposer().setFlags(this, id,
             layer_state_t::eLayerHidden,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 7a68f11..bf8a815 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -102,11 +102,19 @@
     if (err < 0) return err;
     return mClient->setLayerStack(mHandle, layerStack);
 }
+
 status_t SurfaceControl::setLayer(int32_t layer) {
     status_t err = validate();
     if (err < 0) return err;
     return mClient->setLayer(mHandle, layer);
 }
+
+status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) {
+    status_t err = validate();
+    if (err < 0) return err;
+    return mClient->setRelativeLayer(mHandle, relativeTo, layer);
+}
+
 status_t SurfaceControl::setPosition(float x, float y) {
     status_t err = validate();
     if (err < 0) return err;
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 55e6fbf..60c1277 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -1057,7 +1057,7 @@
 
     // Check no free buffers in dump
     String8 dumpString;
-    mConsumer->dumpState(dumpString, nullptr);
+    mConsumer->dumpState(String8{}, &dumpString);
 
     // Parse the dump to ensure that all buffer slots that are FREE also
     // have a null GraphicBuffer
@@ -1181,4 +1181,21 @@
     ASSERT_NE(nullptr, item.mGraphicBuffer.get());
 }
 
+TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    sp<IProducerListener> dummyListener(new DummyProducerListener);
+    ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
+    ASSERT_EQ(OK, mProducer->connect(
+            dummyListener, NATIVE_WINDOW_API_CPU, true, &output));
+    ASSERT_EQ(BAD_VALUE, mProducer->connect(
+            dummyListener, NATIVE_WINDOW_API_MEDIA, true, &output));
+
+    ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
+    ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
+    ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
+}
+
 } // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ce11486..08d6715 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -368,14 +368,15 @@
 public:
     ~FakeSurfaceComposer() override {}
 
+    void setSupportsPresent(bool supportsPresent) {
+        mSupportsPresent = supportsPresent;
+    }
+
     sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
     sp<ISurfaceComposerClient> createScopedConnection(
             const sp<IGraphicBufferProducer>& /* parent */) override {
         return nullptr;
     }
-    sp<IGraphicBufferAlloc> createGraphicBufferAlloc() override {
-        return nullptr;
-    }
     sp<IDisplayEventConnection> createDisplayEventConnection() override {
         return nullptr;
     }
@@ -391,6 +392,26 @@
             const sp<IGraphicBufferProducer>& /*surface*/) const override {
         return false;
     }
+
+    status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported)
+            const override {
+        *outSupported = {
+                FrameEvent::REQUESTED_PRESENT,
+                FrameEvent::ACQUIRE,
+                FrameEvent::LATCH,
+                FrameEvent::FIRST_REFRESH_START,
+                FrameEvent::LAST_REFRESH_START,
+                FrameEvent::GPU_COMPOSITION_DONE,
+                FrameEvent::DEQUEUE_READY,
+                FrameEvent::RELEASE
+        };
+        if (mSupportsPresent) {
+            outSupported->push_back(
+                        FrameEvent::DISPLAY_PRESENT);
+        }
+        return NO_ERROR;
+    }
+
     void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {}
     status_t getDisplayConfigs(const sp<IBinder>& /*display*/,
             Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
@@ -435,7 +456,6 @@
 
 private:
     bool mSupportsPresent{true};
-    bool mSupportsRetire{true};
 };
 
 class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
@@ -864,6 +884,28 @@
     EXPECT_EQ(4, mFakeConsumer->mGetFrameTimestampsCount);
 }
 
+TEST_F(GetFrameTimestampsTest, QueryPresentSupported) {
+    bool displayPresentSupported = true;
+    mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+
+    // Verify supported bits are forwarded.
+    int supportsPresent = -1;
+    mWindow.get()->query(mWindow.get(),
+            NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+    EXPECT_EQ(displayPresentSupported, supportsPresent);
+}
+
+TEST_F(GetFrameTimestampsTest, QueryPresentNotSupported) {
+    bool displayPresentSupported = false;
+    mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+
+    // Verify supported bits are forwarded.
+    int supportsPresent = -1;
+    mWindow.get()->query(mWindow.get(),
+            NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+    EXPECT_EQ(displayPresentSupported, supportsPresent);
+}
+
 TEST_F(GetFrameTimestampsTest, SnapToNextTickBasic) {
     nsecs_t phase = 4000;
     nsecs_t interval = 1000;
@@ -1139,8 +1181,8 @@
     EXPECT_EQ(mFrames[1].mRefreshes[0].kGpuCompositionDoneTime,
             outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
-    EXPECT_EQ(0, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 }
 
 // This test verifies the acquire fence recorded by the consumer is not sent
@@ -1163,7 +1205,7 @@
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
-    EXPECT_EQ(0, outAcquireTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
 
     // Signal acquire fences. Verify a sync call still isn't necessary.
     mFrames[0].signalQueueFences();
@@ -1192,7 +1234,7 @@
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
-    EXPECT_EQ(0, outAcquireTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
 
     // Signal acquire fences. Verify a sync call still isn't necessary.
     mFrames[1].signalQueueFences();
@@ -1228,8 +1270,8 @@
     // Verify a request for no timestamps doesn't result in a sync call.
     int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
     int result = native_window_get_frame_timestamps(mWindow.get(), fId2,
-            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-            nullptr, nullptr, nullptr);
+            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+            nullptr, nullptr);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
 }
@@ -1265,10 +1307,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Verify available timestamps are correct for frame 1 again, before any
     // fence has been signaled.
@@ -1283,10 +1325,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Signal the fences for frame 1.
     mFrames[0].signalRefreshFences();
@@ -1342,10 +1384,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Signal the fences for frame 1.
     mFrames[0].signalRefreshFences();
@@ -1363,7 +1405,7 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
     EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
@@ -1371,7 +1413,7 @@
 
 // This test verifies that if the certain timestamps can't possibly exist for
 // the most recent frame, then a sync call is not done.
-TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) {
+TEST_F(GetFrameTimestampsTest, NoReleaseNoSync) {
     enableFrameTimestamps();
 
     // Dequeue and queue frame 1.
@@ -1401,10 +1443,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     mFrames[0].signalRefreshFences();
     mFrames[0].signalReleaseFences();
@@ -1425,10 +1467,33 @@
     EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
-    EXPECT_EQ(0, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
+}
+
+// This test verifies there are no sync calls for present times
+// when they aren't supported and that an error is returned.
+
+TEST_F(GetFrameTimestampsTest, PresentUnsupportedNoSync) {
+    enableFrameTimestamps();
+    mSurface->mFakeSurfaceComposer->setSupportsPresent(false);
+
+    // Dequeue and queue frame 1.
+    const uint64_t fId1 = getNextFrameId();
+    dequeueAndQueue(0);
+
+    // Verify a query for the Present times do not trigger a sync call if they
+    // are not supported.
+    resetTimestamps();
+    int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+    int result = native_window_get_frame_timestamps(mWindow.get(), fId1,
+            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+            &outDisplayPresentTime, nullptr, nullptr);
+    EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+    EXPECT_EQ(BAD_VALUE, result);
+    EXPECT_EQ(-1, outDisplayPresentTime);
 }
 
 }
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp
index 438d3f5..5d7f660 100644
--- a/libs/hwc2on1adapter/Android.bp
+++ b/libs/hwc2on1adapter/Android.bp
@@ -14,6 +14,7 @@
 
 cc_library_shared {
     name: "libhwc2on1adapter",
+    vendor_available: true,
 
     clang: true,
     cppflags: [
diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
index e35bfc9..8c6ef69 100644
--- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -2246,6 +2246,11 @@
             mHwc1SupportsBackgroundColor = true;
         }
     }
+
+    // Some devices might have HWC1 retire fences that accurately emulate
+    // HWC2 present fences when they are deferred, but it's not very reliable.
+    // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices.
+    mCapabilities.insert(Capability::PresentFenceIsNotReliable);
 }
 
 HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) {
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index a38b4dc..e2647be 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "AHardwareBuffer"
 
-#include <android/hardware_buffer.h>
+#include <vndk/hardware_buffer.h>
 
 #include <errno.h>
 #include <sys/socket.h>
@@ -33,7 +33,7 @@
 #include <private/android/AHardwareBufferHelpers.h>
 
 
-static constexpr int kDataBufferSize = 64 * sizeof(int);  // 64 ints
+static constexpr int kFdBufferSize = 128 * sizeof(int);  // 128 ints
 
 using namespace android;
 
@@ -60,9 +60,10 @@
     uint64_t consumerUsage = 0;
     AHardwareBuffer_convertToGrallocUsageBits(&producerUsage, &consumerUsage, desc->usage0,
             desc->usage1);
+    uint32_t usage = android_convertGralloc1To0Usage(producerUsage, consumerUsage);
 
     sp<GraphicBuffer> gbuffer(new GraphicBuffer(
-            desc->width, desc->height, format, desc->layers, producerUsage, consumerUsage,
+            desc->width, desc->height, format, desc->layers, usage,
             std::string("AHardwareBuffer pid [") + std::to_string(getpid()) + "]"));
 
     status_t err = gbuffer->initCheck();
@@ -70,7 +71,7 @@
         if (err == NO_MEMORY) {
             GraphicBuffer::dumpAllocationsToSystemLog();
         }
-        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
+        ALOGE("GraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
                 desc->width, desc->height, desc->layers, strerror(-err), gbuffer->handle);
         return err;
     }
@@ -169,7 +170,7 @@
     iov[0].iov_base = data.get();
     iov[0].iov_len = flattenedSize;
 
-    char buf[CMSG_SPACE(kDataBufferSize)];
+    char buf[CMSG_SPACE(kFdBufferSize)];
     struct msghdr msg = {
             .msg_control = buf,
             .msg_controllen = sizeof(buf),
@@ -197,11 +198,13 @@
 int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer) {
     if (!outBuffer) return BAD_VALUE;
 
-    char dataBuf[CMSG_SPACE(kDataBufferSize)];
-    char fdBuf[CMSG_SPACE(kDataBufferSize)];
+    static constexpr int kMessageBufferSize = 4096 * sizeof(int);
+
+    std::unique_ptr<char[]> dataBuf(new char[kMessageBufferSize]);
+    char fdBuf[CMSG_SPACE(kFdBufferSize)];
     struct iovec iov[1];
-    iov[0].iov_base = dataBuf;
-    iov[0].iov_len = sizeof(dataBuf);
+    iov[0].iov_base = dataBuf.get();
+    iov[0].iov_len = kMessageBufferSize;
 
     struct msghdr msg = {
             .msg_control = fdBuf,
@@ -259,7 +262,12 @@
     return NO_ERROR;
 }
 
-const struct native_handle* AHardwareBuffer_getNativeHandle(
+
+// ----------------------------------------------------------------------------
+// VNDK functions
+// ----------------------------------------------------------------------------
+
+const native_handle_t* AHardwareBuffer_getNativeHandle(
         const AHardwareBuffer* buffer) {
     if (!buffer) return nullptr;
     const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
@@ -351,8 +359,8 @@
         case HAL_PIXEL_FORMAT_RGBX_8888:    return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
         case HAL_PIXEL_FORMAT_RGB_565:      return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
         case HAL_PIXEL_FORMAT_RGB_888:      return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
-        case HAL_PIXEL_FORMAT_RGBA_FP16:    return AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT;
-        case HAL_PIXEL_FORMAT_RGBA_1010102: return AHARDWAREBUFFER_FORMAT_A2R10G10B10_UNORM_PACK32;
+        case HAL_PIXEL_FORMAT_RGBA_FP16:    return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
+        case HAL_PIXEL_FORMAT_RGBA_1010102: return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
         case HAL_PIXEL_FORMAT_BLOB:         return AHARDWAREBUFFER_FORMAT_BLOB;
         default:ALOGE("Unknown pixel format %u", format);
             return 0;
@@ -365,8 +373,8 @@
         case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:         return HAL_PIXEL_FORMAT_RGBX_8888;
         case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:           return HAL_PIXEL_FORMAT_RGB_565;
         case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:           return HAL_PIXEL_FORMAT_RGB_888;
-        case AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT:    return HAL_PIXEL_FORMAT_RGBA_FP16;
-        case AHARDWAREBUFFER_FORMAT_A2R10G10B10_UNORM_PACK32: return HAL_PIXEL_FORMAT_RGBA_1010102;
+        case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:     return HAL_PIXEL_FORMAT_RGBA_FP16;
+        case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:      return HAL_PIXEL_FORMAT_RGBA_1010102;
         case AHARDWAREBUFFER_FORMAT_BLOB:                   return HAL_PIXEL_FORMAT_BLOB;
         default:ALOGE("Unknown AHardwareBuffer format %u", format);
             return 0;
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 90fb4b6..6c8221d 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -21,7 +21,7 @@
 }
 
 ndk_library {
-    name: "libnativewindow.ndk",
+    name: "libnativewindow",
     symbol_file: "libnativewindow.map.txt",
 
     // Android O
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index e5b6853..f5657ff 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -66,14 +66,14 @@
      *   Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT
      *   OpenGL ES: GL_RGBA16F
      */
-    AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT      = 0x16,
+    AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT       = 0x16,
 
     /**
      * Corresponding formats:
-     *   Vulkan: VK_FORMAT_A2R10G10B10_UNORM_PACK32
+     *   Vulkan: VK_FORMAT_A2B10G10R10_UNORM_PACK32
      *   OpenGL ES: GL_RGB10_A2
      */
-    AHARDWAREBUFFER_FORMAT_A2R10G10B10_UNORM_PACK32 = 0x2b,
+    AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM        = 0x2b,
 
     /**
      * An opaque binary blob format that must have height 1, with width equal to
@@ -252,12 +252,6 @@
  */
 int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer);
 
-// ----------------------------------------------------------------------------
-// Everything below here is part of the public NDK API, but is intended only
-// for use by device-specific graphics drivers.
-struct native_handle;
-const struct native_handle* AHardwareBuffer_getNativeHandle(const AHardwareBuffer* buffer);
-
 __END_DECLS
 
 #endif // ANDROID_HARDWARE_BUFFER_H
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 63d1ad1..fb67a51 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -186,6 +186,12 @@
      * if it is safe (i.e. no crash will occur) to call any method on it.
      */
     NATIVE_WINDOW_IS_VALID = 17,
+
+    /*
+     * Returns 1 if NATIVE_WINDOW_GET_FRAME_TIMESTAMPS will return display
+     * present info, 0 if it won't.
+     */
+    NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT = 18,
 };
 
 /* Valid operations for the (*perform)() hook.
@@ -305,6 +311,14 @@
  */
 static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
 
+/* parameter for NATIVE_WINDOW_GET_FRAME_TIMESTAMPS
+ *
+ * Special timestamp value to indicate the timestamps aren't yet known or
+ * that they are invalid.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_PENDING = -2;
+static const int64_t NATIVE_WINDOW_TIMESTAMP_INVALID = -1;
+
 struct ANativeWindow
 {
 #ifdef __cplusplus
diff --git a/libs/nativewindow/include/vndk/hardware_buffer.h b/libs/nativewindow/include/vndk/hardware_buffer.h
new file mode 100644
index 0000000..dc2dcbe
--- /dev/null
+++ b/libs/nativewindow/include/vndk/hardware_buffer.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VNDK_NATIVEWINDOW_AHARDWAREBUFFER_H
+#define ANDROID_VNDK_NATIVEWINDOW_AHARDWAREBUFFER_H
+
+// vndk is a superset of the NDK
+#include <android/hardware_buffer.h>
+
+#include <cutils/native_handle.h>
+
+__BEGIN_DECLS
+
+const native_handle_t* AHardwareBuffer_getNativeHandle(const AHardwareBuffer* buffer);
+
+__END_DECLS
+
+#endif /* ANDROID_VNDK_NATIVEWINDOW_AHARDWAREBUFFER_H */
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index b29c888..b1d1a72 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -4,7 +4,6 @@
     AHardwareBuffer_allocate;
     AHardwareBuffer_describe;
     AHardwareBuffer_fromHardwareBuffer;
-    AHardwareBuffer_getNativeHandle;
     AHardwareBuffer_lock;
     AHardwareBuffer_recvHandleFromUnixSocket;
     AHardwareBuffer_release;
diff --git a/libs/nativewindow/tests/c_compatibility.c b/libs/nativewindow/tests/c_compatibility.c
index a0dfdf9..befd88f 100644
--- a/libs/nativewindow/tests/c_compatibility.c
+++ b/libs/nativewindow/tests/c_compatibility.c
@@ -16,6 +16,7 @@
 
 #include <android/hardware_buffer.h>
 #include <android/native_window.h>
+#include <vndk/hardware_buffer.h>
 #include <vndk/window.h>
 
 // this checks that all these headers are C-compatible
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 310d25e..5ccf178 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -49,10 +49,7 @@
         "Fence.cpp",
         "FenceTime.cpp",
         "FrameStats.cpp",
-        "Gralloc1.cpp",
-        "Gralloc1On0Adapter.cpp",
-        "GrallocAllocator.cpp",
-        "GrallocMapper.cpp",
+        "Gralloc2.cpp",
         "GraphicBuffer.cpp",
         "GraphicBufferAllocator.cpp",
         "GraphicBufferMapper.cpp",
diff --git a/libs/ui/Gralloc1.cpp b/libs/ui/Gralloc1.cpp
deleted file mode 100644
index 64a8b40..0000000
--- a/libs/ui/Gralloc1.cpp
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-
-#include <ui/Gralloc1.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/Gralloc1On0Adapter.h>
-
-#include <vector>
-
-#undef LOG_TAG
-#define LOG_TAG GRALLOC1_LOG_TAG
-
-namespace android {
-
-namespace Gralloc1 {
-
-Descriptor::~Descriptor()
-{
-    int32_t intError = mShimDevice.mFunctions.destroyDescriptor(
-            mShimDevice.mDevice, mDeviceId);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGE("destroyDescriptor failed: %d", intError);
-    }
-}
-
-gralloc1_error_t Descriptor::setDimensions(uint32_t width, uint32_t height)
-{
-    int32_t intError = mShimDevice.mFunctions.setDimensions(mShimDevice.mDevice,
-            mDeviceId, width, height);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error != GRALLOC1_ERROR_NONE) {
-        return error;
-    }
-    mWidth = width;
-    mHeight = height;
-    return error;
-}
-
-template <typename ApiType>
-struct Setter {
-    typedef int32_t (*Type)(gralloc1_device_t*, gralloc1_buffer_descriptor_t,
-            ApiType);
-};
-
-template <typename ApiType, typename ValueType>
-static inline gralloc1_error_t setHelper(
-        typename Setter<ApiType>::Type setter, gralloc1_device_t* device,
-        gralloc1_buffer_descriptor_t id, ValueType newValue,
-        ValueType* cacheVariable)
-{
-    int32_t intError = setter(device, id, static_cast<ApiType>(newValue));
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error != GRALLOC1_ERROR_NONE) {
-        return error;
-    }
-    *cacheVariable = newValue;
-    return error;
-}
-
-gralloc1_error_t Descriptor::setFormat(android_pixel_format_t format)
-{
-    return setHelper<int32_t>(mShimDevice.mFunctions.setFormat.pfn,
-            mShimDevice.mDevice, mDeviceId, format, &mFormat);
-}
-
-gralloc1_error_t Descriptor::setLayerCount(uint32_t layerCount)
-{
-    if (mShimDevice.hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
-        return setHelper<uint32_t>(mShimDevice.mFunctions.setLayerCount.pfn,
-                mShimDevice.mDevice, mDeviceId, layerCount, &mLayerCount);
-    } else {
-        // Layered buffers are not supported on this device.
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-}
-
-gralloc1_error_t Descriptor::setProducerUsage(gralloc1_producer_usage_t usage)
-{
-    return setHelper<uint64_t>(mShimDevice.mFunctions.setProducerUsage.pfn,
-            mShimDevice.mDevice, mDeviceId, usage, &mProducerUsage);
-}
-
-gralloc1_error_t Descriptor::setConsumerUsage(gralloc1_consumer_usage_t usage)
-{
-    return setHelper<uint64_t>(mShimDevice.mFunctions.setConsumerUsage.pfn,
-            mShimDevice.mDevice, mDeviceId, usage, &mConsumerUsage);
-}
-
-Device::Device(gralloc1_device_t* device)
-  : mDevice(device),
-    mCapabilities(loadCapabilities()),
-    mFunctions()
-{
-    if (!loadFunctions()) {
-        ALOGE("Failed to load a required function, aborting");
-        abort();
-    }
-}
-
-bool Device::hasCapability(gralloc1_capability_t capability) const
-{
-    return mCapabilities.count(capability) > 0;
-}
-
-std::string Device::dump()
-{
-    uint32_t length = 0;
-    mFunctions.dump(mDevice, &length, nullptr);
-
-    std::vector<char> output;
-    output.resize(length);
-    mFunctions.dump(mDevice, &length, output.data());
-
-    return std::string(output.cbegin(), output.cend());
-}
-
-std::shared_ptr<Descriptor> Device::createDescriptor()
-{
-    gralloc1_buffer_descriptor_t descriptorId;
-    int32_t intError = mFunctions.createDescriptor(mDevice, &descriptorId);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error != GRALLOC1_ERROR_NONE) {
-        return nullptr;
-    }
-    auto descriptor = std::make_shared<Descriptor>(*this, descriptorId);
-    return descriptor;
-}
-
-static inline bool allocationSucceded(gralloc1_error_t error)
-{
-    return error == GRALLOC1_ERROR_NONE || error == GRALLOC1_ERROR_NOT_SHARED;
-}
-
-gralloc1_error_t Device::allocate(
-        const std::vector<std::shared_ptr<const Descriptor>>& descriptors,
-        std::vector<buffer_handle_t>* outBuffers)
-{
-    if (mFunctions.allocate.pfn == nullptr) {
-        // Allocation is not supported on this device
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-
-    std::vector<gralloc1_buffer_descriptor_t> deviceIds;
-    for (const auto& descriptor : descriptors) {
-        deviceIds.emplace_back(descriptor->getDeviceId());
-    }
-
-    std::vector<buffer_handle_t> buffers(descriptors.size());
-    int32_t intError = mFunctions.allocate(mDevice,
-            static_cast<uint32_t>(descriptors.size()), deviceIds.data(),
-            buffers.data());
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (allocationSucceded(error)) {
-        *outBuffers = std::move(buffers);
-    }
-
-    return error;
-}
-
-gralloc1_error_t Device::allocate(
-        const std::shared_ptr<const Descriptor>& descriptor,
-        gralloc1_backing_store_t id, buffer_handle_t* outBuffer)
-{
-    gralloc1_error_t error = GRALLOC1_ERROR_NONE;
-
-    if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-        buffer_handle_t buffer = nullptr;
-        int32_t intError = mFunctions.allocateWithId(mDevice,
-                descriptor->getDeviceId(), id, &buffer);
-        error = static_cast<gralloc1_error_t>(intError);
-        if (allocationSucceded(error)) {
-            *outBuffer = buffer;
-        }
-    } else {
-        std::vector<std::shared_ptr<const Descriptor>> descriptors;
-        descriptors.emplace_back(descriptor);
-        std::vector<buffer_handle_t> buffers;
-        error = allocate(descriptors, &buffers);
-        if (allocationSucceded(error)) {
-            *outBuffer = buffers[0];
-        }
-    }
-
-    return error;
-}
-
-gralloc1_error_t Device::retain(buffer_handle_t buffer)
-{
-    int32_t intError = mFunctions.retain(mDevice, buffer);
-    return static_cast<gralloc1_error_t>(intError);
-}
-
-gralloc1_error_t Device::retain(const GraphicBuffer* buffer)
-{
-    if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-        return mFunctions.retainGraphicBuffer(mDevice, buffer);
-    } else {
-        return retain(buffer->getNativeBuffer()->handle);
-    }
-}
-
-gralloc1_error_t Device::release(buffer_handle_t buffer)
-{
-    int32_t intError = mFunctions.release(mDevice, buffer);
-    return static_cast<gralloc1_error_t>(intError);
-}
-
-gralloc1_error_t Device::getDimensions(buffer_handle_t buffer,
-        uint32_t* outWidth, uint32_t* outHeight)
-{
-    uint32_t width = 0;
-    uint32_t height = 0;
-    int32_t intError = mFunctions.getDimensions(mDevice, buffer, &width,
-            &height);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outWidth = width;
-        *outHeight = height;
-    }
-    return error;
-}
-
-gralloc1_error_t Device::getFormat(buffer_handle_t buffer,
-        int32_t* outFormat)
-{
-    int32_t format = 0;
-    int32_t intError = mFunctions.getFormat(mDevice, buffer, &format);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outFormat = format;
-    }
-    return error;
-}
-
-gralloc1_error_t Device::getLayerCount(buffer_handle_t buffer,
-        uint32_t* outLayerCount)
-{
-    if (hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
-        uint32_t layerCount = 0;
-        int32_t intError = mFunctions.getLayerCount(mDevice, buffer,
-                &layerCount);
-        auto error = static_cast<gralloc1_error_t>(intError);
-        if (error == GRALLOC1_ERROR_NONE) {
-            *outLayerCount = layerCount;
-        }
-        return error;
-    } else {
-        // Layered buffers are not supported on this device.
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-}
-
-gralloc1_error_t Device::getProducerUsage(buffer_handle_t buffer,
-        uint64_t* outProducerUsage)
-{
-    uint64_t usage = 0;
-    int32_t intError = mFunctions.getProducerUsage(mDevice, buffer, &usage);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outProducerUsage = usage;
-    }
-    return error;
-}
-
-gralloc1_error_t Device::getConsumerUsage(buffer_handle_t buffer,
-        uint64_t* outConsumerUsage)
-{
-    uint64_t usage = 0;
-    int32_t intError = mFunctions.getConsumerUsage(mDevice, buffer, &usage);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outConsumerUsage = usage;
-    }
-    return error;
-}
-
-gralloc1_error_t Device::getBackingStore(buffer_handle_t buffer,
-        uint64_t* outBackingStore)
-{
-    uint64_t store = 0;
-    int32_t intError = mFunctions.getBackingStore(mDevice, buffer, &store);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outBackingStore = store;
-    }
-    return error;
-}
-
-gralloc1_error_t Device::getStride(buffer_handle_t buffer,
-        uint32_t* outStride)
-{
-    uint32_t stride = 0;
-    int32_t intError = mFunctions.getStride(mDevice, buffer, &stride);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outStride = stride;
-    }
-    return error;
-}
-
-gralloc1_error_t Device::getNumFlexPlanes(buffer_handle_t buffer,
-        uint32_t* outNumPlanes)
-{
-    uint32_t numPlanes = 0;
-    int32_t intError = mFunctions.getNumFlexPlanes(mDevice, buffer, &numPlanes);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outNumPlanes = numPlanes;
-    }
-    return error;
-}
-
-gralloc1_error_t Device::lock(buffer_handle_t buffer,
-        gralloc1_producer_usage_t producerUsage,
-        gralloc1_consumer_usage_t consumerUsage,
-        const gralloc1_rect_t* accessRegion, void** outData,
-        const sp<Fence>& acquireFence)
-{
-    ALOGV("Calling lock(%p)", buffer);
-    return lockHelper(mFunctions.lock, buffer, producerUsage,
-            consumerUsage, accessRegion, outData, acquireFence);
-}
-
-gralloc1_error_t Device::lockFlex(buffer_handle_t buffer,
-        gralloc1_producer_usage_t producerUsage,
-        gralloc1_consumer_usage_t consumerUsage,
-        const gralloc1_rect_t* accessRegion,
-        struct android_flex_layout* outData,
-        const sp<Fence>& acquireFence)
-{
-    ALOGV("Calling lockFlex(%p)", buffer);
-    return lockHelper(mFunctions.lockFlex, buffer, producerUsage,
-            consumerUsage, accessRegion, outData, acquireFence);
-}
-
-gralloc1_error_t Device::lockYCbCr(buffer_handle_t buffer,
-        gralloc1_producer_usage_t producerUsage,
-        gralloc1_consumer_usage_t consumerUsage,
-        const gralloc1_rect_t* accessRegion,
-        struct android_ycbcr* outData,
-        const sp<Fence>& acquireFence)
-{
-    ALOGV("Calling lockYCbCr(%p)", buffer);
-    return lockHelper(mFunctions.lockYCbCr, buffer, producerUsage,
-            consumerUsage, accessRegion, outData, acquireFence);
-}
-
-gralloc1_error_t Device::unlock(buffer_handle_t buffer, sp<Fence>* outFence)
-{
-    int32_t fenceFd = -1;
-    int32_t intError = mFunctions.unlock(mDevice, buffer, &fenceFd);
-    auto error = static_cast<gralloc1_error_t>(intError);
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outFence = new Fence(fenceFd);
-    }
-    return error;
-}
-
-std::unordered_set<gralloc1_capability_t> Device::loadCapabilities()
-{
-    std::vector<int32_t> intCapabilities;
-    uint32_t numCapabilities = 0;
-    mDevice->getCapabilities(mDevice, &numCapabilities, nullptr);
-
-    intCapabilities.resize(numCapabilities);
-    mDevice->getCapabilities(mDevice, &numCapabilities, intCapabilities.data());
-
-    std::unordered_set<gralloc1_capability_t> capabilities;
-    for (const auto intCapability : intCapabilities) {
-        capabilities.emplace(static_cast<gralloc1_capability_t>(intCapability));
-    }
-    return capabilities;
-}
-
-bool Device::loadFunctions()
-{
-    // Functions which must always be present
-    if (!mFunctions.dump.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.createDescriptor.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.destroyDescriptor.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.setConsumerUsage.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.setDimensions.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.setFormat.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.setProducerUsage.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.getBackingStore.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.getConsumerUsage.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.getDimensions.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.getFormat.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.getProducerUsage.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.getStride.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.retain.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.release.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.getNumFlexPlanes.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.lock.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.lockFlex.load(mDevice, true)) {
-        return false;
-    }
-    if (!mFunctions.unlock.load(mDevice, true)) {
-        return false;
-    }
-
-    if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-        // These should always be present on the adapter
-        if (!mFunctions.retainGraphicBuffer.load(mDevice, true)) {
-            return false;
-        }
-        if (!mFunctions.lockYCbCr.load(mDevice, true)) {
-            return false;
-        }
-
-        // allocateWithId may not be present if we're only able to map in this
-        // process
-        mFunctions.allocateWithId.load(mDevice, false);
-    } else {
-        // allocate may not be present if we're only able to map in this process
-        mFunctions.allocate.load(mDevice, false);
-    }
-
-    if (hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
-        if (!mFunctions.setLayerCount.load(mDevice, true)) {
-            return false;
-        }
-        if (!mFunctions.getLayerCount.load(mDevice, true)) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-std::unique_ptr<Gralloc1On0Adapter> Loader::mAdapter = nullptr;
-
-Loader::Loader()
-  : mDevice(nullptr)
-{
-    hw_module_t const* module;
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    uint8_t majorVersion = (module->module_api_version >> 8) & 0xFF;
-    uint8_t minorVersion = module->module_api_version & 0xFF;
-    gralloc1_device_t* device = nullptr;
-    if (majorVersion == 1) {
-        gralloc1_open(module, &device);
-    } else {
-        if (!mAdapter) {
-            mAdapter = std::make_unique<Gralloc1On0Adapter>(module);
-        }
-        device = mAdapter->getDevice();
-    }
-    mDevice = std::make_unique<Gralloc1::Device>(device);
-}
-
-Loader::~Loader() {}
-
-std::unique_ptr<Device> Loader::getDevice()
-{
-    return std::move(mDevice);
-}
-
-} // namespace android::Gralloc1
-
-} // namespace android
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
deleted file mode 100644
index bd7c6a1..0000000
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "Gralloc1On0Adapter"
-//#define LOG_NDEBUG 0
-
-#include <ui/Gralloc1On0Adapter.h>
-
-#include <grallocusage/GrallocUsageConversion.h>
-
-#include <hardware/gralloc.h>
-
-#include <ui/GraphicBuffer.h>
-#include <ui/Gralloc1.h>
-
-#include <utils/Log.h>
-
-#include <inttypes.h>
-
-template <typename PFN, typename T>
-static gralloc1_function_pointer_t asFP(T function)
-{
-    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
-    return reinterpret_cast<gralloc1_function_pointer_t>(function);
-}
-
-namespace android {
-
-Gralloc1On0Adapter::Gralloc1On0Adapter(const hw_module_t* module)
-  : mModule(reinterpret_cast<const gralloc_module_t*>(module)),
-    mMinorVersion(mModule->common.module_api_version & 0xFF),
-    mDevice(nullptr)
-{
-    ALOGV("Constructing");
-    getCapabilities = getCapabilitiesHook;
-    getFunction = getFunctionHook;
-    int error = ::gralloc_open(&(mModule->common), &mDevice);
-    if (error) {
-        ALOGE("Failed to open gralloc0 module: %d", error);
-    }
-    ALOGV("Opened gralloc0 device %p", mDevice);
-}
-
-Gralloc1On0Adapter::~Gralloc1On0Adapter()
-{
-    ALOGV("Destructing");
-    if (mDevice) {
-        ALOGV("Closing gralloc0 device %p", mDevice);
-        ::gralloc_close(mDevice);
-    }
-}
-
-void Gralloc1On0Adapter::doGetCapabilities(uint32_t* outCount,
-        int32_t* outCapabilities)
-{
-    if (outCapabilities == nullptr) {
-        *outCount = 1;
-        return;
-    }
-    if (*outCount >= 1) {
-        *outCapabilities = GRALLOC1_CAPABILITY_ON_ADAPTER;
-        *outCount = 1;
-    }
-}
-
-gralloc1_function_pointer_t Gralloc1On0Adapter::doGetFunction(
-        int32_t intDescriptor)
-{
-    constexpr auto lastDescriptor =
-            static_cast<int32_t>(GRALLOC1_LAST_ADAPTER_FUNCTION);
-    if (intDescriptor < 0 || intDescriptor > lastDescriptor) {
-        ALOGE("Invalid function descriptor");
-        return nullptr;
-    }
-
-    auto descriptor =
-            static_cast<gralloc1_function_descriptor_t>(intDescriptor);
-    switch (descriptor) {
-        case GRALLOC1_FUNCTION_DUMP:
-            return asFP<GRALLOC1_PFN_DUMP>(dumpHook);
-        case GRALLOC1_FUNCTION_CREATE_DESCRIPTOR:
-            return asFP<GRALLOC1_PFN_CREATE_DESCRIPTOR>(createDescriptorHook);
-        case GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR:
-            return asFP<GRALLOC1_PFN_DESTROY_DESCRIPTOR>(destroyDescriptorHook);
-        case GRALLOC1_FUNCTION_SET_CONSUMER_USAGE:
-            return asFP<GRALLOC1_PFN_SET_CONSUMER_USAGE>(setConsumerUsageHook);
-        case GRALLOC1_FUNCTION_SET_DIMENSIONS:
-            return asFP<GRALLOC1_PFN_SET_DIMENSIONS>(setDimensionsHook);
-        case GRALLOC1_FUNCTION_SET_FORMAT:
-            return asFP<GRALLOC1_PFN_SET_FORMAT>(setFormatHook);
-        case GRALLOC1_FUNCTION_SET_LAYER_COUNT:
-            return asFP<GRALLOC1_PFN_SET_LAYER_COUNT>(setLayerCountHook);
-        case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE:
-            return asFP<GRALLOC1_PFN_SET_PRODUCER_USAGE>(setProducerUsageHook);
-        case GRALLOC1_FUNCTION_GET_BACKING_STORE:
-            return asFP<GRALLOC1_PFN_GET_BACKING_STORE>(
-                    bufferHook<decltype(&Buffer::getBackingStore),
-                    &Buffer::getBackingStore, gralloc1_backing_store_t*>);
-        case GRALLOC1_FUNCTION_GET_CONSUMER_USAGE:
-            return asFP<GRALLOC1_PFN_GET_CONSUMER_USAGE>(getConsumerUsageHook);
-        case GRALLOC1_FUNCTION_GET_DIMENSIONS:
-            return asFP<GRALLOC1_PFN_GET_DIMENSIONS>(
-                    bufferHook<decltype(&Buffer::getDimensions),
-                    &Buffer::getDimensions, uint32_t*, uint32_t*>);
-        case GRALLOC1_FUNCTION_GET_FORMAT:
-            return asFP<GRALLOC1_PFN_GET_FORMAT>(
-                    bufferHook<decltype(&Buffer::getFormat),
-                    &Buffer::getFormat, int32_t*>);
-        case GRALLOC1_FUNCTION_GET_LAYER_COUNT:
-            return asFP<GRALLOC1_PFN_GET_LAYER_COUNT>(
-                    bufferHook<decltype(&Buffer::getLayerCount),
-                    &Buffer::getLayerCount, uint32_t*>);
-        case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE:
-            return asFP<GRALLOC1_PFN_GET_PRODUCER_USAGE>(getProducerUsageHook);
-        case GRALLOC1_FUNCTION_GET_STRIDE:
-            return asFP<GRALLOC1_PFN_GET_STRIDE>(
-                    bufferHook<decltype(&Buffer::getStride),
-                    &Buffer::getStride, uint32_t*>);
-        case GRALLOC1_FUNCTION_ALLOCATE:
-            // Not provided, since we'll use ALLOCATE_WITH_ID
-            return nullptr;
-        case GRALLOC1_FUNCTION_ALLOCATE_WITH_ID:
-            if (mDevice != nullptr) {
-                return asFP<GRALLOC1_PFN_ALLOCATE_WITH_ID>(allocateWithIdHook);
-            } else {
-                return nullptr;
-            }
-        case GRALLOC1_FUNCTION_RETAIN:
-            return asFP<GRALLOC1_PFN_RETAIN>(
-                    managementHook<&Gralloc1On0Adapter::retain>);
-        case GRALLOC1_FUNCTION_RELEASE:
-            return asFP<GRALLOC1_PFN_RELEASE>(
-                    managementHook<&Gralloc1On0Adapter::release>);
-        case GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER:
-            return asFP<GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER>(
-                    retainGraphicBufferHook);
-        case GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES:
-            return asFP<GRALLOC1_PFN_GET_NUM_FLEX_PLANES>(
-                    bufferHook<decltype(&Buffer::getNumFlexPlanes),
-                    &Buffer::getNumFlexPlanes, uint32_t*>);
-        case GRALLOC1_FUNCTION_LOCK:
-            return asFP<GRALLOC1_PFN_LOCK>(
-                    lockHook<void*, &Gralloc1On0Adapter::lock>);
-        case GRALLOC1_FUNCTION_LOCK_FLEX:
-            return asFP<GRALLOC1_PFN_LOCK_FLEX>(
-                    lockHook<struct android_flex_layout,
-                    &Gralloc1On0Adapter::lockFlex>);
-        case GRALLOC1_FUNCTION_LOCK_YCBCR:
-            return asFP<GRALLOC1_PFN_LOCK_YCBCR>(
-                    lockHook<struct android_ycbcr,
-                    &Gralloc1On0Adapter::lockYCbCr>);
-        case GRALLOC1_FUNCTION_UNLOCK:
-            return asFP<GRALLOC1_PFN_UNLOCK>(unlockHook);
-        case GRALLOC1_FUNCTION_INVALID:
-            ALOGE("Invalid function descriptor");
-            return nullptr;
-    }
-
-    ALOGE("Unknown function descriptor: %d", intDescriptor);
-    return nullptr;
-}
-
-void Gralloc1On0Adapter::dump(uint32_t* outSize, char* outBuffer)
-{
-    ALOGV("dump(%u (%p), %p", outSize ? *outSize : 0, outSize, outBuffer);
-
-    if (!mDevice->dump) {
-        // dump is optional on gralloc0 implementations
-        *outSize = 0;
-        return;
-    }
-
-    if (!outBuffer) {
-        constexpr int32_t BUFFER_LENGTH = 4096;
-        char buffer[BUFFER_LENGTH] = {};
-        mDevice->dump(mDevice, buffer, BUFFER_LENGTH);
-        buffer[BUFFER_LENGTH - 1] = 0; // Ensure the buffer is null-terminated
-        size_t actualLength = std::strlen(buffer);
-        mCachedDump.resize(actualLength);
-        std::copy_n(buffer, actualLength, mCachedDump.begin());
-        *outSize = static_cast<uint32_t>(actualLength);
-    } else {
-        *outSize = std::min(*outSize,
-                static_cast<uint32_t>(mCachedDump.size()));
-        outBuffer = std::copy_n(mCachedDump.cbegin(), *outSize, outBuffer);
-    }
-}
-
-gralloc1_error_t Gralloc1On0Adapter::createDescriptor(
-        gralloc1_buffer_descriptor_t* outDescriptor)
-{
-    auto descriptorId = sNextBufferDescriptorId++;
-    std::lock_guard<std::mutex> lock(mDescriptorMutex);
-    mDescriptors.emplace(descriptorId,
-            std::make_shared<Descriptor>(this, descriptorId));
-
-    ALOGV("Created descriptor %" PRIu64, descriptorId);
-
-    *outDescriptor = descriptorId;
-    return GRALLOC1_ERROR_NONE;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::destroyDescriptor(
-        gralloc1_buffer_descriptor_t descriptor)
-{
-    ALOGV("Destroying descriptor %" PRIu64, descriptor);
-
-    std::lock_guard<std::mutex> lock(mDescriptorMutex);
-    if (mDescriptors.count(descriptor) == 0) {
-        return GRALLOC1_ERROR_BAD_DESCRIPTOR;
-    }
-
-    mDescriptors.erase(descriptor);
-    return GRALLOC1_ERROR_NONE;
-}
-
-Gralloc1On0Adapter::Buffer::Buffer(buffer_handle_t handle,
-        gralloc1_backing_store_t store, const Descriptor& descriptor,
-        uint32_t stride, bool wasAllocated)
-  : mHandle(handle),
-    mReferenceCount(1),
-    mStore(store),
-    mDescriptor(descriptor),
-    mStride(stride),
-    mWasAllocated(wasAllocated) {}
-
-gralloc1_error_t Gralloc1On0Adapter::allocate(
-        const std::shared_ptr<Descriptor>& descriptor,
-        gralloc1_backing_store_t store,
-        buffer_handle_t* outBufferHandle)
-{
-    ALOGV("allocate(%" PRIu64 ", %#" PRIx64 ")", descriptor->id, store);
-
-    // If this function is being called, it's because we handed out its function
-    // pointer, which only occurs when mDevice has been loaded successfully and
-    // we are permitted to allocate
-
-    int usage = android_convertGralloc1To0Usage(descriptor->producerUsage,
-            descriptor->consumerUsage);
-    buffer_handle_t handle = nullptr;
-    int stride = 0;
-    ALOGV("Calling alloc(%p, %u, %u, %i, %u)", mDevice, descriptor->width,
-            descriptor->height, descriptor->format, usage);
-    auto error = mDevice->alloc(mDevice,
-            static_cast<int>(descriptor->width),
-            static_cast<int>(descriptor->height), descriptor->format,
-            usage, &handle, &stride);
-    if (error != 0) {
-        ALOGE("gralloc0 allocation failed: %d (%s)", error,
-                strerror(-error));
-        return GRALLOC1_ERROR_NO_RESOURCES;
-    }
-
-    *outBufferHandle = handle;
-    auto buffer = std::make_shared<Buffer>(handle, store, *descriptor, stride,
-            true);
-
-    std::lock_guard<std::mutex> lock(mBufferMutex);
-    mBuffers.emplace(handle, std::move(buffer));
-
-    return GRALLOC1_ERROR_NONE;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::allocateWithIdHook(
-        gralloc1_device_t* device, gralloc1_buffer_descriptor_t descriptorId,
-        gralloc1_backing_store_t store, buffer_handle_t* outBuffer)
-{
-    auto adapter = getAdapter(device);
-
-    auto descriptor = adapter->getDescriptor(descriptorId);
-    if (!descriptor) {
-        return GRALLOC1_ERROR_BAD_DESCRIPTOR;
-    }
-
-    buffer_handle_t bufferHandle = nullptr;
-    auto error = adapter->allocate(descriptor, store, &bufferHandle);
-    if (error != GRALLOC1_ERROR_NONE) {
-        return error;
-    }
-
-    *outBuffer = bufferHandle;
-    return error;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::retain(
-        const std::shared_ptr<Buffer>& buffer)
-{
-    std::lock_guard<std::mutex> lock(mBufferMutex);
-    buffer->retain();
-    return GRALLOC1_ERROR_NONE;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::release(
-        const std::shared_ptr<Buffer>& buffer)
-{
-    std::lock_guard<std::mutex> lock(mBufferMutex);
-    if (!buffer->release()) {
-        return GRALLOC1_ERROR_NONE;
-    }
-
-    buffer_handle_t handle = buffer->getHandle();
-    if (buffer->wasAllocated()) {
-        ALOGV("Calling free(%p)", handle);
-        int result = mDevice->free(mDevice, handle);
-        if (result != 0) {
-            ALOGE("gralloc0 free failed: %d", result);
-        }
-    } else {
-        ALOGV("Calling unregisterBuffer(%p)", handle);
-        int result = mModule->unregisterBuffer(mModule, handle);
-        if (result != 0) {
-            ALOGE("gralloc0 unregister failed: %d", result);
-        }
-    }
-
-    mBuffers.erase(handle);
-    return GRALLOC1_ERROR_NONE;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::retain(
-        const android::GraphicBuffer* graphicBuffer)
-{
-    ALOGV("retainGraphicBuffer(%p, %#" PRIx64 ")",
-            graphicBuffer->getNativeBuffer()->handle, graphicBuffer->getId());
-
-    buffer_handle_t handle = graphicBuffer->getNativeBuffer()->handle;
-    std::lock_guard<std::mutex> lock(mBufferMutex);
-    if (mBuffers.count(handle) != 0) {
-        mBuffers[handle]->retain();
-        return GRALLOC1_ERROR_NONE;
-    }
-
-    ALOGV("Calling registerBuffer(%p)", handle);
-    int result = mModule->registerBuffer(mModule, handle);
-    if (result != 0) {
-        ALOGE("gralloc0 register failed: %d", result);
-        return GRALLOC1_ERROR_NO_RESOURCES;
-    }
-
-    Descriptor descriptor{this, sNextBufferDescriptorId++};
-    descriptor.setDimensions(graphicBuffer->getWidth(),
-            graphicBuffer->getHeight());
-    descriptor.setFormat(graphicBuffer->getPixelFormat());
-    descriptor.setProducerUsage(
-            static_cast<gralloc1_producer_usage_t>(graphicBuffer->getUsage()));
-    descriptor.setConsumerUsage(
-            static_cast<gralloc1_consumer_usage_t>(graphicBuffer->getUsage()));
-    auto buffer = std::make_shared<Buffer>(handle,
-            static_cast<gralloc1_backing_store_t>(graphicBuffer->getId()),
-            descriptor, graphicBuffer->getStride(), false);
-    mBuffers.emplace(handle, std::move(buffer));
-    return GRALLOC1_ERROR_NONE;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::lock(
-        const std::shared_ptr<Buffer>& buffer,
-        gralloc1_producer_usage_t producerUsage,
-        gralloc1_consumer_usage_t consumerUsage,
-        const gralloc1_rect_t& accessRegion, void** outData,
-        const sp<Fence>& acquireFence)
-{
-    if (mMinorVersion >= 3) {
-        int result = mModule->lockAsync(mModule, buffer->getHandle(),
-                android_convertGralloc1To0Usage(producerUsage, consumerUsage),
-                accessRegion.left, accessRegion.top, accessRegion.width,
-                accessRegion.height, outData, acquireFence->dup());
-        if (result != 0) {
-            return GRALLOC1_ERROR_UNSUPPORTED;
-        }
-    } else {
-        acquireFence->waitForever("Gralloc1On0Adapter::lock");
-        int result = mModule->lock(mModule, buffer->getHandle(),
-                android_convertGralloc1To0Usage(producerUsage, consumerUsage),
-                accessRegion.left, accessRegion.top, accessRegion.width,
-                accessRegion.height, outData);
-        ALOGV("gralloc0 lock returned %d", result);
-        if (result != 0) {
-            return GRALLOC1_ERROR_UNSUPPORTED;
-        }
-    }
-    return GRALLOC1_ERROR_NONE;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::lockFlex(
-        const std::shared_ptr<Buffer>& /*buffer*/,
-        gralloc1_producer_usage_t /*producerUsage*/,
-        gralloc1_consumer_usage_t /*consumerUsage*/,
-        const gralloc1_rect_t& /*accessRegion*/,
-        struct android_flex_layout* /*outData*/,
-        const sp<Fence>& /*acquireFence*/)
-{
-    // TODO
-    return GRALLOC1_ERROR_UNSUPPORTED;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::lockYCbCr(
-        const std::shared_ptr<Buffer>& buffer,
-        gralloc1_producer_usage_t producerUsage,
-        gralloc1_consumer_usage_t consumerUsage,
-        const gralloc1_rect_t& accessRegion, struct android_ycbcr* outData,
-        const sp<Fence>& acquireFence)
-{
-    if (mMinorVersion >= 3 && mModule->lockAsync_ycbcr) {
-        int result = mModule->lockAsync_ycbcr(mModule, buffer->getHandle(),
-                android_convertGralloc1To0Usage(producerUsage, consumerUsage),
-                accessRegion.left, accessRegion.top, accessRegion.width,
-                accessRegion.height, outData, acquireFence->dup());
-        if (result != 0) {
-            return GRALLOC1_ERROR_UNSUPPORTED;
-        }
-    } else if (mModule->lock_ycbcr) {
-        acquireFence->waitForever("Gralloc1On0Adapter::lockYCbCr");
-        int result = mModule->lock_ycbcr(mModule, buffer->getHandle(),
-                android_convertGralloc1To0Usage(producerUsage, consumerUsage),
-                accessRegion.left, accessRegion.top, accessRegion.width,
-                accessRegion.height, outData);
-        ALOGV("gralloc0 lockYCbCr returned %d", result);
-        if (result != 0) {
-            return GRALLOC1_ERROR_UNSUPPORTED;
-        }
-    } else {
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-
-    return GRALLOC1_ERROR_NONE;
-}
-
-gralloc1_error_t Gralloc1On0Adapter::unlock(
-        const std::shared_ptr<Buffer>& buffer,
-        sp<Fence>* outReleaseFence)
-{
-    if (mMinorVersion >= 3) {
-        int fenceFd = -1;
-        int result = mModule->unlockAsync(mModule, buffer->getHandle(),
-                &fenceFd);
-        if (result != 0) {
-            close(fenceFd);
-            ALOGE("gralloc0 unlockAsync failed: %d", result);
-        } else {
-            *outReleaseFence = new Fence(fenceFd);
-        }
-    } else {
-        int result = mModule->unlock(mModule, buffer->getHandle());
-        if (result != 0) {
-            ALOGE("gralloc0 unlock failed: %d", result);
-        }
-    }
-    return GRALLOC1_ERROR_NONE;
-}
-
-std::shared_ptr<Gralloc1On0Adapter::Descriptor>
-Gralloc1On0Adapter::getDescriptor(gralloc1_buffer_descriptor_t descriptorId)
-{
-    std::lock_guard<std::mutex> lock(mDescriptorMutex);
-    if (mDescriptors.count(descriptorId) == 0) {
-        return nullptr;
-    }
-
-    return mDescriptors[descriptorId];
-}
-
-std::shared_ptr<Gralloc1On0Adapter::Buffer> Gralloc1On0Adapter::getBuffer(
-        buffer_handle_t bufferHandle)
-{
-    std::lock_guard<std::mutex> lock(mBufferMutex);
-    if (mBuffers.count(bufferHandle) == 0) {
-        return nullptr;
-    }
-
-    return mBuffers[bufferHandle];
-}
-
-std::atomic<gralloc1_buffer_descriptor_t>
-        Gralloc1On0Adapter::sNextBufferDescriptorId(1);
-
-} // namespace android
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
new file mode 100644
index 0000000..f8d9401
--- /dev/null
+++ b/libs/ui/Gralloc2.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Gralloc2"
+
+#include <ui/Gralloc2.h>
+
+#include <log/log.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
+#include <sync/sync.h>
+#pragma clang diagnostic pop
+
+namespace android {
+
+namespace Gralloc2 {
+
+static constexpr Error kTransactionError = Error::NO_RESOURCES;
+
+Mapper::Mapper()
+{
+    mMapper = IMapper::getService();
+    if (mMapper == nullptr || mMapper->isRemote()) {
+        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
+    }
+}
+
+Error Mapper::createDescriptor(
+        const IMapper::BufferDescriptorInfo& descriptorInfo,
+        BufferDescriptor* outDescriptor) const
+{
+    Error error;
+    auto ret = mMapper->createDescriptor(descriptorInfo,
+            [&](const auto& tmpError, const auto& tmpDescriptor)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outDescriptor = tmpDescriptor;
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
+        buffer_handle_t* outBufferHandle) const
+{
+    Error error;
+    auto ret = mMapper->importBuffer(rawHandle,
+            [&](const auto& tmpError, const auto& tmpBuffer)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    auto ret = mMapper->freeBuffer(buffer);
+
+    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+    ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
+            buffer, error);
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+        const IMapper::Rect& accessRegion,
+        int acquireFence, void** outData) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    // put acquireFence in a hidl_handle
+    hardware::hidl_handle acquireFenceHandle;
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error;
+    auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpData)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outData = tmpData;
+            });
+
+    // we own acquireFence even on errors
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+        const IMapper::Rect& accessRegion,
+        int acquireFence, YCbCrLayout* outLayout) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    // put acquireFence in a hidl_handle
+    hardware::hidl_handle acquireFenceHandle;
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error;
+    auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
+            acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpLayout)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outLayout = tmpLayout;
+            });
+
+    // we own acquireFence even on errors
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+int Mapper::unlock(buffer_handle_t bufferHandle) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    Error error;
+    auto ret = mMapper->unlock(buffer,
+            [&](const auto& tmpError, const auto& tmpReleaseFence)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                auto fenceHandle = tmpReleaseFence.getNativeHandle();
+                if (fenceHandle && fenceHandle->numFds == 1) {
+                    int fd = dup(fenceHandle->data[0]);
+                    if (fd >= 0) {
+                        releaseFence = fd;
+                    } else {
+                        ALOGD("failed to dup unlock release fence");
+                        sync_wait(fenceHandle->data[0], -1);
+                    }
+                }
+            });
+
+    if (!ret.isOk()) {
+        error = kTransactionError;
+    }
+
+    if (error != Error::NONE) {
+        ALOGE("unlock(%p) failed with %d", buffer, error);
+    }
+
+    return releaseFence;
+}
+
+Allocator::Allocator(const Mapper& mapper)
+    : mMapper(mapper)
+{
+    mAllocator = IAllocator::getService();
+    if (mAllocator == nullptr) {
+        LOG_ALWAYS_FATAL("gralloc-alloc is missing");
+    }
+}
+
+std::string Allocator::dumpDebugInfo() const
+{
+    std::string debugInfo;
+
+    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
+        debugInfo = tmpDebugInfo.c_str();
+    });
+
+    return debugInfo;
+}
+
+Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
+        uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+{
+    Error error;
+    auto ret = mAllocator->allocate(descriptor, count,
+            [&](const auto& tmpError, const auto& tmpStride,
+                const auto& tmpBuffers) {
+                error = tmpError;
+                if (tmpError != Error::NONE) {
+                    return;
+                }
+
+                // import buffers
+                for (uint32_t i = 0; i < count; i++) {
+                    error = mMapper.importBuffer(tmpBuffers[i],
+                            &outBufferHandles[i]);
+                    if (error != Error::NONE) {
+                        for (uint32_t j = 0; j < i; j++) {
+                            mMapper.freeBuffer(outBufferHandles[j]);
+                            outBufferHandles[j] = nullptr;
+                        }
+                        return;
+                    }
+                }
+
+                *outStride = tmpStride;
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
deleted file mode 100644
index 7af55e7..0000000
--- a/libs/ui/GrallocAllocator.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocAllocator"
-
-#include <ui/GrallocAllocator.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-// assume NO_RESOURCES when Status::isOk returns false
-constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Allocator::Allocator()
-{
-    mAllocator = IAllocator::getService();
-    if (mAllocator != nullptr) {
-        mAllocator->createClient(
-                [&](const auto& tmpError, const auto& tmpClient) {
-                    if (tmpError == Error::NONE) {
-                        mClient = tmpClient;
-                    }
-                });
-        if (mClient == nullptr) {
-            mAllocator.clear();
-        }
-    }
-}
-
-std::string Allocator::dumpDebugInfo() const
-{
-    std::string info;
-
-    mAllocator->dumpDebugInfo([&](const auto& tmpInfo) {
-        info = tmpInfo.c_str();
-    });
-
-    return info;
-}
-
-Error Allocator::createBufferDescriptor(
-        const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-        BufferDescriptor* outDescriptor) const
-{
-    Error error = kDefaultError;
-    mClient->createDescriptor(descriptorInfo,
-            [&](const auto& tmpError, const auto& tmpDescriptor) {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outDescriptor = tmpDescriptor;
-            });
-
-    return error;
-}
-
-void Allocator::destroyBufferDescriptor(BufferDescriptor descriptor) const
-{
-    mClient->destroyDescriptor(descriptor);
-}
-
-Error Allocator::allocate(BufferDescriptor descriptor,
-        Buffer* outBuffer) const
-{
-    hardware::hidl_vec<BufferDescriptor> descriptors;
-    descriptors.setToExternal(&descriptor, 1);
-
-    Error error = kDefaultError;
-    auto status = mClient->allocate(descriptors,
-            [&](const auto& tmpError, const auto& tmpBuffers) {
-                error = tmpError;
-                if (tmpError != Error::NONE) {
-                    return;
-                }
-
-                *outBuffer = tmpBuffers[0];
-            });
-
-    return error;
-}
-
-void Allocator::free(Buffer buffer) const
-{
-    mClient->free(buffer);
-}
-
-Error Allocator::exportHandle(BufferDescriptor descriptor, Buffer buffer,
-        native_handle_t** outBufferHandle) const
-{
-    Error error = kDefaultError;
-    auto status = mClient->exportHandle(descriptor, buffer,
-            [&](const auto& tmpError, const auto& tmpBufferHandle) {
-                error = tmpError;
-                if (tmpError != Error::NONE) {
-                    return;
-                }
-
-                *outBufferHandle = native_handle_clone(tmpBufferHandle);
-                if (!*outBufferHandle) {
-                    error = Error::NO_RESOURCES;
-                }
-            });
-
-    return error;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
deleted file mode 100644
index 8095247..0000000
--- a/libs/ui/GrallocMapper.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocMapper"
-
-#include <ui/GrallocMapper.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-static constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Mapper::Mapper()
-{
-    mMapper = IMapper::getService();
-    if (mMapper != nullptr && mMapper->isRemote()) {
-        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
-    }
-}
-
-Error Mapper::retain(buffer_handle_t handle) const
-{
-    auto ret = mMapper->retain(handle);
-    return (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
-}
-
-void Mapper::release(buffer_handle_t handle) const
-{
-    auto ret = mMapper->release(handle);
-
-    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
-    ALOGE_IF(error != Error::NONE,
-            "release(%p) failed with %d", handle, error);
-}
-
-Error Mapper::getDimensions(buffer_handle_t handle,
-        uint32_t* outWidth, uint32_t* outHeight) const
-{
-    Error error = kDefaultError;
-    mMapper->getDimensions(handle,
-            [&](const auto& tmpError, const auto& tmpWidth,
-                    const auto& tmpHeight)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outWidth = tmpWidth;
-                *outHeight = tmpHeight;
-            });
-
-    return error;
-}
-
-Error Mapper::getFormat(buffer_handle_t handle, int32_t* outFormat) const
-{
-    Error error = kDefaultError;
-    mMapper->getFormat(handle,
-            [&](const auto& tmpError, const auto& tmpFormat)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outFormat = static_cast<int32_t>(tmpFormat);
-            });
-
-    return error;
-}
-
-Error Mapper::getLayerCount(buffer_handle_t handle,
-        uint32_t* outLayerCount) const
-{
-    Error error = kDefaultError;
-    mMapper->getLayerCount(handle,
-            [&](const auto& tmpError, const auto& tmpLayerCount)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outLayerCount = tmpLayerCount;
-            });
-
-    return error;
-}
-
-Error Mapper::getProducerUsage(buffer_handle_t handle,
-    uint64_t* outProducerUsage) const
-{
-    Error error = kDefaultError;
-    mMapper->getProducerUsageMask(handle,
-            [&](const auto& tmpError, const auto& tmpProducerUsage)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outProducerUsage = tmpProducerUsage;
-            });
-
-    return error;
-}
-
-Error Mapper::getConsumerUsage(buffer_handle_t handle,
-        uint64_t* outConsumerUsage) const
-{
-    Error error = kDefaultError;
-    mMapper->getConsumerUsageMask(handle,
-            [&](const auto& tmpError, const auto& tmpConsumerUsage)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outConsumerUsage = tmpConsumerUsage;
-            });
-
-    return error;
-}
-
-Error Mapper::getBackingStore(buffer_handle_t handle,
-        uint64_t* outBackingStore) const
-{
-    Error error = kDefaultError;
-    mMapper->getBackingStore(handle,
-            [&](const auto& tmpError, const auto& tmpStore)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outBackingStore = tmpStore;
-            });
-
-    return error;
-}
-
-Error Mapper::getStride(buffer_handle_t handle, uint32_t* outStride) const
-{
-    Error error = kDefaultError;
-    mMapper->getStride(handle,
-            [&](const auto& tmpError, const auto& tmpStride)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outStride = tmpStride;
-            });
-
-    return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
-        uint64_t producerUsage,
-        uint64_t consumerUsage,
-        const IMapper::Rect& accessRegion,
-        int acquireFence, void** outData) const
-{
-    hardware::hidl_handle acquireFenceHandle;
-
-    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-    if (acquireFence >= 0) {
-        auto h = native_handle_init(acquireFenceStorage, 1, 0);
-        h->data[0] = acquireFence;
-        acquireFenceHandle = h;
-    }
-
-    Error error = kDefaultError;
-    mMapper->lock(handle, producerUsage, consumerUsage,
-            accessRegion, acquireFenceHandle,
-            [&](const auto& tmpError, const auto& tmpData)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outData = tmpData;
-            });
-
-    if (error == Error::NONE && acquireFence >= 0) {
-        close(acquireFence);
-    }
-
-    return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
-        uint64_t producerUsage,
-        uint64_t consumerUsage,
-        const IMapper::Rect& accessRegion,
-        int acquireFence, FlexLayout* outLayout) const
-{
-    hardware::hidl_handle acquireFenceHandle;
-
-    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-    if (acquireFence >= 0) {
-        auto h = native_handle_init(acquireFenceStorage, 1, 0);
-        h->data[0] = acquireFence;
-        acquireFenceHandle = h;
-    }
-
-    Error error = kDefaultError;
-    mMapper->lockFlex(handle, producerUsage, consumerUsage,
-            accessRegion, acquireFenceHandle,
-            [&](const auto& tmpError, const auto& tmpLayout)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outLayout = tmpLayout;
-            });
-
-    if (error == Error::NONE && acquireFence >= 0) {
-        close(acquireFence);
-    }
-
-    return error;
-}
-
-int Mapper::unlock(buffer_handle_t handle) const
-{
-    int releaseFence = -1;
-
-    Error error = kDefaultError;
-    mMapper->unlock(handle,
-            [&](const auto& tmpError, const auto& tmpReleaseFence)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                auto fenceHandle = tmpReleaseFence.getNativeHandle();
-                if (fenceHandle && fenceHandle->numFds == 1) {
-                    int fd = dup(fenceHandle->data[0]);
-                    if (fd >= 0) {
-                        releaseFence = fd;
-                    } else {
-                        error = Error::NO_RESOURCES;
-                    }
-                } else {
-                    releaseFence = -1;
-                }
-            });
-
-    if (error != Error::NONE) {
-        ALOGE("unlock(%p) failed with %d", handle, error);
-        releaseFence = -1;
-    }
-
-    return releaseFence;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index d21758d..ee85c9b 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -22,7 +22,7 @@
 
 #include <grallocusage/GrallocUsageConversion.h>
 
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/GraphicBufferMapper.h>
 
@@ -59,18 +59,18 @@
 // deprecated
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
         PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
-    : GraphicBuffer(inWidth, inHeight, inFormat, 1, inUsage, inUsage,
+    : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage),
             requestorName)
 {
 }
 
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inLayerCount, uint64_t producerUsage,
-        uint64_t consumerUsage, std::string requestorName)
+        PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage,
+        std::string requestorName)
     : GraphicBuffer()
 {
     mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,
-            producerUsage, consumerUsage, std::move(requestorName));
+            usage, std::move(requestorName));
 }
 
 // deprecated
@@ -78,7 +78,7 @@
         PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
         uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
     : GraphicBuffer(inHandle, keepOwnership ? TAKE_HANDLE : WRAP_HANDLE,
-            inWidth, inHeight, inFormat, inLayerCount, inUsage, inUsage,
+            inWidth, inHeight, inFormat, inLayerCount, static_cast<uint64_t>(inUsage),
             inStride)
 {
 }
@@ -86,12 +86,12 @@
 GraphicBuffer::GraphicBuffer(const native_handle_t* handle,
         HandleWrapMethod method, uint32_t width, uint32_t height,
         PixelFormat format, uint32_t layerCount,
-        uint64_t producerUsage, uint64_t consumerUsage,
+        uint64_t usage,
         uint32_t stride)
     : GraphicBuffer()
 {
     mInitCheck = initWithHandle(handle, method, width, height, format,
-            layerCount, producerUsage, consumerUsage, stride);
+            layerCount, usage, stride);
 }
 
 GraphicBuffer::~GraphicBuffer()
@@ -104,11 +104,7 @@
 void GraphicBuffer::free_handle()
 {
     if (mOwner == ownHandle) {
-        mBufferMapper.unregisterBuffer(handle);
-        if (!mBufferMapper.getGrallocMapper().valid()) {
-            native_handle_close(handle);
-            native_handle_delete(const_cast<native_handle*>(handle));
-        }
+        mBufferMapper.freeBuffer(handle);
     } else if (mOwner == ownData) {
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
@@ -133,7 +129,7 @@
 }
 
 status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage)
+        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
 {
     if (mOwner != ownData)
         return INVALID_OPERATION;
@@ -152,11 +148,11 @@
         handle = 0;
     }
     return initWithSize(inWidth, inHeight, inFormat, inLayerCount,
-            inUsage, inUsage, "[Reallocation]");
+            inUsage, "[Reallocation]");
 }
 
 bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage)
+        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
 {
     if (static_cast<int>(inWidth) != width) return true;
     if (static_cast<int>(inHeight) != height) return true;
@@ -167,20 +163,20 @@
 }
 
 status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inProducerUsage,
-        uint64_t inConsumerUsage, std::string requestorName)
+        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
+        std::string requestorName)
 {
     GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
     uint32_t outStride = 0;
     status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
-            inProducerUsage, inConsumerUsage, &handle, &outStride, mId,
+            inUsage, &handle, &outStride, mId,
             std::move(requestorName));
     if (err == NO_ERROR) {
         width = static_cast<int>(inWidth);
         height = static_cast<int>(inHeight);
         format = inFormat;
         layerCount = inLayerCount;
-        usage = android_convertGralloc1To0Usage(inProducerUsage, inConsumerUsage);
+        usage = static_cast<int>(inUsage);
         stride = static_cast<int>(outStride);
     }
     return err;
@@ -188,49 +184,38 @@
 
 status_t GraphicBuffer::initWithHandle(const native_handle_t* handle,
         HandleWrapMethod method, uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t layerCount,
-        uint64_t producerUsage, uint64_t consumerUsage,
+        PixelFormat format, uint32_t layerCount, uint64_t usage,
         uint32_t stride)
 {
-    native_handle_t* clone = nullptr;
-
-    if (method == CLONE_HANDLE) {
-        clone = native_handle_clone(handle);
-        if (!clone) {
-            return NO_MEMORY;
-        }
-
-        handle = clone;
-        method = TAKE_UNREGISTERED_HANDLE;
-    }
-
     ANativeWindowBuffer::width  = static_cast<int>(width);
     ANativeWindowBuffer::height = static_cast<int>(height);
     ANativeWindowBuffer::stride = static_cast<int>(stride);
     ANativeWindowBuffer::format = format;
-    ANativeWindowBuffer::usage  =
-        android_convertGralloc1To0Usage(producerUsage, consumerUsage);
+    ANativeWindowBuffer::usage  = static_cast<int>(usage);
 
     ANativeWindowBuffer::layerCount = layerCount;
-    ANativeWindowBuffer::handle = handle;
 
     mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
 
-    if (method == TAKE_UNREGISTERED_HANDLE) {
-        status_t err = mBufferMapper.registerBuffer(this);
+    if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) {
+        buffer_handle_t importedHandle;
+        status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
         if (err != NO_ERROR) {
-            // clean up cloned handle
-            if (clone) {
-                native_handle_close(clone);
-                native_handle_delete(clone);
-            }
-
-            initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0, 0);
+            initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
 
             return err;
         }
+
+        if (method == TAKE_UNREGISTERED_HANDLE) {
+            native_handle_close(handle);
+            native_handle_delete(const_cast<native_handle_t*>(handle));
+        }
+
+        handle = importedHandle;
     }
 
+    ANativeWindowBuffer::handle = handle;
+
     return NO_ERROR;
 }
 
@@ -451,7 +436,8 @@
     mOwner = ownHandle;
 
     if (handle != 0) {
-        status_t err = mBufferMapper.registerBuffer(this);
+        buffer_handle_t importedHandle;
+        status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
         if (err != NO_ERROR) {
             width = height = stride = format = layerCount = usage = 0;
             handle = NULL;
@@ -459,6 +445,10 @@
                     strerror(-err), err);
             return err;
         }
+
+        native_handle_close(handle);
+        native_handle_delete(const_cast<native_handle_t*>(handle));
+        handle = importedHandle;
     }
 
     buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 3f18bbc..eaba1ed 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -22,13 +22,14 @@
 
 #include <stdio.h>
 
+#include <grallocusage/GrallocUsageConversion.h>
+
 #include <log/log.h>
 #include <utils/Singleton.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-#include <ui/GrallocAllocator.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBufferMapper.h>
 
 namespace android {
@@ -41,13 +42,10 @@
     GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
 
 GraphicBufferAllocator::GraphicBufferAllocator()
-  : mAllocator(std::make_unique<Gralloc2::Allocator>()),
-    mMapper(GraphicBufferMapper::getInstance())
+  : mMapper(GraphicBufferMapper::getInstance()),
+    mAllocator(std::make_unique<Gralloc2::Allocator>(
+                mMapper.getGrallocMapper()))
 {
-    if (!mAllocator->valid()) {
-        mLoader = std::make_unique<Gralloc1::Loader>();
-        mDevice = mLoader->getDevice();
-    }
 }
 
 GraphicBufferAllocator::~GraphicBufferAllocator() {}
@@ -66,18 +64,16 @@
         const alloc_rec_t& rec(list.valueAt(i));
         if (rec.size) {
             snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64
-                    ", 0x%" PRIx64 " | %s\n",
+                    " | %s\n",
                     list.keyAt(i), rec.size/1024.0,
                     rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
-                    rec.producerUsage, rec.consumerUsage,
-                    rec.requestorName.c_str());
+                    rec.usage, rec.requestorName.c_str());
         } else {
             snprintf(buffer, SIZE, "%10p: unknown     | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64
-                    ", 0x%" PRIx64 " | %s\n",
+                    " | %s\n",
                     list.keyAt(i),
                     rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
-                    rec.producerUsage, rec.consumerUsage,
-                    rec.requestorName.c_str());
+                    rec.usage, rec.requestorName.c_str());
         }
         result.append(buffer);
         total += rec.size;
@@ -85,13 +81,7 @@
     snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0);
     result.append(buffer);
 
-    std::string deviceDump;
-    if (mAllocator->valid()) {
-        deviceDump = mAllocator->dumpDebugInfo();
-    } else {
-        deviceDump = mDevice->dump();
-    }
-
+    std::string deviceDump = mAllocator->dumpDebugInfo();
     result.append(deviceDump.c_str(), deviceDump.size());
 }
 
@@ -102,113 +92,10 @@
     ALOGD("%s", s.string());
 }
 
-namespace {
-
-class HalBuffer {
-public:
-    HalBuffer(const Gralloc2::Allocator* allocator,
-            uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
-            uint64_t consumerUsage)
-        : mAllocator(allocator), mBufferValid(false)
-    {
-        Gralloc2::IAllocatorClient::BufferDescriptorInfo info = {};
-        info.width = width;
-        info.height = height;
-        info.format = static_cast<Gralloc2::PixelFormat>(format);
-        info.layerCount = layerCount;
-        info.producerUsageMask = producerUsage;
-        info.consumerUsageMask = consumerUsage;
-
-        Gralloc2::BufferDescriptor descriptor;
-        auto error = mAllocator->createBufferDescriptor(info, &descriptor);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to create desc (%u x %u) layerCount %u format %d producerUsage %" PRIx64
-                    " consumerUsage %" PRIx64 ": %d",
-                    width, height, layerCount, format, producerUsage,
-                    consumerUsage, error);
-            return;
-        }
-
-        error = mAllocator->allocate(descriptor, &mBuffer);
-        if (error == Gralloc2::Error::NOT_SHARED) {
-            error = Gralloc2::Error::NONE;
-        }
-
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to allocate (%u x %u) layerCount %u format %d producerUsage %" PRIx64
-                    " consumerUsage %" PRIx64 ": %d",
-                    width, height, layerCount, format, producerUsage,
-                    consumerUsage, error);
-            mAllocator->destroyBufferDescriptor(descriptor);
-            return;
-        }
-
-        error = mAllocator->exportHandle(descriptor, mBuffer, &mHandle);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to export handle");
-            mAllocator->free(mBuffer);
-            mAllocator->destroyBufferDescriptor(descriptor);
-            return;
-        }
-
-        mAllocator->destroyBufferDescriptor(descriptor);
-
-        mBufferValid = true;
-    }
-
-    ~HalBuffer()
-    {
-        if (mBufferValid) {
-            if (mHandle) {
-                native_handle_close(mHandle);
-                native_handle_delete(mHandle);
-            }
-
-            mAllocator->free(mBuffer);
-        }
-    }
-
-    bool exportHandle(GraphicBufferMapper& mapper,
-            buffer_handle_t* handle, uint32_t* stride)
-    {
-        if (!mBufferValid) {
-            return false;
-        }
-
-        if (mapper.registerBuffer(mHandle)) {
-            return false;
-        }
-
-        *handle = mHandle;
-
-        auto error = mapper.getGrallocMapper().getStride(mHandle, stride);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGW("Failed to get stride from buffer: %d", error);
-            *stride = 0;
-        }
-
-        mHandle = nullptr;
-        mAllocator->free(mBuffer);
-        mBufferValid = false;
-
-        return true;
-    }
-
-private:
-    const Gralloc2::Allocator* mAllocator;
-
-    bool mBufferValid;
-    Gralloc2::Buffer mBuffer;
-    native_handle_t* mHandle;
-};
-
-} // namespace
-
 status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
-        uint64_t consumerUsage, buffer_handle_t* handle, uint32_t* stride,
-        uint64_t graphicBufferId, std::string requestorName)
+        PixelFormat format, uint32_t layerCount, uint64_t usage,
+        buffer_handle_t* handle, uint32_t* stride,
+        uint64_t /*graphicBufferId*/, std::string requestorName)
 {
     ATRACE_CALL();
 
@@ -221,70 +108,15 @@
     if (layerCount < 1)
         layerCount = 1;
 
-    gralloc1_error_t error;
-    if (mAllocator->valid()) {
-        HalBuffer buffer(mAllocator.get(), width, height, format, layerCount,
-                producerUsage, consumerUsage);
-        if (!buffer.exportHandle(mMapper, handle, stride)) {
-            return NO_MEMORY;
-        }
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        auto descriptor = mDevice->createDescriptor();
-        error = descriptor->setDimensions(width, height);
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGE("Failed to set dimensions to (%u, %u): %d",
-                    width, height, error);
-            return BAD_VALUE;
-        }
-        error = descriptor->setFormat(
-                static_cast<android_pixel_format_t>(format));
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGE("Failed to set format to %d: %d", format, error);
-            return BAD_VALUE;
-        }
-        if (mDevice->hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
-            error = descriptor->setLayerCount(layerCount);
-            if (error != GRALLOC1_ERROR_NONE) {
-                ALOGE("Failed to set layer count to %u: %d", layerCount, error);
-                return BAD_VALUE;
-            }
-        } else if (layerCount > 1) {
-            ALOGE("Failed to set layer count to %u: capability unsupported",
-                    layerCount);
-            return BAD_VALUE;
-        }
-        error = descriptor->setProducerUsage(
-                static_cast<gralloc1_producer_usage_t>(producerUsage));
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGE("Failed to set producer usage to %" PRIx64 ": %d",
-                    producerUsage, error);
-            return BAD_VALUE;
-        }
-        error = descriptor->setConsumerUsage(
-                static_cast<gralloc1_consumer_usage_t>(consumerUsage));
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGE("Failed to set consumer usage to %" PRIx64 ": %d",
-                    consumerUsage, error);
-            return BAD_VALUE;
-        }
+    Gralloc2::IMapper::BufferDescriptorInfo info = {};
+    info.width = width;
+    info.height = height;
+    info.layerCount = layerCount;
+    info.format = static_cast<Gralloc2::PixelFormat>(format);
+    info.usage = usage;
 
-        error = mDevice->allocate(descriptor, graphicBufferId, handle);
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
-                    "producerUsage %" PRIx64 " consumerUsage %" PRIx64 ": %d",
-                    width, height, layerCount, format, producerUsage,
-                    consumerUsage, error);
-            return NO_MEMORY;
-        }
-
-        error = mDevice->getStride(*handle, stride);
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGW("Failed to get stride from buffer: %d", error);
-        }
-    }
-
-    if (error == NO_ERROR) {
+    Gralloc2::Error error = mAllocator->allocate(info, stride, handle);
+    if (error == Gralloc2::Error::NONE) {
         Mutex::Autolock _l(sLock);
         KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
         uint32_t bpp = bytesPerPixel(format);
@@ -294,31 +126,28 @@
         rec.stride = *stride;
         rec.format = format;
         rec.layerCount = layerCount;
-        rec.producerUsage = producerUsage;
-        rec.consumerUsage = consumerUsage;
+        rec.usage = usage;
         rec.size = static_cast<size_t>(height * (*stride) * bpp);
         rec.requestorName = std::move(requestorName);
         list.add(*handle, rec);
-    }
 
-    return NO_ERROR;
+        return NO_ERROR;
+    } else {
+        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
+                "usage %" PRIx64 ": %d",
+                width, height, layerCount, format, usage,
+                error);
+        return NO_MEMORY;
+    }
 }
 
 status_t GraphicBufferAllocator::free(buffer_handle_t handle)
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error;
-    if (mAllocator->valid()) {
-        error = static_cast<gralloc1_error_t>(
-                mMapper.unregisterBuffer(handle));
-    } else {
-        error = mDevice->release(handle);
-    }
-
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGE("Failed to free buffer: %d", error);
-    }
+    // We allocated a buffer from the allocator and imported it into the
+    // mapper to get the handle.  We just need to free the handle now.
+    mMapper.freeBuffer(handle);
 
     Mutex::Autolock _l(sLock);
     KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 656472f..b9fa640 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -20,6 +20,8 @@
 
 #include <ui/GraphicBufferMapper.h>
 
+#include <grallocusage/GrallocUsageConversion.h>
+
 // We would eliminate the non-conforming zero-length array, but we can't since
 // this is effectively included from the Linux kernel
 #pragma clang diagnostic push
@@ -30,7 +32,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBuffer.h>
 
 #include <system/graphics.h>
@@ -43,76 +45,33 @@
 GraphicBufferMapper::GraphicBufferMapper()
   : mMapper(std::make_unique<const Gralloc2::Mapper>())
 {
-    if (!mMapper->valid()) {
-        mLoader = std::make_unique<Gralloc1::Loader>();
-        mDevice = mLoader->getDevice();
-    }
 }
 
-
-
-status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
+        buffer_handle_t* outHandle)
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
-    } else {
-        // This always returns GRALLOC1_BAD_HANDLE when handle is from a
-        // remote process and mDevice is backed by Gralloc1On0Adapter.
-        error = mDevice->retain(handle);
-        if (error == GRALLOC1_ERROR_BAD_HANDLE &&
-                mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-            ALOGE("registerBuffer by handle is not supported with "
-                  "Gralloc1On0Adapter");
-        }
-    }
+    Gralloc2::Error error = mMapper->importBuffer(
+            hardware::hidl_handle(rawHandle), outHandle);
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
-            handle, error);
+    ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d",
+            rawHandle, error);
 
-    return error;
+    return static_cast<status_t>(error);
 }
 
-status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
+status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        error = static_cast<gralloc1_error_t>(
-                mMapper->retain(buffer->getNativeBuffer()->handle));
-    } else {
-        error = mDevice->retain(buffer);
-    }
+    mMapper->freeBuffer(handle);
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
-            buffer->getNativeBuffer()->handle, error);
-
-    return error;
+    return NO_ERROR;
 }
 
-status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->release(handle);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->release(handle);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
-            handle, error);
-
-    return error;
-}
-
-static inline gralloc1_rect_t asGralloc1Rect(const Rect& rect) {
-    gralloc1_rect_t outRect{};
+static inline Gralloc2::IMapper::Rect asGralloc2Rect(const Rect& rect) {
+    Gralloc2::IMapper::Rect outRect{};
     outRect.left = rect.left;
     outRect.top = rect.top;
     outRect.width = rect.width();
@@ -120,140 +79,6 @@
     return outRect;
 }
 
-
-status_t GraphicBufferMapper::getDimensions(buffer_handle_t handle,
-        uint32_t* outWidth, uint32_t* outHeight) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getDimensions(handle, outWidth, outHeight);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getDimensions(handle, outWidth, outHeight);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getDimensions(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getFormat(buffer_handle_t handle,
-        int32_t* outFormat) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getFormat(handle, outFormat);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getFormat(handle, outFormat);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getFormat(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getLayerCount(buffer_handle_t handle,
-        uint32_t* outLayerCount) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getLayerCount(handle, outLayerCount);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getLayerCount(handle, outLayerCount);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getLayerCount(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getProducerUsage(buffer_handle_t handle,
-        uint64_t* outProducerUsage) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getProducerUsage(handle, outProducerUsage);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getProducerUsage(handle, outProducerUsage);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getProducerUsage(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getConsumerUsage(buffer_handle_t handle,
-        uint64_t* outConsumerUsage) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getConsumerUsage(handle, outConsumerUsage);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getConsumerUsage(handle, outConsumerUsage);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getConsumerUsage(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getBackingStore(buffer_handle_t handle,
-        uint64_t* outBackingStore) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getBackingStore(handle, outBackingStore);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getBackingStore(handle, outBackingStore);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getBackingStore(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getStride(buffer_handle_t handle,
-        uint32_t* outStride) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getStride(handle, outStride);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getStride(handle, outStride);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getStride(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
 status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
         const Rect& bounds, void** vaddr)
 {
@@ -289,26 +114,15 @@
 {
     ATRACE_CALL();
 
-    gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        const Gralloc2::IMapper::Rect& accessRect =
-            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
-        error = static_cast<gralloc1_error_t>(mMapper->lock(
-                    handle, producerUsage, consumerUsage, accessRect,
-                    fenceFd, vaddr));
-    } else {
-        sp<Fence> fence = new Fence(fenceFd);
-        error = mDevice->lock(handle,
-                static_cast<gralloc1_producer_usage_t>(producerUsage),
-                static_cast<gralloc1_consumer_usage_t>(consumerUsage),
-                &accessRegion, vaddr, fence);
-    }
+    const uint64_t usage = static_cast<uint64_t>(
+            android_convertGralloc1To0Usage(producerUsage, consumerUsage));
+    Gralloc2::Error error = mMapper->lock(handle, usage,
+            asGralloc2Rect(bounds), fenceFd, vaddr);
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle,
-            error);
+    ALOGW_IF(error != Gralloc2::Error::NONE, "lock(%p, ...) failed: %d",
+            handle, error);
 
-    return error;
+    return static_cast<status_t>(error);
 }
 
 static inline bool isValidYCbCrPlane(const android_flex_plane_t& plane) {
@@ -339,163 +153,28 @@
 {
     ATRACE_CALL();
 
-    gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
-
-    std::vector<android_flex_plane_t> planes;
-    android_flex_layout_t flexLayout{};
-    gralloc1_error_t error;
-
-    if (mMapper->valid()) {
-        const Gralloc2::IMapper::Rect& accessRect =
-            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
-        Gralloc2::FlexLayout layout{};
-        error = static_cast<gralloc1_error_t>(mMapper->lock(
-                    handle, usage, usage, accessRect, fenceFd, &layout));
-
-        if (error == GRALLOC1_ERROR_NONE) {
-            planes.resize(layout.planes.size());
-            memcpy(planes.data(), layout.planes.data(),
-                    sizeof(planes[0]) * planes.size());
-
-            flexLayout.format = static_cast<android_flex_format_t>(
-                    layout.format);
-            flexLayout.num_planes = static_cast<uint32_t>(planes.size());
-            flexLayout.planes = planes.data();
-        }
-    } else {
-        sp<Fence> fence = new Fence(fenceFd);
-
-        if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-            error = mDevice->lockYCbCr(handle,
-                    static_cast<gralloc1_producer_usage_t>(usage),
-                    static_cast<gralloc1_consumer_usage_t>(usage),
-                    &accessRegion, ycbcr, fence);
-            ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-                    "lockYCbCr(%p, ...) failed: %d", handle, error);
-            return error;
-        }
-
-        uint32_t numPlanes = 0;
-        error = mDevice->getNumFlexPlanes(handle, &numPlanes);
-
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGV("Failed to retrieve number of flex planes: %d", error);
-            return error;
-        }
-        if (numPlanes < 3) {
-            ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);
-            return GRALLOC1_ERROR_UNSUPPORTED;
-        }
-
-        planes.resize(numPlanes);
-        flexLayout.num_planes = numPlanes;
-        flexLayout.planes = planes.data();
-
-        error = mDevice->lockFlex(handle,
-                static_cast<gralloc1_producer_usage_t>(usage),
-                static_cast<gralloc1_consumer_usage_t>(usage),
-                &accessRegion, &flexLayout, fence);
+    Gralloc2::YCbCrLayout layout;
+    Gralloc2::Error error = mMapper->lock(handle, usage,
+            asGralloc2Rect(bounds), fenceFd, &layout);
+    if (error == Gralloc2::Error::NONE) {
+        ycbcr->y = layout.y;
+        ycbcr->cb = layout.cb;
+        ycbcr->cr = layout.cr;
+        ycbcr->ystride = static_cast<size_t>(layout.yStride);
+        ycbcr->cstride = static_cast<size_t>(layout.cStride);
+        ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
     }
 
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGW("lockFlex(%p, ...) failed: %d", handle, error);
-        return error;
-    }
-    if (flexLayout.format != FLEX_FORMAT_YCbCr) {
-        ALOGV("Unable to convert flex-format buffer to YCbCr");
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-
-    // Find planes
-    auto yPlane = planes.cend();
-    auto cbPlane = planes.cend();
-    auto crPlane = planes.cend();
-    for (auto planeIter = planes.cbegin(); planeIter != planes.cend();
-            ++planeIter) {
-        if (planeIter->component == FLEX_COMPONENT_Y) {
-            yPlane = planeIter;
-        } else if (planeIter->component == FLEX_COMPONENT_Cb) {
-            cbPlane = planeIter;
-        } else if (planeIter->component == FLEX_COMPONENT_Cr) {
-            crPlane = planeIter;
-        }
-    }
-    if (yPlane == planes.cend()) {
-        ALOGV("Unable to find Y plane");
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-    if (cbPlane == planes.cend()) {
-        ALOGV("Unable to find Cb plane");
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-    if (crPlane == planes.cend()) {
-        ALOGV("Unable to find Cr plane");
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-
-    // Validate planes
-    if (!isValidYCbCrPlane(*yPlane)) {
-        ALOGV("Y plane is invalid");
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-    if (!isValidYCbCrPlane(*cbPlane)) {
-        ALOGV("Cb plane is invalid");
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-    if (!isValidYCbCrPlane(*crPlane)) {
-        ALOGV("Cr plane is invalid");
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-    if (cbPlane->v_increment != crPlane->v_increment) {
-        ALOGV("Cb and Cr planes have different step (%d vs. %d)",
-                cbPlane->v_increment, crPlane->v_increment);
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-    if (cbPlane->h_increment != crPlane->h_increment) {
-        ALOGV("Cb and Cr planes have different stride (%d vs. %d)",
-                cbPlane->h_increment, crPlane->h_increment);
-        unlock(handle);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
-
-    // Pack plane data into android_ycbcr struct
-    ycbcr->y = yPlane->top_left;
-    ycbcr->cb = cbPlane->top_left;
-    ycbcr->cr = crPlane->top_left;
-    ycbcr->ystride = static_cast<size_t>(yPlane->v_increment);
-    ycbcr->cstride = static_cast<size_t>(cbPlane->v_increment);
-    ycbcr->chroma_step = static_cast<size_t>(cbPlane->h_increment);
-
-    return error;
+    return static_cast<status_t>(error);
 }
 
 status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        *fenceFd = mMapper->unlock(handle);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        sp<Fence> fence = Fence::NO_FENCE;
-        error = mDevice->unlock(handle, &fence);
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGE("unlock(%p) failed: %d", handle, error);
-            return error;
-        }
+    *fenceFd = mMapper->unlock(handle);
 
-        *fenceFd = fence->dup();
-    }
-    return error;
+    return NO_ERROR;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index b55c212..6733505 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -25,9 +25,3 @@
     shared_libs: ["libui"],
     srcs: ["colorspace_test.cpp"],
 }
-
-cc_test {
-    name: "Gralloc1Mapper_test",
-    shared_libs: ["libui", "libutils"],
-    srcs: ["Gralloc1Mapper_test.cpp"],
-}
diff --git a/libs/ui/tests/Gralloc1Mapper_test.cpp b/libs/ui/tests/Gralloc1Mapper_test.cpp
deleted file mode 100644
index b7c9f0f..0000000
--- a/libs/ui/tests/Gralloc1Mapper_test.cpp
+++ /dev/null
@@ -1,105 +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.
- */
-
-#define LOG_TAG "Gralloc1Mapper_test"
-//#define LOG_NDEBUG 0
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
-#include <utils/Errors.h>
-
-#include <gtest/gtest.h>
-
-using namespace android;
-
-class Gralloc1MapperTest : public ::testing::Test
-{
-public:
-    ~Gralloc1MapperTest() override = default;
-
-protected:
-    void SetUp() override {
-        buffer = new GraphicBuffer(4, 8, HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,
-                GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, "Gralloc1MapperTest");
-        ASSERT_NE(nullptr, buffer.get());
-
-        handle = static_cast<buffer_handle_t>(buffer->handle);
-
-        mapper = &GraphicBufferMapper::get();
-    }
-
-    sp<GraphicBuffer> buffer;
-    buffer_handle_t handle;
-    GraphicBufferMapper* mapper;
-};
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getDimensions) {
-    uint32_t width = 0;
-    uint32_t height = 0;
-    status_t err = mapper->getDimensions(handle, &width, &height);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(4U, width);
-    EXPECT_EQ(8U, height);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getFormat) {
-    int32_t value = 0;
-    status_t err = mapper->getFormat(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getLayerCount) {
-    uint32_t value = 0;
-    status_t err = mapper->getLayerCount(handle, &value);
-    if (err != GRALLOC1_ERROR_UNSUPPORTED) {
-        EXPECT_EQ(1U, value);
-    }
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getProducerUsage) {
-    uint64_t value = 0;
-    status_t err = mapper->getProducerUsage(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getConsumerUsage) {
-    uint64_t value = 0;
-    status_t err = mapper->getConsumerUsage(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getBackingStore) {
-    uint64_t value = 0;
-    status_t err = mapper->getBackingStore(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getStride) {
-    uint32_t value = 0;
-    status_t err = mapper->getStride(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    // The stride should be at least the width of the buffer.
-    EXPECT_LE(4U, value);
-}
diff --git a/libs/vr/libbroadcastring/Android.bp b/libs/vr/libbroadcastring/Android.bp
new file mode 100644
index 0000000..13af470
--- /dev/null
+++ b/libs/vr/libbroadcastring/Android.bp
@@ -0,0 +1,35 @@
+cc_library_static {
+    name: "libbroadcastring",
+    clang: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "libbase",
+    ],
+    export_shared_lib_headers: [
+        "libbase",
+    ],
+}
+
+cc_test {
+    name: "broadcast_ring_tests",
+    clang: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "broadcast_ring_test.cc",
+    ],
+    static_libs: [
+        "libbroadcastring",
+    ],
+    shared_libs: [
+        "libbase",
+    ],
+}
diff --git a/libs/vr/libbroadcastring/broadcast_ring_test.cc b/libs/vr/libbroadcastring/broadcast_ring_test.cc
new file mode 100644
index 0000000..dfdd4ef
--- /dev/null
+++ b/libs/vr/libbroadcastring/broadcast_ring_test.cc
@@ -0,0 +1,866 @@
+#include "libbroadcastring/broadcast_ring.h"
+
+#include <stdlib.h>
+#include <memory>
+#include <thread>  // NOLINT
+#include <sys/mman.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+namespace {
+
+template <uint32_t N>
+struct alignas(8) Aligned {
+  char v[N];
+};
+
+template <uint32_t N>
+struct alignas(8) Sized {
+  Sized() { Clear(); }
+  explicit Sized(char c) { Fill(c); }
+  char v[sizeof(Aligned<N>)];
+  void Clear() { memset(v, 0, sizeof(v)); }
+  void Fill(char c) { memset(v, c, sizeof(v)); }
+  static Sized Pattern(uint8_t c) {
+    Sized sized;
+    for (size_t i = 0; i < sizeof(v); ++i) {
+      sized.v[i] = static_cast<char>(c + i);
+    }
+    return sized;
+  }
+  bool operator==(const Sized& right) const {
+    static_assert(sizeof(*this) == sizeof(v), "Size mismatch");
+    return !memcmp(v, right.v, sizeof(v));
+  }
+  template <typename SmallerSized>
+  SmallerSized Truncate() const {
+    SmallerSized val;
+    static_assert(sizeof(val.v) <= sizeof(v), "Cannot truncate to larger size");
+    memcpy(val.v, v, sizeof(val.v));
+    return val;
+  }
+};
+
+char FillChar(int val) { return static_cast<char>(val); }
+
+struct FakeMmap {
+  explicit FakeMmap(size_t size) : size(size), data(new char[size]) {}
+  size_t size;
+  std::unique_ptr<char[]> data;
+  void* mmap() { return static_cast<void*>(data.get()); }
+};
+
+template <typename Ring>
+FakeMmap CreateRing(Ring* ring, uint32_t count) {
+  FakeMmap mmap(Ring::MemorySize(count));
+  *ring = Ring::Create(mmap.mmap(), mmap.size, count);
+  return mmap;
+}
+
+template <typename RecordType, bool StaticSize = false,
+          uint32_t StaticCount = 0, uint32_t MaxReserved = 1,
+          uint32_t MinAvailable = 0>
+struct Traits {
+  using Record = RecordType;
+  static constexpr bool kUseStaticRecordSize = StaticSize;
+  static constexpr uint32_t kStaticRecordCount = StaticCount;
+  static constexpr uint32_t kMaxReservedRecords = MaxReserved;
+  static constexpr uint32_t kMinAvailableRecords = MinAvailable;
+  static constexpr uint32_t kMinRecordCount = MaxReserved + MinAvailable;
+};
+
+template <typename Record, bool StaticSize = false, uint32_t MaxReserved = 1,
+          uint32_t MinAvailable = 7>
+struct TraitsDynamic
+    : public Traits<Record, StaticSize, 0, MaxReserved, MinAvailable> {
+  using Ring = BroadcastRing<Record, TraitsDynamic>;
+  static uint32_t MinCount() { return MaxReserved + MinAvailable; }
+};
+
+template <typename Record, uint32_t StaticCount = 1, bool StaticSize = true,
+          uint32_t MaxReserved = 1, uint32_t MinAvailable = 0>
+struct TraitsStatic
+    : public Traits<Record, true, StaticCount, MaxReserved, MinAvailable> {
+  using Ring = BroadcastRing<Record, TraitsStatic>;
+  static uint32_t MinCount() { return StaticCount; }
+};
+
+using Dynamic_8_NxM = TraitsDynamic<Sized<8>>;
+using Dynamic_16_NxM = TraitsDynamic<Sized<16>>;
+using Dynamic_32_NxM = TraitsDynamic<Sized<32>>;
+using Dynamic_32_32xM = TraitsDynamic<Sized<32>, true>;
+using Dynamic_16_NxM_1plus0 = TraitsDynamic<Sized<16>, false, 1, 0>;
+using Dynamic_16_NxM_1plus1 = TraitsDynamic<Sized<16>, false, 1, 1>;
+using Dynamic_16_NxM_5plus11 = TraitsDynamic<Sized<16>, false, 5, 11>;
+using Dynamic_256_NxM_1plus0 = TraitsDynamic<Sized<256>, false, 1, 0>;
+
+using Static_8_8x1 = TraitsStatic<Sized<8>, 1>;
+using Static_8_8x16 = TraitsStatic<Sized<8>, 16>;
+using Static_16_16x8 = TraitsStatic<Sized<16>, 8>;
+using Static_16_16x16 = TraitsStatic<Sized<16>, 16>;
+using Static_16_16x32 = TraitsStatic<Sized<16>, 32>;
+using Static_32_Nx8 = TraitsStatic<Sized<32>, 8, false>;
+
+using TraitsList = ::testing::Types<Dynamic_8_NxM,           //
+                                    Dynamic_16_NxM,          //
+                                    Dynamic_32_NxM,          //
+                                    Dynamic_32_32xM,         //
+                                    Dynamic_16_NxM_1plus0,   //
+                                    Dynamic_16_NxM_1plus1,   //
+                                    Dynamic_16_NxM_5plus11,  //
+                                    Dynamic_256_NxM_1plus0,  //
+                                    Static_8_8x1,            //
+                                    Static_8_8x16,           //
+                                    Static_16_16x8,          //
+                                    Static_16_16x16,         //
+                                    Static_16_16x32,         //
+                                    Static_32_Nx8>;
+
+}  // namespace
+
+template <typename T>
+class BroadcastRingTest : public ::testing::Test {};
+
+TYPED_TEST_CASE(BroadcastRingTest, TraitsList);
+
+TYPED_TEST(BroadcastRingTest, Geometry) {
+  using Record = typename TypeParam::Record;
+  using Ring = typename TypeParam::Ring;
+  Ring ring;
+  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+  EXPECT_EQ(Ring::Traits::MinCount(), ring.record_count());
+  EXPECT_EQ(sizeof(Record), ring.record_size());
+}
+
+TYPED_TEST(BroadcastRingTest, PutGet) {
+  using Record = typename TypeParam::Record;
+  using Ring = typename TypeParam::Ring;
+  Ring ring;
+  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+  const uint32_t oldest_sequence_at_start = ring.GetOldestSequence();
+  const uint32_t next_sequence_at_start = ring.GetNextSequence();
+  {
+    uint32_t sequence = oldest_sequence_at_start;
+    Record record;
+    EXPECT_FALSE(ring.Get(&sequence, &record));
+    EXPECT_EQ(oldest_sequence_at_start, sequence);
+    EXPECT_EQ(Record(), record);
+  }
+  const Record original_record(0x1a);
+  ring.Put(original_record);
+  {
+    uint32_t sequence = next_sequence_at_start;
+    Record record;
+    EXPECT_TRUE(ring.Get(&sequence, &record));
+    EXPECT_EQ(next_sequence_at_start, sequence);
+    EXPECT_EQ(original_record, record);
+  }
+  {
+    uint32_t sequence = next_sequence_at_start + 1;
+    Record record;
+    EXPECT_FALSE(ring.Get(&sequence, &record));
+    EXPECT_EQ(next_sequence_at_start + 1, sequence);
+    EXPECT_EQ(Record(), record);
+  }
+}
+
+TYPED_TEST(BroadcastRingTest, FillOnce) {
+  using Record = typename TypeParam::Record;
+  using Ring = typename TypeParam::Ring;
+  Ring ring;
+  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+  const uint32_t next_sequence_at_start = ring.GetNextSequence();
+  for (uint32_t i = 0; i < ring.record_count(); ++i)
+    ring.Put(Record(FillChar(i)));
+  for (uint32_t i = 0; i < ring.record_count(); ++i) {
+    const uint32_t expected_sequence = next_sequence_at_start + i;
+    const Record expected_record(FillChar(i));
+    {
+      uint32_t sequence = ring.GetOldestSequence() + i;
+      Record record;
+      EXPECT_TRUE(ring.Get(&sequence, &record));
+      EXPECT_EQ(expected_sequence, sequence);
+      EXPECT_EQ(expected_record, record);
+    }
+  }
+  {
+    uint32_t sequence = ring.GetOldestSequence() + ring.record_count();
+    Record record;
+    EXPECT_FALSE(ring.Get(&sequence, &record));
+  }
+}
+
+TYPED_TEST(BroadcastRingTest, FillTwice) {
+  using Record = typename TypeParam::Record;
+  using Ring = typename TypeParam::Ring;
+  Ring ring;
+  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+  const uint32_t next_sequence_at_start = ring.GetNextSequence();
+  for (uint32_t i = 0; i < 2 * ring.record_count(); ++i) {
+    const Record newest_record(FillChar(i));
+    ring.Put(newest_record);
+
+    const uint32_t newest_sequence = next_sequence_at_start + i;
+    const uint32_t records_available = std::min(i + 1, ring.record_count());
+    const uint32_t oldest_sequence = newest_sequence - records_available + 1;
+    EXPECT_EQ(newest_sequence, ring.GetNewestSequence());
+    EXPECT_EQ(oldest_sequence, ring.GetOldestSequence());
+    EXPECT_EQ(newest_sequence + 1, ring.GetNextSequence());
+
+    for (uint32_t j = 0; j < records_available; ++j) {
+      const uint32_t sequence_jth_newest = newest_sequence - j;
+      const Record record_jth_newest(FillChar(i - j));
+
+      {
+        uint32_t sequence = sequence_jth_newest;
+        Record record;
+        EXPECT_TRUE(ring.Get(&sequence, &record));
+        EXPECT_EQ(sequence_jth_newest, sequence);
+        EXPECT_EQ(record_jth_newest, record);
+      }
+
+      {
+        uint32_t sequence = sequence_jth_newest;
+        Record record;
+        EXPECT_TRUE(ring.GetNewest(&sequence, &record));
+        EXPECT_EQ(newest_sequence, sequence);
+        EXPECT_EQ(newest_record, record);
+      }
+    }
+
+    const Record oldest_record(
+        FillChar(i + (oldest_sequence - newest_sequence)));
+    const uint32_t sequence_0th_overwritten = oldest_sequence - 1;
+    const uint32_t sequence_0th_future = newest_sequence + 1;
+    const uint32_t sequence_1st_future = newest_sequence + 2;
+
+    {
+      uint32_t sequence = sequence_0th_overwritten;
+      Record record;
+      EXPECT_TRUE(ring.Get(&sequence, &record));
+      EXPECT_EQ(oldest_sequence, sequence);
+      EXPECT_EQ(oldest_record, record);
+    }
+
+    {
+      uint32_t sequence = sequence_0th_overwritten;
+      Record record;
+      EXPECT_TRUE(ring.GetNewest(&sequence, &record));
+      EXPECT_EQ(newest_sequence, sequence);
+      EXPECT_EQ(newest_record, record);
+    }
+
+    {
+      uint32_t sequence = sequence_0th_future;
+      Record record;
+      EXPECT_FALSE(ring.Get(&sequence, &record));
+      EXPECT_EQ(sequence_0th_future, sequence);
+      EXPECT_EQ(Record(), record);
+    }
+
+    {
+      uint32_t sequence = sequence_0th_future;
+      Record record;
+      EXPECT_FALSE(ring.GetNewest(&sequence, &record));
+      EXPECT_EQ(sequence_0th_future, sequence);
+      EXPECT_EQ(Record(), record);
+    }
+
+    {
+      uint32_t sequence = sequence_1st_future;
+      Record record;
+      EXPECT_TRUE(ring.Get(&sequence, &record));
+      EXPECT_EQ(oldest_sequence, sequence);
+      EXPECT_EQ(oldest_record, record);
+    }
+
+    {
+      uint32_t sequence = sequence_1st_future;
+      Record record;
+      EXPECT_TRUE(ring.GetNewest(&sequence, &record));
+      EXPECT_EQ(newest_sequence, sequence);
+      EXPECT_EQ(newest_record, record);
+    }
+  }
+}
+
+TYPED_TEST(BroadcastRingTest, Import) {
+  using Record = typename TypeParam::Record;
+  using Ring = typename TypeParam::Ring;
+  Ring ring;
+  auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+
+  const uint32_t sequence_0 = ring.GetNextSequence();
+  const uint32_t sequence_1 = ring.GetNextSequence() + 1;
+  const Record record_0 = Record::Pattern(0x00);
+  const Record record_1 = Record::Pattern(0x80);
+  ring.Put(record_0);
+  ring.Put(record_1);
+
+  {
+    Ring imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) = Ring::Import(mmap.mmap(), mmap.size);
+    EXPECT_TRUE(import_ok);
+    EXPECT_EQ(ring.record_size(), imported_ring.record_size());
+    EXPECT_EQ(ring.record_count(), imported_ring.record_count());
+
+    if (ring.record_count() != 1) {
+      uint32_t sequence = sequence_0;
+      Record imported_record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+      EXPECT_EQ(sequence_0, sequence);
+      EXPECT_EQ(record_0, imported_record);
+    }
+
+    {
+      uint32_t sequence = sequence_1;
+      Record imported_record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+      EXPECT_EQ(sequence_1, sequence);
+      EXPECT_EQ(record_1, imported_record);
+    }
+  }
+}
+
+TEST(BroadcastRingTest, ShouldFailImportIfStaticSizeMismatch) {
+  using OriginalRing = typename Static_16_16x16::Ring;
+  using RecordSizeMismatchRing = typename Static_8_8x16::Ring;
+  using RecordCountMismatchRing = typename Static_16_16x8::Ring;
+
+  OriginalRing original_ring;
+  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+  {
+    using ImportedRing = RecordSizeMismatchRing;
+    ImportedRing imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), mmap.size);
+    EXPECT_FALSE(import_ok);
+    auto mmap_imported =
+        CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
+    EXPECT_NE(original_ring.record_size(), imported_ring.record_size());
+    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+  }
+
+  {
+    using ImportedRing = RecordCountMismatchRing;
+    ImportedRing imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), mmap.size);
+    EXPECT_FALSE(import_ok);
+    auto mmap_imported =
+        CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
+    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+    EXPECT_NE(original_ring.record_count(), imported_ring.record_count());
+  }
+}
+
+TEST(BroadcastRingTest, ShouldFailImportIfDynamicSizeGrows) {
+  using OriginalRing = typename Dynamic_8_NxM::Ring;
+  using RecordSizeGrowsRing = typename Dynamic_16_NxM::Ring;
+
+  OriginalRing original_ring;
+  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+  {
+    using ImportedRing = RecordSizeGrowsRing;
+    ImportedRing imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), mmap.size);
+    EXPECT_FALSE(import_ok);
+    auto mmap_imported =
+        CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
+    EXPECT_LT(original_ring.record_size(), imported_ring.record_size());
+    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+  }
+}
+
+TEST(BroadcastRingTest, ShouldFailImportIfCountTooSmall) {
+  using OriginalRing = typename Dynamic_16_NxM_1plus0::Ring;
+  using MinCountRing = typename Dynamic_16_NxM_1plus1::Ring;
+
+  OriginalRing original_ring;
+  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+  {
+    using ImportedRing = MinCountRing;
+    ImportedRing imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), mmap.size);
+    EXPECT_FALSE(import_ok);
+    auto mmap_imported =
+        CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
+    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+    EXPECT_LT(original_ring.record_count(), imported_ring.record_count());
+  }
+}
+
+TEST(BroadcastRingTest, ShouldFailImportIfMmapTooSmall) {
+  using OriginalRing = typename Dynamic_16_NxM::Ring;
+
+  OriginalRing original_ring;
+  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+  {
+    using ImportedRing = OriginalRing;
+    ImportedRing imported_ring;
+    bool import_ok;
+    const size_t kMinSize =
+        ImportedRing::MemorySize(original_ring.record_count());
+    std::tie(imported_ring, import_ok) = ImportedRing::Import(mmap.mmap(), 0);
+    EXPECT_FALSE(import_ok);
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), kMinSize - 1);
+    EXPECT_FALSE(import_ok);
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), kMinSize);
+    EXPECT_TRUE(import_ok);
+    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+  }
+}
+
+TEST(BroadcastRingTest, ShouldImportIfDynamicSizeShrinks) {
+  using OriginalRing = typename Dynamic_16_NxM::Ring;
+  using RecordSizeShrinksRing = typename Dynamic_8_NxM::Ring;
+
+  OriginalRing original_ring;
+  auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+  using OriginalRecord = typename OriginalRing::Record;
+  const uint32_t original_sequence_0 = original_ring.GetNextSequence();
+  const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
+  const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
+  const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
+  original_ring.Put(original_record_0);
+  original_ring.Put(original_record_1);
+
+  {
+    using ImportedRing = RecordSizeShrinksRing;
+    using ImportedRecord = typename ImportedRing::Record;
+    ImportedRing imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), mmap.size);
+    EXPECT_TRUE(import_ok);
+    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+    EXPECT_GT(sizeof(OriginalRecord), sizeof(ImportedRecord));
+
+    {
+      uint32_t sequence = original_sequence_0;
+      ImportedRecord shrunk_record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &shrunk_record));
+      EXPECT_EQ(original_sequence_0, sequence);
+      EXPECT_EQ(original_record_0.Truncate<ImportedRecord>(), shrunk_record);
+    }
+
+    {
+      uint32_t sequence = original_sequence_1;
+      ImportedRecord shrunk_record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &shrunk_record));
+      EXPECT_EQ(original_sequence_1, sequence);
+      EXPECT_EQ(original_record_1.Truncate<ImportedRecord>(), shrunk_record);
+    }
+  }
+}
+
+TEST(BroadcastRingTest, ShouldImportIfCompatibleDynamicToStatic) {
+  using OriginalRing = typename Dynamic_16_NxM::Ring;
+  using ImportedRing = typename Static_16_16x16::Ring;
+  using OriginalRecord = typename OriginalRing::Record;
+  using ImportedRecord = typename ImportedRing::Record;
+  using StaticRing = ImportedRing;
+
+  OriginalRing original_ring;
+  auto mmap = CreateRing(&original_ring, StaticRing::Traits::MinCount());
+
+  const uint32_t original_sequence_0 = original_ring.GetNextSequence();
+  const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
+  const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
+  const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
+  original_ring.Put(original_record_0);
+  original_ring.Put(original_record_1);
+
+  {
+    ImportedRing imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), mmap.size);
+    EXPECT_TRUE(import_ok);
+    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+
+    {
+      uint32_t sequence = original_sequence_0;
+      ImportedRecord imported_record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+      EXPECT_EQ(original_sequence_0, sequence);
+      EXPECT_EQ(original_record_0, imported_record);
+    }
+
+    {
+      uint32_t sequence = original_sequence_1;
+      ImportedRecord imported_record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+      EXPECT_EQ(original_sequence_1, sequence);
+      EXPECT_EQ(original_record_1, imported_record);
+    }
+  }
+}
+
+TEST(BroadcastRingTest, ShouldImportIfCompatibleStaticToDynamic) {
+  using OriginalRing = typename Static_16_16x16::Ring;
+  using ImportedRing = typename Dynamic_16_NxM::Ring;
+  using OriginalRecord = typename OriginalRing::Record;
+  using ImportedRecord = typename ImportedRing::Record;
+  using StaticRing = OriginalRing;
+
+  OriginalRing original_ring;
+  auto mmap = CreateRing(&original_ring, StaticRing::Traits::MinCount());
+
+  const uint32_t original_sequence_0 = original_ring.GetNextSequence();
+  const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
+  const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
+  const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
+  original_ring.Put(original_record_0);
+  original_ring.Put(original_record_1);
+
+  {
+    ImportedRing imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) =
+        ImportedRing::Import(mmap.mmap(), mmap.size);
+    EXPECT_TRUE(import_ok);
+    EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+    EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+
+    {
+      uint32_t sequence = original_sequence_0;
+      ImportedRecord imported_record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+      EXPECT_EQ(original_sequence_0, sequence);
+      EXPECT_EQ(original_record_0, imported_record);
+    }
+
+    {
+      uint32_t sequence = original_sequence_1;
+      ImportedRecord imported_record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+      EXPECT_EQ(original_sequence_1, sequence);
+      EXPECT_EQ(original_record_1, imported_record);
+    }
+  }
+}
+
+TEST(BroadcastRingTest, ShouldImportIfReadonlyMmap) {
+  using Ring = Dynamic_32_NxM::Ring;
+  using Record = Ring::Record;
+
+  uint32_t record_count = Ring::Traits::MinCount();
+  size_t ring_size = Ring::MemorySize(record_count);
+
+  size_t page_size = sysconf(_SC_PAGESIZE);
+  size_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1);
+  ASSERT_GE(mmap_size, ring_size);
+
+  void* mmap_base = mmap(nullptr, mmap_size, PROT_READ | PROT_WRITE,
+                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  ASSERT_NE(MAP_FAILED, mmap_base);
+
+  Ring ring = Ring::Create(mmap_base, mmap_size, record_count);
+  for (uint32_t i = 0; i < record_count; ++i) ring.Put(Record(FillChar(i)));
+
+  ASSERT_EQ(0, mprotect(mmap_base, mmap_size, PROT_READ));
+
+  {
+    Ring imported_ring;
+    bool import_ok;
+    std::tie(imported_ring, import_ok) = Ring::Import(mmap_base, mmap_size);
+    EXPECT_TRUE(import_ok);
+    EXPECT_EQ(ring.record_size(), imported_ring.record_size());
+    EXPECT_EQ(ring.record_count(), imported_ring.record_count());
+
+    uint32_t oldest_sequence = imported_ring.GetOldestSequence();
+    for (uint32_t i = 0; i < record_count; ++i) {
+      uint32_t sequence = oldest_sequence + i;
+      Record record;
+      EXPECT_TRUE(imported_ring.Get(&sequence, &record));
+      EXPECT_EQ(Record(FillChar(i)), record);
+    }
+  }
+
+  ASSERT_EQ(0, munmap(mmap_base, mmap_size));
+}
+
+TEST(BroadcastRingTest, ShouldDieIfPutReadonlyMmap) {
+  using Ring = Dynamic_32_NxM::Ring;
+  using Record = Ring::Record;
+
+  uint32_t record_count = Ring::Traits::MinCount();
+  size_t ring_size = Ring::MemorySize(record_count);
+
+  size_t page_size = sysconf(_SC_PAGESIZE);
+  size_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1);
+  ASSERT_GE(mmap_size, ring_size);
+
+  void* mmap_base = mmap(nullptr, mmap_size, PROT_READ | PROT_WRITE,
+                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  ASSERT_NE(MAP_FAILED, mmap_base);
+
+  Ring ring = Ring::Create(mmap_base, mmap_size, record_count);
+  for (uint32_t i = 0; i < record_count; ++i) ring.Put(Record(FillChar(i)));
+
+  ASSERT_EQ(0, mprotect(mmap_base, mmap_size, PROT_READ));
+
+  EXPECT_DEATH_IF_SUPPORTED({ ring.Put(Record(7)); }, "");
+
+  ASSERT_EQ(0, munmap(mmap_base, mmap_size));
+}
+
+TEST(BroadcastRingTest, ShouldDieIfCreationMmapTooSmall) {
+  using Ring = Dynamic_32_NxM::Ring;
+  using Record = Ring::Record;
+
+  uint32_t record_count = Ring::Traits::MinCount();
+  size_t ring_size = Ring::MemorySize(record_count);
+  FakeMmap mmap(ring_size);
+
+  EXPECT_DEATH_IF_SUPPORTED({
+    Ring ring = Ring::Create(mmap.mmap(), ring_size - 1, record_count);
+  }, "");
+
+  Ring ring = Ring::Create(mmap.mmap(), ring_size, record_count);
+
+  ring.Put(Record(3));
+
+  {
+    uint32_t sequence = ring.GetNewestSequence();
+    Record record;
+    EXPECT_TRUE(ring.Get(&sequence, &record));
+    EXPECT_EQ(Record(3), record);
+  }
+}
+
+TEST(BroadcastRingTest, ShouldDieIfCreationMmapMisaligned) {
+  using Ring = Static_8_8x1::Ring;
+  using Record = Ring::Record;
+
+  constexpr int kAlign = Ring::mmap_alignment();
+  constexpr int kMisalign = kAlign / 2;
+  size_t ring_size = Ring::MemorySize();
+  std::unique_ptr<char[]> buf(new char[ring_size + kMisalign]);
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      { Ring ring = Ring::Create(buf.get() + kMisalign, ring_size); }, "");
+
+  Ring ring = Ring::Create(buf.get(), ring_size);
+
+  ring.Put(Record(3));
+
+  {
+    uint32_t sequence = ring.GetNewestSequence();
+    Record record;
+    EXPECT_TRUE(ring.Get(&sequence, &record));
+    EXPECT_EQ(Record(3), record);
+  }
+}
+
+template <typename Ring>
+std::unique_ptr<std::thread> CopyTask(std::atomic<bool>* quit, void* in_base,
+                                      size_t in_size, void* out_base,
+                                      size_t out_size) {
+  return std::unique_ptr<std::thread>(
+      new std::thread([quit, in_base, in_size, out_base, out_size]() {
+        using Record = typename Ring::Record;
+
+        bool import_ok;
+        Ring in_ring;
+        Ring out_ring;
+        std::tie(in_ring, import_ok) = Ring::Import(in_base, in_size);
+        ASSERT_TRUE(import_ok);
+        std::tie(out_ring, import_ok) = Ring::Import(out_base, out_size);
+        ASSERT_TRUE(import_ok);
+
+        uint32_t sequence = in_ring.GetOldestSequence();
+        while (!std::atomic_load_explicit(quit, std::memory_order_relaxed)) {
+          Record record;
+          if (in_ring.Get(&sequence, &record)) {
+            out_ring.Put(record);
+            sequence++;
+          }
+        }
+      }));
+}
+
+TEST(BroadcastRingTest, ThreadedCopySingle) {
+  using Ring = Dynamic_32_NxM::Ring;
+  using Record = Ring::Record;
+  Ring in_ring;
+  auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
+
+  Ring out_ring;
+  auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
+
+  std::atomic<bool> quit(false);
+  std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
+      &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
+
+  const Record out_record(0x1c);
+  out_ring.Put(out_record);
+
+  uint32_t in_sequence = in_ring.GetOldestSequence();
+  Record in_record;
+  while (!in_ring.Get(&in_sequence, &in_record)) {
+    // Do nothing.
+  }
+
+  EXPECT_EQ(out_record, in_record);
+  std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
+  copy_task->join();
+}
+
+TEST(BroadcastRingTest, ThreadedCopyLossless) {
+  using Ring = Dynamic_32_NxM::Ring;
+  using Record = Ring::Record;
+  Ring in_ring;
+  auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
+
+  Ring out_ring;
+  auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
+
+  std::atomic<bool> quit(false);
+  std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
+      &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
+
+  constexpr uint32_t kRecordsToProcess = 10000;
+  uint32_t out_records = 0;
+  uint32_t in_records = 0;
+  uint32_t in_sequence = in_ring.GetNextSequence();
+  while (out_records < kRecordsToProcess || in_records < kRecordsToProcess) {
+    if (out_records < kRecordsToProcess &&
+        out_records - in_records < out_ring.record_count()) {
+      const Record out_record(FillChar(out_records));
+      out_ring.Put(out_record);
+      out_records++;
+    }
+
+    Record in_record;
+    while (in_ring.Get(&in_sequence, &in_record)) {
+      EXPECT_EQ(Record(FillChar(in_records)), in_record);
+      in_records++;
+      in_sequence++;
+    }
+  }
+
+  EXPECT_EQ(kRecordsToProcess, out_records);
+  EXPECT_EQ(kRecordsToProcess, in_records);
+
+  std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
+  copy_task->join();
+}
+
+TEST(BroadcastRingTest, ThreadedCopyLossy) {
+  using Ring = Dynamic_32_NxM::Ring;
+  using Record = Ring::Record;
+  Ring in_ring;
+  auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
+
+  Ring out_ring;
+  auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
+
+  std::atomic<bool> quit(false);
+  std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
+      &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
+
+  constexpr uint32_t kRecordsToProcess = 100000;
+  uint32_t out_records = 0;
+  uint32_t in_records = 0;
+  uint32_t in_sequence = in_ring.GetNextSequence();
+  while (out_records < kRecordsToProcess) {
+    const Record out_record(FillChar(out_records));
+    out_ring.Put(out_record);
+    out_records++;
+
+    Record in_record;
+    if (in_ring.GetNewest(&in_sequence, &in_record)) {
+      EXPECT_EQ(Record(in_record.v[0]), in_record);
+      in_records++;
+      in_sequence++;
+    }
+  }
+
+  EXPECT_EQ(kRecordsToProcess, out_records);
+  EXPECT_GE(kRecordsToProcess, in_records);
+
+  std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
+  copy_task->join();
+}
+
+template <typename Ring>
+std::unique_ptr<std::thread> CheckFillTask(std::atomic<bool>* quit,
+                                           void* in_base, size_t in_size) {
+  return std::unique_ptr<std::thread>(
+      new std::thread([quit, in_base, in_size]() {
+        using Record = typename Ring::Record;
+
+        bool import_ok;
+        Ring in_ring;
+        std::tie(in_ring, import_ok) = Ring::Import(in_base, in_size);
+        ASSERT_TRUE(import_ok);
+
+        uint32_t sequence = in_ring.GetOldestSequence();
+        while (!std::atomic_load_explicit(quit, std::memory_order_relaxed)) {
+          Record record;
+          if (in_ring.Get(&sequence, &record)) {
+            ASSERT_EQ(Record(record.v[0]), record);
+            sequence++;
+          }
+        }
+      }));
+}
+
+template <typename Ring>
+void ThreadedOverwriteTorture() {
+  using Record = typename Ring::Record;
+
+  // Maximize overwrites by having few records.
+  const int kMinRecordCount = 1;
+  const int kMaxRecordCount = 4;
+
+  for (int count = kMinRecordCount; count <= kMaxRecordCount; count *= 2) {
+    Ring out_ring;
+    auto out_mmap = CreateRing(&out_ring, count);
+
+    std::atomic<bool> quit(false);
+    std::unique_ptr<std::thread> check_task =
+        CheckFillTask<Ring>(&quit, out_mmap.mmap(), out_mmap.size);
+
+    constexpr int kIterations = 10000;
+    for (int i = 0; i < kIterations; ++i) {
+      const Record record(FillChar(i));
+      out_ring.Put(record);
+    }
+
+    std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
+    check_task->join();
+  }
+}
+
+TEST(BroadcastRingTest, ThreadedOverwriteTortureSmall) {
+  ThreadedOverwriteTorture<Dynamic_16_NxM_1plus0::Ring>();
+}
+
+TEST(BroadcastRingTest, ThreadedOverwriteTortureLarge) {
+  ThreadedOverwriteTorture<Dynamic_256_NxM_1plus0::Ring>();
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
new file mode 100644
index 0000000..69cb648
--- /dev/null
+++ b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
@@ -0,0 +1,668 @@
+#ifndef ANDROID_DVR_BROADCAST_RING_H_
+#define ANDROID_DVR_BROADCAST_RING_H_
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <atomic>
+#include <limits>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "android-base/logging.h"
+
+#if ATOMIC_LONG_LOCK_FREE != 2 || ATOMIC_INT_LOCK_FREE != 2
+#error "This file requires lock free atomic uint32_t and long"
+#endif
+
+namespace android {
+namespace dvr {
+
+struct DefaultRingTraits {
+  // Set this to false to allow compatibly expanding the record size.
+  static constexpr bool kUseStaticRecordSize = false;
+
+  // Set this to a nonzero value to fix the number of records in the ring.
+  static constexpr uint32_t kStaticRecordCount = 0;
+
+  // Set this to the max number of records that can be written simultaneously.
+  static constexpr uint32_t kMaxReservedRecords = 1;
+
+  // Set this to the min number of records that must be readable.
+  static constexpr uint32_t kMinAvailableRecords = 1;
+};
+
+// Nonblocking ring suitable for concurrent single-writer, multi-reader access.
+//
+// Readers never block the writer and thus this is a nondeterministically lossy
+// transport in the absence of external synchronization. Don't use this as a
+// transport when deterministic behavior is required.
+//
+// Readers may have a read-only mapping; each reader's state is a single local
+// sequence number.
+//
+// The implementation takes care to avoid data races on record access.
+// Inconsistent data can only be returned if at least 2^32 records are written
+// during the read-side critical section.
+//
+// In addition, both readers and the writer are careful to avoid accesses
+// outside the bounds of the mmap area passed in during initialization even if
+// there is a misbehaving or malicious task with write access to the mmap area.
+//
+// When dynamic record size is enabled, readers use the record size in the ring
+// header when indexing the ring, so that it is possible to extend the record
+// type without breaking the read-side ABI.
+//
+// Avoid calling Put() in a tight loop; there should be significantly more time
+// between successive puts than it takes to read one record from memory to
+// ensure Get() completes quickly. This requirement should not be difficult to
+// achieve for most practical uses; 4kB puts at 10,000Hz is well below the
+// scaling limit on current mobile chips.
+//
+// Example Writer Usage:
+//
+//   using Record = MyRecordType;
+//   using Ring = BroadcastRing<Record>;
+//
+//   uint32_t record_count = kMyDesiredCount;
+//   uint32_t ring_size = Ring::MemorySize(record_count);
+//
+//   size_t page_size = sysconf(_SC_PAGESIZE);
+//   uint32_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1);
+//
+//   // Allocate & map via your preferred mechanism, e.g.
+//   int fd = open("/dev/shm/ring_test", O_CREAT|O_RDWR|O_CLOEXEC, 0600);
+//   CHECK(fd >= 0);
+//   CHECK(!ftruncate(fd, ring_size));
+//   void *mmap_base = mmap(nullptr, mmap_size, PROT_READ|PROT_WRITE,
+//                          MAP_SHARED, fd, 0);
+//   CHECK(mmap_base != MAP_FAILED);
+//   close(fd);
+//
+//   Ring ring = Ring::Create(mmap_base, mmap_size, record_count);
+//
+//   while (!done)
+//     ring.Put(BuildNextRecordBlocking());
+//
+//   CHECK(!munmap(mmap_base, mmap_size));
+//
+// Example Reader Usage:
+//
+//   using Record = MyRecordType;
+//   using Ring = BroadcastRing<Record>;
+//
+//   // Map via your preferred mechanism, e.g.
+//   int fd = open("/dev/shm/ring_test", O_RDONLY|O_CLOEXEC);
+//   CHECK(fd >= 0);
+//   struct stat st;
+//   CHECK(!fstat(fd, &st));
+//   size_t mmap_size = st.st_size;
+//   void *mmap_base = mmap(nullptr, mmap_size, PROT_READ,
+//                          MAP_SHARED, fd, 0);
+//   CHECK(mmap_base != MAP_FAILED);
+//   close(fd);
+//
+//   Ring ring;
+//   bool import_ok;
+//   std::tie(ring, import_ok) = Ring::Import(mmap_base, mmap_size);
+//   CHECK(import_ok);
+//
+//   uint32_t sequence;
+//
+//   // Choose starting point (using "0" is unpredictable but not dangerous)
+//   sequence = ring.GetOldestSequence();  // The oldest available
+//   sequence = ring.GetNewestSequence();  // The newest available
+//   sequence = ring.GetNextSequence();    // The next one produced
+//
+//   while (!done) {
+//     Record record;
+//
+//     if (you_want_to_process_all_available_records) {
+//       while (ring.Get(&sequence, &record)) {
+//         ProcessRecord(sequence, record);
+//         sequence++;
+//       }
+//     } else if (you_want_to_skip_to_the_newest_record) {
+//       if (ring.GetNewest(&sequence, &record)) {
+//         ProcessRecord(sequence, record);
+//         sequence++;
+//       }
+//     }
+//
+//     DoSomethingExpensiveOrBlocking();
+//   }
+//
+//   CHECK(!munmap(mmap_base, mmap_size));
+//
+template <typename RecordType, typename BaseTraits = DefaultRingTraits>
+class BroadcastRing {
+ public:
+  using Record = RecordType;
+  struct Traits : public BaseTraits {
+    // Must have enough space for writers, plus enough space for readers.
+    static constexpr int kMinRecordCount =
+        BaseTraits::kMaxReservedRecords + BaseTraits::kMinAvailableRecords;
+
+    // Count of zero means dynamic, non-zero means static.
+    static constexpr bool kUseStaticRecordCount =
+        (BaseTraits::kStaticRecordCount != 0);
+
+    // If both record size and count are static then the overall size is too.
+    static constexpr bool kIsStaticSize =
+        BaseTraits::kUseStaticRecordSize && kUseStaticRecordCount;
+  };
+
+  static constexpr bool IsPowerOfTwo(uint32_t size) {
+    return (size & (size - 1)) == 0;
+  }
+
+  // Sanity check the options provided in Traits.
+  static_assert(Traits::kMinRecordCount >= 1, "Min record count too small");
+  static_assert(!Traits::kUseStaticRecordCount ||
+                    Traits::kStaticRecordCount >= Traits::kMinRecordCount,
+                "Static record count is too small");
+  static_assert(!Traits::kStaticRecordCount ||
+                    IsPowerOfTwo(Traits::kStaticRecordCount),
+                "Static record count is not a power of two");
+  static_assert(std::is_standard_layout<Record>::value,
+                "Record type must be standard layout");
+
+  BroadcastRing() {}
+
+  // Creates a new ring at |mmap| with |record_count| records.
+  //
+  // There must be at least |MemorySize(record_count)| bytes of space already
+  // allocated at |mmap|. The ring does not take ownership.
+  //
+  // Use this function for dynamically sized rings.
+  static BroadcastRing Create(void* mmap, size_t mmap_size,
+                              uint32_t record_count) {
+    BroadcastRing ring(mmap);
+    CHECK(ring.ValidateGeometry(mmap_size, sizeof(Record), record_count));
+    ring.InitializeHeader(sizeof(Record), record_count);
+    return ring;
+  }
+
+  // Creates a new ring at |mmap|.
+  //
+  // There must be at least |MemorySize()| bytes of space already allocated at
+  // |mmap|. The ring does not take ownership.
+  //
+  // Use this function for statically sized rings.
+  static BroadcastRing Create(void* mmap, size_t mmap_size) {
+    static_assert(Traits::kUseStaticRecordCount,
+                  "Wrong Create() function called for dynamic record count");
+    return Create(mmap, mmap_size, Traits::kStaticRecordCount);
+  }
+
+  // Imports an existing ring at |mmap|.
+  //
+  // Import may fail if the ring parameters in the mmap header are not sensible.
+  // In this case the returned boolean is false; make sure to check this value.
+  static std::tuple<BroadcastRing, bool> Import(void* mmap, size_t mmap_size) {
+    BroadcastRing ring(mmap);
+    uint32_t record_size = 0;
+    uint32_t record_count = 0;
+    if (mmap_size >= sizeof(Header)) {
+      record_size = std::atomic_load_explicit(&ring.header_mmap()->record_size,
+                                              std::memory_order_relaxed);
+      record_count = std::atomic_load_explicit(
+          &ring.header_mmap()->record_count, std::memory_order_relaxed);
+    }
+    bool ok = ring.ValidateGeometry(mmap_size, record_size, record_count);
+    return std::make_tuple(ring, ok);
+  }
+
+  ~BroadcastRing() {}
+
+  // Calculates the space necessary for a ring of size |record_count|.
+  //
+  // Use this function for dynamically sized rings.
+  static constexpr size_t MemorySize(uint32_t record_count) {
+    return sizeof(Header) + sizeof(Record) * record_count;
+  }
+
+  // Calculates the space necessary for a statically sized ring.
+  //
+  // Use this function for statically sized rings.
+  static constexpr size_t MemorySize() {
+    static_assert(
+        Traits::kUseStaticRecordCount,
+        "Wrong MemorySize() function called for dynamic record count");
+    return MemorySize(Traits::kStaticRecordCount);
+  }
+
+  // Writes a record to the ring.
+  //
+  // The oldest record is overwritten unless the ring is not already full.
+  void Put(const Record& record) {
+    const int kRecordCount = 1;
+    Reserve(kRecordCount);
+    Geometry geometry = GetGeometry();
+    PutRecordInternal(&record, record_mmap_writer(geometry.tail_index));
+    Publish(kRecordCount);
+  }
+
+  // Gets sequence number of the oldest currently available record.
+  uint32_t GetOldestSequence() const {
+    return std::atomic_load_explicit(&header_mmap()->head,
+                                     std::memory_order_relaxed);
+  }
+
+  // Gets sequence number of the first future record.
+  //
+  // If the returned value is passed to Get() and there is no concurrent Put(),
+  // Get() will return false.
+  uint32_t GetNextSequence() const {
+    return std::atomic_load_explicit(&header_mmap()->tail,
+                                     std::memory_order_relaxed);
+  }
+
+  // Gets sequence number of the newest currently available record.
+  uint32_t GetNewestSequence() const { return GetNextSequence() - 1; }
+
+  // Copies the oldest available record with sequence at least |*sequence| to
+  // |record|.
+  //
+  // Returns false if there is no recent enough record available.
+  //
+  // Updates |*sequence| with the sequence number of the record returned. To get
+  // the following record, increment this number by one.
+  //
+  // This function synchronizes with two other operations:
+  //
+  //    (1) Load-Acquire of |tail|
+  //
+  //        Together with the store-release in Publish(), this load-acquire
+  //        ensures each store to a record in PutRecordInternal() happens-before
+  //        any corresponding load in GetRecordInternal().
+  //
+  //        i.e. the stores for the records with sequence numbers < |tail| have
+  //        completed from our perspective
+  //
+  //    (2) Acquire Fence between record access & final load of |head|
+  //
+  //        Together with the release fence in Reserve(), this ensures that if
+  //        GetRecordInternal() loads a value stored in some execution of
+  //        PutRecordInternal(), then the store of |head| in the Reserve() that
+  //        preceeded it happens-before our final load of |head|.
+  //
+  //        i.e. if we read a record with sequence number >= |final_head| then
+  //        no later store to that record has completed from our perspective
+  bool Get(uint32_t* sequence /*inout*/, Record* record /*out*/) const {
+    for (;;) {
+      uint32_t tail = std::atomic_load_explicit(&header_mmap()->tail,
+                                                std::memory_order_acquire);
+      uint32_t head = std::atomic_load_explicit(&header_mmap()->head,
+                                                std::memory_order_relaxed);
+
+      if (tail - head > record_count())
+        continue;  // Concurrent modification; re-try.
+
+      if (*sequence - head > tail - head)
+        *sequence = head;  // Out of window, skip forward to first available.
+
+      if (*sequence == tail) return false;  // No new records available.
+
+      Geometry geometry =
+          CalculateGeometry(record_count(), record_size(), *sequence, tail);
+
+      // Compute address explicitly in case record_size > sizeof(Record).
+      RecordStorage* record_storage = record_mmap_reader(geometry.head_index);
+
+      GetRecordInternal(record_storage, record);
+
+      // NB: It is not sufficient to change this to a load-acquire of |head|.
+      std::atomic_thread_fence(std::memory_order_acquire);
+
+      uint32_t final_head = std::atomic_load_explicit(
+          &header_mmap()->head, std::memory_order_relaxed);
+
+      if (final_head - head > *sequence - head)
+        continue;  // Concurrent modification; re-try.
+
+      // Note: Combining the above 4 comparisons gives:
+      // 0 <= final_head - head <= sequence - head < tail - head <= record_count
+      //
+      // We can also write this as:
+      // head <=* final_head <=* sequence <* tail <=* head + record_count
+      //
+      // where <* orders by difference from head: x <* y if x - head < y - head.
+      // This agrees with the order of sequence updates during "put" operations.
+      return true;
+    }
+  }
+
+  // Copies the newest available record with sequence at least |*sequence| to
+  // |record|.
+  //
+  // Returns false if there is no recent enough record available.
+  //
+  // Updates |*sequence| with the sequence number of the record returned. To get
+  // the following record, increment this number by one.
+  bool GetNewest(uint32_t* sequence, Record* record) const {
+    uint32_t newest_sequence = GetNewestSequence();
+    if (*sequence == newest_sequence + 1) return false;
+    *sequence = newest_sequence;
+    return Get(sequence, record);
+  }
+
+  uint32_t record_count() const { return record_count_internal(); }
+  uint32_t record_size() const { return record_size_internal(); }
+  static constexpr uint32_t mmap_alignment() { return alignof(Mmap); }
+
+ private:
+  struct Header {
+    // Record size for reading out of the ring. Writers always write the full
+    // length; readers may need to read a prefix of each record.
+    std::atomic<uint32_t> record_size;
+
+    // Number of records in the ring.
+    std::atomic<uint32_t> record_count;
+
+    // Readable region is [head % record_count, tail % record_count).
+    //
+    // The region in [tail % record_count, head % record_count) was either never
+    // populated or is being updated.
+    //
+    // These are sequences numbers, not indexes - indexes should be computed
+    // with a modulus.
+    //
+    // To ensure consistency:
+    //
+    // (1) Writes advance |head| past any updated records before writing to
+    //     them, and advance |tail| after they are written.
+    // (2) Readers check |tail| before reading data and |head| after,
+    //     making sure to discard any data that was written to concurrently.
+    std::atomic<uint32_t> head;
+    std::atomic<uint32_t> tail;
+  };
+
+  // Store using the standard word size.
+  using StorageType = long;  // NOLINT
+
+  // Always require 8 byte alignment so that the same record sizes are legal on
+  // 32 and 64 bit builds.
+  static constexpr size_t kRecordAlignment = 8;
+  static_assert(kRecordAlignment % sizeof(StorageType) == 0,
+                "Bad record alignment");
+
+  struct RecordStorage {
+    // This is accessed with relaxed atomics to prevent data races on the
+    // contained data, which would be undefined behavior.
+    std::atomic<StorageType> data[sizeof(Record) / sizeof(StorageType)];
+  };
+
+  static_assert(sizeof(StorageType) *
+                        std::extent<decltype(RecordStorage::data)>() ==
+                    sizeof(Record),
+                "Record length must be a multiple of sizeof(StorageType)");
+
+  struct Geometry {
+    // Static geometry.
+    uint32_t record_count;
+    uint32_t record_size;
+
+    // Copy of atomic sequence counts.
+    uint32_t head;
+    uint32_t tail;
+
+    // First index of readable region.
+    uint32_t head_index;
+
+    // First index of writable region.
+    uint32_t tail_index;
+
+    // Number of records in readable region.
+    uint32_t count;
+
+    // Number of records in writable region.
+    uint32_t space;
+  };
+
+  // Mmap area layout.
+  //
+  // Readers should not index directly into |records| as this is not valid when
+  // dynamic record sizes are used; use record_mmap_reader() instead.
+  struct Mmap {
+    Header header;
+    RecordStorage records[];
+  };
+
+  static_assert(std::is_standard_layout<Mmap>::value,
+                "Mmap must be standard layout");
+  static_assert(sizeof(std::atomic<uint32_t>) == sizeof(uint32_t),
+                "Lockless atomics contain extra state");
+  static_assert(sizeof(std::atomic<StorageType>) == sizeof(StorageType),
+                "Lockless atomics contain extra state");
+
+  explicit BroadcastRing(void* mmap) {
+    CHECK_EQ(0U, reinterpret_cast<uintptr_t>(mmap) % alignof(Mmap));
+    data_.mmap = reinterpret_cast<Mmap*>(mmap);
+  }
+
+  // Initializes the mmap area header for a new ring.
+  void InitializeHeader(uint32_t record_size, uint32_t record_count) {
+    constexpr uint32_t kInitialSequence = -256;  // Force an early wrap.
+    std::atomic_store_explicit(&header_mmap()->record_size, record_size,
+                               std::memory_order_relaxed);
+    std::atomic_store_explicit(&header_mmap()->record_count, record_count,
+                               std::memory_order_relaxed);
+    std::atomic_store_explicit(&header_mmap()->head, kInitialSequence,
+                               std::memory_order_relaxed);
+    std::atomic_store_explicit(&header_mmap()->tail, kInitialSequence,
+                               std::memory_order_relaxed);
+  }
+
+  // Validates ring geometry.
+  //
+  // Ring geometry is validated carefully on import and then cached. This allows
+  // us to avoid out-of-range accesses even if the parameters in the header are
+  // later changed.
+  bool ValidateGeometry(size_t mmap_size, uint32_t header_record_size,
+                        uint32_t header_record_count) {
+    set_record_size(header_record_size);
+    set_record_count(header_record_count);
+
+    if (record_size() != header_record_size) return false;
+    if (record_count() != header_record_count) return false;
+    if (record_count() < Traits::kMinRecordCount) return false;
+    if (record_size() < sizeof(Record)) return false;
+    if (record_size() % kRecordAlignment != 0) return false;
+    if (!IsPowerOfTwo(record_count())) return false;
+
+    size_t memory_size = record_count() * record_size();
+    if (memory_size / record_size() != record_count()) return false;
+    if (memory_size + sizeof(Header) < memory_size) return false;
+    if (memory_size + sizeof(Header) > mmap_size) return false;
+
+    return true;
+  }
+
+  // Copies a record into the ring.
+  //
+  // This is done with relaxed atomics because otherwise it is racy according to
+  // the C++ memory model. This is very low overhead once optimized.
+  static inline void PutRecordInternal(const Record* in, RecordStorage* out) {
+    StorageType data[sizeof(Record) / sizeof(StorageType)];
+    memcpy(data, in, sizeof(*in));
+    for (size_t i = 0; i < std::extent<decltype(data)>(); ++i) {
+      std::atomic_store_explicit(&out->data[i], data[i],
+                                 std::memory_order_relaxed);
+    }
+  }
+
+  // Copies a record out of the ring.
+  //
+  // This is done with relaxed atomics because otherwise it is racy according to
+  // the C++ memory model. This is very low overhead once optimized.
+  static inline void GetRecordInternal(RecordStorage* in, Record* out) {
+    StorageType data[sizeof(Record) / sizeof(StorageType)];
+    for (size_t i = 0; i < std::extent<decltype(data)>(); ++i) {
+      data[i] =
+          std::atomic_load_explicit(&in->data[i], std::memory_order_relaxed);
+    }
+    memcpy(out, &data, sizeof(*out));
+  }
+
+  // Converts a record's sequence number into a storage index.
+  static uint32_t SequenceToIndex(uint32_t sequence, uint32_t record_count) {
+    return sequence & (record_count - 1);
+  }
+
+  // Computes readable & writable ranges from ring parameters.
+  static Geometry CalculateGeometry(uint32_t record_count, uint32_t record_size,
+                                    uint32_t head, uint32_t tail) {
+    Geometry geometry;
+    geometry.record_count = record_count;
+    geometry.record_size = record_size;
+    DCHECK_EQ(0U, geometry.record_size % kRecordAlignment);
+    geometry.head = head;
+    geometry.tail = tail;
+    geometry.head_index = SequenceToIndex(head, record_count);
+    geometry.tail_index = SequenceToIndex(tail, record_count);
+    geometry.count = geometry.tail - geometry.head;
+    DCHECK_LE(geometry.count, record_count);
+    geometry.space = geometry.record_count - geometry.count;
+    return geometry;
+  }
+
+  // Gets the current ring readable & writable regions.
+  //
+  // This this is always safe from the writing thread since it is the only
+  // thread allowed to update the header.
+  Geometry GetGeometry() const {
+    return CalculateGeometry(
+        record_count(), record_size(),
+        std::atomic_load_explicit(&header_mmap()->head,
+                                  std::memory_order_relaxed),
+        std::atomic_load_explicit(&header_mmap()->tail,
+                                  std::memory_order_relaxed));
+  }
+
+  // Makes space for at least |reserve_count| records.
+  //
+  // There is nothing to prevent overwriting records that have concurrent
+  // readers. We do however ensure that this situation can be detected: the
+  // fence ensures the |head| update will be the first update seen by readers,
+  // and readers check this value after reading and discard data that may have
+  // been concurrently modified.
+  void Reserve(uint32_t reserve_count) {
+    Geometry geometry = GetGeometry();
+    DCHECK_LE(reserve_count, Traits::kMaxReservedRecords);
+    uint32_t needed =
+        (geometry.space >= reserve_count ? 0 : reserve_count - geometry.space);
+
+    std::atomic_store_explicit(&header_mmap()->head, geometry.head + needed,
+                               std::memory_order_relaxed);
+
+    // NB: It is not sufficient to change this to a store-release of |head|.
+    std::atomic_thread_fence(std::memory_order_release);
+  }
+
+  // Makes |publish_count| records visible to readers.
+  //
+  // Space must have been reserved by a previous call to Reserve().
+  void Publish(uint32_t publish_count) {
+    Geometry geometry = GetGeometry();
+    DCHECK_LE(publish_count, geometry.space);
+    std::atomic_store_explicit(&header_mmap()->tail,
+                               geometry.tail + publish_count,
+                               std::memory_order_release);
+  }
+
+  // Helpers to compute addresses in mmap area.
+  Mmap* mmap() const { return data_.mmap; }
+  Header* header_mmap() const { return &data_.mmap->header; }
+  RecordStorage* record_mmap_writer(uint32_t index) const {
+    DCHECK_EQ(sizeof(Record), record_size());
+    return &data_.mmap->records[index];
+  }
+  RecordStorage* record_mmap_reader(uint32_t index) const {
+    if (Traits::kUseStaticRecordSize) {
+      return &data_.mmap->records[index];
+    } else {
+      // Calculate the location of a record in the ring without assuming that
+      // sizeof(Record) == record_size.
+      return reinterpret_cast<RecordStorage*>(
+          reinterpret_cast<char*>(data_.mmap->records) + index * record_size());
+    }
+  }
+
+  // The following horrifying template gunk enables us to store just the mmap
+  // base pointer for compile-time statically sized rings. Dynamically sized
+  // rings also store the validated copy of the record size & count.
+  //
+  // This boils down to: use a compile time constant if available, and otherwise
+  // load the value that was validated on import from a member variable.
+  template <typename T = Traits>
+  typename std::enable_if<T::kUseStaticRecordSize, uint32_t>::type
+  record_size_internal() const {
+    return sizeof(Record);
+  }
+
+  template <typename T = Traits>
+  typename std::enable_if<!T::kUseStaticRecordSize, uint32_t>::type
+  record_size_internal() const {
+    return data_.record_size;
+  }
+
+  template <typename T = Traits>
+  typename std::enable_if<T::kUseStaticRecordSize, void>::type set_record_size(
+      uint32_t /*record_size*/) {}
+
+  template <typename T = Traits>
+  typename std::enable_if<!T::kUseStaticRecordSize, void>::type set_record_size(
+      uint32_t record_size) {
+    data_.record_size = record_size;
+  }
+
+  template <typename T = Traits>
+  typename std::enable_if<T::kUseStaticRecordCount, uint32_t>::type
+  record_count_internal() const {
+    return Traits::kStaticRecordCount;
+  }
+
+  template <typename T = Traits>
+  typename std::enable_if<!T::kUseStaticRecordCount, uint32_t>::type
+  record_count_internal() const {
+    return data_.record_count;
+  }
+
+  template <typename T = Traits>
+  typename std::enable_if<T::kUseStaticRecordCount, void>::type
+  set_record_count(uint32_t /*record_count*/) const {}
+
+  template <typename T = Traits>
+  typename std::enable_if<!T::kUseStaticRecordCount, void>::type
+  set_record_count(uint32_t record_count) {
+    data_.record_count = record_count;
+  }
+
+  // Data we need to store for statically sized rings.
+  struct DataStaticSize {
+    Mmap* mmap = nullptr;
+  };
+
+  // Data we need to store for dynamically sized rings.
+  struct DataDynamicSize {
+    Mmap* mmap = nullptr;
+
+    // These are cached to make sure misbehaving writers cannot cause
+    // out-of-bounds memory accesses by updating the values in the mmap header.
+    uint32_t record_size = 0;
+    uint32_t record_count = 0;
+  };
+
+  using DataStaticOrDynamic =
+      typename std::conditional<Traits::kIsStaticSize, DataStaticSize,
+                                DataDynamicSize>::type;
+
+  DataStaticOrDynamic data_;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_BROADCAST_RING_H_
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 452bad0..68b9c81 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -25,6 +25,7 @@
 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 2749fd1..a1f952e 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -20,6 +20,7 @@
 
 namespace {
 
+// TODO(hendrikw): These flags can not be hard coded.
 constexpr int kUncachedBlobUsageFlags = GRALLOC_USAGE_SW_READ_RARELY |
                                         GRALLOC_USAGE_SW_WRITE_RARELY |
                                         GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -110,6 +111,7 @@
 int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
   int width = static_cast<int>(size);
   int height = 1;
+  // TODO(hendrikw): These flags can not be hard coded.
   constexpr int usage = GRALLOC_USAGE_SW_READ_RARELY |
                         GRALLOC_USAGE_SW_WRITE_RARELY |
                         GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -196,18 +198,27 @@
       InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
 }
 
-BufferProducer::BufferProducer(int width, int height, int format, int usage,
+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) {}
+
+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)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
-           "BufferProducer::BufferProducer: fd=%d width=%d height=%d format=%d "
-           "usage=%d, metadata_size=%zu, slice_count=%zu",
-           event_fd(), width, height, format, usage, metadata_size,
-           slice_count);
+           "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+           " metadata_size=%zu slice_count=%zu",
+           event_fd(), width, height, format, producer_usage, consumer_usage,
+           metadata_size, slice_count);
 
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, usage, metadata_size, slice_count);
+      width, height, format, producer_usage, consumer_usage, metadata_size,
+      slice_count);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -226,21 +237,29 @@
 }
 
 BufferProducer::BufferProducer(const std::string& name, int user_id,
-                               int group_id, int width, int height, int format,
-                               int usage, size_t meta_size_bytes,
+                               int group_id, uint32_t width, uint32_t height,
+                               uint32_t format, uint32_t usage,
+                               size_t meta_size_bytes, size_t slice_count)
+    : BufferProducer(name, user_id, group_id, width, height, format, usage,
+                     usage, meta_size_bytes, slice_count) {}
+
+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)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
-           "group_id=%d width=%d height=%d format=%d usage=%d, "
-           "meta_size_bytes=%zu, slice_count=%zu",
+           "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
            event_fd(), name.c_str(), user_id, group_id, width, height, format,
-           usage, meta_size_bytes, slice_count);
+           producer_usage, consumer_usage, meta_size_bytes, slice_count);
 
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
-      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
-      slice_count);
+      name, user_id, group_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes, slice_count);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -260,18 +279,25 @@
   }
 }
 
-BufferProducer::BufferProducer(int usage, size_t size)
+BufferProducer::BufferProducer(uint32_t usage, size_t size)
+    : BufferProducer(usage, usage, size) {}
+
+BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
+                               size_t size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
-  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%d size=%zu", usage,
-           size);
+  ALOGD_IF(TRACE,
+           "BufferProducer::BufferProducer: producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64 " size=%zu",
+           producer_usage, consumer_usage, size);
   const int width = static_cast<int>(size);
   const int height = 1;
   const int format = HAL_PIXEL_FORMAT_BLOB;
   const size_t meta_size_bytes = 0;
   const size_t slice_count = 1;
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, usage, meta_size_bytes, slice_count);
+      width, height, format, producer_usage, consumer_usage, meta_size_bytes,
+      slice_count);
   if (!status) {
     ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
           status.GetErrorMessage().c_str());
@@ -289,21 +315,27 @@
 }
 
 BufferProducer::BufferProducer(const std::string& name, int user_id,
-                               int group_id, int usage, size_t size)
+                               int group_id, uint32_t usage, size_t size)
+    : BufferProducer(name, user_id, group_id, usage, usage, size) {}
+
+BufferProducer::BufferProducer(const std::string& name, int user_id,
+                               int group_id, uint64_t producer_usage,
+                               uint64_t consumer_usage, size_t size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
-           "usage=%d size=%zu",
-           name.c_str(), user_id, group_id, usage, size);
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu",
+           name.c_str(), user_id, group_id, producer_usage, consumer_usage,
+           size);
   const int width = static_cast<int>(size);
   const int height = 1;
   const int format = HAL_PIXEL_FORMAT_BLOB;
   const size_t meta_size_bytes = 0;
   const size_t slice_count = 1;
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
-      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
-      slice_count);
+      name, user_id, group_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes, slice_count);
   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 dfeed50..c772ed3 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -107,11 +107,14 @@
   // The following methods return settings of the first buffer. Currently,
   // it is only possible to create multi-buffer BufferHubBuffers with the same
   // settings.
-  int width() const { return slices_[0].width(); }
-  int height() const { return slices_[0].height(); }
-  int stride() const { return slices_[0].stride(); }
-  int format() const { return slices_[0].format(); }
-  int usage() const { return slices_[0].usage(); }
+  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(); }
 
  protected:
   explicit BufferHubBuffer(LocalChannelHandle channel);
@@ -218,8 +221,12 @@
   // arguments as the constructors.
 
   // Constructs a buffer with the given geometry and parameters.
-  BufferProducer(int width, int height, int format, int usage,
-                 size_t metadata_size = 0, size_t slice_count = 1);
+  BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+                 uint32_t usage, size_t metadata_size = 0,
+                 size_t slice_count = 1);
+  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);
 
   // 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
@@ -233,16 +240,24 @@
   // created and cannot be changed. A user or group id of -1 disables checks for
   // that respective id. A user or group id of 0 is substituted with the
   // effective user or group id of the calling process.
-  BufferProducer(const std::string& name, int user_id, int group_id, int width,
-                 int height, int format, int 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,
+                 uint32_t usage, size_t metadata_size = 0,
                  size_t slice_count = 1);
+  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);
 
   // Constructs a blob (flat) buffer with the given usage flags.
-  BufferProducer(int usage, size_t size);
+  BufferProducer(uint32_t usage, size_t size);
+  BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);
 
   // Constructs a persistent blob (flat) buffer and binds it to |name|.
-  BufferProducer(const std::string& name, int user_id, int group_id, int usage,
-                 size_t size);
+  BufferProducer(const std::string& name, int user_id, int group_id,
+                 uint32_t usage, size_t size);
+  BufferProducer(const std::string& name, int user_id, int group_id,
+                 uint64_t producer_usage, uint64_t consumer_usage, size_t size);
 
   // Constructs a channel to persistent buffer by name only. The buffer must
   // have been previously created or made persistent.
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index 7ed024f..b6302f1 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -24,7 +24,8 @@
         width_(buffer.width()),
         height_(buffer.height()),
         format_(buffer.format()),
-        usage_(buffer.usage()) {
+        producer_usage_(buffer.producer_usage()),
+        consumer_usage_(buffer.consumer_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;
@@ -37,6 +38,7 @@
     }
   }
   NativeBufferHandle(NativeBufferHandle&& other) = default;
+  NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
 
   // Imports the native handle into the given IonBuffer instance.
   int Import(IonBuffer* buffer) {
@@ -46,9 +48,10 @@
     for (const auto& fd : fds_)
       fd_ints.push_back(fd.Get());
 
-    const int ret = buffer->Import(fd_ints.data(), fd_ints.size(),
-                                   opaque_ints_.data(), opaque_ints_.size(),
-                                   width_, height_, stride_, format_, usage_);
+    const int ret =
+        buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
+                       opaque_ints_.size(), width_, height_, stride_, format_,
+                       producer_usage_, consumer_usage_);
     if (ret < 0)
       return ret;
 
@@ -68,24 +71,32 @@
 
  private:
   int id_;
-  int stride_;
-  int width_;
-  int height_;
-  int format_;
-  int usage_;
+  uint32_t stride_;
+  uint32_t width_;
+  uint32_t height_;
+  uint32_t format_;
+  uint64_t producer_usage_;
+  uint64_t consumer_usage_;
   std::vector<int> opaque_ints_;
   std::vector<FileHandleType> fds_;
 
-  void Clear() { id_ = stride_ = width_ = height_ = format_ = usage_ = -1; }
+  void Clear() {
+    id_ = -1;
+    stride_ = width_ = height_ = format_ = producer_usage_ = consumer_usage_ =
+        0;
+  }
 
   PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
-                           width_, height_, format_, usage_, opaque_ints_,
-                           fds_);
+                           width_, height_, format_, producer_usage_,
+                           consumer_usage_, opaque_ints_, fds_);
 
   NativeBufferHandle(const NativeBufferHandle&) = delete;
   void operator=(const NativeBufferHandle&) = delete;
 };
 
+using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>;
+using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>;
+
 template <typename FileHandleType>
 class FenceHandle {
  public:
@@ -127,6 +138,23 @@
   PDX_SERIALIZABLE_MEMBERS(QueueInfo, meta_size_bytes, id);
 };
 
+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;
+
+ 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);
+};
+
 // BufferHub Service RPC interface. Defines the endpoints, op codes, and method
 // type signatures supported by bufferhubd.
 struct BufferHubRPC {
@@ -173,44 +201,46 @@
 
   // Methods.
   PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
-                    int(int width, int height, int format, int usage,
-                        size_t meta_size_bytes, size_t slice_count));
+                    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));
   PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
-                    int(const std::string& name, int user_id, int group_id,
-                        int width, int height, int format, int usage,
-                        size_t meta_size_bytes, size_t slice_count));
+                    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));
   PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
-                    int(const std::string& name));
+                    void(const std::string& name));
   PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
                     NativeBufferHandle<LocalHandle>(unsigned index));
   PDX_REMOTE_METHOD(GetBuffers, kOpGetBuffers,
                     std::vector<NativeBufferHandle<LocalHandle>>(Void));
   PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
-                    int(const std::string& name, int user_id, int group_id));
+                    void(const std::string& name, int user_id, int group_id));
   PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence,
-                    int(Void));
+                    void(Void));
   PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
-                    int(LocalFence acquire_fence, MetaData));
+                    void(LocalFence acquire_fence, MetaData));
   PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
   PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire,
                     std::pair<LocalFence, MetaData>(std::size_t metadata_size));
   PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
-                    int(LocalFence release_fence));
-  PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, int(bool ignore));
+                    void(LocalFence release_fence));
+  PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
 
   // Buffer Queue Methods.
   PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
-                    QueueInfo(size_t meta_size_bytes, int usage_set_mask,
-                              int usage_clear_mask, int usage_deny_set_mask,
-                              int usage_deny_clear_mask));
+                    QueueInfo(size_t meta_size_bytes,
+                              const UsagePolicy& usage_policy));
   PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
                     LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void));
   PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
                     kOpProducerQueueAllocateBuffers,
                     std::vector<std::pair<LocalChannelHandle, size_t>>(
-                        int width, int height, int format, int usage,
+                        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));
   PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
                     void(size_t slot));
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index ffc42d6..e167a17 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -12,11 +12,20 @@
 class IonBuffer {
  public:
   IonBuffer();
-  IonBuffer(int width, int height, int format, int usage);
-  IonBuffer(buffer_handle_t handle, int width, int height, int stride,
-            int format, int usage);
-  IonBuffer(buffer_handle_t handle, int width, int height, int layer_count,
-            int stride, int layer_stride, int format, int usage);
+  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(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t stride, uint32_t format, uint32_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);
   ~IonBuffer();
 
   IonBuffer(IonBuffer&& other);
@@ -30,25 +39,36 @@
   // 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(int width, int height, int format, int usage);
+  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);
 
   // Resets the underlying native handle and parameters, freeing the previous
   // native handle if necessary.
-  void Reset(buffer_handle_t handle, int width, int height, int stride,
-             int format, int usage);
+  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);
 
   // 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, int width, int height, int stride,
-             int format, int usage);
+  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);
 
   // 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, int width, int height, int stride, int format,
-             int usage);
+             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);
 
   // Duplicates the native handle underlying |other| and then imports it. This
   // is useful for creating multiple, independent views of the same Ion/Gralloc
@@ -56,8 +76,8 @@
   // duplication or import fail the previous native handle is left intact.
   int Duplicate(const IonBuffer* other);
 
-  int Lock(int usage, int x, int y, int width, int height, void** address);
-  int LockYUV(int usage, int x, int y, int width, int height,
+  int Lock(uint32_t usage, int x, int y, int width, int height, void** address);
+  int LockYUV(uint32_t usage, int x, int y, int width, int height,
               struct android_ycbcr* yuv);
   int Unlock();
 
@@ -65,19 +85,29 @@
   buffer_handle_t handle() const {
     return buffer_.get() ? buffer_->handle : nullptr;
   }
-  int width() const { return buffer_.get() ? buffer_->getWidth() : 0; }
-  int height() const { return buffer_.get() ? buffer_->getHeight() : 0; }
-  int layer_count() const {
+  uint32_t width() const { return buffer_.get() ? buffer_->getWidth() : 0; }
+  uint32_t height() const { return buffer_.get() ? buffer_->getHeight() : 0; }
+  uint32_t layer_count() const {
     return buffer_.get() ? buffer_->getLayerCount() : 0;
   }
-  int stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
-  int layer_stride() const { return 0; }
-  int format() const { return buffer_.get() ? buffer_->getPixelFormat() : 0; }
-  int usage() const { return buffer_.get() ? buffer_->getUsage() : 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; }
 
  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/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index e5a56c1..0a6996e 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -2,44 +2,64 @@
 
 #include <log/log.h>
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <grallocusage/GrallocUsageConversion.h>
 #include <utils/Trace.h>
 
 #include <mutex>
 
+namespace {
+
+constexpr uint32_t kDefaultGraphicBufferLayerCount = 1;
+
+}  // anonymous namespace
+
 namespace android {
 namespace dvr {
 
 IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
 
-IonBuffer::IonBuffer(int width, int height, int format, int usage)
+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)
     : IonBuffer() {
-  Alloc(width, height, format, usage);
+  Alloc(width, height, format, producer_usage, consumer_usage);
 }
 
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
-                     int format, int 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) {}
 
+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, int width, int height,
-                     int layer_count, int stride, int layer_stride, int format,
-                     int 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)
     : buffer_(nullptr) {
   ALOGD_IF(TRACE,
-         "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
-         "stride=%d layer stride=%d format=%d usage=%d",
-         handle, width, height, layer_count, stride, layer_stride,
-         format, usage);
+           "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);
   if (handle != 0) {
-    Import(handle, width, height, stride, format, usage);
+    Import(handle, width, height, stride, format, producer_usage,
+           consumer_usage);
   }
 }
 
 IonBuffer::~IonBuffer() {
   ALOGD_IF(TRACE,
-           "IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
-           "format=%d usage=%d",
-           handle() , width(), height(), stride(), format(), usage());
+           "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
+           "format=%u usage=%x",
+           handle(), width(), height(), stride(), format(), usage());
   FreeHandle();
 }
 
@@ -62,55 +82,105 @@
   if (buffer_.get()) {
     // GraphicBuffer unregisters and cleans up the handle if needed
     buffer_ = nullptr;
+    producer_usage_ = 0;
+    consumer_usage_ = 0;
   }
 }
 
-int IonBuffer::Alloc(int width, int height, int format, int usage) {
-  ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
-           width, height, format, usage);
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+                     uint32_t usage) {
+  return Alloc(width, height, format, usage, usage);
+}
 
-  buffer_ = new GraphicBuffer(width, height, format, usage);
-  if (buffer_->initCheck() != OK) {
+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));
+  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;
   }
-  return 0;
 }
 
-void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
-                      int format, int usage) {
+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) {
   ALOGD_IF(TRACE,
-           "IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
-           "usage=%d",
-           handle, width, height, stride, format, usage);
-  Import(handle, width, height, stride, format, usage);
+           "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);
 }
 
-int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
-                      int format, int 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) {
   ATRACE_NAME("IonBuffer::Import1");
   ALOGD_IF(
       TRACE,
-      "IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
-      "usage=%d",
-      handle, width, height, stride, format, usage);
+      "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);
   FreeHandle();
-  buffer_ = new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE,
-          width, height, format, 1, usage, stride);
-  if (buffer_->initCheck() != OK) {
+  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);
+  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;
   }
-  return 0;
 }
 
 int IonBuffer::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, 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) {
   ATRACE_NAME("IonBuffer::Import2");
   ALOGD_IF(TRACE,
-           "IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
-           "stride=%d format=%d usage=%d",
-           fd_count, int_count, width, height, stride, format, usage);
+           "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);
 
   if (fd_count < 0 || int_count < 0) {
     ALOGE("IonBuffer::Import: invalid arguments.");
@@ -128,7 +198,8 @@
   memcpy(handle->data, fd_array, sizeof(int) * fd_count);
   memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
 
-  int ret = Import(handle, width, height, stride, format, usage);
+  const int ret = Import(handle, width, height, stride, format, producer_usage,
+                         consumer_usage);
   if (ret < 0) {
     ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
           strerror(-ret));
@@ -163,8 +234,9 @@
   memcpy(handle->data + fd_count, other->handle()->data + fd_count,
          sizeof(int) * int_count);
 
-  const int ret = Import(handle, other->width(), other->height(),
-                         other->stride(), other->format(), other->usage());
+  const int ret =
+      Import(handle, other->width(), other->height(), other->stride(),
+             other->format(), other->producer_usage(), other->consumer_usage());
   if (ret < 0) {
     ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
           strerror(-ret));
@@ -175,7 +247,7 @@
   return ret;
 }
 
-int IonBuffer::Lock(int usage, int x, int y, int width, int height,
+int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
                     void** address) {
   ATRACE_NAME("IonBuffer::Lock");
   ALOGD_IF(TRACE,
@@ -183,23 +255,23 @@
            "address=%p",
            handle(), usage, x, y, width, height, address);
 
-  status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
-                               address);
+  status_t err =
+      buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
   if (err != NO_ERROR)
     return -EINVAL;
   else
     return 0;
 }
 
-int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
+int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
                        struct android_ycbcr* yuv) {
   ATRACE_NAME("IonBuffer::LockYUV");
   ALOGD_IF(TRACE,
            "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
            handle(), usage, x, y, width, height);
 
-  status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
-                                    yuv);
+  status_t err =
+      buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
   if (err != NO_ERROR)
     return -EINVAL;
   else
@@ -216,5 +288,5 @@
   else
     return 0;
 }
-} // namespace dvr
-} // namespace android
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index e491abc..b431d2f 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -317,7 +317,7 @@
 }
 
 ProducerQueue::ProducerQueue(size_t meta_size)
-    : ProducerQueue(meta_size, 0, 0, 0, 0) {}
+    : ProducerQueue(meta_size, 0, 0, 0, 0, 0, 0, 0, 0) {}
 
 ProducerQueue::ProducerQueue(LocalChannelHandle handle)
     : BASE(std::move(handle)) {
@@ -329,13 +329,22 @@
   }
 }
 
-ProducerQueue::ProducerQueue(size_t meta_size, int usage_set_mask,
-                             int usage_clear_mask, int usage_deny_set_mask,
-                             int usage_deny_clear_mask)
+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)
     : BASE(BufferHubRPC::kClientPath) {
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
-      meta_size, usage_set_mask, usage_clear_mask, usage_deny_set_mask,
-      usage_deny_clear_mask);
+      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});
   if (!status) {
     ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
           status.GetErrorMessage().c_str());
@@ -346,8 +355,17 @@
   SetupQueue(status.get().meta_size_bytes, status.get().id);
 }
 
-int ProducerQueue::AllocateBuffer(int width, int height, int format, int usage,
+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) {
   if (out_slot == nullptr) {
     ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
     return -EINVAL;
@@ -363,7 +381,8 @@
 
   Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
-          width, height, format, usage, slice_count, kBufferCount);
+          width, height, format, producer_usage, consumer_usage, slice_count,
+          kBufferCount);
   if (!status) {
     ALOGE(
         "ProducerQueue::AllocateBuffer failed to create producer buffer "
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 3fe7642..e236c31 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -38,22 +38,8 @@
   }
 
   const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+  sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
 
-  // Create new GraphicBuffer based on the newly created |buffer_producer|. Here
-  // we have to cast |buffer_handle_t| to |native_handle_t|, it's OK because
-  // internally, GraphicBuffer is still an |ANativeWindowBuffer| and |handle|
-  // is still type of |buffer_handle_t| and bears const property.
-  sp<GraphicBuffer> graphic_buffer(new GraphicBuffer(
-      buffer_producer->width(), buffer_producer->height(),
-      buffer_producer->format(),
-      1, /* layer count */
-      buffer_producer->usage(),
-      buffer_producer->stride(),
-      const_cast<native_handle_t*>(buffer_producer->buffer()->handle()),
-      false));
-
-  LOG_ALWAYS_FATAL_IF(NO_ERROR != graphic_buffer->initCheck(),
-                      "Failed to init GraphicBuffer.");
   core_->buffers_[slot].mGraphicBuffer = graphic_buffer;
   core_->buffers_[slot].mRequestBufferCalled = true;
 
@@ -155,9 +141,9 @@
     if (!buffer_producer)
       return NO_MEMORY;
 
-    if (static_cast<int>(width) == buffer_producer->width() &&
-        static_cast<int>(height) == buffer_producer->height() &&
-        static_cast<int>(format) == buffer_producer->format()) {
+    if (width == buffer_producer->width() &&
+        height == buffer_producer->height() &&
+        static_cast<uint32_t>(format) == buffer_producer->format()) {
       // The producer queue returns a buffer producer matches the request.
       break;
     }
@@ -165,8 +151,8 @@
     // Needs reallocation.
     // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
     ALOGI(
-        "dequeueBuffer: requested buffer (w=%u, h=%u, format=%d) is different "
-        "from the buffer returned at slot: %zu (w=%d, h=%d, format=%d). Need "
+        "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
+        "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
         "re-allocattion.",
         width, height, format, slot, buffer_producer->width(),
         buffer_producer->height(), buffer_producer->format());
@@ -322,7 +308,7 @@
 
   output->width = buffer_producer->width();
   output->height = buffer_producer->height();
-  output->transformHint = 0; // default value, we don't use it yet.
+  output->transformHint = 0;  // default value, we don't use it yet.
 
   // |numPendingBuffers| counts of the number of buffers that has been enqueued
   // by the producer but not yet acquired by the consumer. Due to the nature
@@ -456,7 +442,7 @@
   return NO_ERROR;
 }
 
-status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode mode) {
+status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) {
   // Consumer interaction are actually handled by buffer hub, and we need
   // to maintain consumer operations here.  We only need to perform basic input
   // parameter checks here.
@@ -464,7 +450,9 @@
 
   std::unique_lock<std::mutex> lock(core_->mutex_);
 
-  if (api != core_->connected_api_) {
+  if (BufferHubQueueCore::kNoConnectedApi == core_->connected_api_) {
+    return NO_INIT;
+  } else if (api != core_->connected_api_) {
     return BAD_VALUE;
   }
 
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 2b70c5b..255793f 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
@@ -274,12 +274,27 @@
   // |usage_deny_clear_mask| shall not conflict with each other. Such
   // configuration will be treated as invalid input on creation.
   template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create(int usage_set_mask,
-                                               int usage_clear_mask,
-                                               int usage_deny_set_mask,
-                                               int usage_deny_clear_mask) {
+  static std::unique_ptr<ProducerQueue> Create(uint32_t usage_set_mask,
+                                               uint32_t usage_clear_mask,
+                                               uint32_t usage_deny_set_mask,
+                                               uint32_t usage_deny_clear_mask) {
     return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask);
+                        usage_deny_set_mask, usage_deny_clear_mask,
+                        usage_set_mask, usage_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);
   }
 
   // Import a |ProducerQueue| from a channel handle.
@@ -301,7 +316,10 @@
   // use (i.e. in |Gain|'ed mode).
   // Returns Zero on success and negative error code when buffer allocation
   // fails.
-  int AllocateBuffer(int width, int height, int format, int usage,
+  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);
 
   // Add a producer buffer to populate the queue. Once added, a producer buffer
@@ -327,8 +345,14 @@
   // arguments as the constructors.
   explicit ProducerQueue(size_t meta_size);
   ProducerQueue(LocalChannelHandle handle);
-  ProducerQueue(size_t meta_size, int usage_set_mask, int usage_clear_mask,
-                int usage_deny_set_mask, int usage_deny_clear_mask);
+  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);
 
   int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
                     LocalHandle* release_fence) override;
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 6d39cdb..ef50a0f 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -216,7 +216,8 @@
   return 0;
 }
 
-pdx::Status<void> DisplayClient::SetViewerParams(const ViewerParams& viewer_params) {
+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",
@@ -252,16 +253,20 @@
   return DisplaySurfaceClient::Create(width, height, format, usage, flags);
 }
 
-std::unique_ptr<BufferConsumer> DisplayClient::GetPoseBuffer() {
-  auto status = InvokeRemoteMethod<DisplayRPC::GetPoseBuffer>();
+std::unique_ptr<IonBuffer> DisplayClient::GetNamedBuffer(
+    const std::string& name) {
+  auto status = InvokeRemoteMethod<DisplayRPC::GetNamedBuffer>(name);
   if (!status) {
     ALOGE(
-        "DisplayClient::GetPoseBuffer: Failed to get pose buffer %s",
-        status.GetErrorMessage().c_str());
+        "DisplayClient::GetNamedBuffer: Failed to get pose buffer. name=%s, "
+        "error=%s",
+        name.c_str(), status.GetErrorMessage().c_str());
     return nullptr;
   }
 
-  return BufferConsumer::Import(std::move(status));
+  auto ion_buffer = std::make_unique<IonBuffer>();
+  status.take().Import(ion_buffer.get());
+  return ion_buffer;
 }
 
 bool DisplayClient::IsVrAppRunning() {
diff --git a/libs/vr/libdisplay/display_manager_client_impl.cpp b/libs/vr/libdisplay/display_manager_client_impl.cpp
index 7993fce..44b3c4b 100644
--- a/libs/vr/libdisplay/display_manager_client_impl.cpp
+++ b/libs/vr/libdisplay/display_manager_client_impl.cpp
@@ -31,19 +31,22 @@
   return 0;
 }
 
-std::unique_ptr<BufferProducer> DisplayManagerClient::SetupPoseBuffer(
-    size_t extended_region_size, int usage) {
-  auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
-      extended_region_size, usage);
+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::SetupPoseBuffer: Failed to create the pose "
-        "buffer %s",
-        status.GetErrorMessage().c_str());
+        "DisplayManagerClient::SetupNamedBuffer: Failed to create the named "
+        "buffer: name=%s, error=%s",
+        name.c_str(), status.GetErrorMessage().c_str());
     return {};
   }
 
-  return BufferProducer::Import(std::move(status));
+  auto ion_buffer = std::make_unique<IonBuffer>();
+  status.take().Import(ion_buffer.get());
+  return ion_buffer;
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 378f67c..fec2ea5 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -108,7 +108,7 @@
   std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
       int width, int height, int format, int usage, int flags);
 
-  std::unique_ptr<BufferConsumer> GetPoseBuffer();
+  std::unique_ptr<IonBuffer> GetNamedBuffer(const std::string& name);
 
   // Temporary query for current VR status. Will be removed later.
   bool IsVrAppRunning();
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
index 144cd3b..b0a7d13 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
@@ -17,8 +17,10 @@
 
   int GetSurfaceList(std::vector<DisplaySurfaceInfo>* surface_list);
 
-  std::unique_ptr<BufferProducer> SetupPoseBuffer(size_t extended_region_size,
-                                                  int usage);
+  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;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
index ac08650..c12b090 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -9,6 +9,7 @@
 #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 {
@@ -218,7 +219,7 @@
     kOpCreateVideoMeshSurface,
     kOpVideoMeshSurfaceCreateProducerQueue,
     kOpSetViewerParams,
-    kOpGetPoseBuffer,
+    kOpGetNamedBuffer,
     kOpIsVrAppRunning,
   };
 
@@ -247,8 +248,8 @@
                     LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
                     void(const ViewerParams& viewer_params));
-  PDX_REMOTE_METHOD(GetPoseBuffer, kOpGetPoseBuffer,
-                    LocalChannelHandle(Void));
+  PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
+                    LocalNativeBufferHandle(const std::string& name));
   PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, int(Void));
 };
 
@@ -260,7 +261,7 @@
   enum {
     kOpGetSurfaceList = 0,
     kOpUpdateSurfaces,
-    kOpSetupPoseBuffer,
+    kOpSetupNamedBuffer,
   };
 
   // Aliases.
@@ -273,8 +274,11 @@
   PDX_REMOTE_METHOD(
       UpdateSurfaces, kOpUpdateSurfaces,
       int(const std::map<int, DisplaySurfaceAttributes>& updates));
-  PDX_REMOTE_METHOD(SetupPoseBuffer, kOpSetupPoseBuffer,
-                    LocalChannelHandle(size_t extended_region_size, int usage));
+  PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
+                    LocalNativeBufferHandle(const std::string& name,
+                                            size_t size,
+                                            uint64_t producer_usage,
+                                            uint64_t consumer_usage));
 };
 
 struct ScreenshotData {
diff --git a/libs/vr/libdisplay/include/private/dvr/late_latch.h b/libs/vr/libdisplay/include/private/dvr/late_latch.h
index d0eff51..b7c5e4f 100644
--- a/libs/vr/libdisplay/include/private/dvr/late_latch.h
+++ b/libs/vr/libdisplay/include/private/dvr/late_latch.h
@@ -178,6 +178,9 @@
   LateLatchOutput* eds_late_latch_output_;
 
   DvrPose* pose_client_;
+
+  pdx::LocalHandle surface_metadata_fd_;
+  pdx::LocalHandle pose_buffer_fd_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libdisplay/late_latch.cpp b/libs/vr/libdisplay/late_latch.cpp
index b1a1589..e67f009 100644
--- a/libs/vr/libdisplay/late_latch.cpp
+++ b/libs/vr/libdisplay/late_latch.cpp
@@ -252,7 +252,8 @@
                      LocalHandle&& surface_metadata_fd)
     : is_app_late_latch_(is_app_late_latch),
       app_late_latch_output_(NULL),
-      eds_late_latch_output_(NULL) {
+      eds_late_latch_output_(NULL),
+      surface_metadata_fd_(std::move(surface_metadata_fd)) {
   CHECK_GL();
   glGenBuffers(1, &input_buffer_id_);
   glBindBuffer(GL_SHADER_STORAGE_BUFFER, input_buffer_id_);
@@ -264,12 +265,11 @@
                GL_DYNAMIC_COPY);
   CHECK_GL();
 
-  LocalHandle pose_buffer_fd;
   pose_client_ = dvrPoseCreate();
   if (!pose_client_) {
     ALOGE("LateLatch Error: failed to create pose client");
   } else {
-    int ret = privateDvrPoseGetRingBufferFd(pose_client_, &pose_buffer_fd);
+    int ret = privateDvrPoseGetRingBufferFd(pose_client_, &pose_buffer_fd_);
     if (ret < 0) {
       ALOGE("LateLatch Error: failed to get pose ring buffer");
     }
@@ -280,20 +280,20 @@
   if (!glBindSharedBufferQCOM) {
     ALOGE("Error: Missing gralloc buffer extension, no pose data");
   } else {
-    if (pose_buffer_fd) {
+    if (pose_buffer_fd_) {
       glBindBuffer(GL_SHADER_STORAGE_BUFFER, pose_buffer_object_);
       glBindSharedBufferQCOM(GL_SHADER_STORAGE_BUFFER,
                              kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync),
-                             pose_buffer_fd.Release());
+                             pose_buffer_fd_.Get());
     }
     CHECK_GL();
   }
 
   glBindBuffer(GL_SHADER_STORAGE_BUFFER, metadata_buffer_id_);
-  if (surface_metadata_fd && glBindSharedBufferQCOM) {
+  if (surface_metadata_fd_ && glBindSharedBufferQCOM) {
     glBindSharedBufferQCOM(GL_SHADER_STORAGE_BUFFER,
                            sizeof(DisplaySurfaceMetadata),
-                           surface_metadata_fd.Release());
+                           surface_metadata_fd_.Get());
   } else {
     // Fall back on internal metadata buffer when none provided, for example
     // when distortion is done in the application process.
diff --git a/libs/vr/libdvr/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
index 7cbfc21..64c7f16 100644
--- a/libs/vr/libdvr/display_manager_client.cpp
+++ b/libs/vr/libdvr/display_manager_client.cpp
@@ -1,6 +1,7 @@
 #include "include/dvr/display_manager_client.h"
 
 #include <dvr/dvr_buffer.h>
+#include <private/android/AHardwareBufferHelpers.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/display_manager_client_impl.h>
 
@@ -42,14 +43,17 @@
   delete client;
 }
 
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
-    uint64_t usage0, uint64_t usage1) {
-  // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
-  auto buffer_producer = client->client->SetupPoseBuffer(
-      extended_region_size, static_cast<int>(usage0));
-  if (buffer_producer) {
-    return CreateDvrWriteBufferFromBufferProducer(std::move(buffer_producer));
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+                                             const char* name, size_t size,
+                                             uint64_t usage0, uint64_t usage1) {
+  uint64_t producer_usage = 0;
+  uint64_t consumer_usage = 0;
+  android::AHardwareBuffer_convertToGrallocUsageBits(
+      &producer_usage, &consumer_usage, usage0, usage1);
+  auto ion_buffer = client->client->SetupNamedBuffer(name, size, producer_usage,
+                                                     consumer_usage);
+  if (ion_buffer) {
+    return CreateDvrBufferFromIonBuffer(std::move(ion_buffer));
   }
   return nullptr;
 }
@@ -109,8 +113,8 @@
 }
 
 int dvrDisplayManagerClientGetSurfaceBuffers(
-    DvrDisplayManagerClient* client, int surface_id,
-    DvrDisplayManagerClientSurfaceBuffers** surface_buffers) {
+    DvrDisplayManagerClient* /* client */, int /* surface_id */,
+    DvrDisplayManagerClientSurfaceBuffers** /* surface_buffers */) {
   // TODO(jwcai, hendrikw) Remove this after we replacing
   // dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
   return -1;
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 49702fd..c4634b1 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -31,8 +31,8 @@
         dvrDisplayManagerClientGetSurfaceList;
     dvr_api->display_manager_client_surface_list_destroy =
         dvrDisplayManagerClientSurfaceListDestroy;
-    dvr_api->display_manager_setup_pose_buffer =
-        dvrDisplayManagerSetupPoseBuffer;
+    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 =
@@ -48,19 +48,23 @@
 
     // dvr_buffer.h
     dvr_api->write_buffer_destroy = dvrWriteBufferDestroy;
-    dvr_api->write_buffer_get_blob_fds = dvrWriteBufferGetBlobFds;
     dvr_api->write_buffer_get_ahardwarebuffer =
         dvrWriteBufferGetAHardwareBuffer;
     dvr_api->write_buffer_post = dvrWriteBufferPost;
     dvr_api->write_buffer_gain = dvrWriteBufferGain;
     dvr_api->write_buffer_gain_async = dvrWriteBufferGainAsync;
+    dvr_api->write_buffer_get_native_handle = dvrWriteBufferGetNativeHandle;
 
     dvr_api->read_buffer_destroy = dvrReadBufferDestroy;
-    dvr_api->read_buffer_get_blob_fds = dvrReadBufferGetBlobFds;
     dvr_api->read_buffer_get_ahardwarebuffer = dvrReadBufferGetAHardwareBuffer;
     dvr_api->read_buffer_acquire = dvrReadBufferAcquire;
     dvr_api->read_buffer_release = dvrReadBufferRelease;
     dvr_api->read_buffer_release_async = dvrReadBufferReleaseAsync;
+    dvr_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;
@@ -77,7 +81,7 @@
     dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
 
     // dvr_surface.h
-    dvr_api->get_pose_buffer = dvrGetPoseBuffer;
+    dvr_api->get_named_buffer = dvrGetNamedBuffer;
     dvr_api->surface_create = dvrSurfaceCreate;
     dvr_api->surface_get_write_buffer_queue = dvrSurfaceGetWriteBufferQueue;
 
@@ -109,6 +113,11 @@
     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;
@@ -121,6 +130,19 @@
     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;
 
     return 0;
   }
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 25128a6..28820e7 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -1,18 +1,21 @@
 #include "include/dvr/dvr_buffer.h"
 
+#include <android/hardware_buffer.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <ui/GraphicBuffer.h>
 
 using namespace android;
 
 struct DvrWriteBuffer {
-  std::shared_ptr<dvr::BufferProducer> write_buffer_;
-  sp<GraphicBuffer> graphic_buffer_;
+  std::shared_ptr<dvr::BufferProducer> write_buffer;
 };
 
 struct DvrReadBuffer {
-  std::shared_ptr<dvr::BufferConsumer> read_buffer_;
-  sp<GraphicBuffer> graphic_buffer_;
+  std::shared_ptr<dvr::BufferConsumer> read_buffer;
+};
+
+struct DvrBuffer {
+  std::shared_ptr<dvr::IonBuffer> buffer;
 };
 
 namespace android {
@@ -20,16 +23,23 @@
 
 DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
     const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
-  DvrWriteBuffer* write_buffer = new DvrWriteBuffer;
-  write_buffer->write_buffer_ = std::move(buffer_producer);
-  return write_buffer;
+  if (!buffer_producer)
+    return nullptr;
+  return new DvrWriteBuffer{std::move(buffer_producer)};
 }
 
 DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
     const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
-  DvrReadBuffer* read_buffer = new DvrReadBuffer;
-  read_buffer->read_buffer_ = std::move(buffer_consumer);
-  return read_buffer;
+  if (!buffer_consumer)
+    return nullptr;
+  return new DvrReadBuffer{std::move(buffer_consumer)};
+}
+
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+    const std::shared_ptr<IonBuffer>& ion_buffer) {
+  if (!ion_buffer)
+    return nullptr;
+  return new DvrBuffer{std::move(ion_buffer)};
 }
 
 }  // namespace dvr
@@ -45,83 +55,103 @@
       false /* keep ownership */));
 }
 
+int ConvertToAHardwareBuffer(GraphicBuffer* graphic_buffer,
+                             AHardwareBuffer** hardware_buffer) {
+  if (!hardware_buffer || !graphic_buffer) {
+    return -EINVAL;
+  }
+  *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(graphic_buffer);
+  AHardwareBuffer_acquire(*hardware_buffer);
+  return 0;
+}
+
 }  // anonymous namespace
 
 extern "C" {
 
-void dvrWriteBufferDestroy(DvrWriteBuffer* client) { delete client; }
-
-void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
-                              size_t* fds_count, size_t max_fds_count) {
-  client->write_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
+  delete write_buffer;
 }
 
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
+  return write_buffer->write_buffer->id();
+}
+
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer) {
-  if (!client->graphic_buffer_.get()) {
-    InitializeGraphicBuffer(client->write_buffer_.get(),
-                            &client->graphic_buffer_);
-  }
-  *hardware_buffer =
-      reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
-  return 0;
+  return ConvertToAHardwareBuffer(
+      write_buffer->write_buffer->buffer()->buffer().get(), hardware_buffer);
 }
 
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes) {
   pdx::LocalHandle fence(ready_fence_fd);
-  int result = client->write_buffer_->Post(fence, meta, meta_size_bytes);
-  fence.Release();
+  int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
   return result;
 }
 
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd) {
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
   pdx::LocalHandle release_fence;
-  int result = client->write_buffer_->Gain(&release_fence);
+  int result = write_buffer->write_buffer->Gain(&release_fence);
   *release_fence_fd = release_fence.Release();
   return result;
 }
 
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client) {
-  return client->write_buffer_->GainAsync();
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
+  return write_buffer->write_buffer->GainAsync();
 }
 
-void dvrReadBufferDestroy(DvrReadBuffer* client) { delete client; }
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
 
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
-                             size_t max_fds_count) {
-  client->read_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
+  return read_buffer->read_buffer->id();
 }
 
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer) {
-  if (!client->graphic_buffer_.get()) {
-    InitializeGraphicBuffer(client->read_buffer_.get(),
-                            &client->graphic_buffer_);
-  }
-  *hardware_buffer =
-      reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
-  return 0;
+  return ConvertToAHardwareBuffer(
+      read_buffer->read_buffer->buffer()->buffer().get(), hardware_buffer);
 }
 
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
-                         size_t meta_size_bytes) {
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+                         void* meta, size_t meta_size_bytes) {
   pdx::LocalHandle ready_fence;
   int result =
-      client->read_buffer_->Acquire(&ready_fence, meta, meta_size_bytes);
+      read_buffer->read_buffer->Acquire(&ready_fence, meta, meta_size_bytes);
   *ready_fence_fd = ready_fence.Release();
   return result;
 }
 
-int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd) {
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
   pdx::LocalHandle fence(release_fence_fd);
-  int result = client->read_buffer_->Release(fence);
-  fence.Release();
+  int result = read_buffer->read_buffer->Release(fence);
   return result;
 }
 
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client) {
-  return client->read_buffer_->ReleaseAsync();
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
+  return read_buffer->read_buffer->ReleaseAsync();
+}
+
+void dvrBufferDestroy(DvrBuffer* buffer) { delete buffer; }
+
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+                                AHardwareBuffer** hardware_buffer) {
+  return ConvertToAHardwareBuffer(buffer->buffer->buffer().get(),
+                                  hardware_buffer);
+}
+
+const struct native_handle* dvrWriteBufferGetNativeHandle(
+    DvrWriteBuffer* write_buffer) {
+  return write_buffer->write_buffer->native_handle();
+}
+
+const struct native_handle* dvrReadBufferGetNativeHandle(
+    DvrReadBuffer* read_buffer) {
+  return read_buffer->read_buffer->native_handle();
+}
+
+const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer) {
+  return buffer->buffer->handle();
 }
 
 }  // extern "C"
diff --git a/libs/vr/libdvr/dvr_hardware_composer_client.cpp b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
index e5665e1..d3ae299 100644
--- a/libs/vr/libdvr/dvr_hardware_composer_client.cpp
+++ b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
@@ -84,7 +84,7 @@
   delete frame;
 }
 
-Display dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
+DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
   return frame->frame.display_id;
 }
 
@@ -104,7 +104,30 @@
   return frame->frame.layers.size();
 }
 
-Layer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
+uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame) {
+  return static_cast<uint32_t>(frame->frame.active_config);
+}
+
+uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame) {
+  return static_cast<uint32_t>(frame->frame.color_mode);
+}
+
+void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix,
+                                  int32_t* out_hint) {
+  *out_hint = frame->frame.color_transform_hint;
+  memcpy(out_matrix, frame->frame.color_transform,
+         sizeof(frame->frame.color_transform));
+}
+
+uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame) {
+  return static_cast<uint32_t>(frame->frame.power_mode);
+}
+
+uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame) {
+  return static_cast<uint32_t>(frame->frame.vsync_enabled);
+}
+
+DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
   return frame->frame.layers[layer_index].id;
 }
 
@@ -120,8 +143,9 @@
   return frame->frame.layers[layer_index].fence->dup();
 }
 
-Recti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index) {
-  return Recti{
+DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
+                                            size_t layer_index) {
+  return DvrHwcRecti{
     frame->frame.layers[layer_index].display_frame.left,
     frame->frame.layers[layer_index].display_frame.top,
     frame->frame.layers[layer_index].display_frame.right,
@@ -129,8 +153,8 @@
   };
 }
 
-Rectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
-  return Rectf{
+DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
+  return DvrHwcRectf{
     frame->frame.layers[layer_index].crop.left,
     frame->frame.layers[layer_index].crop.top,
     frame->frame.layers[layer_index].crop.right,
@@ -138,8 +162,10 @@
   };
 }
 
-BlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index) {
-  return static_cast<BlendMode>(frame->frame.layers[layer_index].blend_mode);
+DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
+                                             size_t layer_index) {
+  return static_cast<DvrHwcBlendMode>(
+      frame->frame.layers[layer_index].blend_mode);
 }
 
 float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index) {
@@ -154,3 +180,58 @@
                                           size_t layer_index) {
   return frame->frame.layers[layer_index].app_id;
 }
+
+uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index) {
+  return frame->frame.layers[layer_index].z_order;
+}
+
+void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index,
+                               int32_t* out_x, int32_t* out_y) {
+  *out_x = frame->frame.layers[layer_index].cursor_x;
+  *out_y = frame->frame.layers[layer_index].cursor_y;
+}
+
+uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index) {
+  return frame->frame.layers[layer_index].transform;
+}
+
+uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index) {
+  return frame->frame.layers[layer_index].dataspace;
+}
+
+uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index) {
+  const auto& color = frame->frame.layers[layer_index].color;
+  return color.r | (static_cast<uint32_t>(color.g) << 8) |
+         (static_cast<uint32_t>(color.b) << 16) |
+         (static_cast<uint32_t>(color.a) << 24);
+}
+
+uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame,
+                                              size_t layer_index) {
+  return frame->frame.layers[layer_index].visible_regions.size();
+}
+
+DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame,
+                                             size_t layer_index, size_t index) {
+  return DvrHwcRecti{
+      frame->frame.layers[layer_index].visible_regions[index].left,
+      frame->frame.layers[layer_index].visible_regions[index].top,
+      frame->frame.layers[layer_index].visible_regions[index].right,
+      frame->frame.layers[layer_index].visible_regions[index].bottom,
+  };
+}
+
+uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame,
+                                              size_t layer_index) {
+  return frame->frame.layers[layer_index].damaged_regions.size();
+}
+
+DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame,
+                                             size_t layer_index, size_t index) {
+  return DvrHwcRecti{
+      frame->frame.layers[layer_index].damaged_regions[index].left,
+      frame->frame.layers[layer_index].damaged_regions[index].top,
+      frame->frame.layers[layer_index].damaged_regions[index].right,
+      frame->frame.layers[layer_index].damaged_regions[index].bottom,
+  };
+}
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a3cbba5..a04ed50 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -58,14 +58,25 @@
   return 0;
 }
 
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
   auto client = android::dvr::DisplayClient::Create();
   if (!client) {
-    ALOGE("Failed to create display client!");
+    ALOGE("dvrGetNamedBuffer: Failed to create display client!");
     return -ECOMM;
   }
 
-  *pose_buffer = CreateDvrReadBufferFromBufferConsumer(client->GetPoseBuffer());
+  if (out_buffer == nullptr || name == nullptr) {
+    ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
+          out_buffer);
+    return -EINVAL;
+  }
+
+  auto named_buffer = client->GetNamedBuffer(name);
+  if (!named_buffer) {
+    ALOGE("dvrGetNamedBuffer: Failed to find named buffer: %s.", name);
+    return -EINVAL;
+  }
+  *out_buffer = CreateDvrBufferFromIonBuffer(std::move(named_buffer));
   return 0;
 }
 
diff --git a/libs/vr/libdvr/include/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
index 0928d43..8cd948c 100644
--- a/libs/vr/libdvr/include/dvr/display_manager_client.h
+++ b/libs/vr/libdvr/include/dvr/display_manager_client.h
@@ -14,15 +14,15 @@
     DvrDisplayManagerClientSurfaceList;
 typedef struct DvrDisplayManagerClientSurfaceBuffers
     DvrDisplayManagerClientSurfaceBuffers;
-typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrBuffer DvrBuffer;
 
 DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
 
 void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
 
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
-    uint64_t usage0, uint64_t usage1);
+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
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index a4fef19..56f937b 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -30,6 +30,7 @@
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
 typedef struct AHardwareBuffer AHardwareBuffer;
 
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
@@ -37,14 +38,16 @@
 
 typedef struct DvrSurface DvrSurface;
 
+struct native_handle;
+
 // display_manager_client.h
 typedef int (*DvrDisplayManagerClientGetSurfaceListPtr)(
     DvrDisplayManagerClient* client,
     DvrDisplayManagerClientSurfaceList** surface_list);
 typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
     DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrWriteBuffer* (*DvrDisplayManagerSetupPoseBufferPtr)(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
+typedef DvrBuffer* (*DvrDisplayManagerSetupNamedBufferPtr)(
+    DvrDisplayManagerClient* client, const char* name, size_t size,
     uint64_t usage0, uint64_t usage1);
 typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
     DvrDisplayManagerClientSurfaceList* surface_list);
@@ -62,9 +65,6 @@
 
 // dvr_buffer.h
 typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
-typedef void (*DvrWriteBufferGetBlobFdsPtr)(DvrWriteBuffer* client, int* fds,
-                                            size_t* fds_count,
-                                            size_t max_fds_count);
 typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
     DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
 typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
@@ -72,11 +72,10 @@
 typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* client,
                                      int* release_fence_fd);
 typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
+typedef const struct native_handle* (*DvrWriteBufferGetNativeHandle)(
+    DvrWriteBuffer* write_buffer);
 
 typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
-typedef void (*DvrReadBufferGetBlobFdsPtr)(DvrReadBuffer* client, int* fds,
-                                           size_t* fds_count,
-                                           size_t max_fds_count);
 typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
     DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
 typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
@@ -85,6 +84,14 @@
 typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
                                        int release_fence_fd);
 typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
+typedef const struct native_handle* (*DvrReadBufferGetNativeHandle)(
+    DvrReadBuffer* read_buffer);
+
+typedef void (*DvrBufferDestroy)(DvrBuffer* buffer);
+typedef int (*DvrBufferGetAHardwareBuffer)(DvrBuffer* buffer,
+                                           AHardwareBuffer** hardware_buffer);
+typedef const struct native_handle* (*DvrBufferGetNativeHandle)(
+    DvrBuffer* buffer);
 
 // dvr_buffer_queue.h
 typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
@@ -110,7 +117,7 @@
                                             size_t meta_size_bytes);
 
 // dvr_surface.h
-typedef int (*DvrGetPoseBufferPtr)(DvrReadBuffer** pose_buffer);
+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);
@@ -149,33 +156,68 @@
 // dvr_hardware_composer_client.h
 typedef struct DvrHwcClient DvrHwcClient;
 typedef struct DvrHwcFrame DvrHwcFrame;
-typedef int(*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
+typedef int (*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
 typedef DvrHwcClient* (*DvrHwcClientCreatePtr)(DvrHwcOnFrameCallback callback,
                                                void* client_state);
 typedef void (*DvrHwcClientDestroyPtr)(DvrHwcClient* client);
 typedef void (*DvrHwcFrameDestroyPtr)(DvrHwcFrame* frame);
-typedef Display (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame);
+typedef DvrHwcDisplay (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame);
 typedef int32_t (*DvrHwcFrameGetDisplayWidthPtr)(DvrHwcFrame* frame);
 typedef int32_t (*DvrHwcFrameGetDisplayHeightPtr)(DvrHwcFrame* frame);
 typedef bool (*DvrHwcFrameGetDisplayRemovedPtr)(DvrHwcFrame* frame);
 typedef size_t (*DvrHwcFrameGetLayerCountPtr)(DvrHwcFrame* frame);
-typedef Layer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame, size_t layer_index);
+typedef DvrHwcLayer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame,
+                                                size_t layer_index);
+typedef uint32_t (*DvrHwcFrameGetActiveConfigPtr)(DvrHwcFrame* frame);
+typedef uint32_t (*DvrHwcFrameGetColorModePtr)(DvrHwcFrame* frame);
+typedef void (*DvrHwcFrameGetColorTransformPtr)(DvrHwcFrame* frame,
+                                                float* out_matrix,
+                                                int32_t* out_hint);
+typedef uint32_t (*DvrHwcFrameGetPowerModePtr)(DvrHwcFrame* frame);
+typedef uint32_t (*DvrHwcFrameGetVsyncEnabledPtr)(DvrHwcFrame* frame);
 typedef AHardwareBuffer* (*DvrHwcFrameGetLayerBufferPtr)(DvrHwcFrame* frame,
                                                          size_t layer_index);
 typedef int (*DvrHwcFrameGetLayerFencePtr)(DvrHwcFrame* frame,
                                            size_t layer_index);
-typedef Recti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame,
-                                                    size_t layer_index);
-typedef Rectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame,
-                                            size_t layer_index);
-typedef BlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame,
-                                                     size_t layer_index);
+typedef DvrHwcRecti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame,
+                                                          size_t layer_index);
+typedef DvrHwcRectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame,
+                                                  size_t layer_index);
+typedef DvrHwcBlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame,
+                                                           size_t layer_index);
 typedef float (*DvrHwcFrameGetLayerAlphaPtr)(DvrHwcFrame* frame,
                                              size_t layer_index);
 typedef uint32_t (*DvrHwcFrameGetLayerTypePtr)(DvrHwcFrame* frame,
                                                size_t layer_index);
 typedef uint32_t (*DvrHwcFrameGetLayerApplicationIdPtr)(DvrHwcFrame* frame,
                                                         size_t layer_index);
+typedef uint32_t (*DvrHwcFrameGetLayerZOrderPtr)(DvrHwcFrame* frame,
+                                                 size_t layer_index);
+
+typedef void (*DvrHwcFrameGetLayerCursorPtr)(DvrHwcFrame* frame,
+                                             size_t layer_index, int32_t* out_x,
+                                             int32_t* out_y);
+
+typedef uint32_t (*DvrHwcFrameGetLayerTransformPtr)(DvrHwcFrame* frame,
+                                                    size_t layer_index);
+
+typedef uint32_t (*DvrHwcFrameGetLayerDataspacePtr)(DvrHwcFrame* frame,
+                                                    size_t layer_index);
+
+typedef uint32_t (*DvrHwcFrameGetLayerColorPtr)(DvrHwcFrame* frame,
+                                                size_t layer_index);
+
+typedef uint32_t (*DvrHwcFrameGetLayerNumVisibleRegionsPtr)(DvrHwcFrame* frame,
+                                                            size_t layer_index);
+typedef DvrHwcRecti (*DvrHwcFrameGetLayerVisibleRegionPtr)(DvrHwcFrame* frame,
+                                                           size_t layer_index,
+                                                           size_t index);
+
+typedef uint32_t (*DvrHwcFrameGetLayerNumDamagedRegionsPtr)(DvrHwcFrame* frame,
+                                                            size_t layer_index);
+typedef DvrHwcRecti (*DvrHwcFrameGetLayerDamagedRegionPtr)(DvrHwcFrame* frame,
+                                                           size_t layer_index,
+                                                           size_t index);
 
 struct DvrApi_v1 {
   // Display manager client
@@ -185,7 +227,7 @@
       display_manager_client_get_surface_list;
   DvrDisplayManagerClientSurfaceListDestroyPtr
       display_manager_client_surface_list_destroy;
-  DvrDisplayManagerSetupPoseBufferPtr display_manager_setup_pose_buffer;
+  DvrDisplayManagerSetupNamedBufferPtr display_manager_setup_named_buffer;
   DvrDisplayManagerClientSurfaceListGetSizePtr
       display_manager_client_surface_list_get_size;
   DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
@@ -201,19 +243,24 @@
 
   // Write buffer
   DvrWriteBufferDestroyPtr write_buffer_destroy;
-  DvrWriteBufferGetBlobFdsPtr write_buffer_get_blob_fds;
   DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_ahardwarebuffer;
   DvrWriteBufferPostPtr write_buffer_post;
   DvrWriteBufferGainPtr write_buffer_gain;
   DvrWriteBufferGainAsyncPtr write_buffer_gain_async;
+  DvrWriteBufferGetNativeHandle write_buffer_get_native_handle;
 
   // Read buffer
   DvrReadBufferDestroyPtr read_buffer_destroy;
-  DvrReadBufferGetBlobFdsPtr read_buffer_get_blob_fds;
   DvrReadBufferGetAHardwareBufferPtr read_buffer_get_ahardwarebuffer;
   DvrReadBufferAcquirePtr read_buffer_acquire;
   DvrReadBufferReleasePtr read_buffer_release;
   DvrReadBufferReleaseAsyncPtr read_buffer_release_async;
+  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;
@@ -235,7 +282,7 @@
   DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info;
 
   // Display surface
-  DvrGetPoseBufferPtr get_pose_buffer;
+  DvrGetNamedBufferPtr get_named_buffer;
   DvrSurfaceCreatePtr surface_create;
   DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue;
 
@@ -262,6 +309,11 @@
   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;
@@ -272,6 +324,17 @@
   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;
 };
 
 int dvrGetApi(void* api, size_t struct_size, int version);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index bbfbb00..3e8357c 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -1,9 +1,9 @@
 #ifndef ANDROID_DVR_BUFFER_H_
 #define ANDROID_DVR_BUFFER_H_
 
-#include <memory>
 #include <stdbool.h>
 #include <stdint.h>
+#include <memory>
 
 #ifdef __cplusplus
 extern "C" {
@@ -11,29 +11,42 @@
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
 typedef struct AHardwareBuffer AHardwareBuffer;
+struct native_handle;
 
 // Write buffer
-void dvrWriteBufferDestroy(DvrWriteBuffer* client);
-void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
-                              size_t* fds_count, size_t max_fds_count);
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
+// Caller must call AHardwareBuffer_release on hardware_buffer.
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer);
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes);
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd);
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
+const struct native_handle* dvrWriteBufferGetNativeHandle(
+    DvrWriteBuffer* write_buffer);
 
 // Read buffer
-void dvrReadBufferDestroy(DvrReadBuffer* client);
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
-                             size_t max_fds_count);
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
+// Caller must call AHardwareBuffer_release on hardware_buffer.
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer);
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
-                         size_t meta_size_bytes);
-int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd);
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client);
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+                         void* meta, size_t meta_size_bytes);
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
+const struct native_handle* dvrReadBufferGetNativeHandle(
+    DvrReadBuffer* read_buffer);
+
+// Buffer
+void dvrBufferDestroy(DvrBuffer* buffer);
+// Caller must call AHardwareBuffer_release on hardware_buffer.
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+                                AHardwareBuffer** hardware_buffer);
+const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer);
 
 #ifdef __cplusplus
 }  // extern "C"
@@ -44,11 +57,14 @@
 
 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
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
index 692864d..7ee7f9e 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
@@ -29,7 +29,7 @@
 // Called to free the frame information.
 void dvrHwcFrameDestroy(DvrHwcFrame* frame);
 
-Display dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
+DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
 
 int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame);
 
@@ -43,7 +43,14 @@
 // @return Number of layers in the frame.
 size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame);
 
-Layer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
+uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame);
+uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame);
+void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix,
+                                  int32_t* out_hint);
+uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame);
+uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame);
+
+DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
 
 // Return the graphic buffer associated with the layer at |layer_index| in
 // |frame|.
@@ -58,11 +65,13 @@
 // @return Fence FD. Caller owns the FD and is responsible for closing it.
 int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index);
 
-Recti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
+                                            size_t layer_index);
 
-Rectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
 
-BlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
+                                             size_t layer_index);
 
 float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index);
 
@@ -71,6 +80,26 @@
 uint32_t dvrHwcFrameGetLayerApplicationId(DvrHwcFrame* frame,
                                           size_t layer_index);
 
+uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index);
+
+void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index,
+                               int32_t* out_x, int32_t* out_y);
+
+uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index);
+
+uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index);
+
+uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index);
+
+uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame,
+                                              size_t layer_index);
+DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame,
+                                             size_t layer_index, size_t index);
+
+uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame,
+                                              size_t layer_index);
+DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame,
+                                             size_t layer_index, size_t index);
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
index 546ed7b..36c30f9 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
@@ -10,33 +10,33 @@
 // NOTE: These definitions must match the ones in
 // //hardware/libhardware/include/hardware/hwcomposer2.h. They are used by the
 // client side which does not have access to hwc2 headers.
-enum BlendMode {
-  BLEND_MODE_INVALID = 0,
-  BLEND_MODE_NONE = 1,
-  BLEND_MODE_PREMULTIPLIED = 2,
-  BLEND_MODE_COVERAGE = 3,
+enum DvrHwcBlendMode {
+  DVR_HWC_BLEND_MODE_INVALID = 0,
+  DVR_HWC_BLEND_MODE_NONE = 1,
+  DVR_HWC_BLEND_MODE_PREMULTIPLIED = 2,
+  DVR_HWC_BLEND_MODE_COVERAGE = 3,
 };
 
-enum Composition {
-  COMPOSITION_INVALID = 0,
-  COMPOSITION_CLIENT = 1,
-  COMPOSITION_DEVICE = 2,
-  COMPOSITION_SOLID_COLOR = 3,
-  COMPOSITION_CURSOR = 4,
-  COMPOSITION_SIDEBAND = 5,
+enum DvrHwcComposition {
+  DVR_HWC_COMPOSITION_INVALID = 0,
+  DVR_HWC_COMPOSITION_CLIENT = 1,
+  DVR_HWC_COMPOSITION_DEVICE = 2,
+  DVR_HWC_COMPOSITION_SOLID_COLOR = 3,
+  DVR_HWC_COMPOSITION_CURSOR = 4,
+  DVR_HWC_COMPOSITION_SIDEBAND = 5,
 };
 
-typedef uint64_t Display;
-typedef uint64_t Layer;
+typedef uint64_t DvrHwcDisplay;
+typedef uint64_t DvrHwcLayer;
 
-struct Recti {
+struct DvrHwcRecti {
   int32_t left;
   int32_t top;
   int32_t right;
   int32_t bottom;
 };
 
-struct Rectf {
+struct DvrHwcRectf {
   float left;
   float top;
   float right;
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 2712f24..e5228d6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -12,7 +12,7 @@
 typedef struct DvrSurfaceParameter DvrSurfaceParameter;
 
 // Get a pointer to the global pose buffer.
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
+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);
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
index 75e2a7d..29cdc13 100644
--- a/libs/vr/libdvr/tests/Android.mk
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -17,14 +17,18 @@
     libbufferhub \
     libchrome \
     libdvrcommon \
+    libdisplay \
     libpdx_default_transport \
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp
+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_buffer_queue-test\" -DTRACE=0 -O0 -g
-LOCAL_MODULE := dvr_buffer_queue-test
+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_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
new file mode 100644
index 0000000..2866f47
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -0,0 +1,156 @@
+#include <android/hardware_buffer.h>
+#include <dvr/display_manager_client.h>
+#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_surface.h>
+#include <system/graphics.h>
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+class DvrNamedBufferTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    client_ = dvrDisplayManagerClientCreate();
+    ASSERT_NE(nullptr, client_);
+  }
+
+  void TearDown() override {
+    if (client_ != nullptr) {
+      dvrDisplayManagerClientDestroy(client_);
+      client_ = nullptr;
+    }
+  }
+
+  DvrDisplayManagerClient* client_ = nullptr;
+};
+
+TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
+  const char* buffer_name = "same_name";
+  DvrBuffer* buffer1 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  ASSERT_NE(nullptr, buffer1);
+
+  DvrBuffer* buffer2 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  ASSERT_NE(nullptr, buffer2);
+
+  AHardwareBuffer* hardware_buffer1 = nullptr;
+  int e1 = dvrBufferGetAHardwareBuffer(buffer1, &hardware_buffer1);
+  ASSERT_EQ(0, e1);
+  ASSERT_NE(nullptr, hardware_buffer1);
+
+  AHardwareBuffer* hardware_buffer2 = nullptr;
+  int e2 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer2);
+  ASSERT_EQ(0, e2);
+  ASSERT_NE(nullptr, hardware_buffer2);
+
+  AHardwareBuffer_Desc desc1 = {};
+  AHardwareBuffer_describe(hardware_buffer1, &desc1);
+  AHardwareBuffer_Desc desc2 = {};
+  AHardwareBuffer_describe(hardware_buffer2, &desc2);
+  ASSERT_EQ(desc1.width, 10u);
+  ASSERT_EQ(desc1.height, 1u);
+  ASSERT_EQ(desc1.layers, 1u);
+  ASSERT_EQ(desc1.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc1.usage0, 0u);
+  ASSERT_EQ(desc1.usage1, 0u);
+  ASSERT_EQ(desc2.width, 10u);
+  ASSERT_EQ(desc2.height, 1u);
+  ASSERT_EQ(desc2.layers, 1u);
+  ASSERT_EQ(desc2.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc2.usage0, 0u);
+  ASSERT_EQ(desc2.usage1, 0u);
+
+  dvrBufferDestroy(buffer1);
+  dvrBufferDestroy(buffer2);
+
+  DvrBuffer* buffer3 = nullptr;
+  int e3 = dvrGetNamedBuffer(buffer_name, &buffer3);
+  ASSERT_NE(nullptr, buffer3);
+  ASSERT_EQ(0, e3);
+
+  AHardwareBuffer* hardware_buffer3 = nullptr;
+  int e4 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer3);
+  ASSERT_EQ(0, e4);
+  ASSERT_NE(nullptr, hardware_buffer3);
+
+  AHardwareBuffer_Desc desc3 = {};
+  AHardwareBuffer_describe(hardware_buffer3, &desc3);
+  ASSERT_EQ(desc3.width, 10u);
+  ASSERT_EQ(desc3.height, 1u);
+  ASSERT_EQ(desc3.layers, 1u);
+  ASSERT_EQ(desc3.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc3.usage0, 0u);
+  ASSERT_EQ(desc3.usage1, 0u);
+
+  dvrBufferDestroy(buffer3);
+
+  AHardwareBuffer_release(hardware_buffer1);
+  AHardwareBuffer_release(hardware_buffer2);
+  AHardwareBuffer_release(hardware_buffer3);
+}
+
+TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
+  const char* buffer_name1 = "test1";
+  const char* buffer_name2 = "test2";
+  DvrBuffer* setup_buffer1 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0, 0);
+  ASSERT_NE(nullptr, setup_buffer1);
+  dvrBufferDestroy(setup_buffer1);
+
+  DvrBuffer* setup_buffer2 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0, 0);
+  ASSERT_NE(nullptr, setup_buffer2);
+  dvrBufferDestroy(setup_buffer2);
+
+  DvrBuffer* buffer1 = nullptr;
+  int e1 = dvrGetNamedBuffer(buffer_name1, &buffer1);
+  ASSERT_NE(nullptr, buffer1);
+  ASSERT_EQ(0, e1);
+  dvrBufferDestroy(buffer1);
+
+  DvrBuffer* buffer2 = nullptr;
+  int e2 = dvrGetNamedBuffer(buffer_name2, &buffer2);
+  ASSERT_NE(nullptr, buffer2);
+  ASSERT_EQ(0, e2);
+  dvrBufferDestroy(buffer2);
+}
+
+TEST_F(DvrNamedBufferTest, TestNamedBufferUsage) {
+  const char* buffer_name = "buffer_usage";
+
+  // Set usage0 to AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE. We use this because
+  // internally AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE is converted to
+  // 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_USAGE0_VIDEO_ENCODE.
+  const int64_t usage0 = AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE;
+
+  DvrBuffer* setup_buffer =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage0, 0);
+  ASSERT_NE(nullptr, setup_buffer);
+
+  AHardwareBuffer* hardware_buffer = nullptr;
+  int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
+  ASSERT_EQ(0, e2);
+  ASSERT_NE(nullptr, hardware_buffer);
+
+  AHardwareBuffer_Desc desc = {};
+  AHardwareBuffer_describe(hardware_buffer, &desc);
+
+  ASSERT_EQ(desc.usage0, AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE);
+
+  dvrBufferDestroy(setup_buffer);
+  AHardwareBuffer_release(hardware_buffer);
+}
+
+
+}  // namespace
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libdvrcommon/include/private/dvr/benchmark.h b/libs/vr/libdvrcommon/include/private/dvr/benchmark.h
index 2dbb5f2..7eeab16 100644
--- a/libs/vr/libdvrcommon/include/private/dvr/benchmark.h
+++ b/libs/vr/libdvrcommon/include/private/dvr/benchmark.h
@@ -19,7 +19,7 @@
 // ... code to benchmark ...
 // Btrace("End execution");
 //
-// Use compute_benchmarks.py (currently in dreamos/system/core/applications),
+// Use compute_benchmarks.py
 // with the trace path "Start execution,End execution",
 // to report the elapsed time between the two calls.
 //
diff --git a/libs/vr/libdvrgraphics/gpu_profiler.cpp b/libs/vr/libdvrgraphics/gpu_profiler.cpp
index 49c515f..c8c978d 100644
--- a/libs/vr/libdvrgraphics/gpu_profiler.cpp
+++ b/libs/vr/libdvrgraphics/gpu_profiler.cpp
@@ -7,6 +7,12 @@
 namespace android {
 namespace dvr {
 
+namespace {
+
+constexpr int kMaxPendingQueries = 32;
+
+}  // anonynmous namespace
+
 static int64_t AdjustTimerQueryToNs(int64_t gpu_time) { return gpu_time; }
 
 void GpuProfiler::TimerData::reset() {
@@ -21,6 +27,7 @@
 
 // Enter a scope, records the timestamp for later matching with leave.
 void GpuProfiler::TimerData::enter(int64_t timestamp_ns) {
+  entered = true;
   enter_timestamp_ns = timestamp_ns;
 }
 
@@ -28,6 +35,15 @@
 void GpuProfiler::TimerData::leave(int64_t timestamp_ns, const char* name,
                                    std::weak_ptr<int64_t> duration_ns,
                                    int print_period) {
+  if (!entered) {
+    // We got the leave event but are missing the enter. This can happen if
+    // OnPendingQueryOverflow() is called, or if the calls to enter()/leave()
+    // aren't properly balanced. Ignore the call but print a warning.
+    ALOGW("Ignoring GpuProfiler::TimerData::leave event with no enter event");
+    return;
+  }
+  entered = false;
+
   int64_t elapsed = timestamp_ns - enter_timestamp_ns;
   if (elapsed > 1000 * 1000 * 1000) {
     // More than one second, drop it as invalid data.
@@ -50,12 +66,12 @@
 
 GpuProfiler::GpuProfiler()
     : enable_gpu_tracing_(true),
+      has_gl_context_(false),
       sync_with_cpu_time_(false),
       gl_timer_offset_ns_(0) {
-  SyncGlTimebase();
 }
 
-GpuProfiler::~GpuProfiler() {}
+GpuProfiler::~GpuProfiler() { Clear(); }
 
 bool GpuProfiler::IsGpuProfilingSupported() const {
   // TODO(jbates) check for GL_EXT_disjoint_timer_query
@@ -63,6 +79,9 @@
 }
 
 GLuint GpuProfiler::TryAllocateGlQueryId() {
+  if (pending_gpu_queries_.size() >= kMaxPendingQueries)
+    OnPendingQueryOverflow();
+
   GLuint query_id = 0;
   if (gl_timer_query_id_pool_.empty()) {
     glGenQueries(1, &query_id);
@@ -95,6 +114,35 @@
   }
 }
 
+void GpuProfiler::OnGlContextCreated() {
+  has_gl_context_ = true;
+  gl_timer_offset_ns_ = 0;
+  SyncGlTimebase();
+}
+
+void GpuProfiler::OnGlContextDestroyed() {
+  has_gl_context_ = false;
+  Clear();
+}
+
+void GpuProfiler::Clear() {
+  events_.clear();
+  for (auto& query : pending_gpu_queries_)
+    glDeleteQueries(1, &query.query_id);
+  pending_gpu_queries_.clear();
+  while (!gl_timer_query_id_pool_.empty()) {
+    GLuint id = gl_timer_query_id_pool_.top();
+    gl_timer_query_id_pool_.pop();
+    glDeleteQueries(1, &id);
+  }
+}
+
+void GpuProfiler::OnPendingQueryOverflow() {
+  ALOGW("Reached limit of %d pending queries in GpuProfiler."
+        " Clearing all queries.", kMaxPendingQueries);
+  Clear();
+}
+
 void GpuProfiler::SyncGlTimebase() {
   if (!sync_with_cpu_time_) {
     return;
diff --git a/libs/vr/libdvrgraphics/include/private/dvr/graphics/gpu_profiler.h b/libs/vr/libdvrgraphics/include/private/dvr/graphics/gpu_profiler.h
index 2905d00..c6e752b 100644
--- a/libs/vr/libdvrgraphics/include/private/dvr/graphics/gpu_profiler.h
+++ b/libs/vr/libdvrgraphics/include/private/dvr/graphics/gpu_profiler.h
@@ -38,7 +38,7 @@
   // one of the TRACE_GPU* macros defined below.
   void SetEnableGpuTracing(bool enabled) { enable_gpu_tracing_ = enabled; }
 
-  bool enabled() const { return enable_gpu_tracing_; }
+  bool enabled() const { return enable_gpu_tracing_ && has_gl_context_; }
 
   // Attempt to keep the GPU times in sync with CPU times.
   void SetEnableSyncCpuTime(bool enabled) { sync_with_cpu_time_ = enabled; }
@@ -62,6 +62,14 @@
   void LeaveGlScope(const char* scope_name, std::weak_ptr<int64_t> duration_ns,
                     int print_period);
 
+  // Must be called when the GL context is created. The GpuProfiler will be
+  // inactive until this is called.
+  void OnGlContextCreated();
+
+  // Must be called before the GL context is destroyed. The GpuProfiler will be
+  // inactive until a call to OnGlContextCreated().
+  void OnGlContextDestroyed();
+
  private:
   // Data to queue the pending GPU timer queries that need to be polled
   // for completion.
@@ -105,11 +113,20 @@
     void leave(int64_t timestamp_ns, const char* name,
                std::weak_ptr<int64_t> duration_ns, int print_period);
 
+    bool entered = false;
     int64_t total_elapsed_ns = 0;
     int64_t enter_timestamp_ns = 0;
     int num_events = 0;
   };
 
+  // Clear out events and free GL resources.
+  void Clear();
+
+  // Called when we detect that we've overflowed the pending query queue. This
+  // shouldn't occur in practice, and probably indicates some internal
+  // mismanagement of the gl query objects.
+  void OnPendingQueryOverflow();
+
   // Synchronises the GL timebase with the CallTraceManager timebase.
   void SyncGlTimebase();
 
@@ -119,6 +136,10 @@
   // Setting for enabling GPU tracing.
   bool enable_gpu_tracing_;
 
+  // True if we have a GL context, false otherwise. When the GpuProfiler is
+  // first created we assume no GL context.
+  bool has_gl_context_;
+
   // Setting for synchronizing GPU timestamps with CPU time.
   bool sync_with_cpu_time_;
 
diff --git a/libs/vr/libeds/Android.bp b/libs/vr/libeds/Android.bp
index 187cbbf..a149853 100644
--- a/libs/vr/libeds/Android.bp
+++ b/libs/vr/libeds/Android.bp
@@ -16,12 +16,9 @@
     "eds.cpp",
     "eds_mesh.cpp",
     "composite_hmd.cpp",
-    "cpu_thread_pose_updater.cpp",
     "display_metrics.cpp",
     "distortion_renderer.cpp",
-    "lucid_metrics.cpp",
-    "lucid_pose_tracker.cpp",
-    "lookup_radial_distortion.cpp",
+    "device_metrics.cpp",
     "polynomial_radial_distortion.cpp",
 ]
 
diff --git a/libs/vr/libeds/cpu_thread_pose_updater.cpp b/libs/vr/libeds/cpu_thread_pose_updater.cpp
deleted file mode 100644
index 5b8a734..0000000
--- a/libs/vr/libeds/cpu_thread_pose_updater.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "include/private/dvr/cpu_thread_pose_updater.h"
-
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#define ATRACE_TAG ATRACE_TAG_INPUT
-#include <utils/Trace.h>
-
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/debug.h>
-
-namespace android {
-namespace dvr {
-
-CpuThreadPoseUpdater::CpuThreadPoseUpdater()
-    : stop_request_(false), update_period_us_(0), count_(0) {}
-
-CpuThreadPoseUpdater::~CpuThreadPoseUpdater() { StopAndJoin(); }
-
-void CpuThreadPoseUpdater::Start(volatile RawPosePair* mapped_pose_buffer,
-                                 int period_us) {
-  mapped_pose_buffer_ = mapped_pose_buffer;
-  update_period_us_ = period_us;
-  stop_request_ = false;
-
-  // First buffer is odd (starts at 1), second is even (starts at 2).
-  count_ = 0;
-  mapped_pose_buffer_->pose1.Reset(++count_);
-  mapped_pose_buffer_->pose2.Reset(++count_);
-
-  update_thread_ = std::thread(&CpuThreadPoseUpdater::UpdateThread, this);
-}
-
-void CpuThreadPoseUpdater::StopAndJoin() {
-  stop_request_ = true;
-  if (update_thread_.joinable()) {
-    update_thread_.join();
-  }
-}
-
-void CpuThreadPoseUpdater::UpdateThread() {
-  prctl(PR_SET_NAME, reinterpret_cast<intptr_t>("CpuPoseUpdater"),
-        0, 0, 0);
-
-  ATRACE_NAME(__PRETTY_FUNCTION__);
-  for (;;) {
-    if (stop_request_) {
-      break;
-    }
-
-    ++count_;
-
-    // Choose the writable pose based on whether count is odd or even.
-    volatile RawPose* out_pose = nullptr;
-    if (count_ & 1) {
-      out_pose = &mapped_pose_buffer_->pose1;
-    } else {
-      out_pose = &mapped_pose_buffer_->pose2;
-    }
-
-    {
-      ATRACE_NAME("GetPose");
-      Posef pose = pose_tracker_.GetPose(GetSystemClockNs());
-      out_pose->qx = pose.GetRotation().x();
-      out_pose->qy = pose.GetRotation().y();
-      out_pose->qz = pose.GetRotation().z();
-      out_pose->qw = pose.GetRotation().w();
-      out_pose->px = pose.GetPosition()[0];
-      out_pose->py = pose.GetPosition()[1];
-      out_pose->pz = pose.GetPosition()[2];
-      // Atomically store the count so that it hits memory last:
-      out_pose->count.store(count_, std::memory_order_release);
-    }
-
-    // Sleep to simulate the IMU update process.
-    usleep(update_period_us_);
-    // TODO(jbates) sleep_for returns immediately, we need to fix our toolchain!
-    // int64_t c1 = GetSystemClockNs();
-    // std::this_thread::sleep_for(std::chrono::milliseconds(10));
-    // int64_t c2 = GetSystemClockNs();
-    // fprintf(stderr, "%lld us\n", (long long)(c2 - c1) / 1000);
-  }
-}
-
-}  // namesapce dvr
-}  // namesapce android
diff --git a/libs/vr/libeds/device_metrics.cpp b/libs/vr/libeds/device_metrics.cpp
new file mode 100644
index 0000000..68ee186
--- /dev/null
+++ b/libs/vr/libeds/device_metrics.cpp
@@ -0,0 +1,172 @@
+#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/include/private/dvr/cpu_thread_pose_updater.h b/libs/vr/libeds/include/private/dvr/cpu_thread_pose_updater.h
deleted file mode 100644
index 6a2c8a6..0000000
--- a/libs/vr/libeds/include/private/dvr/cpu_thread_pose_updater.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef ANDROID_DVR_CPU_THREAD_POSE_UPDATER_H_
-#define ANDROID_DVR_CPU_THREAD_POSE_UPDATER_H_
-
-#include <atomic>
-#include <thread>
-
-#include <private/dvr/lucid_pose_tracker.h>
-#include <private/dvr/raw_pose.h>
-
-namespace android {
-namespace dvr {
-
-// Temporary version of pose updater that uses a CPU thread to update
-// the pose buffer. Note that this thread starts and runs indefinitely
-class CpuThreadPoseUpdater {
- public:
-  CpuThreadPoseUpdater();
-  ~CpuThreadPoseUpdater();
-
-  // Start the thread to update the given buffer with the given number of
-  // microseconds between updates.
-  void Start(volatile RawPosePair* mapped_pose_buffer, int period_us);
-
-  void StopAndJoin();
-
- private:
-  void UpdateThread();
-
-  volatile RawPosePair* mapped_pose_buffer_;
-
-  // Pose update thread.
-  std::thread update_thread_;
-
-  volatile bool stop_request_;
-
-  // Update period in microseconds.
-  int update_period_us_;
-
-  // Current pose count, used to avoid writing to the same buffer that is being
-  // read by the GPU.
-  uint32_t count_;
-  LucidPoseTracker pose_tracker_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_CPU_THREAD_POSE_UPDATER_H_
diff --git a/libs/vr/libeds/include/private/dvr/lucid_metrics.h b/libs/vr/libeds/include/private/dvr/device_metrics.h
similarity index 84%
rename from libs/vr/libeds/include/private/dvr/lucid_metrics.h
rename to libs/vr/libeds/include/private/dvr/device_metrics.h
index 0e4ada4..7985f28 100644
--- a/libs/vr/libeds/include/private/dvr/lucid_metrics.h
+++ b/libs/vr/libeds/include/private/dvr/device_metrics.h
@@ -1,5 +1,5 @@
-#ifndef ANDROID_DVR_LUCID_METRICS_H_
-#define ANDROID_DVR_LUCID_METRICS_H_
+#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>
@@ -19,4 +19,4 @@
 }  // namespace dvr
 }  // namespace android
 
-#endif  // ANDROID_DVR_LUCID_METRICS_H_
+#endif  // ANDROID_DVR_DEVICE_METRICS_H_
diff --git a/libs/vr/libeds/include/private/dvr/distortion_renderer.h b/libs/vr/libeds/include/private/dvr/distortion_renderer.h
index e1c8114..28fd48a 100644
--- a/libs/vr/libeds/include/private/dvr/distortion_renderer.h
+++ b/libs/vr/libeds/include/private/dvr/distortion_renderer.h
@@ -9,7 +9,6 @@
 #include <private/dvr/eds_mesh.h>
 #include <private/dvr/graphics/shader_program.h>
 #include <private/dvr/late_latch.h>
-#include <private/dvr/lucid_pose_tracker.h>
 #include <private/dvr/render_texture_params.h>
 #include <private/dvr/types.h>
 
diff --git a/libs/vr/libeds/include/private/dvr/lookup_radial_distortion.h b/libs/vr/libeds/include/private/dvr/lookup_radial_distortion.h
deleted file mode 100644
index 56fc5db..0000000
--- a/libs/vr/libeds/include/private/dvr/lookup_radial_distortion.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef ANDROID_DVR_LOOKUP_RADIAL_DISTORTION_H_
-#define ANDROID_DVR_LOOKUP_RADIAL_DISTORTION_H_
-
-#include <vector>
-
-#include <private/dvr/color_channel_distortion.h>
-
-namespace android {
-namespace dvr {
-
-// LookupRadialDistortion implements a radial distortion based using using a
-// vector of tan(angle) -> multipliers.  This can use measured data directly.
-class LookupRadialDistortion : public ColorChannelDistortion {
- public:
-  // lookup.x = tan(angle), lookup.y = distance from center multiplier.
-  explicit LookupRadialDistortion(const vec2* lookup, size_t count);
-
-  vec2 Distort(vec2 p) const override;
-  vec2 DistortInverse(vec2 p) const override;
-
- private:
-  float DistortionFactor(float r) const;
-  float DistortRadius(float r) const;
-
-  std::vector<vec2> lookup_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_LOOKUP_RADIAL_DISTORTION_H_
diff --git a/libs/vr/libeds/include/private/dvr/lucid_pose_tracker.h b/libs/vr/libeds/include/private/dvr/lucid_pose_tracker.h
deleted file mode 100644
index 4ceda5a..0000000
--- a/libs/vr/libeds/include/private/dvr/lucid_pose_tracker.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef ANDROID_DVR_LUCID_POSE_TRACKER_H_
-#define ANDROID_DVR_LUCID_POSE_TRACKER_H_
-
-#include <memory>
-
-#include <dvr/pose_client.h>
-
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-// Provides pose tracking via the system pose service.
-class LucidPoseTracker {
- public:
-  // When set, the pose service is ignored and the given pose is always returned
-  // by GetPose. As long as this is called before any LucidPoseTracker is
-  // used, the pose service will not be created.
-  // Threading: this is not thread safe.
-  static void SetPoseOverride(const Posef& pose);
-
-  // Reset prior override pose.
-  static void ClearPoseOverride();
-
-  LucidPoseTracker();
-  ~LucidPoseTracker();
-
-  // Currently GetPose() will ignore timestamp_ns and always return the most
-  // recent orientation.
-  // TODO(stefanus): support prediction.
-  Posef GetPose(uint64_t timestamp_ns);
-
- private:
-  static bool is_override_pose_;
-  static Posef override_pose_;
-
-  DvrPose* pose_client_;
-
-  // The most recent pose.
-  Posef latest_pose_;
-
-  // The time stamp corresponding to when latest_pose_ was last updated.
-  uint64_t latest_timestamp_ns_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_LUCID_POSE_TRACKER_H_
diff --git a/libs/vr/libeds/lookup_radial_distortion.cpp b/libs/vr/libeds/lookup_radial_distortion.cpp
deleted file mode 100644
index 2cee863..0000000
--- a/libs/vr/libeds/lookup_radial_distortion.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include "include/private/dvr/lookup_radial_distortion.h"
-
-namespace android {
-namespace dvr {
-
-LookupRadialDistortion::LookupRadialDistortion(const vec2* lookup, size_t count)
-    : lookup_(lookup, lookup + count) {}
-
-float LookupRadialDistortion::DistortionFactor(float r) const {
-  for (size_t i = 1; i < lookup_.size(); ++i) {
-    if (lookup_[i].x() > r) {
-      float t =
-          (r - lookup_[i - 1].x()) / (lookup_[i].x() - lookup_[i - 1].x());
-      return lookup_[i - 1].y() + t * (lookup_[i].y() - lookup_[i - 1].y());
-    }
-  }
-  return lookup_.back().y();
-}
-
-float LookupRadialDistortion::DistortRadius(float r) const {
-  return r * DistortionFactor(r);
-}
-
-vec2 LookupRadialDistortion::Distort(vec2 p) const {
-  return p * DistortionFactor(p.norm());
-}
-
-vec2 LookupRadialDistortion::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;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libeds/lucid_metrics.cpp b/libs/vr/libeds/lucid_metrics.cpp
deleted file mode 100644
index 690c326..0000000
--- a/libs/vr/libeds/lucid_metrics.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-#include "include/private/dvr/display_metrics.h"
-#include <private/dvr/head_mount_metrics.h>
-#include <private/dvr/identity_distortion.h>
-#include <private/dvr/lookup_radial_distortion.h>
-#include <private/dvr/lucid_metrics.h>
-#include <private/dvr/types.h>
-
-namespace {
-
-// These numbers are specific to the OnePlus One and therefore
-// temporary until we advance to the next Lucid development platform.
-
-// Head mount metrics for Lucid A00
-static const float kDefaultInterLensDistance = 0.064f;  // 64mm
-static const float kDefaultTrayToLensDistance = 0.035f;
-static const float kDefaultVirtualEyeToScreenDistance = 0.042f;
-static const android::dvr::HeadMountMetrics::VerticalAlignment
-    kDefaultVerticalAlignment = android::dvr::HeadMountMetrics::kCenter;
-static const float kDefaultFovHalfAngleInsideH = 43.7f * M_PI / 180.0f;
-static const float kDefaultFovHalfAngleOutsideH = 47.8f * M_PI / 180.0f;
-static const float kDefaultFovHalfAngleV = 54.2f * M_PI / 180.0f;
-
-// Screen size in meters for Lucid (Nexus 6 display in portrait mode).
-static const android::dvr::vec2 kScreenSizeInMeters(0.0742177f, 0.131943f);
-
-// Border size in meters for the OnePlus One.
-static const float kScreenBorderSize = 0.004f;
-
-// Refresh rate.
-static const float kScreenRefreshRate = 60.0f;
-
-// Lucid display orientation is portrait.
-static const android::dvr::DisplayOrientation kDisplayOrientation =
-    android::dvr::DisplayOrientation::kPortrait;
-
-}  // anonymous namespace
-
-namespace android {
-namespace dvr {
-
-// The distortion lookup tables were generated via a raytraced lens simulation.
-// Please see for full calculations:
-// https://docs.google.com/a/google.com/spreadsheets/d/
-//       15cfHmCw5mHVOQ1rAJxMhta4q0e8zzcUDka1nRkfl7pY/edit?usp=sharing
-LookupRadialDistortion* GetBlueDistortionLookup() {
-  // clang-format off
-  vec2 kBlueDistortionLookup[] = {
-    {0.00000000000f, 1.00000000000f},
-    {0.01888626190f, 1.00096958278f},
-    {0.03777223810f, 1.00133301793f},
-    {0.05665761905f, 1.00193985168f},
-    {0.07554214286f, 1.00279048731f},
-    {0.09442542857f, 1.00388751781f},
-    {0.11330704762f, 1.00523363045f},
-    {0.13218657143f, 1.00683149424f},
-    {0.15106340476f, 1.00868516849f},
-    {0.16993695238f, 1.01079861126f},
-    {0.18880640476f, 1.01317712726f},
-    {0.20767092857f, 1.01582607321f},
-    {0.22652945238f, 1.01875203063f},
-    {0.24538078571f, 1.02196207850f},
-    {0.26422352381f, 1.02546421601f},
-    {0.28305602381f, 1.02926737969f},
-    {0.30187640476f, 1.03338139216f},
-    {0.32068252381f, 1.03781702504f},
-    {0.33947190476f, 1.04258620905f},
-    {0.35824171429f, 1.04770206653f},
-    {0.37698869048f, 1.05317909331f},
-    {0.39570916667f, 1.05903306635f},
-    {0.41439900000f, 1.06528124790f},
-    {0.43305350000f, 1.07194257391f},
-    {0.45166738095f, 1.07903777957f},
-    {0.47023471429f, 1.08658953759f},
-    {0.48874897619f, 1.09462239798f},
-    {0.50720285714f, 1.10316330018f},
-    {0.52558835714f, 1.11224144183f},
-    {0.54389669048f, 1.12188861421f},
-    {0.56211826190f, 1.13213939967f},
-    {0.58024261905f, 1.14303145047f},
-    {0.59825847619f, 1.15460566091f},
-    {0.61615335714f, 1.16690711338f},
-    {0.63391345238f, 1.17998560444f},
-    {0.65152300000f, 1.19389708987f},
-    {0.66896328571f, 1.20870580446f},
-    {0.68621100000f, 1.22448751087f},
-    {0.70323578571f, 1.24133415620f},
-    {0.71999716667f, 1.25935962776f},
-    {0.73643969048f, 1.27870875648f},
-    {0.75250778571f, 1.29953256670f},
-    {0.76817614286f, 1.32193822000f},
-    {0.78342009524f, 1.34604270338f},
-    {0.79828314286f, 1.37185833833f},
-    {0.81267376190f, 1.39964322604f},
-    {0.82656559524f, 1.42955958262f},
-    {0.83983054762f, 1.46196539657f},
-    {0.85234333333f, 1.49724142650f},
-    {0.86394971429f, 1.53585530271f},
-    {0.87422461905f, 1.57881139444f},
-    {0.88382583095f, 1.62091537826f},
-    {0.89571361286f, 1.67610209261f},
-    {0.90490389167f, 1.72118819668f},
-    {0.91526452143f, 1.77496904481f},
-    {0.92651365452f, 1.83722833673f},
-    {0.93437489976f, 1.88337590145f},
-    {0.94654105500f, 1.95937892848f},
-    {0.95476685095f, 2.01469745492f},
-    {0.96720383310f, 2.10451495481f},
-    {0.97546726405f, 2.16904926656f},
-    {0.98774046786f, 2.27302748020f},
-    {0.99579206762f, 2.34720582421f},
-    {1.00763328857f, 2.46603526105f},
-    {1.01533118405f, 2.55049232288f},
-    {1.02287120929f, 2.63936582235f}
-  };
-  // clang-format on
-  return new LookupRadialDistortion(
-      kBlueDistortionLookup, sizeof(kBlueDistortionLookup) / sizeof(vec2));
-}
-
-LookupRadialDistortion* GetGreenDistortionLookup() {
-  // clang-format off
-  vec2 kGreenDistortionLookup[] = {
-    {0.00000000000f, 1.00000000000f},
-    {0.01898883333f, 1.00000000000f},
-    {0.03797750000f, 1.00000000000f},
-    {0.05696585714f, 1.00000000000f},
-    {0.07595369048f, 1.00000000000f},
-    {0.09494078571f, 1.00000000000f},
-    {0.11392685714f, 1.00000000000f},
-    {0.13291157143f, 1.00000000000f},
-    {0.15189450000f, 1.00176560670f},
-    {0.17087511905f, 1.00384553961f},
-    {0.18985280952f, 1.00618614484f},
-    {0.20882680952f, 1.00879302066f},
-    {0.22779623810f, 1.01167234096f},
-    {0.24675997619f, 1.01483135203f},
-    {0.26571680952f, 1.01827767641f},
-    {0.28466519048f, 1.02202026825f},
-    {0.30360342857f, 1.02606859705f},
-    {0.32252950000f, 1.03043334057f},
-    {0.34144104762f, 1.03512630376f},
-    {0.36033538095f, 1.04016038545f},
-    {0.37920942857f, 1.04554970984f},
-    {0.39805966667f, 1.05130981266f},
-    {0.41688209524f, 1.05745768999f},
-    {0.43567214286f, 1.06401204155f},
-    {0.45442473810f, 1.07099310305f},
-    {0.47313411905f, 1.07842314596f},
-    {0.49179388095f, 1.08632639514f},
-    {0.51039692857f, 1.09472920992f},
-    {0.52893538095f, 1.10366038032f},
-    {0.54740061905f, 1.11315113705f},
-    {0.56578326190f, 1.12323535769f},
-    {0.58407300000f, 1.13395008040f},
-    {0.60225871429f, 1.14533547370f},
-    {0.62032809524f, 1.15743581542f},
-    {0.63826750000f, 1.17030000749f},
-    {0.65606135714f, 1.18398295206f},
-    {0.67369107143f, 1.19854780583f},
-    {0.69113350000f, 1.21406895255f},
-    {0.70835842857f, 1.23063670464f},
-    {0.72532545238f, 1.24836302903f},
-    {0.74197478571f, 1.26739777609f},
-    {0.75822164286f, 1.28793886907f},
-    {0.77407361905f, 1.31003521318f},
-    {0.78948523810f, 1.33383710115f},
-    {0.80448471429f, 1.35938255065f},
-    {0.81901733333f, 1.38686361242f},
-    {0.83305214286f, 1.41644808409f},
-    {0.84646438095f, 1.44848277406f},
-    {0.85912733333f, 1.48334485259f},
-    {0.87088369048f, 1.52149970074f},
-    {0.88131250000f, 1.56392750036f},
-    {0.89105132929f, 1.60552684742f},
-    {0.90312479476f, 1.66002695068f},
-    {0.91244067452f, 1.70458805205f},
-    {0.92297971714f, 1.75767475825f},
-    {0.93440940905f, 1.81916050294f},
-    {0.94237194976f, 1.86478635937f},
-    {0.95471202405f, 1.93989738862f},
-    {0.96305355738f, 1.99457325750f},
-    {0.97567372071f, 2.08333293385f},
-    {0.98407229071f, 2.14708073108f},
-    {0.99653762071f, 2.24981649552f},
-    {1.00471276167f, 2.32311751786f},
-    {1.01672394000f, 2.44057411530f},
-    {1.02452363381f, 2.52407947994f},
-    {1.03216732667f, 2.61194301580f}
-  };
-  // clang-format on
-  return new LookupRadialDistortion(
-      kGreenDistortionLookup, sizeof(kGreenDistortionLookup) / sizeof(vec2));
-}
-
-LookupRadialDistortion* GetRedDistortionLookup() {
-  // clang-format off
-  vec2 kRedDistortionLookup[] = {
-    {0.00000000000f, 1.00000000000f},
-    {0.01906776190f, 1.00000000000f},
-    {0.03813547619f, 1.00000000000f},
-    {0.05720304762f, 1.00000000000f},
-    {0.07627040476f, 1.00000000000f},
-    {0.09533740476f, 1.00000000000f},
-    {0.11440385714f, 1.00000000000f},
-    {0.13346952381f, 1.00000000000f},
-    {0.15253409524f, 1.00000000000f},
-    {0.17159714286f, 1.00000000000f},
-    {0.19065814286f, 1.00053530030f},
-    {0.20971645238f, 1.00310924426f},
-    {0.22877123810f, 1.00595236192f},
-    {0.24782154762f, 1.00907150786f},
-    {0.26686623810f, 1.01247435420f},
-    {0.28590388095f, 1.01616968529f},
-    {0.30493288095f, 1.02016688932f},
-    {0.32395133333f, 1.02447646681f},
-    {0.34295697619f, 1.02911011406f},
-    {0.36194726190f, 1.03408046560f},
-    {0.38091921429f, 1.03940151599f},
-    {0.39986942857f, 1.04508858434f},
-    {0.41879402381f, 1.05115843585f},
-    {0.43768857143f, 1.05762946333f},
-    {0.45654809524f, 1.06452169646f},
-    {0.47536695238f, 1.07185711363f},
-    {0.49413888095f, 1.07965956927f},
-    {0.51285690476f, 1.08795508025f},
-    {0.53151326190f, 1.09677206014f},
-    {0.55009952381f, 1.10614118417f},
-    {0.56860633333f, 1.11609607621f},
-    {0.58702361905f, 1.12667304464f},
-    {0.60534028571f, 1.13791190276f},
-    {0.62354421429f, 1.14985618930f},
-    {0.64162188095f, 1.16255413653f},
-    {0.65955780952f, 1.17605992962f},
-    {0.67733352381f, 1.19043584317f},
-    {0.69492602381f, 1.20575517508f},
-    {0.71230514286f, 1.22210708787f},
-    {0.72943057143f, 1.23960199799f},
-    {0.74623921429f, 1.25839340501f},
-    {0.76262400000f, 1.27871385661f},
-    {0.77861754762f, 1.30056919119f},
-    {0.79415866667f, 1.32413401001f},
-    {0.80926385714f, 1.34946540639f},
-    {0.82390640476f, 1.37670655635f},
-    {0.83805190476f, 1.40602920817f},
-    {0.85157807143f, 1.43777181543f},
-    {0.86435700000f, 1.47230885729f},
-    {0.87622914286f, 1.51010361811f},
-    {0.88677650000f, 1.55211817236f},
-    {0.89663317738f, 1.59330127207f},
-    {0.90883197952f, 1.64729627820f},
-    {0.91827594357f, 1.69138814689f},
-    {0.92892199405f, 1.74398939784f},
-    {0.94047261548f, 1.80490554711f},
-    {0.94852659262f, 1.85009630648f},
-    {0.96099790167f, 1.92451421938f},
-    {0.96945317500f, 1.97863645920f},
-    {0.98221554286f, 2.06656418112f},
-    {0.99069599476f, 2.12974390154f},
-    {1.00331392976f, 2.23149730290f},
-    {1.01157138762f, 2.30414058939f},
-    {1.02372409452f, 2.42049694265f},
-    {1.03162992905f, 2.50318810924f},
-    {1.03934762000f, 2.59027212626f}
-  };
-  // clang-format on
-  return new LookupRadialDistortion(
-      kRedDistortionLookup, sizeof(kRedDistortionLookup) / sizeof(vec2));
-}
-
-HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov,
-                                        const FieldOfView& r_fov) {
-  std::shared_ptr<ColorChannelDistortion> default_distortion_r(
-      GetRedDistortionLookup());
-  std::shared_ptr<ColorChannelDistortion> default_distortion_g(
-      GetGreenDistortionLookup());
-  std::shared_ptr<ColorChannelDistortion> default_distortion_b(
-      GetBlueDistortionLookup());
-
-  return HeadMountMetrics(
-      kDefaultInterLensDistance, kDefaultTrayToLensDistance,
-      kDefaultVirtualEyeToScreenDistance, kDefaultVerticalAlignment, l_fov,
-      r_fov, default_distortion_r, default_distortion_g, default_distortion_b,
-      HeadMountMetrics::EyeOrientation::kCCW0Degrees,
-      HeadMountMetrics::EyeOrientation::kCCW0Degrees,
-      kDefaultInterLensDistance / 2.0f);
-}
-
-HeadMountMetrics CreateHeadMountMetrics() {
-  FieldOfView l_fov(kDefaultFovHalfAngleOutsideH, kDefaultFovHalfAngleInsideH,
-                    kDefaultFovHalfAngleV, kDefaultFovHalfAngleV);
-  FieldOfView r_fov(kDefaultFovHalfAngleInsideH, kDefaultFovHalfAngleOutsideH,
-                    kDefaultFovHalfAngleV, kDefaultFovHalfAngleV);
-
-  return CreateHeadMountMetrics(l_fov, r_fov);
-}
-
-DisplayMetrics CreateDisplayMetrics(vec2i screen_size) {
-  vec2 meters_per_pixel(
-      kScreenSizeInMeters[0] / static_cast<float>(screen_size[0]),
-      kScreenSizeInMeters[1] / static_cast<float>(screen_size[1]));
-  return DisplayMetrics(screen_size, meters_per_pixel, kScreenBorderSize,
-                        1000.0f / kScreenRefreshRate, kDisplayOrientation);
-}
-
-HeadMountMetrics CreateUndistortedHeadMountMetrics() {
-  FieldOfView l_fov(kDefaultFovHalfAngleOutsideH, kDefaultFovHalfAngleInsideH,
-                    kDefaultFovHalfAngleV, kDefaultFovHalfAngleV);
-  FieldOfView r_fov(kDefaultFovHalfAngleInsideH, kDefaultFovHalfAngleOutsideH,
-                    kDefaultFovHalfAngleV, kDefaultFovHalfAngleV);
-  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(kDefaultInterLensDistance, kDefaultTrayToLensDistance,
-                          kDefaultVirtualEyeToScreenDistance,
-                          kDefaultVerticalAlignment, l_fov, r_fov,
-                          distortion_all, distortion_all, distortion_all,
-                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
-                          HeadMountMetrics::EyeOrientation::kCCW0Degrees,
-                          kDefaultInterLensDistance / 2.0f);
-}
-
-}  // namespace dvr
-}  // namespace dvr
diff --git a/libs/vr/libeds/lucid_pose_tracker.cpp b/libs/vr/libeds/lucid_pose_tracker.cpp
deleted file mode 100644
index 5247020..0000000
--- a/libs/vr/libeds/lucid_pose_tracker.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "include/private/dvr/lucid_pose_tracker.h"
-
-#define LOG_TAG "LucidPoseTracker"
-#include <log/log.h>
-
-#include <private/dvr/clock_ns.h>
-
-namespace android {
-namespace dvr {
-
-bool LucidPoseTracker::is_override_pose_ = false;
-Posef LucidPoseTracker::override_pose_ = Posef();
-
-void LucidPoseTracker::SetPoseOverride(const Posef& pose) {
-  is_override_pose_ = true;
-  override_pose_ = pose;
-}
-
-void LucidPoseTracker::ClearPoseOverride() {
-  is_override_pose_ = false;
-  override_pose_ = Posef();
-}
-
-LucidPoseTracker::LucidPoseTracker() : pose_client_(NULL) {}
-
-LucidPoseTracker::~LucidPoseTracker() {
-  if (pose_client_) {
-    dvrPoseDestroy(pose_client_);
-  }
-}
-
-Posef LucidPoseTracker::GetPose(uint64_t timestamp_ns) {
-  if (is_override_pose_) {
-    return override_pose_;
-  }
-
-  if (!pose_client_) {
-    pose_client_ = dvrPoseCreate();
-
-    if (!pose_client_) {
-      ALOGE("No pose service, returning identity pose");
-      return Posef();
-    }
-  }
-
-  DvrPoseState state;
-  dvrPosePoll(pose_client_, &state);
-
-  const vec4 head_rotation_in_start_quat(
-      state.head_from_start_rotation.x, state.head_from_start_rotation.y,
-      state.head_from_start_rotation.z, state.head_from_start_rotation.w);
-
-  // When the pose service hasn't computed a pose yet, it returns a zero
-  // quaternion; just use the identity rotation in that case.
-  // TODO(stefanus): Find a better way to signal and check this.
-  if (head_rotation_in_start_quat.squaredNorm() < 0.5f) {
-    latest_pose_.SetRotation(quat::Identity());
-  } else {
-    latest_pose_.SetRotation(
-        quat(head_rotation_in_start_quat.w(), head_rotation_in_start_quat.x(),
-             head_rotation_in_start_quat.y(), head_rotation_in_start_quat.z())
-            .normalized());
-  }
-
-  const vec3 head_position_in_start(state.head_from_start_translation.x,
-                                    state.head_from_start_translation.y,
-                                    state.head_from_start_translation.z);
-  latest_pose_.SetPosition(head_position_in_start);
-
-  latest_timestamp_ns_ = GetSystemClockNs();
-
-  // PoseState pose_state;
-  // pose_state.timestamp_ns = latest_timestamp_ns_;
-  // pose_state.sensor_from_start_rotation =
-  //    ion::math::Rotationd::FromQuaternion(ion::math::Vector4d(
-  //        state.head_from_start_rotation.x, state.head_from_start_rotation.y,
-  //        state.head_from_start_rotation.z,
-  //        state.head_from_start_rotation.w));
-  //// TODO(stefanus): Determine the first derivative of the rotation and set it
-  //// here.
-  // pose_state.sensor_from_start_rotation_velocity =
-  // ion::math::Vector3d::Zero();
-
-  // TODO(stefanus): perform prediction.
-
-  return latest_pose_;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libimageio/include/private/dvr/image_io_base.h b/libs/vr/libimageio/include/private/dvr/image_io_base.h
index 009cad4..5f29de7 100644
--- a/libs/vr/libimageio/include/private/dvr/image_io_base.h
+++ b/libs/vr/libimageio/include/private/dvr/image_io_base.h
@@ -1,5 +1,5 @@
-#ifndef LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_BASE_H_
-#define LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_BASE_H_
+#ifndef LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_BASE_H_
+#define LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_BASE_H_
 
 #include <memory>
 #include <string>
@@ -53,4 +53,4 @@
   ImageIoWriter() = delete;
 };
 
-#endif  // LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_BASE_H_
+#endif  // LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_BASE_H_
diff --git a/libs/vr/libimageio/include/private/dvr/image_io_logging.h b/libs/vr/libimageio/include/private/dvr/image_io_logging.h
index ac78179..a2629f3 100644
--- a/libs/vr/libimageio/include/private/dvr/image_io_logging.h
+++ b/libs/vr/libimageio/include/private/dvr/image_io_logging.h
@@ -1,5 +1,5 @@
-#ifndef LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_LOGGING_H_
-#define LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_LOGGING_H_
+#ifndef LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_LOGGING_H_
+#define LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_LOGGING_H_
 
 // This header acts as log/log.h if LOG_TO_STDERR is not defined.
 // If LOG_TO_STDERR is defined, then android logging macros (such as ALOGE)
@@ -36,4 +36,4 @@
 #include <log/log.h>
 #endif  // LOG_TO_STDERR
 
-#endif  // LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_LOGGING_H_
+#endif  // LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_LOGGING_H_
diff --git a/libs/vr/libimageio/include/private/dvr/image_io_png.h b/libs/vr/libimageio/include/private/dvr/image_io_png.h
index e3b19db..e06a17a 100644
--- a/libs/vr/libimageio/include/private/dvr/image_io_png.h
+++ b/libs/vr/libimageio/include/private/dvr/image_io_png.h
@@ -1,5 +1,5 @@
-#ifndef LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_PNG_H_
-#define LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_PNG_H_
+#ifndef LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PNG_H_
+#define LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PNG_H_
 
 #include <fstream>
 
@@ -21,4 +21,4 @@
   friend class ImageIoWriter;
 };
 
-#endif  // LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_PNG_H_
+#endif  // LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PNG_H_
diff --git a/libs/vr/libimageio/include/private/dvr/image_io_ppm.h b/libs/vr/libimageio/include/private/dvr/image_io_ppm.h
index 00264bd..8a1a96c 100644
--- a/libs/vr/libimageio/include/private/dvr/image_io_ppm.h
+++ b/libs/vr/libimageio/include/private/dvr/image_io_ppm.h
@@ -1,5 +1,5 @@
-#ifndef LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_PPM_H_
-#define LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_PPM_H_
+#ifndef LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PPM_H_
+#define LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PPM_H_
 
 #include <private/dvr/image_io_base.h>
 
@@ -25,4 +25,4 @@
   friend class ImageIoWriter;
 };
 
-#endif  // LIB_LIBIMAGEIO_PRIVATE_DREAMOS_IMAGE_IO_PPM_H_
+#endif  // LIB_LIBIMAGEIO_PRIVATE_DVR_IMAGE_IO_PPM_H_
diff --git a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
index 0b658fb..fa0adf0 100644
--- a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
+++ b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
@@ -516,9 +516,8 @@
     std::cerr << "Starting service instance " << service_id_counter
               << std::endl;
     auto service = BenchmarkService::Create(
-        android::pdx::default_transport::Endpoint::Create(
+        android::pdx::default_transport::Endpoint::CreateAndBindSocket(
             GetServicePath(path, service_id_counter),
-            android::pdx::default_transport::Endpoint::kDefaultMode,
             android::pdx::default_transport::Endpoint::kBlocking));
     if (!service) {
       std::cerr << "Failed to create service instance!!" << std::endl;
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index a73ba34..cfc2022 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -35,10 +35,13 @@
         "-Werror",
     ],
     srcs: [
+        "client_channel_tests.cpp",
+        "ipc_helper_tests.cpp",
         "remote_method_tests.cpp",
         "service_framework_tests.cpp",
     ],
     static_libs: [
+        "libgmock",
         "libpdx_uds",
         "libpdx",
     ],
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 924335f..9d91617 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -156,6 +156,7 @@
 
 Status<void> ClientChannel::SendImpulse(int opcode, const void* buffer,
                                         size_t length) {
+  std::unique_lock<std::mutex> lock(socket_mutex_);
   Status<void> status;
   android::pdx::uds::RequestHeader<BorrowedHandle> request;
   if (length > request.impulse_payload.size() ||
@@ -174,6 +175,7 @@
                                           size_t send_count,
                                           const iovec* receive_vector,
                                           size_t receive_count) {
+  std::unique_lock<std::mutex> lock(socket_mutex_);
   Status<int> result;
   if ((send_vector == nullptr && send_count != 0) ||
       (receive_vector == nullptr && receive_count != 0)) {
diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp
index 323236d..850c6d3 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -39,32 +39,43 @@
 ClientChannelFactory::ClientChannelFactory(const std::string& endpoint_path)
     : endpoint_path_{GetEndpointPath(endpoint_path)} {}
 
+ClientChannelFactory::ClientChannelFactory(LocalHandle socket)
+    : socket_{std::move(socket)} {}
+
 std::unique_ptr<pdx::ClientChannelFactory> ClientChannelFactory::Create(
     const std::string& endpoint_path) {
   return std::unique_ptr<pdx::ClientChannelFactory>{
       new ClientChannelFactory{endpoint_path}};
 }
 
+std::unique_ptr<pdx::ClientChannelFactory> ClientChannelFactory::Create(
+    LocalHandle socket) {
+  return std::unique_ptr<pdx::ClientChannelFactory>{
+      new ClientChannelFactory{std::move(socket)}};
+}
+
 Status<std::unique_ptr<pdx::ClientChannel>> ClientChannelFactory::Connect(
     int64_t timeout_ms) const {
   Status<void> status;
 
-  LocalHandle socket_fd{socket(AF_UNIX, SOCK_STREAM, 0)};
-  if (!socket_fd) {
+  bool connected = socket_.IsValid();
+  if (!connected) {
+    socket_.Reset(socket(AF_UNIX, SOCK_STREAM, 0));
+    LOG_ALWAYS_FATAL_IF(
+        endpoint_path_.empty(),
+        "ClientChannelFactory::Connect: unspecified socket path");
+  }
+
+  if (!socket_) {
     ALOGE("ClientChannelFactory::Connect: socket error: %s", strerror(errno));
     return ErrorStatus(errno);
   }
 
-  sockaddr_un remote;
-  remote.sun_family = AF_UNIX;
-  strncpy(remote.sun_path, endpoint_path_.c_str(), sizeof(remote.sun_path));
-  remote.sun_path[sizeof(remote.sun_path) - 1] = '\0';
-
   bool use_timeout = (timeout_ms >= 0);
   auto now = steady_clock::now();
   auto time_end = now + std::chrono::milliseconds{timeout_ms};
 
-  bool connected = false;
+  int max_eaccess = 5;  // Max number of times to retry when EACCES returned.
   while (!connected) {
     int64_t timeout = -1;
     if (use_timeout) {
@@ -73,6 +84,10 @@
       if (timeout < 0)
         return ErrorStatus(ETIMEDOUT);
     }
+    sockaddr_un remote;
+    remote.sun_family = AF_UNIX;
+    strncpy(remote.sun_path, endpoint_path_.c_str(), sizeof(remote.sun_path));
+    remote.sun_path[sizeof(remote.sun_path) - 1] = '\0';
     ALOGD("ClientChannelFactory: Waiting for endpoint at %s", remote.sun_path);
     status = WaitForEndpoint(endpoint_path_, timeout);
     if (!status)
@@ -80,14 +95,18 @@
 
     ALOGD("ClientChannelFactory: Connecting to %s", remote.sun_path);
     int ret = RETRY_EINTR(connect(
-        socket_fd.Get(), reinterpret_cast<sockaddr*>(&remote), sizeof(remote)));
+        socket_.Get(), reinterpret_cast<sockaddr*>(&remote), sizeof(remote)));
     if (ret == -1) {
       ALOGD("ClientChannelFactory: Connect error %d: %s", errno,
             strerror(errno));
-      if (errno == ECONNREFUSED) {
-        // Connection refused can be the result of connecting too early (the
-        // service socket is created but not being listened to yet).
-        ALOGD("ClientChannelFactory: Connection refused, waiting...");
+      // if |max_eaccess| below reaches zero when errno is EACCES, the control
+      // flows into the next "else if" statement and a permanent error is
+      // returned from this function.
+      if (errno == ECONNREFUSED || (errno == EACCES && max_eaccess-- > 0)) {
+        // Connection refused/Permission denied can be the result of connecting
+        // too early (the service socket is created but its access rights are
+        // not set or not being listened to yet).
+        ALOGD("ClientChannelFactory: %s, waiting...", strerror(errno));
         using namespace std::literals::chrono_literals;
         std::this_thread::sleep_for(100ms);
       } else if (errno != ENOENT && errno != ENOTDIR) {
@@ -102,20 +121,20 @@
       }
     } else {
       connected = true;
+      ALOGD("ClientChannelFactory: Connected successfully to %s...",
+            remote.sun_path);
     }
     if (use_timeout)
       now = steady_clock::now();
   }  // while (!connected)
 
-  ALOGD("ClientChannelFactory: Connected successfully to %s...",
-        remote.sun_path);
   RequestHeader<BorrowedHandle> request;
   InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false);
-  status = SendData(socket_fd.Borrow(), request);
+  status = SendData(socket_.Borrow(), request);
   if (!status)
     return ErrorStatus(status.error());
   ResponseHeader<LocalHandle> response;
-  status = ReceiveData(socket_fd.Borrow(), &response);
+  status = ReceiveData(socket_.Borrow(), &response);
   if (!status)
     return ErrorStatus(status.error());
   int ref = response.ret_code;
@@ -124,7 +143,7 @@
 
   LocalHandle event_fd = std::move(response.file_descriptors[ref]);
   return ClientChannel::Create(ChannelManager::Get().CreateHandle(
-      std::move(socket_fd), std::move(event_fd)));
+      std::move(socket_), std::move(event_fd)));
 }
 
 }  // namespace uds
diff --git a/libs/vr/libpdx_uds/client_channel_tests.cpp b/libs/vr/libpdx_uds/client_channel_tests.cpp
new file mode 100644
index 0000000..7c3c68a
--- /dev/null
+++ b/libs/vr/libpdx_uds/client_channel_tests.cpp
@@ -0,0 +1,162 @@
+#include <uds/client_channel.h>
+
+#include <sys/socket.h>
+
+#include <algorithm>
+#include <limits>
+#include <random>
+#include <thread>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <pdx/client.h>
+#include <pdx/rpc/remote_method.h>
+#include <pdx/service.h>
+
+#include <uds/client_channel_factory.h>
+#include <uds/service_endpoint.h>
+
+using testing::Return;
+using testing::_;
+
+using android::pdx::ClientBase;
+using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
+using android::pdx::Message;
+using android::pdx::ServiceBase;
+using android::pdx::ServiceDispatcher;
+using android::pdx::Status;
+using android::pdx::rpc::DispatchRemoteMethod;
+using android::pdx::uds::ClientChannel;
+using android::pdx::uds::ClientChannelFactory;
+using android::pdx::uds::Endpoint;
+
+namespace {
+
+struct TestProtocol {
+  using DataType = int8_t;
+  enum {
+    kOpSum = 0,
+  };
+  PDX_REMOTE_METHOD(Sum, kOpSum, int64_t(const std::vector<DataType>&));
+};
+
+class TestService : public ServiceBase<TestService> {
+ public:
+  TestService(std::unique_ptr<Endpoint> endpoint)
+      : ServiceBase{"TestService", std::move(endpoint)} {}
+
+  Status<void> HandleMessage(Message& message) override {
+    switch (message.GetOp()) {
+      case TestProtocol::kOpSum:
+        DispatchRemoteMethod<TestProtocol::Sum>(*this, &TestService::OnSum,
+                                                message);
+        return {};
+
+      default:
+        return Service::HandleMessage(message);
+    }
+  }
+
+  int64_t OnSum(Message& /*message*/,
+                const std::vector<TestProtocol::DataType>& data) {
+    return std::accumulate(data.begin(), data.end(), int64_t{0});
+  }
+};
+
+class TestClient : public ClientBase<TestClient> {
+ public:
+  using ClientBase::ClientBase;
+
+  int64_t Sum(const std::vector<TestProtocol::DataType>& data) {
+    auto status = InvokeRemoteMethod<TestProtocol::Sum>(data);
+    return status ? status.get() : -1;
+  }
+};
+
+class TestServiceRunner {
+ public:
+  TestServiceRunner(LocalHandle channel_socket) {
+    auto endpoint = Endpoint::CreateFromSocketFd(LocalHandle{});
+    endpoint->RegisterNewChannelForTests(std::move(channel_socket));
+    service_ = TestService::Create(std::move(endpoint));
+    dispatcher_ = android::pdx::uds::ServiceDispatcher::Create();
+    dispatcher_->AddService(service_);
+    dispatch_thread_ = std::thread(
+        std::bind(&ServiceDispatcher::EnterDispatchLoop, dispatcher_.get()));
+  }
+
+  ~TestServiceRunner() {
+    dispatcher_->SetCanceled(true);
+    dispatch_thread_.join();
+    dispatcher_->RemoveService(service_);
+  }
+
+ private:
+  std::shared_ptr<TestService> service_;
+  std::unique_ptr<ServiceDispatcher> dispatcher_;
+  std::thread dispatch_thread_;
+};
+
+class ClientChannelTest : public testing::Test {
+ public:
+  void SetUp() override {
+    int channel_sockets[2] = {};
+    ASSERT_EQ(
+        0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, channel_sockets));
+    LocalHandle service_channel{channel_sockets[0]};
+    LocalHandle client_channel{channel_sockets[1]};
+
+    service_runner_.reset(new TestServiceRunner{std::move(service_channel)});
+    auto factory = ClientChannelFactory::Create(std::move(client_channel));
+    auto status = factory->Connect(android::pdx::Client::kInfiniteTimeout);
+    ASSERT_TRUE(status);
+    client_ = TestClient::Create(status.take());
+  }
+
+  void TearDown() override {
+    service_runner_.reset();
+    client_.reset();
+  }
+
+ protected:
+  std::unique_ptr<TestServiceRunner> service_runner_;
+  std::shared_ptr<TestClient> client_;
+};
+
+TEST_F(ClientChannelTest, MultithreadedClient) {
+  constexpr int kNumTestThreads = 8;
+  constexpr size_t kDataSize = 1000;  // Try to keep RPC buffer size below 4K.
+
+  std::random_device rd;
+  std::mt19937 gen{rd()};
+  std::uniform_int_distribution<TestProtocol::DataType> dist{
+      std::numeric_limits<TestProtocol::DataType>::min(),
+      std::numeric_limits<TestProtocol::DataType>::max()};
+
+  auto worker = [](std::shared_ptr<TestClient> client,
+                   std::vector<TestProtocol::DataType> data) {
+    constexpr int kMaxIterations = 500;
+    int64_t expected = std::accumulate(data.begin(), data.end(), int64_t{0});
+    for (int i = 0; i < kMaxIterations; i++) {
+      ASSERT_EQ(expected, client->Sum(data));
+    }
+  };
+
+  // Start client threads.
+  std::vector<TestProtocol::DataType> data;
+  data.resize(kDataSize);
+  std::vector<std::thread> threads;
+  for (int i = 0; i < kNumTestThreads; i++) {
+    std::generate(data.begin(), data.end(),
+                  [&dist, &gen]() { return dist(gen); });
+    threads.emplace_back(worker, client_, data);
+  }
+
+  // Wait for threads to finish.
+  for (auto& thread : threads)
+    thread.join();
+}
+
+}  // namespace
diff --git a/libs/vr/libpdx_uds/ipc_helper.cpp b/libs/vr/libpdx_uds/ipc_helper.cpp
index d604f62..d75ce86 100644
--- a/libs/vr/libpdx_uds/ipc_helper.cpp
+++ b/libs/vr/libpdx_uds/ipc_helper.cpp
@@ -18,6 +18,150 @@
 namespace pdx {
 namespace uds {
 
+namespace {
+
+// Default implementations of Send/Receive interfaces to use standard socket
+// send/sendmsg/recv/recvmsg functions.
+class SocketSender : public SendInterface {
+ public:
+  ssize_t Send(int socket_fd, const void* data, size_t size,
+               int flags) override {
+    return send(socket_fd, data, size, flags);
+  }
+  ssize_t SendMessage(int socket_fd, const msghdr* msg, int flags) override {
+    return sendmsg(socket_fd, msg, flags);
+  }
+} g_socket_sender;
+
+class SocketReceiver : public RecvInterface {
+ public:
+  ssize_t Receive(int socket_fd, void* data, size_t size, int flags) override {
+    return recv(socket_fd, data, size, flags);
+  }
+  ssize_t ReceiveMessage(int socket_fd, msghdr* msg, int flags) override {
+    return recvmsg(socket_fd, msg, flags);
+  }
+} g_socket_receiver;
+
+}  // anonymous namespace
+
+// Helper wrappers around send()/sendmsg() which repeat send() calls on data
+// that was not sent with the initial call to send/sendmsg. This is important to
+// handle transmissions interrupted by signals.
+Status<void> SendAll(SendInterface* sender, const BorrowedHandle& socket_fd,
+                     const void* data, size_t size) {
+  Status<void> ret;
+  const uint8_t* ptr = static_cast<const uint8_t*>(data);
+  while (size > 0) {
+    ssize_t size_written =
+        RETRY_EINTR(sender->Send(socket_fd.Get(), ptr, size, MSG_NOSIGNAL));
+    if (size_written < 0) {
+      ret.SetError(errno);
+      ALOGE("SendAll: Failed to send data over socket: %s",
+            ret.GetErrorMessage().c_str());
+      break;
+    }
+    size -= size_written;
+    ptr += size_written;
+  }
+  return ret;
+}
+
+Status<void> SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd,
+                        const msghdr* msg) {
+  Status<void> ret;
+  ssize_t sent_size =
+      RETRY_EINTR(sender->SendMessage(socket_fd.Get(), msg, MSG_NOSIGNAL));
+  if (sent_size < 0) {
+    ret.SetError(errno);
+    ALOGE("SendMsgAll: Failed to send data over socket: %s",
+          ret.GetErrorMessage().c_str());
+    return ret;
+  }
+
+  ssize_t chunk_start_offset = 0;
+  for (size_t i = 0; i < msg->msg_iovlen; i++) {
+    ssize_t chunk_end_offset = chunk_start_offset + msg->msg_iov[i].iov_len;
+    if (sent_size < chunk_end_offset) {
+      size_t offset_within_chunk = sent_size - chunk_start_offset;
+      size_t data_size = msg->msg_iov[i].iov_len - offset_within_chunk;
+      const uint8_t* chunk_base =
+          static_cast<const uint8_t*>(msg->msg_iov[i].iov_base);
+      ret = SendAll(sender, socket_fd, chunk_base + offset_within_chunk,
+                    data_size);
+      if (!ret)
+        break;
+      sent_size += data_size;
+    }
+    chunk_start_offset = chunk_end_offset;
+  }
+  return ret;
+}
+
+// Helper wrappers around recv()/recvmsg() which repeat recv() calls on data
+// that was not received with the initial call to recvmsg(). This is important
+// to handle transmissions interrupted by signals as well as the case when
+// initial data did not arrive in a single chunk over the socket (e.g. socket
+// buffer was full at the time of transmission, and only portion of initial
+// message was sent and the rest was blocked until the buffer was cleared by the
+// receiving side).
+Status<void> RecvMsgAll(RecvInterface* receiver,
+                        const BorrowedHandle& socket_fd, msghdr* msg) {
+  Status<void> ret;
+  ssize_t size_read = RETRY_EINTR(receiver->ReceiveMessage(
+      socket_fd.Get(), msg, MSG_WAITALL | MSG_CMSG_CLOEXEC));
+  if (size_read < 0) {
+    ret.SetError(errno);
+    ALOGE("RecvMsgAll: Failed to receive data from socket: %s",
+          ret.GetErrorMessage().c_str());
+    return ret;
+  } else if (size_read == 0) {
+    ret.SetError(ESHUTDOWN);
+    ALOGW("RecvMsgAll: Socket has been shut down");
+    return ret;
+  }
+
+  ssize_t chunk_start_offset = 0;
+  for (size_t i = 0; i < msg->msg_iovlen; i++) {
+    ssize_t chunk_end_offset = chunk_start_offset + msg->msg_iov[i].iov_len;
+    if (size_read < chunk_end_offset) {
+      size_t offset_within_chunk = size_read - chunk_start_offset;
+      size_t data_size = msg->msg_iov[i].iov_len - offset_within_chunk;
+      uint8_t* chunk_base = static_cast<uint8_t*>(msg->msg_iov[i].iov_base);
+      ret = RecvAll(receiver, socket_fd, chunk_base + offset_within_chunk,
+                    data_size);
+      if (!ret)
+        break;
+      size_read += data_size;
+    }
+    chunk_start_offset = chunk_end_offset;
+  }
+  return ret;
+}
+
+Status<void> RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd,
+                     void* data, size_t size) {
+  Status<void> ret;
+  uint8_t* ptr = static_cast<uint8_t*>(data);
+  while (size > 0) {
+    ssize_t size_read = RETRY_EINTR(receiver->Receive(
+        socket_fd.Get(), ptr, size, MSG_WAITALL | MSG_CMSG_CLOEXEC));
+    if (size_read < 0) {
+      ret.SetError(errno);
+      ALOGE("RecvAll: Failed to receive data from socket: %s",
+            ret.GetErrorMessage().c_str());
+      break;
+    } else if (size_read == 0) {
+      ret.SetError(ESHUTDOWN);
+      ALOGW("RecvAll: Socket has been shut down");
+      break;
+    }
+    size -= size_read;
+    ptr += size_read;
+  }
+  return ret;
+}
+
 uint32_t kMagicPreamble = 0x7564736d;  // 'udsm'.
 
 struct MessagePreamble {
@@ -32,17 +176,14 @@
 
 Status<void> SendPayload::Send(const BorrowedHandle& socket_fd,
                                const ucred* cred) {
+  SendInterface* sender = sender_ ? sender_ : &g_socket_sender;
   MessagePreamble preamble;
   preamble.magic = kMagicPreamble;
   preamble.data_size = buffer_.size();
   preamble.fd_count = file_handles_.size();
-
-  ssize_t ret = RETRY_EINTR(
-      send(socket_fd.Get(), &preamble, sizeof(preamble), MSG_NOSIGNAL));
-  if (ret < 0)
-    return ErrorStatus(errno);
-  if (ret != sizeof(preamble))
-    return ErrorStatus(EIO);
+  Status<void> ret = SendAll(sender, socket_fd, &preamble, sizeof(preamble));
+  if (!ret)
+    return ret;
 
   msghdr msg = {};
   iovec recv_vect = {buffer_.data(), buffer_.size()};
@@ -72,12 +213,7 @@
     }
   }
 
-  ret = RETRY_EINTR(sendmsg(socket_fd.Get(), &msg, MSG_NOSIGNAL));
-  if (ret < 0)
-    return ErrorStatus(errno);
-  if (static_cast<size_t>(ret) != buffer_.size())
-    return ErrorStatus(EIO);
-  return {};
+  return SendMsgAll(sender, socket_fd, &msg);
 }
 
 // MessageWriter
@@ -132,15 +268,17 @@
 
 Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd,
                                      ucred* cred) {
+  RecvInterface* receiver = receiver_ ? receiver_ : &g_socket_receiver;
   MessagePreamble preamble;
-  ssize_t ret = RETRY_EINTR(
-      recv(socket_fd.Get(), &preamble, sizeof(preamble), MSG_WAITALL));
-  if (ret < 0)
-    return ErrorStatus(errno);
-  else if (ret == 0)
-    return ErrorStatus(ESHUTDOWN);
-  else if (ret != sizeof(preamble) || preamble.magic != kMagicPreamble)
-    return ErrorStatus(EIO);
+  Status<void> ret = RecvAll(receiver, socket_fd, &preamble, sizeof(preamble));
+  if (!ret)
+    return ret;
+
+  if (preamble.magic != kMagicPreamble) {
+    ALOGE("ReceivePayload::Receive: Message header is invalid");
+    ret.SetError(EIO);
+    return ret;
+  }
 
   buffer_.resize(preamble.data_size);
   file_handles_.clear();
@@ -159,13 +297,9 @@
     msg.msg_control = alloca(msg.msg_controllen);
   }
 
-  ret = RETRY_EINTR(recvmsg(socket_fd.Get(), &msg, MSG_WAITALL));
-  if (ret < 0)
-    return ErrorStatus(errno);
-  else if (ret == 0)
-    return ErrorStatus(ESHUTDOWN);
-  else if (static_cast<uint32_t>(ret) != preamble.data_size)
-    return ErrorStatus(EIO);
+  ret = RecvMsgAll(receiver, socket_fd, &msg);
+  if (!ret)
+    return ret;
 
   bool cred_available = false;
   file_handles_.reserve(preamble.fd_count);
@@ -187,10 +321,11 @@
   }
 
   if (cred && !cred_available) {
-    return ErrorStatus(EIO);
+    ALOGE("ReceivePayload::Receive: Failed to obtain message credentials");
+    ret.SetError(EIO);
   }
 
-  return {};
+  return ret;
 }
 
 // MessageReader
@@ -223,13 +358,7 @@
 
 Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
                       size_t size) {
-  ssize_t size_written =
-      RETRY_EINTR(send(socket_fd.Get(), data, size, MSG_NOSIGNAL));
-  if (size_written < 0)
-    return ErrorStatus(errno);
-  if (static_cast<size_t>(size_written) != size)
-    return ErrorStatus(EIO);
-  return {};
+  return SendAll(&g_socket_sender, socket_fd, data, size);
 }
 
 Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
@@ -237,26 +366,12 @@
   msghdr msg = {};
   msg.msg_iov = const_cast<iovec*>(data);
   msg.msg_iovlen = count;
-  ssize_t size_written =
-      RETRY_EINTR(sendmsg(socket_fd.Get(), &msg, MSG_NOSIGNAL));
-  if (size_written < 0)
-    return ErrorStatus(errno);
-  if (static_cast<size_t>(size_written) != CountVectorSize(data, count))
-    return ErrorStatus(EIO);
-  return {};
+  return SendMsgAll(&g_socket_sender, socket_fd, &msg);
 }
 
 Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
                          size_t size) {
-  ssize_t size_read =
-      RETRY_EINTR(recv(socket_fd.Get(), data, size, MSG_WAITALL));
-  if (size_read < 0)
-    return ErrorStatus(errno);
-  else if (size_read == 0)
-    return ErrorStatus(ESHUTDOWN);
-  else if (static_cast<size_t>(size_read) != size)
-    return ErrorStatus(EIO);
-  return {};
+  return RecvAll(&g_socket_receiver, socket_fd, data, size);
 }
 
 Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
@@ -264,14 +379,7 @@
   msghdr msg = {};
   msg.msg_iov = const_cast<iovec*>(data);
   msg.msg_iovlen = count;
-  ssize_t size_read = RETRY_EINTR(recvmsg(socket_fd.Get(), &msg, MSG_WAITALL));
-  if (size_read < 0)
-    return ErrorStatus(errno);
-  else if (size_read == 0)
-    return ErrorStatus(ESHUTDOWN);
-  else if (static_cast<size_t>(size_read) != CountVectorSize(data, count))
-    return ErrorStatus(EIO);
-  return {};
+  return RecvMsgAll(&g_socket_receiver, socket_fd, &msg);
 }
 
 size_t CountVectorSize(const iovec* vector, size_t count) {
diff --git a/libs/vr/libpdx_uds/ipc_helper_tests.cpp b/libs/vr/libpdx_uds/ipc_helper_tests.cpp
new file mode 100644
index 0000000..bfa827e
--- /dev/null
+++ b/libs/vr/libpdx_uds/ipc_helper_tests.cpp
@@ -0,0 +1,365 @@
+#include "uds/ipc_helper.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using testing::Return;
+using testing::SetErrnoAndReturn;
+using testing::_;
+
+using android::pdx::BorrowedHandle;
+using android::pdx::uds::SendInterface;
+using android::pdx::uds::RecvInterface;
+using android::pdx::uds::SendAll;
+using android::pdx::uds::SendMsgAll;
+using android::pdx::uds::RecvAll;
+using android::pdx::uds::RecvMsgAll;
+
+namespace {
+
+// Useful constants for tests.
+static constexpr intptr_t kPtr = 1234;
+static constexpr int kSocketFd = 5678;
+static const BorrowedHandle kSocket{kSocketFd};
+
+// Helper functions to construct test data pointer values.
+void* IntToPtr(intptr_t value) { return reinterpret_cast<void*>(value); }
+const void* IntToConstPtr(intptr_t value) {
+  return reinterpret_cast<const void*>(value);
+}
+
+// Mock classes for SendInterface/RecvInterface.
+class MockSender : public SendInterface {
+ public:
+  MOCK_METHOD4(Send, ssize_t(int socket_fd, const void* data, size_t size,
+                             int flags));
+  MOCK_METHOD3(SendMessage,
+               ssize_t(int socket_fd, const msghdr* msg, int flags));
+};
+
+class MockReceiver : public RecvInterface {
+ public:
+  MOCK_METHOD4(Receive,
+               ssize_t(int socket_fd, void* data, size_t size, int flags));
+  MOCK_METHOD3(ReceiveMessage, ssize_t(int socket_fd, msghdr* msg, int flags));
+};
+
+// Test case classes.
+class SendTest : public testing::Test {
+ public:
+  SendTest() {
+    ON_CALL(sender_, Send(_, _, _, _))
+        .WillByDefault(SetErrnoAndReturn(EIO, -1));
+    ON_CALL(sender_, SendMessage(_, _, _))
+        .WillByDefault(SetErrnoAndReturn(EIO, -1));
+  }
+
+ protected:
+  MockSender sender_;
+};
+
+class RecvTest : public testing::Test {
+ public:
+  RecvTest() {
+    ON_CALL(receiver_, Receive(_, _, _, _))
+        .WillByDefault(SetErrnoAndReturn(EIO, -1));
+    ON_CALL(receiver_, ReceiveMessage(_, _, _))
+        .WillByDefault(SetErrnoAndReturn(EIO, -1));
+  }
+
+ protected:
+  MockReceiver receiver_;
+};
+
+class MessageTestBase : public testing::Test {
+ public:
+  MessageTestBase() {
+    memset(&msg_, 0, sizeof(msg_));
+    msg_.msg_iovlen = data_.size();
+    msg_.msg_iov = data_.data();
+  }
+
+ protected:
+  static constexpr intptr_t kPtr1 = kPtr;
+  static constexpr intptr_t kPtr2 = kPtr + 200;
+  static constexpr intptr_t kPtr3 = kPtr + 1000;
+
+  MockSender sender_;
+  msghdr msg_;
+  std::vector<iovec> data_{
+      {IntToPtr(kPtr1), 100}, {IntToPtr(kPtr2), 200}, {IntToPtr(kPtr3), 300}};
+};
+
+class SendMessageTest : public MessageTestBase {
+ public:
+  SendMessageTest() {
+    ON_CALL(sender_, Send(_, _, _, _))
+        .WillByDefault(SetErrnoAndReturn(EIO, -1));
+    ON_CALL(sender_, SendMessage(_, _, _))
+        .WillByDefault(SetErrnoAndReturn(EIO, -1));
+  }
+
+ protected:
+  MockSender sender_;
+};
+
+class RecvMessageTest : public MessageTestBase {
+ public:
+  RecvMessageTest() {
+    ON_CALL(receiver_, Receive(_, _, _, _))
+        .WillByDefault(SetErrnoAndReturn(EIO, -1));
+    ON_CALL(receiver_, ReceiveMessage(_, _, _))
+        .WillByDefault(SetErrnoAndReturn(EIO, -1));
+  }
+
+ protected:
+  MockReceiver receiver_;
+};
+
+// Actual tests.
+
+// SendAll
+TEST_F(SendTest, Complete) {
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
+      .WillOnce(Return(100));
+
+  auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(SendTest, Signal) {
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
+      .WillOnce(Return(20));
+  EXPECT_CALL(sender_,
+              Send(kSocketFd, IntToConstPtr(kPtr + 20), 80, MSG_NOSIGNAL))
+      .WillOnce(Return(40));
+  EXPECT_CALL(sender_,
+              Send(kSocketFd, IntToConstPtr(kPtr + 60), 40, MSG_NOSIGNAL))
+      .WillOnce(Return(40));
+
+  auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(SendTest, Eintr) {
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
+      .WillOnce(SetErrnoAndReturn(EINTR, -1))
+      .WillOnce(Return(100));
+
+  auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(SendTest, Error) {
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
+      .WillOnce(SetErrnoAndReturn(EIO, -1));
+
+  auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
+  ASSERT_FALSE(status);
+  EXPECT_EQ(EIO, status.error());
+}
+
+TEST_F(SendTest, Error2) {
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL))
+      .WillOnce(Return(50));
+  EXPECT_CALL(sender_,
+              Send(kSocketFd, IntToConstPtr(kPtr + 50), 50, MSG_NOSIGNAL))
+      .WillOnce(SetErrnoAndReturn(EIO, -1));
+
+  auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100);
+  ASSERT_FALSE(status);
+  EXPECT_EQ(EIO, status.error());
+}
+
+// RecvAll
+TEST_F(RecvTest, Complete) {
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100,
+                                 MSG_WAITALL | MSG_CMSG_CLOEXEC))
+      .WillOnce(Return(100));
+
+  auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(RecvTest, Signal) {
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _))
+      .WillOnce(Return(20));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 20), 80, _))
+      .WillOnce(Return(40));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 60), 40, _))
+      .WillOnce(Return(40));
+
+  auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(RecvTest, Eintr) {
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _))
+      .WillOnce(SetErrnoAndReturn(EINTR, -1))
+      .WillOnce(Return(100));
+
+  auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(RecvTest, Error) {
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _))
+      .WillOnce(SetErrnoAndReturn(EIO, -1));
+
+  auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
+  ASSERT_FALSE(status);
+  EXPECT_EQ(EIO, status.error());
+}
+
+TEST_F(RecvTest, Error2) {
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _))
+      .WillOnce(Return(30));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 30), 70, _))
+      .WillOnce(SetErrnoAndReturn(EIO, -1));
+
+  auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100);
+  ASSERT_FALSE(status);
+  EXPECT_EQ(EIO, status.error());
+}
+
+// SendMsgAll
+TEST_F(SendMessageTest, Complete) {
+  EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, MSG_NOSIGNAL))
+      .WillOnce(Return(600));
+
+  auto status = SendMsgAll(&sender_, kSocket, &msg_);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(SendMessageTest, Partial) {
+  EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(70));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 70), 30, _))
+      .WillOnce(Return(30));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2), 200, _))
+      .WillOnce(Return(190));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2 + 190), 10, _))
+      .WillOnce(Return(10));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3), 300, _))
+      .WillOnce(Return(300));
+
+  auto status = SendMsgAll(&sender_, kSocket, &msg_);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(SendMessageTest, Partial2) {
+  EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(310));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3 + 10), 290, _))
+      .WillOnce(Return(290));
+
+  auto status = SendMsgAll(&sender_, kSocket, &msg_);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(SendMessageTest, Eintr) {
+  EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _))
+      .WillOnce(SetErrnoAndReturn(EINTR, -1))
+      .WillOnce(Return(70));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 70), 30, _))
+      .WillOnce(SetErrnoAndReturn(EINTR, -1))
+      .WillOnce(Return(30));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2), 200, _))
+      .WillOnce(Return(200));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3), 300, _))
+      .WillOnce(Return(300));
+
+  auto status = SendMsgAll(&sender_, kSocket, &msg_);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(SendMessageTest, Error) {
+  EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _))
+      .WillOnce(SetErrnoAndReturn(EBADF, -1));
+
+  auto status = SendMsgAll(&sender_, kSocket, &msg_);
+  ASSERT_FALSE(status);
+  EXPECT_EQ(EBADF, status.error());
+}
+
+TEST_F(SendMessageTest, Error2) {
+  EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(20));
+  EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 20), 80, _))
+      .WillOnce(SetErrnoAndReturn(EBADF, -1));
+
+  auto status = SendMsgAll(&sender_, kSocket, &msg_);
+  ASSERT_FALSE(status);
+  EXPECT_EQ(EBADF, status.error());
+}
+
+// RecvMsgAll
+TEST_F(RecvMessageTest, Complete) {
+  EXPECT_CALL(receiver_,
+              ReceiveMessage(kSocketFd, &msg_, MSG_WAITALL | MSG_CMSG_CLOEXEC))
+      .WillOnce(Return(600));
+
+  auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(RecvMessageTest, Partial) {
+  EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
+      .WillOnce(Return(70));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 70), 30, _))
+      .WillOnce(Return(30));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2), 200, _))
+      .WillOnce(Return(190));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2 + 190), 10, _))
+      .WillOnce(Return(10));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3), 300, _))
+      .WillOnce(Return(300));
+
+  auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(RecvMessageTest, Partial2) {
+  EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
+      .WillOnce(Return(310));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3 + 10), 290, _))
+      .WillOnce(Return(290));
+
+  auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(RecvMessageTest, Eintr) {
+  EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
+      .WillOnce(SetErrnoAndReturn(EINTR, -1))
+      .WillOnce(Return(70));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 70), 30, _))
+      .WillOnce(SetErrnoAndReturn(EINTR, -1))
+      .WillOnce(Return(30));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2), 200, _))
+      .WillOnce(Return(200));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3), 300, _))
+      .WillOnce(Return(300));
+
+  auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
+  EXPECT_TRUE(status);
+}
+
+TEST_F(RecvMessageTest, Error) {
+  EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
+      .WillOnce(SetErrnoAndReturn(EBADF, -1));
+
+  auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
+  ASSERT_FALSE(status);
+  EXPECT_EQ(EBADF, status.error());
+}
+
+TEST_F(RecvMessageTest, Error2) {
+  EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _))
+      .WillOnce(Return(20));
+  EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 20), 80, _))
+      .WillOnce(SetErrnoAndReturn(EBADF, -1));
+
+  auto status = RecvMsgAll(&receiver_, kSocket, &msg_);
+  ASSERT_FALSE(status);
+  EXPECT_EQ(EBADF, status.error());
+}
+
+}  // namespace
diff --git a/libs/vr/libpdx_uds/private/uds/client_channel.h b/libs/vr/libpdx_uds/private/uds/client_channel.h
index 45f6473..8f607f5 100644
--- a/libs/vr/libpdx_uds/private/uds/client_channel.h
+++ b/libs/vr/libpdx_uds/private/uds/client_channel.h
@@ -3,6 +3,8 @@
 
 #include <pdx/client_channel.h>
 
+#include <mutex>
+
 #include <uds/channel_event_set.h>
 #include <uds/channel_manager.h>
 #include <uds/service_endpoint.h>
@@ -73,6 +75,7 @@
 
   LocalChannelHandle channel_handle_;
   ChannelManager::ChannelData* channel_data_;
+  std::mutex socket_mutex_;
 };
 
 }  // namespace uds
diff --git a/libs/vr/libpdx_uds/private/uds/client_channel_factory.h b/libs/vr/libpdx_uds/private/uds/client_channel_factory.h
index 6f80d31..c43c5c7 100644
--- a/libs/vr/libpdx_uds/private/uds/client_channel_factory.h
+++ b/libs/vr/libpdx_uds/private/uds/client_channel_factory.h
@@ -13,6 +13,7 @@
  public:
   static std::unique_ptr<pdx::ClientChannelFactory> Create(
       const std::string& endpoint_path);
+  static std::unique_ptr<pdx::ClientChannelFactory> Create(LocalHandle socket);
 
   Status<std::unique_ptr<pdx::ClientChannel>> Connect(
       int64_t timeout_ms) const override;
@@ -22,7 +23,9 @@
 
  private:
   explicit ClientChannelFactory(const std::string& endpoint_path);
+  explicit ClientChannelFactory(LocalHandle socket);
 
+  mutable LocalHandle socket_;
   std::string endpoint_path_;
 };
 
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 82950a2..5b7e5ff 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -14,6 +14,38 @@
 namespace pdx {
 namespace uds {
 
+// Test interfaces used for unit-testing payload sending/receiving over sockets.
+class SendInterface {
+ public:
+  virtual ssize_t Send(int socket_fd, const void* data, size_t size,
+                       int flags) = 0;
+  virtual ssize_t SendMessage(int socket_fd, const msghdr* msg, int flags) = 0;
+
+ protected:
+  virtual ~SendInterface() = default;
+};
+
+class RecvInterface {
+ public:
+  virtual ssize_t Receive(int socket_fd, void* data, size_t size,
+                          int flags) = 0;
+  virtual ssize_t ReceiveMessage(int socket_fd, msghdr* msg, int flags) = 0;
+
+ protected:
+  virtual ~RecvInterface() = default;
+};
+
+// Helper methods that allow to send/receive data through abstract interfaces.
+// Useful for mocking out the underlying socket I/O.
+Status<void> SendAll(SendInterface* sender, const BorrowedHandle& socket_fd,
+                     const void* data, size_t size);
+Status<void> SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd,
+                        const msghdr* msg);
+Status<void> RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd,
+                     void* data, size_t size);
+Status<void> RecvMsgAll(RecvInterface* receiver,
+                        const BorrowedHandle& socket_fd, msghdr* msg);
+
 #define RETRY_EINTR(fnc_call)                 \
   ([&]() -> decltype(fnc_call) {              \
     decltype(fnc_call) result;                \
@@ -25,6 +57,7 @@
 
 class SendPayload : public MessageWriter, public OutputResourceMapper {
  public:
+  SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
   Status<void> Send(const BorrowedHandle& socket_fd);
   Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred);
 
@@ -44,12 +77,14 @@
       const RemoteChannelHandle& handle) override;
 
  private:
+  SendInterface* sender_;
   ByteBuffer buffer_;
   std::vector<int> file_handles_;
 };
 
 class ReceivePayload : public MessageReader, public InputResourceMapper {
  public:
+  ReceivePayload(RecvInterface* receiver = nullptr) : receiver_{receiver} {}
   Status<void> Receive(const BorrowedHandle& socket_fd);
   Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred);
 
@@ -64,6 +99,7 @@
                         LocalChannelHandle* handle) override;
 
  private:
+  RecvInterface* receiver_;
   ByteBuffer buffer_;
   std::vector<LocalHandle> file_handles_;
   size_t read_pos_{0};
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index f747abc..eb87827 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -97,6 +97,14 @@
   static std::unique_ptr<Endpoint> CreateAndBindSocket(
       const std::string& endpoint_path, bool blocking = kDefaultBlocking);
 
+  // Helper method to create an endpoint from an existing socket FD.
+  // Mostly helpful for tests.
+  static std::unique_ptr<Endpoint> CreateFromSocketFd(LocalHandle socket_fd);
+
+  // Test helper method to register a new channel identified by |channel_fd|
+  // socket file descriptor.
+  Status<void> RegisterNewChannelForTests(LocalHandle channel_fd);
+
   int epoll_fd() const { return epoll_fd_.Get(); }
 
  private:
@@ -109,6 +117,9 @@
   // This class must be instantiated using Create() static methods above.
   Endpoint(const std::string& endpoint_path, bool blocking,
            bool use_init_socket_fd = true);
+  Endpoint(LocalHandle socket_fd);
+
+  void Init(LocalHandle socket_fd);
 
   Endpoint(const Endpoint&) = delete;
   void operator=(const Endpoint&) = delete;
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 65fd59f..6c92259 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -161,9 +161,16 @@
         bind(fd.Get(), reinterpret_cast<sockaddr*>(&local), sizeof(local));
     CHECK_EQ(ret, 0) << "Endpoint::Endpoint: bind error: " << strerror(errno);
   }
-  CHECK_EQ(listen(fd.Get(), kMaxBackLogForSocketListen), 0)
-      << "Endpoint::Endpoint: listen error: " << strerror(errno);
+  Init(std::move(fd));
+}
 
+Endpoint::Endpoint(LocalHandle socket_fd) { Init(std::move(socket_fd)); }
+
+void Endpoint::Init(LocalHandle socket_fd) {
+  if (socket_fd) {
+    CHECK_EQ(listen(socket_fd.Get(), kMaxBackLogForSocketListen), 0)
+        << "Endpoint::Endpoint: listen error: " << strerror(errno);
+  }
   cancel_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
   CHECK(cancel_event_fd_.IsValid())
       << "Endpoint::Endpoint: Failed to create event fd: " << strerror(errno);
@@ -172,24 +179,27 @@
   CHECK(epoll_fd_.IsValid())
       << "Endpoint::Endpoint: Failed to create epoll fd: " << strerror(errno);
 
-  epoll_event socket_event;
-  socket_event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
-  socket_event.data.fd = fd.Get();
+  if (socket_fd) {
+    epoll_event socket_event;
+    socket_event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
+    socket_event.data.fd = socket_fd.Get();
+    int ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, socket_fd.Get(),
+                        &socket_event);
+    CHECK_EQ(ret, 0)
+        << "Endpoint::Endpoint: Failed to add socket fd to epoll fd: "
+        << strerror(errno);
+  }
 
   epoll_event cancel_event;
   cancel_event.events = EPOLLIN;
   cancel_event.data.fd = cancel_event_fd_.Get();
 
-  int ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd.Get(), &socket_event);
-  CHECK_EQ(ret, 0)
-      << "Endpoint::Endpoint: Failed to add socket fd to epoll fd: "
-      << strerror(errno);
-  ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, cancel_event_fd_.Get(),
-                  &cancel_event);
+  int ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, cancel_event_fd_.Get(),
+                      &cancel_event);
   CHECK_EQ(ret, 0)
       << "Endpoint::Endpoint: Failed to add cancel event fd to epoll fd: "
       << strerror(errno);
-  socket_fd_ = std::move(fd);
+  socket_fd_ = std::move(socket_fd);
 }
 
 void* Endpoint::AllocateMessageState() { return new MessageState; }
@@ -199,6 +209,9 @@
 }
 
 Status<void> Endpoint::AcceptConnection(Message* message) {
+  if (!socket_fd_)
+    return ErrorStatus(EBADF);
+
   sockaddr_un remote;
   socklen_t addrlen = sizeof(remote);
   LocalHandle channel_fd{accept4(socket_fd_.Get(),
@@ -515,7 +528,7 @@
     return ErrorStatus{ESHUTDOWN};
   }
 
-  if (event.data.fd == socket_fd_.Get()) {
+  if (socket_fd_ && event.data.fd == socket_fd_.Get()) {
     auto status = AcceptConnection(message);
     if (!status)
       return status;
@@ -680,6 +693,23 @@
       new Endpoint(endpoint_path, blocking, false));
 }
 
+std::unique_ptr<Endpoint> Endpoint::CreateFromSocketFd(LocalHandle socket_fd) {
+  return std::unique_ptr<Endpoint>(new Endpoint(std::move(socket_fd)));
+}
+
+Status<void> Endpoint::RegisterNewChannelForTests(LocalHandle channel_fd) {
+  int optval = 1;
+  if (setsockopt(channel_fd.Get(), SOL_SOCKET, SO_PASSCRED, &optval,
+                 sizeof(optval)) == -1) {
+    ALOGE(
+        "Endpoint::RegisterNewChannelForTests: Failed to enable the receiving"
+        "of the credentials for channel %d: %s",
+        channel_fd.Get(), strerror(errno));
+    return ErrorStatus(errno);
+  }
+  return OnNewChannel(std::move(channel_fd));
+}
+
 }  // namespace uds
 }  // namespace pdx
 }  // namespace android
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 0daab64..632978b 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -47,6 +47,7 @@
 ]
 
 sharedLibraries = [
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.allocator@2.0",
     "android.hardware.graphics.composer@2.1",
     "libbinder",
@@ -75,7 +76,7 @@
     cflags: [
         "-DLOG_TAG=\"vr_flinger\"",
         "-DTRACE=0",
-	"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
         "-DGL_GLEXT_PROTOTYPES",
         "-DEGL_EGLEXT_PROTOTYPES",
     ],
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 050cd5f..1d14a38 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -43,7 +43,7 @@
 
   // Accessors for the underlying BufferConsumer, the acquire fence, and the
   // use-case specific sequence value from the acquisition (see
-  // dreamos/buffer_hub_client.h).
+  // private/dvr/buffer_hub_client.h).
   std::shared_ptr<BufferConsumer> buffer() const { return buffer_; }
   int acquire_fence() const { return acquire_fence_.Get(); }
 
diff --git a/libs/vr/libvrflinger/compositor.cpp b/libs/vr/libvrflinger/compositor.cpp
index 5a111d4..d1d4f45 100644
--- a/libs/vr/libvrflinger/compositor.cpp
+++ b/libs/vr/libvrflinger/compositor.cpp
@@ -13,12 +13,12 @@
 #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/lucid_metrics.h>
 #include <private/dvr/native_buffer.h>
 #include <private/dvr/platform_defines.h>
 #include <utils/Log.h>
@@ -48,10 +48,10 @@
     std::make_shared<int64_t>(0);
 
 static constexpr char kDisableLensDistortionProp[] =
-    "persist.dreamos.disable_distort";
+    "persist.dvr.disable_distort";
 
 static constexpr char kEnableEdsPoseSaveProp[] =
-    "persist.dreamos.save_eds_pose";
+    "persist.dvr.save_eds_pose";
 
 namespace android {
 namespace dvr {
@@ -246,16 +246,17 @@
 
 class Compositor::RenderPoseBufferObject {
  public:
-  RenderPoseBufferObject(LocalHandle&& render_pose_buffer_fd) {
+  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 (render_pose_buffer_fd) {
+    if (fd_) {
       LOG_ALWAYS_FATAL_IF(!glBindSharedBufferQCOM);
       if (glBindSharedBufferQCOM)
         glBindSharedBufferQCOM(GL_UNIFORM_BUFFER,
                                sizeof(DisplaySurfaceMetadata),
-                               render_pose_buffer_fd.Get());
+                               fd_.Get());
       else
         ALOGE("Error: Missing gralloc buffer extension");
       CHECK_GL();
@@ -271,6 +272,7 @@
   // 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;
@@ -403,6 +405,7 @@
   }
 
   load_gl_extensions();
+  GpuProfiler::Get()->OnGlContextCreated();
 
   glEnable(BINNING_CONTROL_HINT_QCOM);
   glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
@@ -428,6 +431,7 @@
 }
 
 void Compositor::Shutdown() {
+  glFinish();
   render_target_[0].Destroy();
   render_target_[1].Destroy();
   layers_.clear();
@@ -438,6 +442,7 @@
   eds_renderer_.reset();
 
   if (context_) {
+    GpuProfiler::Get()->OnGlContextDestroyed();
     eglDestroyContext(display_, context_);
     context_ = 0;
   }
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 49b6f09..99f93bf 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -2,7 +2,9 @@
 
 #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/trusted_uids.h>
 #include <sys/poll.h>
 
 #include <array>
@@ -82,9 +84,9 @@
           *this, &DisplayManagerService::OnUpdateSurfaces, message);
       return {};
 
-  case DisplayManagerRPC::SetupPoseBuffer::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
-          *this, &DisplayManagerService::OnSetupPoseBuffer, message);
+    case DisplayManagerRPC::SetupNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+          *this, &DisplayManagerService::OnSetupNamedBuffer, message);
       return {};
 
     default:
@@ -188,9 +190,20 @@
   return 0;
 }
 
-pdx::BorrowedChannelHandle DisplayManagerService::OnSetupPoseBuffer(
-    pdx::Message& /*message*/, size_t extended_region_size, int usage) {
-  return display_service_->SetupPoseBuffer(extended_region_size, usage);
+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 {};
+  }
+  return display_service_->SetupNamedBuffer(name, size, producer_usage,
+                                            consumer_usage);
 }
 
 void DisplayManagerService::OnDisplaySurfaceChange() {
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 80324fd..7b037de 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -54,9 +54,9 @@
   int OnUpdateSurfaces(pdx::Message& message,
                        const std::map<int, DisplaySurfaceAttributes>& updates);
 
-  pdx::BorrowedChannelHandle OnSetupPoseBuffer(pdx::Message& message,
-                                               size_t extended_region_size,
-                                               int usage);
+  pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
+      pdx::Message& message, const std::string& name, size_t size,
+      uint64_t producer_usage, uint64_t consumer_usage);
 
   // Called by the display service to indicate changes to display surfaces that
   // the display manager should evaluate.
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index bb8613c..d3d50d0 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -1,13 +1,14 @@
 #include "display_service.h"
 
+#include <unistd.h>
 #include <vector>
 
 #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/lucid_metrics.h>
 #include <private/dvr/numeric.h>
 #include <private/dvr/polynomial_radial_distortion.h>
 #include <private/dvr/types.h>
@@ -18,20 +19,10 @@
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::rpc::WrapBuffer;
 
-namespace {
-
-constexpr char kPersistentPoseBufferName[] = "DvrPersistentPoseBuffer";
-const int kPersistentPoseBufferUserId = 0;
-const int kPersistentPoseBufferGroupId = 0;
-const size_t kTimingDataSizeOffset = 128;
-
-}  // anonymous namespace
-
 namespace android {
 namespace dvr {
 
-DisplayService::DisplayService()
-    : DisplayService(nullptr) {}
+DisplayService::DisplayService() : DisplayService(nullptr) {}
 
 DisplayService::DisplayService(Hwc2::Composer* hidl)
     : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
@@ -89,9 +80,9 @@
           *this, &DisplayService::OnSetViewerParams, message);
       return {};
 
-    case DisplayRPC::GetPoseBuffer::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetPoseBuffer>(
-          *this, &DisplayService::OnGetPoseBuffer, message);
+    case DisplayRPC::GetNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayRPC::GetNamedBuffer>(
+          *this, &DisplayService::OnGetNamedBuffer, message);
       return {};
 
     case DisplayRPC::IsVrAppRunning::Opcode:
@@ -254,13 +245,14 @@
   compositor->UpdateHeadMountMetrics(head_mount_metrics);
 }
 
-pdx::LocalChannelHandle DisplayService::OnGetPoseBuffer(pdx::Message& message) {
-  if (pose_buffer_) {
-    return pose_buffer_->CreateConsumer().take();
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
+    pdx::Message& /* message */, const std::string& name) {
+  auto named_buffer = named_buffers_.find(name);
+  if (named_buffer != named_buffers_.end()) {
+    return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
   }
 
-  pdx::rpc::RemoteMethodError(message, EAGAIN);
-  return {};
+  return pdx::ErrorStatus(EINVAL);
 }
 
 // Calls the message handler for the DisplaySurface associated with this
@@ -334,16 +326,20 @@
   hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
-pdx::BorrowedChannelHandle DisplayService::SetupPoseBuffer(
-    size_t extended_region_size, int usage) {
-  if (!pose_buffer_) {
-    pose_buffer_ = BufferProducer::Create(
-        kPersistentPoseBufferName, kPersistentPoseBufferUserId,
-        kPersistentPoseBufferGroupId, usage,
-        extended_region_size + kTimingDataSizeOffset);
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
+    const std::string& name, size_t size, int producer_usage,
+    int consumer_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);
+    named_buffer =
+        named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
+            .first;
   }
 
-  return pose_buffer_->GetChannelHandle().Borrow();
+  return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
 }
 
 void DisplayService::OnHardwareComposerRefresh() {
@@ -362,10 +358,11 @@
 
 int DisplayService::IsVrAppRunning(pdx::Message& message) {
   bool visible = false;
-  ForEachDisplaySurface([&visible](const std::shared_ptr<DisplaySurface>& surface) {
-    if (surface->client_z_order() == 0 && surface->IsVisible())
-      visible = true;
-  });
+  ForEachDisplaySurface(
+      [&visible](const std::shared_ptr<DisplaySurface>& surface) {
+        if (surface->client_z_order() == 0 && surface->IsVisible())
+          visible = true;
+      });
 
   REPLY_SUCCESS_RETURN(message, visible, 0);
 }
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index da80a84..db89064 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -3,6 +3,7 @@
 
 #include <pdx/service.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>
 
@@ -38,8 +39,9 @@
   // any change to client/manager attributes that affect visibility or z order.
   void UpdateActiveDisplaySurfaces();
 
-  pdx::BorrowedChannelHandle SetupPoseBuffer(size_t extended_region_size,
-                                             int usage);
+  pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
+      const std::string& name, size_t size, int producer_usage,
+      int consumer_usage);
 
   template <class A>
   void ForEachDisplaySurface(A action) const {
@@ -85,7 +87,8 @@
 
   void OnSetViewerParams(pdx::Message& message,
                          const ViewerParams& view_params);
-  pdx::LocalChannelHandle OnGetPoseBuffer(pdx::Message& message);
+  pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
+      pdx::Message& message, const std::string& name);
 
   // Temporary query for current VR status. Will be removed later.
   int IsVrAppRunning(pdx::Message& message);
@@ -102,7 +105,7 @@
   HardwareComposer hardware_composer_;
   DisplayConfigurationUpdateNotifier update_notifier_;
 
-  std::unique_ptr<BufferProducer> pose_buffer_;
+  std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 542bbd9..18ff4f5 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -64,7 +64,7 @@
 
 const char kDvrPerformanceProperty[] = "sys.dvr.performance";
 
-const char kRightEyeOffsetProperty[] = "dreamos.right_eye_offset_ns";
+const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
 
 // Returns our best guess for the time the compositor will spend rendering the
 // next frame.
@@ -1416,7 +1416,7 @@
 
 void Layer::Prepare() {
   int right, bottom;
-  buffer_handle_t handle;
+  sp<GraphicBuffer> handle;
 
   if (surface_) {
     // Only update the acquired buffer when one is either available or this is
@@ -1465,14 +1465,14 @@
     }
     right = acquired_buffer_.buffer()->width();
     bottom = acquired_buffer_.buffer()->height();
-    handle = acquired_buffer_.buffer()->native_handle();
+    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_->handle();
+    handle = direct_buffer_->buffer();
     acquire_fence_fd_.Close();
   }
 
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index bf831a7..d0996f0 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -627,19 +627,21 @@
 
 #ifndef EGL_ANDROID_get_frame_timestamps
 #define EGL_ANDROID_get_frame_timestamps 1
-#define EGL_TIMESTAMPS_ANDROID 0x314D
-#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
-#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
-#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
-#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
-#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
-#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
-#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
-#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
-#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
-#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
-#define EGL_READS_DONE_TIME_ANDROID 0x3159
+#define EGL_TIMESTAMPS_ANDROID 0x3430
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+#define EGL_READS_DONE_TIME_ANDROID 0x343C
+#define EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID, -2)
+#define EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID, -1)
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
 EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 6a62e8d..a895e63 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -23,28 +23,28 @@
 
 // The headers modules are in frameworks/native/opengl/Android.bp.
 ndk_library {
-    name: "libEGL.ndk",
+    name: "libEGL",
     symbol_file: "libEGL.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv1_CM.ndk",
+    name: "libGLESv1_CM",
     symbol_file: "libGLESv1_CM.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv2.ndk",
+    name: "libGLESv2",
     symbol_file: "libGLESv2.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv3.ndk",
+    name: "libGLESv3",
     symbol_file: "libGLESv3.map.txt",
     first_version: "18",
     unversioned_until: "current",
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index b00d401..9de15d0 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -223,6 +223,10 @@
             (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
     { "eglGetFrameTimestampSupportedANDROID",
             (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
+
+    // EGL_ANDROID_native_fence_sync
+    { "eglDupNativeFenceFDANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglDupNativeFenceFDANDROID },
 };
 
 /*
@@ -232,8 +236,7 @@
 #define FILTER_EXTENSIONS(procname) \
         (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") ||    \
          !strcmp((procname), "eglHibernateProcessIMG")      ||    \
-         !strcmp((procname), "eglAwakenProcessIMG")         ||    \
-         !strcmp((procname), "eglDupNativeFenceFDANDROID"))
+         !strcmp((procname), "eglAwakenProcessIMG"))
 
 
 
@@ -2166,10 +2169,15 @@
         case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
         case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
         case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
-        case EGL_DISPLAY_PRESENT_TIME_ANDROID:
         case EGL_DEQUEUE_READY_TIME_ANDROID:
         case EGL_READS_DONE_TIME_ANDROID:
             return EGL_TRUE;
+        case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
+            int value = 0;
+            window->query(window,
+                    NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
+            return value == 0 ? EGL_FALSE : EGL_TRUE;
+        }
         default:
             return EGL_FALSE;
     }
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index 61b9b66..b8a9add 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -28,7 +28,7 @@
 
 Version
 
-    Version 1, January 13, 2017
+    Version 8, April 11, 2017
 
 Number
 
@@ -81,19 +81,21 @@
 
 New Tokens
 
-    EGL_TIMESTAMPS_ANDROID 0x314D
-    EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
-    EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
-    EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
-    EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
-    EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
-    EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
-    EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
-    EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
-    EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
-    EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
-    EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
-    EGL_READS_DONE_TIME_ANDROID 0x3159
+    EGL_TIMESTAMPS_ANDROID 0x3430
+    EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+    EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+    EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+    EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+    EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+    EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+    EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+    EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+    EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+    EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+    EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+    EGL_READS_DONE_TIME_ANDROID 0x343C
+    EGL_TIMESTAMP_PENDING_ANDROID -2
+    EGL_TIMESTAMP_INVALID_ANDROID -1
 
 Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
 "Surface Attributes", page 43:
@@ -155,10 +157,12 @@
     limited history of timestamp data. If a query is made for a frame whose
     timestamp history no longer exists then EGL_BAD_ACCESS is generated. If
     timestamp collection has not been enabled for the surface then
-    EGL_BAD_SURFACE is generated.  Timestamps for events that will not occur or
-    have not yet occurred will be zero. Timestamp queries that are not
-    supported will generate an EGL_BAD_PARAMETER error. If any error is
-    generated the function will return EGL_FALSE.
+    EGL_BAD_SURFACE is generated.  Timestamps for events that might still occur
+    will have the value EGL_TIMESTAMP_PENDING_ANDROID. Timestamps for events
+    that did not occur will have the value EGL_TIMESTAMP_INVALID_ANDROID.
+    Otherwise, the timestamp will be valid and indicate the event has occured.
+    Timestamp queries that are not supported will generate an EGL_BAD_PARAMETER
+    error. If any error is generated the function will return EGL_FALSE.
 
     The application can poll for the timestamp of particular events by calling
     eglGetFrameTimestamps over and over without needing to call any other EGL
@@ -222,6 +226,12 @@
 
 Revision History
 
+#8 (Brian Anderson, April 11, 2017)
+    - Use reserved enumerant values.
+
+#7 (Brian Anderson, March 21, 2017)
+    - Differentiate between pending events and events that did not occur.
+
 #6 (Brian Anderson, March 16, 2017)
     - Remove DISPLAY_RETIRE_TIME_ANDROID.
 
diff --git a/opengl/specs/README b/opengl/specs/README
index e922740..cba4453 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -4,8 +4,14 @@
 The table below tracks usage of EGL enumerant values that have been reserved
 for use by Android extensions.
 
+See https://github.com/KhronosGroup/EGL-Registry/blob/master/api/egl.xml
+for a list of all enumarant values currently reserved and registered with
+Khronos.
+
      Value                       Extension
-----------------     ----------------------------------
+================     ==================================
+0x3140 - 0x314F      Reserved block
+================     ==================================
 0x3140               EGL_NATIVE_BUFFER_ANDROID (EGL_ANDROID_image_native_buffer)
 0x3141               EGL_PLATFORM_ANDROID_KHR (KHR_platform_android)
 0x3142               EGL_RECORDABLE_ANDROID (EGL_ANDROID_recordable)
@@ -18,17 +24,23 @@
 0x314A               EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop)
 0x314B               EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
 0x314C               EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
-0x314D               EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314E               EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314F               EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3150               EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3151               EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3152               EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3153               EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3154               EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3155               EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3156               EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3157               EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3158               EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3159               EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x315A - 0x315F      (unused)
+0x314D - 0x314F      (unused)
+
+     Value                       Extension
+================     ==================================
+0x3430 - 0x343F      Reserved block
+================     ==================================
+0x3430               EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3431               EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3432               EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3433               EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3434               EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3435               EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3436               EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3437               EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3438               EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3439               EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343A               EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343B               EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343C               EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343D - 0x343F      (unused)
diff --git a/services/schedulerservice/SchedulingPolicyService.cpp b/services/schedulerservice/SchedulingPolicyService.cpp
index 522a8c0..1f6ed57 100644
--- a/services/schedulerservice/SchedulingPolicyService.cpp
+++ b/services/schedulerservice/SchedulingPolicyService.cpp
@@ -17,8 +17,6 @@
 
 #include "SchedulingPolicyService.h"
 
-#include <private/android_filesystem_config.h> // for AID_CAMERASERVER
-
 #include <log/log.h>
 #include <hwbinder/IPCThreadState.h>
 #include <mediautils/SchedulingPolicyService.h>
@@ -29,23 +27,36 @@
 namespace V1_0 {
 namespace implementation {
 
-Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
-    using ::android::hardware::IPCThreadState;
+bool SchedulingPolicyService::isAllowed() {
+    // TODO(b/37291237)
+    return true;
+}
 
+Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
     if (priority < static_cast<int32_t>(Priority::MIN) ||
             priority > static_cast<int32_t>(Priority::MAX)) {
         return false;
     }
 
-    if (IPCThreadState::self()->getCallingUid() != AID_CAMERASERVER) {
+    if (!isAllowed()) {
         return false;
     }
 
+    // TODO(b/37226359): decouple from and remove AIDL service
     // this should always be allowed since we are in system_server.
     int value = ::android::requestPriority(pid, tid, priority, false /* isForApp */);
     return value == 0 /* success */;
 }
 
+Return<int32_t> SchedulingPolicyService::getMaxAllowedPriority() {
+    if (!isAllowed()) {
+        return 0;
+    }
+
+    // TODO(b/37226359): decouple from and remove AIDL service
+    return 3;
+}
+
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace schedulerservice
diff --git a/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
index eb5a4ae..7d1c478 100644
--- a/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
+++ b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
@@ -38,6 +38,9 @@
 
 struct SchedulingPolicyService : public ISchedulingPolicyService {
     Return<bool> requestPriority(int32_t pid, int32_t tid, int32_t priority) override;
+    Return<int32_t> getMaxAllowedPriority() override;
+private:
+    bool isAllowed();
 };
 
 }  // namespace implementation
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 080c02b..7d9b0b7 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -31,6 +31,7 @@
 using namespace android::hardware::sensors::V1_0;
 using namespace android::hardware::sensors::V1_0::implementation;
 
+
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -55,6 +56,9 @@
     if (!connectHidlService()) {
         return;
     }
+
+    float minPowerMa = 0.001; // 1 microAmp
+
     checkReturn(mSensors->getSensorsList(
             [&](const auto &list) {
                 const size_t count = list.size();
@@ -64,6 +68,12 @@
                 for (size_t i=0 ; i < count; i++) {
                     sensor_t sensor;
                     convertToSensor(list[i], &sensor);
+                    // Sanity check and clamp power if it is 0 (or close)
+                    if (sensor.power < minPowerMa) {
+                        ALOGE("Reported power %f not deemed sane, clamping to %f",
+                              sensor.power, minPowerMa);
+                        sensor.power = minPowerMa;
+                    }
                     mSensorList.push_back(sensor);
 
                     mActivationCount.add(list[i].sensorHandle, model);
@@ -138,20 +148,19 @@
 
         result.append("sampling_period(ms) = {");
         for (size_t j = 0; j < info.batchParams.size(); j++) {
-            const BatchParams& params = info.batchParams.valueAt(j);
-            result.appendFormat("%.1f%s", params.batchDelay / 1e6f,
+            const BatchParams& params = info.batchParams[j];
+            result.appendFormat("%.1f%s", params.mTSample / 1e6f,
                 j < info.batchParams.size() - 1 ? ", " : "");
         }
-        result.appendFormat("}, selected = %.1f ms; ", info.bestBatchParams.batchDelay / 1e6f);
+        result.appendFormat("}, selected = %.2f ms; ", info.bestBatchParams.mTSample / 1e6f);
 
         result.append("batching_period(ms) = {");
         for (size_t j = 0; j < info.batchParams.size(); j++) {
-            BatchParams params = info.batchParams.valueAt(j);
-
-            result.appendFormat("%.1f%s", params.batchTimeout / 1e6f,
+            const BatchParams& params = info.batchParams[j];
+            result.appendFormat("%.1f%s", params.mTBatch / 1e6f,
                     j < info.batchParams.size() - 1 ? ", " : "");
         }
-        result.appendFormat("}, selected = %.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
+        result.appendFormat("}, selected = %.2f ms\n", info.bestBatchParams.mTBatch / 1e6f);
     }
 
     return result.string();
@@ -270,13 +279,10 @@
                 // batch_rate and timeout. One of the apps has unregistered for sensor
                 // events, and the best effort batch parameters might have changed.
                 ALOGD_IF(DEBUG_CONNECTIONS,
-                         "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
-                         info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                         info.bestBatchParams.batchTimeout);
+                         "\t>>> actuating h/w batch 0x%08x %" PRId64 " %" PRId64, handle,
+                         info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
                 checkReturn(mSensors->batch(
-                        handle,
-                        info.bestBatchParams.batchDelay,
-                        info.bestBatchParams.batchTimeout));
+                        handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
             }
         } else {
             // sensor wasn't enabled for this ident
@@ -314,6 +320,9 @@
     if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
         samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
     }
+    if (maxBatchReportLatencyNs < 0) {
+        maxBatchReportLatencyNs = 0;
+    }
 
     ALOGD_IF(DEBUG_CONNECTIONS,
              "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
@@ -323,7 +332,7 @@
     Info& info(mActivationCount.editValueFor(handle));
 
     if (info.batchParams.indexOfKey(ident) < 0) {
-        BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
+        BatchParams params(samplingPeriodNs, maxBatchReportLatencyNs);
         info.batchParams.add(ident, params);
     } else {
         // A batch has already been called with this ident. Update the batch parameters.
@@ -337,25 +346,21 @@
     ALOGD_IF(DEBUG_CONNECTIONS,
              "\t>>> curr_period=%" PRId64 " min_period=%" PRId64
              " curr_timeout=%" PRId64 " min_timeout=%" PRId64,
-             prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay,
-             prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout);
+             prevBestBatchParams.mTSample, info.bestBatchParams.mTSample,
+             prevBestBatchParams.mTBatch, info.bestBatchParams.mTBatch);
 
     status_t err(NO_ERROR);
     // If the min period or min timeout has changed since the last batch call, call batch.
     if (prevBestBatchParams != info.bestBatchParams) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
-                 info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                 info.bestBatchParams.batchTimeout);
+        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
+                 info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
         err = StatusFromResult(
                 checkReturn(mSensors->batch(
-                    handle,
-                    info.bestBatchParams.batchDelay,
-                    info.bestBatchParams.batchTimeout)));
+                    handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch)));
         if (err != NO_ERROR) {
-            ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
-                  mSensors.get(), handle,
-                  info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                  info.bestBatchParams.batchTimeout, strerror(-err));
+            ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
+                  mSensors.get(), handle, info.bestBatchParams.mTSample,
+                  info.bestBatchParams.mTBatch, strerror(-err));
             info.removeBatchParamsForIdent(ident);
         }
     }
@@ -363,28 +368,7 @@
 }
 
 status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
-    if (mSensors == nullptr) return NO_INIT;
-    if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
-        samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
-    }
-    Mutex::Autolock _l(mLock);
-    if (isClientDisabledLocked(ident)) return INVALID_OPERATION;
-    Info& info( mActivationCount.editValueFor(handle) );
-    // If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
-    // Calling setDelay() in batch mode is an invalid operation.
-    if (info.bestBatchParams.batchTimeout != 0) {
-      return INVALID_OPERATION;
-    }
-    ssize_t index = info.batchParams.indexOfKey(ident);
-    if (index < 0) {
-        return BAD_INDEX;
-    }
-    BatchParams& params = info.batchParams.editValueAt(index);
-    params.batchDelay = samplingPeriodNs;
-    info.selectBatchParams();
-
-    return StatusFromResult(
-            checkReturn(mSensors->batch(handle, info.bestBatchParams.batchDelay, 0)));
+    return batch(ident, handle, 0, samplingPeriodNs, 0);
 }
 
 int SensorDevice::getHalDeviceVersion() const {
@@ -423,8 +407,8 @@
         status_t err = StatusFromResult(
                 checkReturn(mSensors->batch(
                     sensor_handle,
-                    info.bestBatchParams.batchDelay,
-                    info.bestBatchParams.batchTimeout)));
+                    info.bestBatchParams.mTSample,
+                    info.bestBatchParams.mTBatch)));
         ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
 
         if (err == NO_ERROR) {
@@ -581,35 +565,35 @@
     return num;
 }
 
-status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
+status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int,
                                                     int64_t samplingPeriodNs,
                                                     int64_t maxBatchReportLatencyNs) {
     ssize_t index = batchParams.indexOfKey(ident);
     if (index < 0) {
-        ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64 " timeout=%" PRId64 ") failed (%s)",
+        ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64
+              " timeout=%" PRId64 ") failed (%s)",
               ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
         return BAD_INDEX;
     }
     BatchParams& params = batchParams.editValueAt(index);
-    params.flags = flags;
-    params.batchDelay = samplingPeriodNs;
-    params.batchTimeout = maxBatchReportLatencyNs;
+    params.mTSample = samplingPeriodNs;
+    params.mTBatch = maxBatchReportLatencyNs;
     return NO_ERROR;
 }
 
 void SensorDevice::Info::selectBatchParams() {
-    BatchParams bestParams(0, -1, -1);
+    BatchParams bestParams; // default to max Tsample and max Tbatch
     SensorDevice& device(SensorDevice::getInstance());
 
     for (size_t i = 0; i < batchParams.size(); ++i) {
-        if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
-        BatchParams params = batchParams.valueAt(i);
-        if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) {
-            bestParams.batchDelay = params.batchDelay;
+        if (device.isClientDisabledLocked(batchParams.keyAt(i))) {
+            continue;
         }
-        if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) {
-            bestParams.batchTimeout = params.batchTimeout;
-        }
+        bestParams.merge(batchParams[i]);
+    }
+    // if mTBatch <= mTSample, it is in streaming mode. set mTbatch to 0 to demand this explicitly.
+    if (bestParams.mTBatch <= bestParams.mTSample) {
+        bestParams.mTBatch = 0;
     }
     bestBatchParams = bestParams;
 }
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 2520a81..fd6cee6 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -27,7 +27,8 @@
 #include <utils/String8.h>
 
 #include <string>
-#include <map>
+#include <unordered_map>
+#include <algorithm> //std::max std::min
 
 #include "android/hardware/sensors/1.0/ISensors.h"
 
@@ -106,7 +107,7 @@
 
     sp<android::hardware::sensors::V1_0::ISensors> mSensors;
     Vector<sensor_t> mSensorList;
-    std::map<int32_t, sensor_t*> mConnectedDynamicSensors;
+    std::unordered_map<int32_t, sensor_t*> mConnectedDynamicSensors;
 
     static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz
     mutable Mutex mLock; // protect mActivationCount[].batchParams
@@ -115,15 +116,18 @@
     // Struct to store all the parameters(samplingPeriod, maxBatchReportLatency and flags) from
     // batch call. For continous mode clients, maxBatchReportLatency is set to zero.
     struct BatchParams {
-      // TODO: Get rid of flags parameter everywhere.
-      int flags;
-      nsecs_t batchDelay, batchTimeout;
-      BatchParams() : flags(0), batchDelay(0), batchTimeout(0) {}
-      BatchParams(int flag, nsecs_t delay, nsecs_t timeout): flags(flag), batchDelay(delay),
-          batchTimeout(timeout) { }
+      nsecs_t mTSample, mTBatch;
+      BatchParams() : mTSample(INT64_MAX), mTBatch(INT64_MAX) {}
+      BatchParams(nsecs_t tSample, nsecs_t tBatch): mTSample(tSample), mTBatch(tBatch) {}
       bool operator != (const BatchParams& other) {
-          return other.batchDelay != batchDelay || other.batchTimeout != batchTimeout ||
-                 other.flags != flags;
+          return !(mTSample == other.mTSample && mTBatch == other.mTBatch);
+      }
+      // Merge another parameter with this one. The updated mTSample will be the min of the two.
+      // The update mTBatch will be the min of original mTBatch and the apparent batch period
+      // of the other. the apparent batch is the maximum of mTBatch and mTSample,
+      void merge(const BatchParams &other) {
+          mTSample = std::min(mTSample, other.mTSample);
+          mTBatch = std::min(mTBatch, std::max(other.mTBatch, other.mTSample));
       }
     };
 
@@ -139,7 +143,6 @@
         // requested by the client.
         KeyedVector<void*, BatchParams> batchParams;
 
-        Info() : bestBatchParams(0, -1, -1) {}
         // Sets batch parameters for this ident. Returns error if this ident is not already present
         // in the KeyedVector above.
         status_t setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs,
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index b096e1c..91923b3 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -185,17 +185,18 @@
                 struct stat s1, s2;
                 int fd1, fd2;
                 fd1 = mMem.handle->data[0];
-                fd2 = mem->handle->data[1];
+                fd2 = mem->handle->data[0];
                 if (fstat(fd1, &s1) < 0 || fstat(fd2, &s2) < 0 || s1.st_ino == s2.st_ino) {
                     ret = true;
                 }
                 break;
             }
             case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
-                LOG_FATAL("%s: Implement GRALLOC or remove", __FUNCTION__);
-                ret = true;
+                // there is no known method to test if two gralloc handle are equivalent
+                ret = false;
                 break;
             default:
+                // should never happen
                 ALOGE("Unexpected mem type %d", mMem.type);
                 ret = true;
                 break;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 4d76272..26f9143 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -978,6 +978,7 @@
     for (auto &i : mDirectConnections) {
         sp<SensorDirectConnection> connection(i.promote());
         if (connection != nullptr && connection->isEquivalent(&mem)) {
+            ALOGE("Duplicate create channel request for the same share memory");
             return nullptr;
         }
     }
@@ -988,14 +989,15 @@
             int fd = resource->data[0];
             int size2 = ashmem_get_size_region(fd);
             // check size consistency
-            if (size2 != static_cast<int>(size)) {
-                ALOGE("Ashmem direct channel size mismatch, %" PRIu32 " vs %d", size, size2);
+            if (size2 < static_cast<int>(size)) {
+                ALOGE("Ashmem direct channel size %" PRIu32 " greater than shared memory size %d",
+                      size, size2);
                 return nullptr;
             }
             break;
         }
         case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
-            LOG_FATAL("%s: Finish implementation of ION and GRALLOC or remove", __FUNCTION__);
+            // no specific checks for gralloc
             break;
         default:
             ALOGE("Unknown direct connection memory type %d", type);
diff --git a/services/sensorservice/hidl/DirectReportChannel.cpp b/services/sensorservice/hidl/DirectReportChannel.cpp
index 773ce8c..adc4675 100644
--- a/services/sensorservice/hidl/DirectReportChannel.cpp
+++ b/services/sensorservice/hidl/DirectReportChannel.cpp
@@ -31,10 +31,13 @@
 }
 
 // Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
-Return<Result> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate) {
+Return<void> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate,
+        configure_cb _hidl_cb) {
     int token = mManager.configureDirectChannel(mId,
             static_cast<int>(sensorHandle), static_cast<int>(rate));
-    return token <= 0 ? convertResult(token) : Result::OK;
+    _hidl_cb(token <= 0 ? 0 : token,
+             token <= 0 ? convertResult(token) : Result::OK);
+    return Void();
 }
 
 
diff --git a/services/sensorservice/hidl/DirectReportChannel.h b/services/sensorservice/hidl/DirectReportChannel.h
index 9134944..dd67827 100644
--- a/services/sensorservice/hidl/DirectReportChannel.h
+++ b/services/sensorservice/hidl/DirectReportChannel.h
@@ -47,7 +47,8 @@
     ~DirectReportChannel();
 
     // Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
-    Return<Result> configure(int32_t sensorHandle, RateLevel rate) override;
+    Return<void> configure(int32_t sensorHandle, RateLevel rate,
+            configure_cb _hidl_cb) override;
 
 private:
     ::android::SensorManager& mManager;
diff --git a/services/sensorservice/hidl/EventQueue.cpp b/services/sensorservice/hidl/EventQueue.cpp
index 86d365c..ff20066 100644
--- a/services/sensorservice/hidl/EventQueue.cpp
+++ b/services/sensorservice/hidl/EventQueue.cpp
@@ -27,7 +27,8 @@
 
 class EventQueueLooperCallback : public ::android::LooperCallback {
 public:
-    EventQueueLooperCallback(sp<EventQueue> queue, sp<IEventQueueCallback> callback)
+    EventQueueLooperCallback(sp<::android::SensorEventQueue> queue,
+                             sp<IEventQueueCallback> callback)
             : mQueue(queue), mCallback(callback) {
     }
 
@@ -35,18 +36,23 @@
 
         ASensorEvent event;
         ssize_t actual;
-        const sp<::android::SensorEventQueue>& internalQueue = mQueue->mInternalQueue;
+
+        auto internalQueue = mQueue.promote();
+        if (internalQueue == nullptr) {
+            return 1;
+        }
 
         while ((actual = internalQueue->read(&event, 1 /* count */)) > 0) {
             internalQueue->sendAck(&event, actual);
-            mCallback->onEvent(convertEvent(event));
+            Return<void> ret = mCallback->onEvent(convertEvent(event));
+            (void)ret.isOk(); // ignored
         }
 
         return 1; // continue to receive callbacks
     }
 
 private:
-    sp<EventQueue> mQueue;
+    wp<::android::SensorEventQueue> mQueue;
     sp<IEventQueueCallback> mCallback;
 };
 
@@ -57,18 +63,18 @@
             : mLooper(looper),
               mInternalQueue(internalQueue) {
 
-    mLooper->addFd(mInternalQueue->getFd(), ALOOPER_POLL_CALLBACK, ALOOPER_EVENT_INPUT,
-            new EventQueueLooperCallback(this, callback), NULL /* data */);
+    mLooper->addFd(internalQueue->getFd(), ALOOPER_POLL_CALLBACK, ALOOPER_EVENT_INPUT,
+            new EventQueueLooperCallback(internalQueue, callback), NULL /* data */);
 }
 
-EventQueue::~EventQueue() {
+void EventQueue::onLastStrongRef(const void *id) {
+    IEventQueue::onLastStrongRef(id);
     mLooper->removeFd(mInternalQueue->getFd());
 }
 
 // Methods from ::android::frameworks::sensorservice::V1_0::IEventQueue follow.
 Return<Result> EventQueue::enableSensor(int32_t sensorHandle, int32_t samplingPeriodUs,
         int64_t maxBatchReportLatencyUs) {
-    // TODO implement
     return convertResult(mInternalQueue->enableSensor(sensorHandle, samplingPeriodUs,
             maxBatchReportLatencyUs, 0 /* reserved flags */));
 }
diff --git a/services/sensorservice/hidl/EventQueue.h b/services/sensorservice/hidl/EventQueue.h
index 87c614b..6be03b7 100644
--- a/services/sensorservice/hidl/EventQueue.h
+++ b/services/sensorservice/hidl/EventQueue.h
@@ -42,7 +42,7 @@
         sp<IEventQueueCallback> callback,
         sp<::android::Looper> looper,
         sp<::android::SensorEventQueue> internalQueue);
-    ~EventQueue();
+    void onLastStrongRef(const void *) override;
 
     // Methods from ::android::frameworks::sensorservice::V1_0::IEventQueue follow.
     Return<Result> enableSensor(int32_t sensorHandle, int32_t samplingPeriodUs, int64_t maxBatchReportLatencyUs) override;
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 0743fc3..06ff95c 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -22,12 +22,14 @@
 
 #include "SensorManager.h"
 
+#include <sched.h>
+
+#include <thread>
+
 #include "EventQueue.h"
 #include "DirectReportChannel.h"
 #include "utils.h"
 
-#include <thread>
-
 namespace android {
 namespace frameworks {
 namespace sensorservice {
@@ -131,6 +133,14 @@
         std::condition_variable looperSet;
 
         std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet] {
+
+            struct sched_param p = {0};
+            p.sched_priority = 10;
+            if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
+                LOG(WARNING) << "Could not use SCHED_FIFO for looper thread: "
+                        << strerror(errno);
+            }
+
             std::unique_lock<std::mutex> lock(mutex);
             looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
             lock.unlock();
diff --git a/services/sensorservice/hidl/utils.cpp b/services/sensorservice/hidl/utils.cpp
index b540525..2f9e922 100644
--- a/services/sensorservice/hidl/utils.cpp
+++ b/services/sensorservice/hidl/utils.cpp
@@ -63,6 +63,8 @@
             return Result::NO_MEMORY;
         case NO_INIT:
             return Result::NO_INIT;
+        case PERMISSION_DENIED:
+            return Result::PERMISSION_DENIED;
         case BAD_VALUE:
             return Result::BAD_VALUE;
         case INVALID_OPERATION:
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 76baa01..7bb20ba 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -133,10 +133,15 @@
     main_surfaceflinger.cpp
 
 LOCAL_SHARED_LIBRARIES := \
+    android.hardware.configstore@1.0 \
+    android.hardware.configstore-utils \
+    android.hardware.graphics.allocator@2.0 \
     libsurfaceflinger \
     libcutils \
     liblog \
     libbinder \
+    libhidlbase \
+    libhidltransport \
     libutils \
     libui \
     libgui \
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 33aa759..262ab62 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -17,7 +17,6 @@
 #undef LOG_TAG
 #define LOG_TAG "HwcComposer"
 
-#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <inttypes.h>
 #include <log/log.h>
 #include <gui/BufferQueue.h>
@@ -26,7 +25,6 @@
 
 namespace android {
 
-using frameworks::vr::composer::V1_0::IVrComposerClient;
 using hardware::Return;
 using hardware::hidl_vec;
 using hardware::hidl_handle;
@@ -124,6 +122,41 @@
     endCommand();
 }
 
+void Composer::CommandWriter::setClientTargetMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    constexpr uint16_t kSetClientTargetMetadataLength = 7;
+    beginCommand(
+        static_cast<IComposerClient::Command>(
+            IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA),
+        kSetClientTargetMetadataLength);
+    writeBufferMetadata(metadata);
+    endCommand();
+}
+
+void Composer::CommandWriter::setLayerBufferMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    constexpr uint16_t kSetLayerBufferMetadataLength = 7;
+    beginCommand(
+        static_cast<IComposerClient::Command>(
+            IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA),
+        kSetLayerBufferMetadataLength);
+    writeBufferMetadata(metadata);
+    endCommand();
+}
+
+void Composer::CommandWriter::writeBufferMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    write(metadata.width);
+    write(metadata.height);
+    write(metadata.stride);
+    write(metadata.layerCount);
+    writeSigned(static_cast<int32_t>(metadata.format));
+    write64(metadata.usage);
+}
+
 Composer::Composer(bool useVrComposer)
     : mWriter(kWriterInitialSize),
       mIsUsingVrComposer(useVrComposer)
@@ -426,12 +459,29 @@
 }
 
 Error Composer::setClientTarget(Display display, uint32_t slot,
-        const native_handle_t* target,
+        const sp<GraphicBuffer>& target,
         int acquireFence, Dataspace dataspace,
         const std::vector<IComposerClient::Rect>& damage)
 {
     mWriter.selectDisplay(display);
-    mWriter.setClientTarget(slot, target, acquireFence, dataspace, damage);
+    if (mIsUsingVrComposer && target.get()) {
+        IVrComposerClient::BufferMetadata metadata = {
+            .width = target->getWidth(),
+            .height = target->getHeight(),
+            .stride = target->getStride(),
+            .layerCount = target->getLayerCount(),
+            .format = static_cast<PixelFormat>(target->getPixelFormat()),
+            .usage = target->getUsage(),
+        };
+        mWriter.setClientTargetMetadata(metadata);
+    }
+
+    const native_handle_t* handle = nullptr;
+    if (target.get()) {
+        handle = target->getNativeBuffer()->handle;
+    }
+
+    mWriter.setClientTarget(slot, handle, acquireFence, dataspace, damage);
     return Error::NONE;
 }
 
@@ -502,11 +552,28 @@
 }
 
 Error Composer::setLayerBuffer(Display display, Layer layer,
-        uint32_t slot, const native_handle_t* buffer, int acquireFence)
+        uint32_t slot, const sp<GraphicBuffer>& buffer, int acquireFence)
 {
     mWriter.selectDisplay(display);
     mWriter.selectLayer(layer);
-    mWriter.setLayerBuffer(slot, buffer, acquireFence);
+    if (mIsUsingVrComposer && buffer.get()) {
+        IVrComposerClient::BufferMetadata metadata = {
+            .width = buffer->getWidth(),
+            .height = buffer->getHeight(),
+            .stride = buffer->getStride(),
+            .layerCount = buffer->getLayerCount(),
+            .format = static_cast<PixelFormat>(buffer->getPixelFormat()),
+            .usage = buffer->getUsage(),
+        };
+        mWriter.setLayerBufferMetadata(metadata);
+    }
+
+    const native_handle_t* handle = nullptr;
+    if (buffer.get()) {
+        handle = buffer->getNativeBuffer()->handle;
+    }
+
+    mWriter.setLayerBuffer(slot, handle, acquireFence);
     return Error::NONE;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 18af9dd..37b7766 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -23,6 +23,7 @@
 #include <utility>
 #include <vector>
 
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <utils/StrongPointer.h>
 #include <IComposerCommandBuffer.h>
@@ -31,6 +32,8 @@
 
 namespace Hwc2 {
 
+using android::frameworks::vr::composer::V1_0::IVrComposerClient;
+
 using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::ColorTransform;
 using android::hardware::graphics::common::V1_0::Dataspace;
@@ -179,7 +182,7 @@
      * When target is not nullptr, the cache is updated with the new target.
      */
     Error setClientTarget(Display display, uint32_t slot,
-            const native_handle_t* target,
+            const sp<GraphicBuffer>& target,
             int acquireFence, Dataspace dataspace,
             const std::vector<IComposerClient::Rect>& damage);
     Error setColorMode(Display display, ColorMode mode);
@@ -199,7 +202,7 @@
             int32_t x, int32_t y);
     /* see setClientTarget for the purpose of slot */
     Error setLayerBuffer(Display display, Layer layer, uint32_t slot,
-            const native_handle_t* buffer, int acquireFence);
+            const sp<GraphicBuffer>& buffer, int acquireFence);
     Error setLayerSurfaceDamage(Display display, Layer layer,
             const std::vector<IComposerClient::Rect>& damage);
     Error setLayerBlendMode(Display display, Layer layer,
@@ -232,6 +235,14 @@
         ~CommandWriter() override;
 
         void setLayerInfo(uint32_t type, uint32_t appId);
+        void setClientTargetMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
+        void setLayerBufferMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
+
+    private:
+        void writeBufferMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
     };
 
     // Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 1b598f8..5b869e1 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -32,7 +32,6 @@
 #include <hardware/hardware.h>
 #include <gui/BufferItem.h>
 #include <gui/BufferQueue.h>
-#include <gui/GraphicBufferAlloc.h>
 #include <gui/Surface.h>
 
 #include <ui/GraphicBuffer.h>
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e49e734..8270c39 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -244,7 +244,7 @@
         ALOGE("Failed to get display by id");
         return Error::BadDisplay;
     }
-    (*outDisplay)->setVirtual();
+    (*outDisplay)->setConnected(true);
     return Error::None;
 }
 
@@ -531,15 +531,28 @@
   : mDevice(device),
     mId(id),
     mIsConnected(false),
-    mIsVirtual(false)
+    mType(DisplayType::Invalid)
 {
     ALOGV("Created display %" PRIu64, id);
+
+#ifdef BYPASS_IHWC
+    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
+            reinterpret_cast<int32_t *>(&mType));
+#else
+    auto intError = mDevice.mComposer->getDisplayType(mId,
+            reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
+#endif
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
+              id, to_string(error).c_str(), intError);
+    }
 }
 
 Display::~Display()
 {
     ALOGV("Destroyed display %" PRIu64, mId);
-    if (mIsVirtual) {
+    if (mType == DisplayType::Virtual) {
         mDevice.destroyVirtualDisplay(mId);
     }
 }
@@ -802,21 +815,7 @@
 
 Error Display::getType(DisplayType* outType) const
 {
-#ifdef BYPASS_IHWC
-    int32_t intType = 0;
-    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
-            &intType);
-#else
-    Hwc2::IComposerClient::DisplayType intType =
-        Hwc2::IComposerClient::DisplayType::INVALID;
-    auto intError = mDevice.mComposer->getDisplayType(mId, &intType);
-#endif
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    *outType = static_cast<DisplayType>(intType);
+    *outType = mType;
     return Error::None;
 }
 
@@ -961,14 +960,19 @@
     return static_cast<Error>(intError);
 }
 
-Error Display::setClientTarget(uint32_t slot, buffer_handle_t target,
+Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,
         const sp<Fence>& acquireFence, android_dataspace_t dataspace)
 {
     // TODO: Properly encode client target surface damage
     int32_t fenceFd = acquireFence->dup();
 #ifdef BYPASS_IHWC
     (void) slot;
-    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
+    buffer_handle_t handle = nullptr;
+    if (target.get() && target->getNativeBuffer()) {
+        handle = target->getNativeBuffer()->handle;
+    }
+
+    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
             fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
 #else
     auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
@@ -1195,14 +1199,19 @@
     return static_cast<Error>(intError);
 }
 
-Error Layer::setBuffer(uint32_t slot, buffer_handle_t buffer,
+Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
         const sp<Fence>& acquireFence)
 {
     int32_t fenceFd = acquireFence->dup();
 #ifdef BYPASS_IHWC
     (void) slot;
+    buffer_handle_t handle = nullptr;
+    if (buffer.get() && buffer->getNativeBuffer()) {
+        handle = buffer->getNativeBuffer()->handle;
+    }
+
     int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
-            mId, buffer, fenceFd);
+            mId, handle, fenceFd);
 #else
     auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
             mId, slot, buffer, fenceFd);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 4419dc1..643b1e0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -329,7 +329,7 @@
     [[clang::warn_unused_result]] Error setActiveConfig(
             const std::shared_ptr<const Config>& config);
     [[clang::warn_unused_result]] Error setClientTarget(
-            uint32_t slot, buffer_handle_t target,
+            uint32_t slot, const android::sp<android::GraphicBuffer>& target,
             const android::sp<android::Fence>& acquireFence,
             android_dataspace_t dataspace);
     [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
@@ -352,12 +352,6 @@
 private:
     // For use by Device
 
-    // Virtual displays are always connected
-    void setVirtual() {
-        mIsVirtual = true;
-        mIsConnected = true;
-    }
-
     void setConnected(bool connected) { mIsConnected = connected; }
     int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
     void loadConfig(hwc2_config_t configId);
@@ -375,7 +369,7 @@
     Device& mDevice;
     hwc2_display_t mId;
     bool mIsConnected;
-    bool mIsVirtual;
+    DisplayType mType;
     std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
     std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
 };
@@ -392,7 +386,7 @@
 
     [[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
     [[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
-            buffer_handle_t buffer,
+            const android::sp<android::GraphicBuffer>& buffer,
             const android::sp<android::Fence>& acquireFence);
     [[clang::warn_unused_result]] Error setSurfaceDamage(
             const android::Region& damage);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 09434f6..40979c9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -206,7 +206,7 @@
         }
         disp = DisplayDevice::DISPLAY_EXTERNAL;
     }
-    mEventHandler->onHotplugReceived(disp,
+    mEventHandler->onHotplugReceived(this, disp,
             connected == HWC2::Connection::Connected);
 }
 
@@ -465,12 +465,7 @@
 
     ALOGV("setClientTarget for display %d", displayId);
     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
-    buffer_handle_t handle = nullptr;
-    if ((target != nullptr) && target->getNativeBuffer()) {
-        handle = target->getNativeBuffer()->handle;
-    }
-    auto error = hwcDisplay->setClientTarget(slot, handle,
-            acquireFence, dataspace);
+    auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
     if (error != HWC2::Error::None) {
         ALOGE("Failed to set client target for display %d: %s (%d)", displayId,
                 to_string(error).c_str(), static_cast<int32_t>(error));
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 81f1619..78d0307 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -70,7 +70,7 @@
         friend class HWComposer;
         virtual void onVSyncReceived(
             HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(int32_t disp, bool connected) = 0;
+        virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0;
         virtual void onInvalidateReceived(HWComposer* composer) = 0;
     protected:
         virtual ~EventHandler() {}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index 5b5f1cf..dcb2913 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -315,7 +315,7 @@
     queryDisplayProperties(disp);
     // Do not teardown or recreate the primary display
     if (disp != HWC_DISPLAY_PRIMARY) {
-        mEventHandler.onHotplugReceived(disp, bool(connected));
+        mEventHandler.onHotplugReceived(this, disp, bool(connected));
     }
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index f64d69a..4bc63bb 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -62,7 +62,7 @@
         friend class HWComposer;
         virtual void onVSyncReceived(
             HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(int disp, bool connected) = 0;
+        virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected) = 0;
         virtual void onInvalidateReceived(HWComposer* composer) = 0;
     protected:
         virtual ~EventHandler() {}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c211c7b..d044f37 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -167,7 +167,7 @@
     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
-    BufferQueue::createBufferQueue(&producer, &consumer, nullptr, true);
+    BufferQueue::createBufferQueue(&producer, &consumer, true);
     mProducer = new MonitoredProducer(producer, mFlinger, this);
     mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
@@ -852,18 +852,12 @@
     }
 
     uint32_t hwcSlot = 0;
-    buffer_handle_t hwcHandle = nullptr;
-    {
-        sp<GraphicBuffer> hwcBuffer;
-        hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
-                &hwcSlot, &hwcBuffer);
-        if (hwcBuffer != nullptr) {
-            hwcHandle = hwcBuffer->handle;
-        }
-    }
+    sp<GraphicBuffer> hwcBuffer;
+    hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+            &hwcSlot, &hwcBuffer);
 
     auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
-    error = hwcLayer->setBuffer(hwcSlot, hwcHandle, acquireFence);
+    error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
     if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
                 mActiveBuffer->handle, to_string(error).c_str(),
@@ -1719,10 +1713,55 @@
     mCurrentState.sequence++;
     mCurrentState.z = z;
     mCurrentState.modified = true;
+
+    // Discard all relative layering.
+    if (mCurrentState.zOrderRelativeOf != nullptr) {
+        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+        if (strongRelative != nullptr) {
+            strongRelative->removeZOrderRelative(this);
+        }
+        mCurrentState.zOrderRelativeOf = nullptr;
+    }
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
+void Layer::removeZOrderRelative(const wp<Layer>& relative) {
+    mCurrentState.zOrderRelatives.remove(relative);
+    mCurrentState.sequence++;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
+}
+
+void Layer::addZOrderRelative(const wp<Layer>& relative) {
+    mCurrentState.zOrderRelatives.add(relative);
+    mCurrentState.modified = true;
+    mCurrentState.sequence++;
+    setTransactionFlags(eTransactionNeeded);
+}
+
+bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) {
+    sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get());
+    if (handle == nullptr) {
+        return false;
+    }
+    sp<Layer> relative = handle->owner.promote();
+    if (relative == nullptr) {
+        return false;
+    }
+
+    mCurrentState.sequence++;
+    mCurrentState.modified = true;
+    mCurrentState.z = z;
+
+    mCurrentState.zOrderRelativeOf = relative;
+    relative->addZOrderRelative(this);
+
+    setTransactionFlags(eTransactionNeeded);
+
+    return true;
+}
+
 bool Layer::setSize(uint32_t w, uint32_t h) {
     if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
         return false;
@@ -2506,40 +2545,70 @@
     return mDrawingState.z;
 }
 
+LayerVector Layer::makeTraversalList() {
+    if (mDrawingState.zOrderRelatives.size() == 0) {
+        return mDrawingChildren;
+    }
+    LayerVector traverse;
+
+    for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+        sp<Layer> strongRelative = weakRelative.promote();
+        if (strongRelative != nullptr) {
+            traverse.add(strongRelative);
+        } else {
+            // We need to erase from current state instead of drawing
+            // state so we don't overwrite when copying
+            // the current state to the drawing state.
+            mCurrentState.zOrderRelatives.remove(weakRelative);
+        }
+    }
+
+    for (const sp<Layer>& child : mDrawingChildren) {
+        traverse.add(child);
+    }
+
+    return traverse;
+}
+
 /**
- * Negatively signed children are before 'this' in Z-order.
+ * Negatively signed relatives are before 'this' in Z-order.
  */
 void Layer::traverseInZOrder(const std::function<void(Layer*)>& exec) {
+    LayerVector list = makeTraversalList();
+
     size_t i = 0;
-    for (; i < mDrawingChildren.size(); i++) {
-        const auto& child = mDrawingChildren[i];
-        if (child->getZ() >= 0)
+    for (; i < list.size(); i++) {
+        const auto& relative = list[i];
+        if (relative->getZ() >= 0) {
             break;
-        child->traverseInZOrder(exec);
+        }
+        relative->traverseInZOrder(exec);
     }
     exec(this);
-    for (; i < mDrawingChildren.size(); i++) {
-        const auto& child = mDrawingChildren[i];
-        child->traverseInZOrder(exec);
+    for (; i < list.size(); i++) {
+        const auto& relative = list[i];
+        relative->traverseInZOrder(exec);
     }
 }
 
 /**
- * Positively signed children are before 'this' in reverse Z-order.
+ * Positively signed relatives are before 'this' in reverse Z-order.
  */
 void Layer::traverseInReverseZOrder(const std::function<void(Layer*)>& exec) {
+    LayerVector list = makeTraversalList();
+
     int32_t i = 0;
-    for (i = mDrawingChildren.size()-1; i>=0; i--) {
-        const auto& child = mDrawingChildren[i];
-        if (child->getZ() < 0) {
+    for (i = list.size()-1; i>=0; i--) {
+        const auto& relative = list[i];
+        if (relative->getZ() < 0) {
             break;
         }
-        child->traverseInReverseZOrder(exec);
+        relative->traverseInReverseZOrder(exec);
     }
     exec(this);
     for (; i>=0; i--) {
-        const auto& child = mDrawingChildren[i];
-        child->traverseInReverseZOrder(exec);
+        const auto& relative = list[i];
+        relative->traverseInReverseZOrder(exec);
     }
 }
 
@@ -2548,6 +2617,21 @@
     const auto& p = getParent();
     if (p != nullptr) {
         t = p->getTransform();
+
+        // If the parent is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g.
+        // it isFixedSize) then there may be additional scaling not accounted
+        // for in the transform. We need to mirror this scaling in child surfaces
+        // or we will break the contract where WM can treat child surfaces as
+        // pixels in the parent surface.
+        if (p->isFixedSize()) {
+            float sx = p->getDrawingState().active.w /
+                    static_cast<float>(p->mActiveBuffer->getWidth());
+            float sy = p->getDrawingState().active.h /
+                    static_cast<float>(p->mActiveBuffer->getHeight());
+            Transform extraParentScaling;
+            extraParentScaling.set(sx, 0, 0, sy);
+            t = t * extraParentScaling;
+        }
     }
     return t * getDrawingState().active.transform;
 }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e21be8b..a5224ec 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -151,6 +151,12 @@
 
         uint32_t appId;
         uint32_t type;
+
+        // If non-null, a Surface this Surface's Z-order is interpreted relative to.
+        wp<Layer> zOrderRelativeOf;
+
+        // A list of surfaces whose Z-order is interpreted relative to ours.
+        SortedVector<wp<Layer>> zOrderRelatives;
     };
 
     // -----------------------------------------------------------------------
@@ -173,6 +179,8 @@
     bool setFinalCrop(const Rect& crop, bool immediate);
 
     bool setLayer(int32_t z);
+    bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
+
     bool setSize(uint32_t w, uint32_t h);
 #ifdef USE_HWC2
     bool setAlpha(float alpha);
@@ -549,6 +557,10 @@
 
     void setParent(const sp<Layer>& layer);
 
+    LayerVector makeTraversalList();
+    void addZOrderRelative(const wp<Layer>& relative);
+    void removeZOrderRelative(const wp<Layer>& relative);
+
     // -----------------------------------------------------------------------
 
     class SyncPoint
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 7ba6ad3..90e6395 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -42,13 +42,21 @@
 
 void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const {
     for (size_t i = 0; i < size(); i++) {
-        (*this)[i]->traverseInZOrder(consume);
+        const auto& layer = (*this)[i];
+        if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+            continue;
+        }
+        layer->traverseInZOrder(consume);
     }
 }
 
 void LayerVector::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const {
     for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
-        (*this)[i]->traverseInReverseZOrder(consume);
+        const auto& layer = (*this)[i];
+        if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+            continue;
+        }
+        layer->traverseInReverseZOrder(consume);
      }
 }
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 26baaae..9cd1214 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -45,7 +45,6 @@
 #include <gui/GuiConfig.h>
 #include <gui/IDisplayEventConnection.h>
 #include <gui/Surface.h>
-#include <gui/GraphicBufferAlloc.h>
 
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
@@ -340,12 +339,6 @@
     return mBuiltinDisplays[id];
 }
 
-sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
-{
-    sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
-    return gba;
-}
-
 void SurfaceFlinger::bootFinished()
 {
     if (mStartBootAnimThread->join() != NO_ERROR) {
@@ -578,6 +571,14 @@
 
     Mutex::Autolock _l(mStateLock);
 
+    // Inform native graphics APIs whether the present timestamp is supported:
+    if (getHwComposer().hasCapability(
+            HWC2::Capability::PresentFenceIsNotReliable)) {
+        property_set(kTimestampProperty, "0");
+    } else {
+        property_set(kTimestampProperty, "1");
+    }
+
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
             mVrFlingerRequestsDisplay = requestDisplay;
@@ -598,7 +599,7 @@
 
     // make the GLContext current so that we can create textures when creating
     // Layers (which may happens before we render something)
-    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
 
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -651,6 +652,25 @@
     return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
 }
 
+status_t SurfaceFlinger::getSupportedFrameTimestamps(
+        std::vector<FrameEvent>* outSupported) const {
+    *outSupported = {
+        FrameEvent::REQUESTED_PRESENT,
+        FrameEvent::ACQUIRE,
+        FrameEvent::LATCH,
+        FrameEvent::FIRST_REFRESH_START,
+        FrameEvent::LAST_REFRESH_START,
+        FrameEvent::GPU_COMPOSITION_DONE,
+        FrameEvent::DEQUEUE_READY,
+        FrameEvent::RELEASE,
+    };
+    if (!getHwComposer().hasCapability(
+            HWC2::Capability::PresentFenceIsNotReliable)) {
+        outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
+    }
+    return NO_ERROR;
+}
+
 status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
         Vector<DisplayInfo>* configs) {
     if ((configs == NULL) || (display.get() == NULL)) {
@@ -772,10 +792,12 @@
         ALOGE("%s : display is NULL", __func__);
         return BAD_VALUE;
     }
-    sp<DisplayDevice> device(getDisplayDevice(display));
+
+    sp<const DisplayDevice> device(getDisplayDevice(display));
     if (device != NULL) {
         return device->getActiveConfig();
     }
+
     return BAD_VALUE;
 }
 
@@ -863,7 +885,7 @@
 }
 
 android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
-    sp<DisplayDevice> device(getDisplayDevice(display));
+    sp<const DisplayDevice> device(getDisplayDevice(display));
     if (device != nullptr) {
         return device->getActiveColorMode();
     }
@@ -945,7 +967,7 @@
         HdrCapabilities* outCapabilities) const {
     Mutex::Autolock _l(mStateLock);
 
-    sp<const DisplayDevice> displayDevice(getDisplayDevice(display));
+    sp<const DisplayDevice> displayDevice(getDisplayDeviceLocked(display));
     if (displayDevice == nullptr) {
         ALOGE("getHdrCapabilities: Invalid display %p", displayDevice.get());
         return BAD_VALUE;
@@ -1124,55 +1146,59 @@
     *compositorTiming = mCompositorTiming;
 }
 
-void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) {
+void SurfaceFlinger::createDefaultDisplayDevice() {
+    const int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+    wp<IBinder> token = mBuiltinDisplays[type];
+
+    // All non-virtual displays are currently considered secure.
+    const bool isSecure = true;
+
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, type, consumer);
+
+    bool hasWideColorModes = false;
+    std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
+    for (android_color_mode_t colorMode : modes) {
+        switch (colorMode) {
+            case HAL_COLOR_MODE_DISPLAY_P3:
+            case HAL_COLOR_MODE_ADOBE_RGB:
+            case HAL_COLOR_MODE_DCI_P3:
+                hasWideColorModes = true;
+                break;
+            default:
+                break;
+        }
+    }
+    sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
+                                             token, fbs, producer, mRenderEngine->getEGLConfig(),
+                                             hasWideColorModes && hasWideColorDisplay);
+    mDisplays.add(token, hw);
+    android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
+    if (hasWideColorModes && hasWideColorDisplay) {
+        defaultColorMode = HAL_COLOR_MODE_SRGB;
+    }
+    setActiveColorModeInternal(hw, defaultColorMode);
+}
+
+void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
     ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+
+    if (composer->isUsingVrComposer()) {
+        // We handle initializing the primary display device for the VR
+        // window manager hwc explicitly at the time of transition.
+        if (disp != DisplayDevice::DISPLAY_PRIMARY) {
+            ALOGE("External displays are not supported by the vr hardware composer.");
+        }
+        return;
+    }
+
     if (disp == DisplayDevice::DISPLAY_PRIMARY) {
         Mutex::Autolock lock(mStateLock);
-
-        // All non-virtual displays are currently considered secure.
-        bool isSecure = true;
-
-        int32_t type = DisplayDevice::DISPLAY_PRIMARY;
-
-        // When we're using the vr composer, the assumption is that we've
-        // already created the IBinder object for the primary display.
-        if (!mHwc->isUsingVrComposer()) {
-            createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
-        }
-
-        wp<IBinder> token = mBuiltinDisplays[type];
-
-        sp<IGraphicBufferProducer> producer;
-        sp<IGraphicBufferConsumer> consumer;
-        BufferQueue::createBufferQueue(&producer, &consumer,
-                new GraphicBufferAlloc());
-
-        sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
-                DisplayDevice::DISPLAY_PRIMARY, consumer);
-
-        bool hasWideColorModes = false;
-        std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
-        for (android_color_mode_t colorMode : modes) {
-            switch (colorMode) {
-                case HAL_COLOR_MODE_DISPLAY_P3:
-                case HAL_COLOR_MODE_ADOBE_RGB:
-                case HAL_COLOR_MODE_DCI_P3:
-                    hasWideColorModes = true;
-                    break;
-                default:
-                    break;
-            }
-        }
-        sp<DisplayDevice> hw =
-                new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
-                                  producer, mRenderEngine->getEGLConfig(),
-                                  hasWideColorModes && hasWideColorDisplay);
-        mDisplays.add(token, hw);
-        android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
-        if (hasWideColorModes && hasWideColorDisplay) {
-            defaultColorMode = HAL_COLOR_MODE_SRGB;
-        }
-        setActiveColorModeInternal(hw, defaultColorMode);
+        createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+        createDefaultDisplayDevice();
     } else {
         auto type = DisplayDevice::DISPLAY_EXTERNAL;
         Mutex::Autolock _l(mStateLock);
@@ -1214,7 +1240,8 @@
     }
 }
 
-void SurfaceFlinger::resetHwc() {
+// Note: it is assumed the caller holds |mStateLock| when this is called
+void SurfaceFlinger::resetHwcLocked() {
     disableHardwareVsync(true);
     clearHwcLayers(mDrawingState.layersSortedByZ);
     clearHwcLayers(mCurrentState.layersSortedByZ);
@@ -1223,6 +1250,13 @@
     // mCurrentState and mDrawingState and re-apply all changes when we make the
     // transition.
     mDrawingState.displays.clear();
+    // Release virtual display hwcId during vr mode transition.
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
+        if (displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL) {
+            displayDevice->disconnect(getHwComposer());
+        }
+    }
     mDisplays.clear();
     initializeDisplays();
 }
@@ -1234,36 +1268,45 @@
     if (vrFlingerRequestsDisplay == mHwc->isUsingVrComposer()) {
         return;
     }
+
     if (vrFlingerRequestsDisplay && !mVrHwc) {
         // Construct new HWComposer without holding any locks.
         mVrHwc = new HWComposer(true);
+
+        // Set up the event handlers. This step is neccessary to initialize the internal state of
+        // the hardware composer object properly. Our callbacks are designed such that if they are
+        // triggered between now and the point where the display is properly re-initialized, they
+        // will not have any effect, so this is safe to do here, before the lock is aquired.
+        mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
         ALOGV("Vr HWC created");
     }
-    {
-        Mutex::Autolock _l(mStateLock);
 
-        if (vrFlingerRequestsDisplay) {
-            resetHwc();
+    Mutex::Autolock _l(mStateLock);
 
-            mHwc = mVrHwc;
-            mVrFlinger->GrantDisplayOwnership();
-        } else {
-            mVrFlinger->SeizeDisplayOwnership();
+    if (vrFlingerRequestsDisplay) {
+        resetHwcLocked();
 
-            resetHwc();
+        mHwc = mVrHwc;
+        mVrFlinger->GrantDisplayOwnership();
 
-            mHwc = mRealHwc;
-            enableHardwareVsync();
-        }
+    } else {
+        mVrFlinger->SeizeDisplayOwnership();
 
-        mVisibleRegionsDirty = true;
-        invalidateHwcGeometry();
-        android_atomic_or(1, &mRepaintEverything);
-        setTransactionFlags(eDisplayTransactionNeeded);
+        resetHwcLocked();
+
+        mHwc = mRealHwc;
+        enableHardwareVsync();
     }
-    if (mVrHwc) {
-        mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
-    }
+
+    mVisibleRegionsDirty = true;
+    invalidateHwcGeometry();
+
+    // Explicitly re-initialize the primary display. This is because some other
+    // parts of this class rely on the primary display always being available.
+    createDefaultDisplayDevice();
+
+    android_atomic_or(1, &mRepaintEverything);
+    setTransactionFlags(eDisplayTransactionNeeded);
 }
 
 void SurfaceFlinger::onMessageReceived(int32_t what) {
@@ -1473,7 +1516,8 @@
         layer->releasePendingBuffer(dequeueReadyTime);
     }
 
-    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    // |mStateLock| not needed as we are on the main thread
+    const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
     if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
@@ -1821,7 +1865,8 @@
     mLastSwapBufferTime = systemTime() - now;
     mDebugInSwapBuffers = 0;
 
-    uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
+    // |mStateLock| not needed as we are on the main thread
+    uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
     if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
         logFrameStats();
     }
@@ -1906,9 +1951,9 @@
                         // Call makeCurrent() on the primary display so we can
                         // be sure that nothing associated with this display
                         // is current.
-                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
                         defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
-                        sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
+                        sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
                         if (hw != NULL)
                             hw->disconnect(getHwComposer());
                         if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
@@ -1928,7 +1973,7 @@
                         // recreating the DisplayDevice, so we just remove it
                         // from the drawing state, so that it get re-added
                         // below.
-                        sp<DisplayDevice> hw(getDisplayDevice(display));
+                        sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
                         if (hw != NULL)
                             hw->disconnect(getHwComposer());
                         mDisplays.removeItem(display);
@@ -1938,7 +1983,7 @@
                         continue;
                     }
 
-                    const sp<DisplayDevice> disp(getDisplayDevice(display));
+                    const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
                     if (disp != NULL) {
                         if (state.layerStack != draw[i].layerStack) {
                             disp->setLayerStack(state.layerStack);
@@ -1967,8 +2012,7 @@
                     sp<IGraphicBufferProducer> producer;
                     sp<IGraphicBufferProducer> bqProducer;
                     sp<IGraphicBufferConsumer> bqConsumer;
-                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
-                            new GraphicBufferAlloc());
+                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
 
                     int32_t hwcId = -1;
                     if (state.isVirtualDisplay()) {
@@ -2096,7 +2140,7 @@
                 // could be null when this layer is using a layerStack
                 // that is not visible on any display. Also can occur at
                 // screen off/on times.
-                disp = getDefaultDisplayDevice();
+                disp = getDefaultDisplayDeviceLocked();
             }
             layer->updateTransformHint(disp);
 
@@ -2327,6 +2371,7 @@
 
     bool visibleRegions = false;
     bool frameQueued = false;
+    bool newDataLatched = false;
 
     // Store the set of layers that need updates. This set must not change as
     // buffers are being latched, as this could result in a deadlock.
@@ -2354,6 +2399,9 @@
         const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
         layer->useSurfaceDamage();
         invalidateLayerStack(layer->getLayerStack(), dirty);
+        if (!dirty.isEmpty()) {
+            newDataLatched = true;
+        }
     }
 
     mVisibleRegionsDirty |= visibleRegions;
@@ -2366,7 +2414,7 @@
     }
 
     // Only continue with the refresh if there is actually new work to do
-    return !mLayersWithQueuedFrames.empty();
+    return !mLayersWithQueuedFrames.empty() && newDataLatched;
 }
 
 void SurfaceFlinger::invalidateHwcGeometry()
@@ -2452,7 +2500,9 @@
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                   displayDevice->getDisplayName().string());
             eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
+
+            // |mStateLock| not needed as we are on the main thread
+            if(!getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext)) {
               ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
             }
             return false;
@@ -2820,6 +2870,11 @@
                 }
             }
         }
+        if (what & layer_state_t::eRelativeLayerChanged) {
+            if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
+        }
         if (what & layer_state_t::eSizeChanged) {
             if (layer->setSize(s.w, s.h)) {
                 flags |= eTraversalNeeded;
@@ -3539,7 +3594,7 @@
     colorizer.reset(result);
 
     HWComposer& hwc(getHwComposer());
-    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     colorizer.bold(result);
     result.appendFormat("EGL implementation : %s\n",
@@ -3633,7 +3688,7 @@
         // Just use the primary display so we have something to return
         dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
     }
-    return getDisplayDevice(dpy)->getVisibleLayersSortedByZ();
+    return getDisplayDeviceLocked(dpy)->getVisibleLayersSortedByZ();
 }
 
 bool SurfaceFlinger::startDdmConnection()
@@ -3768,7 +3823,6 @@
                 reply->writeInt32(mDebugDisableHWC);
                 return NO_ERROR;
             case 1013: {
-                Mutex::Autolock _l(mStateLock);
                 sp<const DisplayDevice> hw(getDefaultDisplayDevice());
                 reply->writeInt32(hw->getPageFlipCount());
                 return NO_ERROR;
@@ -4055,7 +4109,7 @@
         }
         virtual bool handler() {
             Mutex::Autolock _l(flinger->mStateLock);
-            sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
+            sp<const DisplayDevice> hw(flinger->getDisplayDeviceLocked(display));
             result = flinger->captureScreenImplLocked(hw, producer,
                     sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
                     useIdentityTransform, rotation, isLocalScreenshot);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 46121cf..c01f701 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -76,7 +76,6 @@
 class Client;
 class DisplayEventConnection;
 class EventThread;
-class IGraphicBufferAlloc;
 class Layer;
 class LayerDim;
 class Surface;
@@ -185,7 +184,8 @@
 
     // returns the default Display
     sp<const DisplayDevice> getDefaultDisplayDevice() const {
-        return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+        Mutex::Autolock _l(mStateLock);
+        return getDefaultDisplayDeviceLocked();
     }
 
     // utility function to delete a texture on the main thread
@@ -227,6 +227,7 @@
     enum { LOG_FRAME_STATS_PERIOD =  30*60*60 };
 
     static const size_t MAX_LAYERS = 4096;
+    static constexpr const char* kTimestampProperty = "service.sf.present_timestamp";
 
     // We're reference counted, never destroy SurfaceFlinger directly
     virtual ~SurfaceFlinger();
@@ -256,7 +257,6 @@
      */
     virtual sp<ISurfaceComposerClient> createConnection();
     virtual sp<ISurfaceComposerClient> createScopedConnection(const sp<IGraphicBufferProducer>& gbp);
-    virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
     virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
     virtual void destroyDisplay(const sp<IBinder>& display);
     virtual sp<IBinder> getBuiltInDisplay(int32_t id);
@@ -265,6 +265,8 @@
     virtual void bootFinished();
     virtual bool authenticateSurfaceTexture(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
+    virtual status_t getSupportedFrameTimestamps(
+            std::vector<FrameEvent>* outSupported) const;
     virtual sp<IDisplayEventConnection> createDisplayEventConnection();
     virtual status_t captureScreen(const sp<IBinder>& display,
             const sp<IGraphicBufferProducer>& producer,
@@ -304,7 +306,7 @@
      * HWComposer::EventHandler interface
      */
     virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
-    virtual void onHotplugReceived(int disp, bool connected);
+    virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
     virtual void onInvalidateReceived(HWComposer* composer);
 
     /* ------------------------------------------------------------------------
@@ -429,16 +431,33 @@
     // Create an IBinder for a builtin display and add it to current state
     void createBuiltinDisplayLocked(DisplayDevice::DisplayType type);
 
-    // NOTE: can only be called from the main thread or with mStateLock held
+
     sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const {
+      Mutex::Autolock _l(mStateLock);
+      return getDisplayDeviceLocked(dpy);
+    }
+
+    sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) {
+      Mutex::Autolock _l(mStateLock);
+      return getDisplayDeviceLocked(dpy);
+    }
+
+    // NOTE: can only be called from the main thread or with mStateLock held
+    sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& dpy) const {
         return mDisplays.valueFor(dpy);
     }
 
     // NOTE: can only be called from the main thread or with mStateLock held
-    sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) {
+    sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& dpy) {
         return mDisplays.valueFor(dpy);
     }
 
+    sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const {
+        return getDisplayDeviceLocked(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+    }
+
+    void createDefaultDisplayDevice();
+
     int32_t getDisplayType(const sp<IBinder>& display) {
         if (!display.get()) return NAME_NOT_FOUND;
         for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
@@ -546,7 +565,7 @@
      * VrFlinger
      */
     void clearHwcLayers(const LayerVector& layers);
-    void resetHwc();
+    void resetHwcLocked();
 
     // Check to see if we should handoff to vr flinger.
     void updateVrFlinger();
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 1d2b485..9babeef 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -139,7 +139,9 @@
 }
 
 sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const {
-    return mConsumer->getSidebandStream();
+    sp<NativeHandle> stream;
+    mConsumer->getSidebandStream(&stream);
+    return stream;
 }
 
 // We need to determine the time when a buffer acquired now will be
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index e640ef7..02923ae 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -42,7 +42,6 @@
 #include <gui/GuiConfig.h>
 #include <gui/IDisplayEventConnection.h>
 #include <gui/Surface.h>
-#include <gui/GraphicBufferAlloc.h>
 
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/HdrCapabilities.h>
@@ -319,12 +318,6 @@
     return mBuiltinDisplays[id];
 }
 
-sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
-{
-    sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
-    return gba;
-}
-
 void SurfaceFlinger::bootFinished()
 {
     if (mStartBootAnimThread->join() != NO_ERROR) {
@@ -549,6 +542,9 @@
     LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
             "couldn't create EGLContext");
 
+    // Inform native graphics APIs that the present timestamp is NOT supported:
+    property_set(kTimestampProperty, "0");
+
     // initialize our non-virtual displays
     for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
         DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
@@ -561,8 +557,7 @@
 
             sp<IGraphicBufferProducer> producer;
             sp<IGraphicBufferConsumer> consumer;
-            BufferQueue::createBufferQueue(&producer, &consumer,
-                    new GraphicBufferAlloc());
+            BufferQueue::createBufferQueue(&producer, &consumer);
 
             sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                     consumer);
@@ -584,7 +579,7 @@
 
     // make the GLContext current so that we can create textures when creating Layers
     // (which may happens before we render something)
-    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
 
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -647,6 +642,21 @@
     return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
 }
 
+status_t SurfaceFlinger::getSupportedFrameTimestamps(
+        std::vector<FrameEvent>* outSupported) const {
+    *outSupported = {
+        FrameEvent::REQUESTED_PRESENT,
+        FrameEvent::ACQUIRE,
+        FrameEvent::LATCH,
+        FrameEvent::FIRST_REFRESH_START,
+        FrameEvent::LAST_REFRESH_START,
+        FrameEvent::GPU_COMPOSITION_DONE,
+        FrameEvent::DEQUEUE_READY,
+        FrameEvent::RELEASE,
+    };
+    return NO_ERROR;
+}
+
 status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
         Vector<DisplayInfo>* configs) {
     if ((configs == NULL) || (display.get() == NULL)) {
@@ -755,7 +765,7 @@
 }
 
 int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
-    sp<DisplayDevice> device(getDisplayDevice(display));
+    sp<const DisplayDevice> device(getDisplayDevice(display));
     if (device != NULL) {
         return device->getActiveConfig();
     }
@@ -1040,7 +1050,7 @@
     *compositorTiming = mCompositorTiming;
 }
 
-void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
+void SurfaceFlinger::onHotplugReceived(HWComposer* /*composer*/, int type, bool connected) {
     if (mEventThread == NULL) {
         // This is a temporary workaround for b/7145521.  A non-null pointer
         // does not mean EventThread has finished initializing, so this
@@ -1626,9 +1636,9 @@
                         // Call makeCurrent() on the primary display so we can
                         // be sure that nothing associated with this display
                         // is current.
-                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
                         defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
-                        sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
+                        sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
                         if (hw != NULL)
                             hw->disconnect(getHwComposer());
                         if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
@@ -1648,7 +1658,7 @@
                         // recreating the DisplayDevice, so we just remove it
                         // from the drawing state, so that it get re-added
                         // below.
-                        sp<DisplayDevice> hw(getDisplayDevice(display));
+                        sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
                         if (hw != NULL)
                             hw->disconnect(getHwComposer());
                         mDisplays.removeItem(display);
@@ -1658,7 +1668,7 @@
                         continue;
                     }
 
-                    const sp<DisplayDevice> disp(getDisplayDevice(display));
+                    const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
                     if (disp != NULL) {
                         if (state.layerStack != draw[i].layerStack) {
                             disp->setLayerStack(state.layerStack);
@@ -1687,8 +1697,7 @@
                     sp<IGraphicBufferProducer> producer;
                     sp<IGraphicBufferProducer> bqProducer;
                     sp<IGraphicBufferConsumer> bqConsumer;
-                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
-                            new GraphicBufferAlloc());
+                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
 
                     int32_t hwcDisplayId = -1;
                     if (state.isVirtualDisplay()) {
@@ -1814,7 +1823,7 @@
                 // could be null when this layer is using a layerStack
                 // that is not visible on any display. Also can occur at
                 // screen off/on times.
-                disp = getDefaultDisplayDevice();
+                disp = getDefaultDisplayDeviceLocked();
             }
             layer->updateTransformHint(disp);
 
@@ -3222,7 +3231,7 @@
     colorizer.reset(result);
 
     HWComposer& hwc(getHwComposer());
-    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     colorizer.bold(result);
     result.appendFormat("EGL implementation : %s\n",
@@ -3298,7 +3307,7 @@
         // Just use the primary display so we have something to return
         dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
     }
-    return getDisplayDevice(dpy)->getVisibleLayersSortedByZ();
+    return getDisplayDeviceLocked(dpy)->getVisibleLayersSortedByZ();
 }
 
 bool SurfaceFlinger::startDdmConnection()
@@ -3713,7 +3722,7 @@
         }
         virtual bool handler() {
             Mutex::Autolock _l(flinger->mStateLock);
-            sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
+            sp<const DisplayDevice> hw(flinger->getDisplayDeviceLocked(display));
             result = flinger->captureScreenImplLocked(hw, producer,
                     sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
                     useIdentityTransform, rotation, isLocalScreenshot);
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index f151087..d15376e 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -18,17 +18,44 @@
 
 #include <sched.h>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <cutils/sched_policy.h>
 #include <binder/IServiceManager.h>
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <hidl/LegacySupport.h>
+#include <configstore/Utils.h>
 #include "GpuService.h"
 #include "SurfaceFlinger.h"
 
 using namespace android;
 
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+using android::hardware::configstore::getBool;
+using android::hardware::configstore::getBool;
+
+static status_t startGraphicsAllocatorService() {
+    hardware::configureRpcThreadpool( 1 /* maxThreads */,
+            false /* callerWillJoin */);
+    status_t result =
+        hardware::registerPassthroughServiceImplementation<IAllocator>();
+    if (result != OK) {
+        ALOGE("could not start graphics allocator service");
+        return result;
+    }
+
+    return OK;
+}
+
 int main(int, char**) {
+    if (getBool<ISurfaceFlingerConfigs,
+            &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
+        startGraphicsAllocatorService();
+    }
+
     signal(SIGPIPE, SIG_IGN);
     // When SF is launched in its own process, limit the number of
     // binder threads to 4.
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index a46ba48..7a8b4ab 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -662,6 +662,49 @@
     }
 }
 
+TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before adding relative surface");
+        ScreenCapture::captureScreen(&sc);
+        sc->expectBGColor(24, 24);
+        sc->expectFGColor(75, 75);
+        sc->expectBGColor(145, 145);
+    }
+
+    auto relativeSurfaceControl = mComposerClient->createSurface(
+            String8("Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
+    fillSurfaceRGBA8(relativeSurfaceControl, 255, 177, 177);
+    waitForPostedBuffers();
+
+    // Now we stack the surface above the foreground surface and make sure it is visible.
+    SurfaceComposerClient::openGlobalTransaction();
+    relativeSurfaceControl->setPosition(64, 64);
+    relativeSurfaceControl->show();
+    relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+
+    {
+        SCOPED_TRACE("after adding relative surface");
+        ScreenCapture::captureScreen(&sc);
+        // our relative surface should be visible now.
+        sc->checkPixel(75, 75, 255, 177, 177);
+    }
+
+    // A call to setLayer will override a call to setRelativeLayer
+    SurfaceComposerClient::openGlobalTransaction();
+    relativeSurfaceControl->setLayer(0);
+    SurfaceComposerClient::closeGlobalTransaction();
+
+    {
+        SCOPED_TRACE("after set layer");
+        ScreenCapture::captureScreen(&sc);
+        // now the FG surface should be visible again.
+        sc->expectFGColor(75, 75);
+    }
+}
+
 class ChildLayerTest : public LayerUpdateTest {
 protected:
     void SetUp() override {
@@ -866,4 +909,36 @@
     }
 }
 
+TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
+    SurfaceComposerClient::openGlobalTransaction();
+    mChild->show();
+    mChild->setPosition(0, 0);
+    mFGSurfaceControl->setPosition(0, 0);
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // We've positioned the child in the top left.
+        mCapture->expectChildColor(0, 0);
+        // But it's only 10x10.
+        mCapture->expectFGColor(10, 10);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setOverrideScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+    // We cause scaling by 2.
+    mFGSurfaceControl->setSize(128, 128);
+    SurfaceComposerClient::closeGlobalTransaction();
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // We've positioned the child in the top left.
+        mCapture->expectChildColor(0, 0);
+        mCapture->expectChildColor(10, 10);
+        mCapture->expectChildColor(19, 19);
+        // And now it should be scaled all the way to 20x20
+        mCapture->expectFGColor(20, 20);
+    }
+}
+
 }
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 2ce60e5..4b1a522 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -1,5 +1,6 @@
 #include "buffer_hub.h"
 
+#include <inttypes.h>
 #include <log/log.h>
 #include <poll.h>
 #include <utils/Trace.h>
@@ -52,7 +53,7 @@
   stream << " ";
   stream << std::setw(6) << "Format";
   stream << " ";
-  stream << std::setw(10) << "Usage";
+  stream << std::setw(21) << "Usage";
   stream << " ";
   stream << "Name";
   stream << std::endl;
@@ -79,7 +80,9 @@
       stream << std::setw(6) << info.format;
       stream << " ";
       stream << "0x" << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage;
+      stream << std::setw(8) << info.producer_usage;
+      stream << "0x";
+      stream << std::setw(8) << info.consumer_usage;
       stream << std::dec << std::setfill(' ');
       stream << " ";
       stream << info.name;
@@ -137,6 +140,10 @@
   stream << " UsageClearMask";
   stream << " UsageDenySetMask";
   stream << " UsageDenyClearMask";
+  stream << " UsageSetMask";
+  stream << " UsageClearMask";
+  stream << " UsageDenySetMask";
+  stream << " UsageDenyClearMask";
   stream << " ";
   stream << std::endl;
 
@@ -150,16 +157,30 @@
       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_set_mask;
+      stream << std::setw(8) << info.usage_policy.producer_set_mask;
       stream << std::setw(7) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_clear_mask;
+      stream << std::setw(8) << info.usage_policy.producer_clear_mask;
       stream << std::setw(9) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_deny_set_mask;
+      stream << std::setw(8) << info.usage_policy.producer_deny_set_mask;
       stream << std::setw(11) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_deny_clear_mask;
+      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::hex << std::setfill('0');
+      stream << std::endl;
     }
   }
 
@@ -177,6 +198,7 @@
 
       stream << std::right << std::setw(6) << info.id;
       stream << std::right << std::setw(12) << info.capacity;
+      stream << std::endl;
     }
   }
 
@@ -235,48 +257,53 @@
     buffer->Detach();
 }
 
-int BufferHubService::OnCreateBuffer(Message& message, int width, int height,
-                                     int format, int usage,
-                                     size_t meta_size_bytes,
-                                     size_t slice_count) {
+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) {
   // 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=%d height=%d "
-           "format=%d usage=%d meta_size_bytes=%zu slice_count=%zu",
-           buffer_id, width, height, format, usage, meta_size_bytes,
-           slice_count);
+           "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);
 
   // See if this channel is already attached to a buffer.
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
     ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
           buffer_id);
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
-  int error;
-  if (const auto producer_channel =
-          ProducerChannel::Create(this, buffer_id, width, height, format, usage,
-                                  meta_size_bytes, slice_count, &error)) {
-    message.SetChannel(producer_channel);
-    return 0;
+  auto status = ProducerChannel::Create(this, buffer_id, width, height, format,
+                                        producer_usage, consumer_usage,
+                                        meta_size_bytes, slice_count);
+  if (status) {
+    message.SetChannel(status.take());
+    return {};
   } else {
-    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return error;
+    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
+          status.GetErrorMessage().c_str());
+    return status.error_status();
   }
 }
 
-int BufferHubService::OnCreatePersistentBuffer(
+Status<void> BufferHubService::OnCreatePersistentBuffer(
     Message& message, const std::string& name, int user_id, int group_id,
-    int width, int height, int format, int usage, size_t meta_size_bytes,
-    size_t slice_count) {
+    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) {
   const int channel_id = message.GetChannelId();
   ALOGD_IF(TRACE,
            "BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
-           "user_id=%d group_id=%d width=%d height=%d format=%d usage=%d "
-           "meta_size_bytes=%zu slice_count=%zu",
+           "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",
            channel_id, name.c_str(), user_id, group_id, width, height, format,
-           usage, meta_size_bytes, slice_count);
+           producer_usage, consumer_usage, meta_size_bytes, slice_count);
 
   // See if this channel is already attached to a buffer.
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -284,12 +311,11 @@
         "BufferHubService::OnCreatePersistentBuffer: Channel already attached "
         "to buffer: channel_id=%d buffer_id=%d",
         channel_id, channel->buffer_id());
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
   const int euid = message.GetEffectiveUserId();
   const int egid = message.GetEffectiveGroupId();
-  int error;
 
   if (auto buffer = GetNamedBuffer(name)) {
     if (!buffer->CheckAccess(euid, egid)) {
@@ -297,41 +323,45 @@
           "BufferHubService::OnCreatePersistentBuffer: Requesting process does "
           "not have permission to access named buffer: name=%s euid=%d egid=%d",
           name.c_str(), euid, euid);
-      return -EPERM;
-    } else if (!buffer->CheckParameters(width, height, format, usage,
-                                        meta_size_bytes, slice_count)) {
+      return ErrorStatus(EPERM);
+    } else if (!buffer->CheckParameters(width, height, format, producer_usage,
+                                        consumer_usage, meta_size_bytes,
+                                        slice_count)) {
       ALOGE(
           "BufferHubService::OnCreatePersistentBuffer: Requested an existing "
           "buffer with different parameters: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else if (!buffer->IsDetached()) {
       ALOGE(
           "BufferHubService::OnCreatePersistentBuffer: Requesting a persistent "
           "buffer that is already attached to a channel: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else {
       buffer->Attach(channel_id);
       message.SetChannel(buffer);
-      return 0;
+      return {};
     }
-  } else if (auto buffer = ProducerChannel::Create(
-                 this, channel_id, width, height, format, usage,
-                 meta_size_bytes, slice_count, &error)) {
-    const int ret =
-        buffer->OnProducerMakePersistent(message, name, user_id, group_id);
-    if (!ret)
-      message.SetChannel(buffer);
-    return ret;
   } else {
-    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return error;
+    auto status = ProducerChannel::Create(
+        this, channel_id, width, height, format, producer_usage, consumer_usage,
+        meta_size_bytes, slice_count);
+    if (!status) {
+      ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
+      return status.error_status();
+    }
+    auto persistent_buffer = status.take();
+    auto make_persistent_status = persistent_buffer->OnProducerMakePersistent(
+        message, name, user_id, group_id);
+    if (make_persistent_status)
+      message.SetChannel(persistent_buffer);
+    return make_persistent_status;
   }
 }
 
-int BufferHubService::OnGetPersistentBuffer(Message& message,
-                                            const std::string& name) {
+Status<void> BufferHubService::OnGetPersistentBuffer(Message& message,
+                                                     const std::string& name) {
   const int channel_id = message.GetChannelId();
   ALOGD_IF(TRACE,
            "BufferHubService::OnGetPersistentBuffer: channel_id=%d name=%s",
@@ -343,7 +373,7 @@
         "BufferHubService::OnGetPersistentBuffer: Channel already attached to "
         "buffer: channel_id=%d buffer_id=%d",
         channel_id, channel->buffer_id());
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
   const int euid = message.GetEffectiveUserId();
@@ -355,28 +385,28 @@
           "BufferHubService::OnGetPersistentBuffer: Requesting process does "
           "not have permission to access named buffer: name=%s euid=%d egid=%d",
           name.c_str(), euid, egid);
-      return -EPERM;
+      return ErrorStatus(EPERM);
     } else if (!buffer->IsDetached()) {
       ALOGE(
           "BufferHubService::OnGetPersistentBuffer: Requesting a persistent "
           "buffer that is already attached to a channel: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else {
       buffer->Attach(channel_id);
       message.SetChannel(buffer);
-      return 0;
+      return {};
     }
   } else {
     ALOGE("BufferHubService::OnGetPersistentBuffer: Buffer \"%s\" not found!",
           name.c_str());
-    return -ENOENT;
+    return ErrorStatus(ENOENT);
   }
 }
 
 Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
-    pdx::Message& message, size_t meta_size_bytes, int usage_set_mask,
-    int usage_clear_mask, int usage_deny_set_mask, int usage_deny_clear_mask) {
+    pdx::Message& message, size_t meta_size_bytes,
+    const UsagePolicy& usage_policy) {
   // Use the producer channel id as the global queue id.
   const int queue_id = message.GetChannelId();
   ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
@@ -389,15 +419,14 @@
     return ErrorStatus(EALREADY);
   }
 
-  int error;
-  if (const auto producer_channel = ProducerQueueChannel::Create(
-          this, queue_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
-          usage_deny_set_mask, usage_deny_clear_mask, &error)) {
-    message.SetChannel(producer_channel);
+  auto status = ProducerQueueChannel::Create(this, queue_id, meta_size_bytes,
+                                             usage_policy);
+  if (status) {
+    message.SetChannel(status.take());
     return {{meta_size_bytes, queue_id}};
   } else {
     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return ErrorStatus(-error);
+    return status.error_status();
   }
 }
 
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 150e399..4cb1eb9 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -48,43 +48,40 @@
     size_t consumer_count = 0;
 
     // Data field for buffer producer.
-    int width = 0;
-    int height = 0;
-    int format = 0;
-    int usage = 0;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    uint32_t format = 0;
+    uint64_t producer_usage = 0;
+    uint64_t consumer_usage = 0;
     size_t slice_count = 0;
     std::string name;
 
     // Data filed for producer queue.
     size_t capacity = 0;
-    int usage_set_mask = 0;
-    int usage_clear_mask = 0;
-    int usage_deny_set_mask = 0;
-    int usage_deny_clear_mask = 0;
+    UsagePolicy usage_policy{0, 0, 0, 0, 0, 0, 0, 0};
 
-    BufferInfo(int id, size_t consumer_count, int width, int height, int format,
-               int usage, size_t slice_count, const std::string& name)
+    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)
         : id(id),
           type(kProducerType),
           consumer_count(consumer_count),
           width(width),
           height(height),
           format(format),
-          usage(usage),
+          producer_usage(producer_usage),
+          consumer_usage(consumer_usage),
           slice_count(slice_count),
           name(name) {}
 
     BufferInfo(int id, size_t consumer_count, size_t capacity,
-               int usage_set_mask, int usage_clear_mask,
-               int usage_deny_set_mask, int usage_deny_clear_mask)
+               const UsagePolicy& usage_policy)
         : id(id),
           type(kProducerQueueType),
           consumer_count(consumer_count),
           capacity(capacity),
-          usage_set_mask(usage_set_mask),
-          usage_clear_mask(usage_clear_mask),
-          usage_deny_set_mask(usage_deny_set_mask),
-          usage_deny_clear_mask(usage_deny_clear_mask) {}
+          usage_policy(usage_policy) {}
 
     BufferInfo() {}
   };
@@ -162,16 +159,19 @@
   std::unordered_map<std::string, std::shared_ptr<ProducerChannel>>
       named_buffers_;
 
-  int OnCreateBuffer(pdx::Message& message, int width, int height, int format,
-                     int usage, size_t meta_size_bytes, size_t slice_count);
-  int OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
-                               int user_id, int group_id, int width, int height,
-                               int format, int usage, size_t meta_size_bytes,
-                               size_t slice_count);
-  int OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
-  pdx::Status<QueueInfo> OnCreateProducerQueue(
-      pdx::Message& message, size_t meta_size_bytes, int usage_set_mask,
-      int usage_clear_mask, int usage_deny_set_mask, int usage_deny_clear_mask);
+  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<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
+                                               size_t meta_size_bytes,
+                                               const UsagePolicy& usage_policy);
 
   BufferHubService(const BufferHubService&) = delete;
   void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 2264cef..311f5c6 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -8,9 +8,11 @@
 #include <private/dvr/bufferhub_rpc.h>
 #include "producer_channel.h"
 
+using android::pdx::ErrorStatus;
 using android::pdx::BorrowedHandle;
 using android::pdx::Channel;
 using android::pdx::Message;
+using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
@@ -103,53 +105,53 @@
   }
 }
 
-std::pair<BorrowedFence, ConsumerChannel::MetaData>
+Status<std::pair<BorrowedFence, ConsumerChannel::MetaData>>
 ConsumerChannel::OnConsumerAcquire(Message& message,
                                    std::size_t metadata_size) {
   ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
   auto producer = GetProducer();
   if (!producer)
-    REPLY_ERROR_RETURN(message, EPIPE, {});
+    return ErrorStatus(EPIPE);
 
   if (ignored_ || handled_) {
     ALOGE(
         "ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
         "ignored=%d handled=%d channel_id=%d buffer_id=%d",
         ignored_, handled_, message.GetChannelId(), producer->buffer_id());
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
   } else {
     ClearAvailable();
     return producer->OnConsumerAcquire(message, metadata_size);
   }
 }
 
-int ConsumerChannel::OnConsumerRelease(Message& message,
-                                       LocalFence release_fence) {
+Status<void> ConsumerChannel::OnConsumerRelease(Message& message,
+                                                LocalFence release_fence) {
   ATRACE_NAME("ConsumerChannel::OnConsumerRelease");
   auto producer = GetProducer();
   if (!producer)
-    return -EPIPE;
+    return ErrorStatus(EPIPE);
 
   if (ignored_ || handled_) {
     ALOGE(
         "ConsumerChannel::OnConsumerRelease: Release when not acquired: "
         "ignored=%d handled=%d channel_id=%d buffer_id=%d",
         ignored_, handled_, message.GetChannelId(), producer->buffer_id());
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   } else {
     ClearAvailable();
-    const int ret =
+    auto status =
         producer->OnConsumerRelease(message, std::move(release_fence));
-    handled_ = ret == 0;
-    return ret;
+    handled_ = !!status;
+    return status;
   }
 }
 
-int ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
+Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
   ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
   auto producer = GetProducer();
   if (!producer)
-    return -EPIPE;
+    return ErrorStatus(EPIPE);
 
   ignored_ = ignored;
   if (ignored_ && !handled_) {
@@ -160,7 +162,7 @@
     handled_ = false;
   }
 
-  return 0;
+  return {};
 }
 
 bool ConsumerChannel::OnProducerPosted() {
diff --git a/services/vr/bufferhubd/consumer_channel.h b/services/vr/bufferhubd/consumer_channel.h
index d2a078f..d84055c 100644
--- a/services/vr/bufferhubd/consumer_channel.h
+++ b/services/vr/bufferhubd/consumer_channel.h
@@ -32,10 +32,11 @@
 
   std::shared_ptr<ProducerChannel> GetProducer() const;
 
-  std::pair<BorrowedFence, MetaData> OnConsumerAcquire(
+  pdx::Status<std::pair<BorrowedFence, MetaData>> OnConsumerAcquire(
       Message& message, std::size_t metadata_size);
-  int OnConsumerRelease(Message& message, LocalFence release_fence);
-  int OnConsumerSetIgnore(Message& message, bool ignore);
+  pdx::Status<void> OnConsumerRelease(Message& message,
+                                      LocalFence release_fence);
+  pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore);
 
   bool handled_;  // True if we have processed RELEASE.
   bool ignored_;  // True if we are ignoring events.
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index cc16f1f..7422751 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -4,7 +4,9 @@
 
 #include "producer_channel.h"
 
+using android::pdx::ErrorStatus;
 using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
@@ -83,7 +85,7 @@
   SignalAvailable();
 }
 
-std::vector<std::pair<RemoteChannelHandle, size_t>>
+Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
 ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) {
   std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
   ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers");
@@ -106,31 +108,30 @@
       continue;
     }
 
-    RemoteChannelHandle consumer_handle(
-        producer_channel->CreateConsumer(message));
+    auto status = producer_channel->CreateConsumer(message);
 
     // If no buffers are imported successfully, clear available and return an
     // error. Otherwise, return all consumer handles already imported
     // successfully, but keep available bits on, so that the client can retry
     // importing remaining consumer buffers.
-    if (!consumer_handle.valid()) {
+    if (!status) {
       ALOGE(
-          "ConsumerQueueChannel::OnConsumerQueueImportBuffers: imported "
-          "consumer handle is invalid.");
+          "ConsumerQueueChannel::OnConsumerQueueImportBuffers: Failed create "
+          "consumer: %s",
+          status.GetErrorMessage().c_str());
       if (buffer_handles.empty()) {
         ClearAvailable();
-        REPLY_ERROR_RETURN(message, EIO, {});
+        return status.error_status();
       } else {
-        return buffer_handles;
+        return {std::move(buffer_handles)};
       }
     }
 
-    // Move consumer_handle into buffer_handles.
-    buffer_handles.emplace_back(std::move(consumer_handle), producer_slot);
+    buffer_handles.emplace_back(status.take(), producer_slot);
   }
 
   ClearAvailable();
-  return buffer_handles;
+  return {std::move(buffer_handles)};
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index b345595..e1005e4 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -36,7 +36,7 @@
   // allocated. Clients uses kOpConsumerQueueImportBuffers to import new
   // consumer buffers and this handler returns a vector of fd representing
   // BufferConsumers that clients can import.
-  std::vector<std::pair<RemoteChannelHandle, size_t>>
+  pdx::Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
   OnConsumerQueueImportBuffers(Message& message);
 
  private:
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 903d174..c946a8d 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -13,8 +13,10 @@
 #include "consumer_channel.h"
 
 using android::pdx::BorrowedHandle;
+using android::pdx::ErrorStatus;
 using android::pdx::Message;
 using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
 using android::pdx::rpc::BufferWrapper;
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::rpc::WrapBuffer;
@@ -23,7 +25,9 @@
 namespace dvr {
 
 ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
-                                 int width, int height, int format, int usage,
+                                 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)
     : BufferHubChannel(service, channel_id, channel_id, kProducerType),
@@ -33,7 +37,8 @@
       meta_size_bytes_(meta_size_bytes),
       meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) {
   for (auto& ion_buffer : slices_) {
-    const int ret = ion_buffer.Alloc(width, height, format, usage);
+    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));
@@ -46,17 +51,18 @@
   *error = 0;
 }
 
-std::shared_ptr<ProducerChannel> ProducerChannel::Create(
-    BufferHubService* service, int channel_id, int width, int height,
-    int format, int usage, size_t meta_size_bytes, size_t slice_count,
-    int* error) {
-  std::shared_ptr<ProducerChannel> producer(
-      new ProducerChannel(service, channel_id, width, height, format, usage,
-                          meta_size_bytes, slice_count, error));
-  if (*error < 0)
-    return nullptr;
+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) {
+  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));
+  if (error < 0)
+    return ErrorStatus(-error);
   else
-    return producer;
+    return {std::move(producer)};
 }
 
 ProducerChannel::~ProducerChannel() {
@@ -70,7 +76,8 @@
 BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
   return BufferInfo(buffer_id(), consumer_channels_.size(), slices_[0].width(),
                     slices_[0].height(), slices_[0].format(),
-                    slices_[0].usage(), slices_.size(), name_);
+                    slices_[0].producer_usage(), slices_[0].consumer_usage(),
+                    slices_.size(), name_);
 }
 
 void ProducerChannel::HandleImpulse(Message& message) {
@@ -125,28 +132,28 @@
   }
 }
 
-NativeBufferHandle<BorrowedHandle> ProducerChannel::OnGetBuffer(
+Status<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffer(
     Message& message, unsigned index) {
   ATRACE_NAME("ProducerChannel::OnGetBuffer");
   ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d", buffer_id());
   if (index < slices_.size()) {
-    return NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id());
+    return {NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id())};
   } else {
-    REPLY_ERROR_RETURN(message, EINVAL, NativeBufferHandle<BorrowedHandle>());
+    return ErrorStatus(EINVAL);
   }
 }
 
-std::vector<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffers(
-    Message&) {
+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 buffer_handles;
+  return {std::move(buffer_handles)};
 }
 
-RemoteChannelHandle ProducerChannel::CreateConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
   ATRACE_NAME("ProducerChannel::CreateConsumer");
   ALOGD_IF(TRACE, "ProducerChannel::CreateConsumer: buffer_id=%d", buffer_id());
 
@@ -154,9 +161,9 @@
   auto status = message.PushChannel(0, nullptr, &channel_id);
   if (!status) {
     ALOGE(
-        "ProducerChannel::CreateConsumer: failed to push consumer channel: %s",
+        "ProducerChannel::CreateConsumer: Failed to push consumer channel: %s",
         status.GetErrorMessage().c_str());
-    return RemoteChannelHandle();
+    return ErrorStatus(ENOMEM);
   }
 
   auto consumer = std::make_shared<ConsumerChannel>(
@@ -167,7 +174,7 @@
         "ProducerChannel::CreateConsumer: failed to set new consumer channel: "
         "%s",
         channel_status.GetErrorMessage().c_str());
-    return RemoteChannelHandle();
+    return ErrorStatus(ENOMEM);
   }
 
   if (!producer_owns_) {
@@ -176,33 +183,27 @@
       pending_consumers_++;
   }
 
-  return status.take();
+  return {status.take()};
 }
 
-RemoteChannelHandle ProducerChannel::OnNewConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
   ATRACE_NAME("ProducerChannel::OnNewConsumer");
   ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id());
-
-  RemoteChannelHandle consumer_handle(CreateConsumer(message));
-
-  if (consumer_handle.valid())
-    return consumer_handle;
-  else
-    REPLY_ERROR_RETURN(message, ENOMEM, RemoteChannelHandle());
+  return CreateConsumer(message);
 }
 
-int ProducerChannel::OnProducerPost(
+Status<void> ProducerChannel::OnProducerPost(
     Message&, LocalFence acquire_fence,
     BufferWrapper<std::vector<std::uint8_t>> metadata) {
   ATRACE_NAME("ProducerChannel::OnProducerPost");
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
   if (!producer_owns_) {
     ALOGE("ProducerChannel::OnProducerPost: Not in gained state!");
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   }
 
   if (meta_size_bytes_ != metadata.size())
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   std::copy(metadata.begin(), metadata.end(), meta_.get());
 
   post_fence_ = std::move(acquire_fence);
@@ -220,29 +221,29 @@
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: %d pending consumers",
            pending_consumers_);
 
-  return 0;
+  return {};
 }
 
-LocalFence ProducerChannel::OnProducerGain(Message& message) {
+Status<LocalFence> ProducerChannel::OnProducerGain(Message& message) {
   ATRACE_NAME("ProducerChannel::OnGain");
   ALOGD_IF(TRACE, "ProducerChannel::OnGain: buffer_id=%d", buffer_id());
   if (producer_owns_) {
     ALOGE("ProducerChanneL::OnGain: Already in gained state: channel=%d",
           channel_id());
-    REPLY_ERROR_RETURN(message, EALREADY, {});
+    return ErrorStatus(EALREADY);
   }
 
   // There are still pending consumers, return busy.
   if (pending_consumers_ > 0)
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
 
   ClearAvailable();
   producer_owns_ = true;
   post_fence_.close();
-  return std::move(returned_fence_);
+  return {std::move(returned_fence_)};
 }
 
-std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>
+Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
 ProducerChannel::OnConsumerAcquire(Message& message,
                                    std::size_t metadata_size) {
   ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
@@ -250,26 +251,27 @@
            buffer_id());
   if (producer_owns_) {
     ALOGE("ProducerChannel::OnConsumerAcquire: Not in posted state!");
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
   }
 
   // Return a borrowed fd to avoid unnecessary duplication of the underlying fd.
   // Serialization just needs to read the handle.
   if (metadata_size == 0)
-    return std::make_pair(post_fence_.borrow(),
-                          WrapBuffer<std::uint8_t>(nullptr, 0));
+    return {std::make_pair(post_fence_.borrow(),
+                           WrapBuffer<std::uint8_t>(nullptr, 0))};
   else
-    return std::make_pair(post_fence_.borrow(),
-                          WrapBuffer(meta_.get(), meta_size_bytes_));
+    return {std::make_pair(post_fence_.borrow(),
+                           WrapBuffer(meta_.get(), meta_size_bytes_))};
 }
 
-int ProducerChannel::OnConsumerRelease(Message&, LocalFence release_fence) {
+Status<void> ProducerChannel::OnConsumerRelease(Message&,
+                                                LocalFence release_fence) {
   ATRACE_NAME("ProducerChannel::OnConsumerRelease");
   ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d",
            buffer_id());
   if (producer_owns_) {
     ALOGE("ProducerChannel::OnConsumerRelease: Not in acquired state!");
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   }
 
   // Attempt to merge the fences if necessary.
@@ -282,7 +284,7 @@
       if (!merged_fence) {
         ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s",
               strerror(error));
-        return -error;
+        return ErrorStatus(error);
       }
       returned_fence_ = std::move(merged_fence);
     } else {
@@ -291,7 +293,7 @@
   }
 
   OnConsumerIgnored();
-  return 0;
+  return {};
 }
 
 void ProducerChannel::OnConsumerIgnored() {
@@ -302,9 +304,10 @@
            buffer_id(), pending_consumers_);
 }
 
-int ProducerChannel::OnProducerMakePersistent(Message& message,
-                                              const std::string& name,
-                                              int user_id, int group_id) {
+Status<void> ProducerChannel::OnProducerMakePersistent(Message& message,
+                                                       const std::string& name,
+                                                       int user_id,
+                                                       int group_id) {
   ATRACE_NAME("ProducerChannel::OnProducerMakePersistent");
   ALOGD_IF(TRACE,
            "ProducerChannel::OnProducerMakePersistent: buffer_id=%d name=%s "
@@ -313,7 +316,7 @@
 
   if (name.empty() || (user_id < 0 && user_id != kNoCheckId) ||
       (group_id < 0 && group_id != kNoCheckId)) {
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   }
 
   // Try to add this buffer with the requested name.
@@ -331,18 +334,18 @@
     owner_user_id_ = user_id;
     owner_group_id_ = group_id;
     name_ = name;
-    return 0;
+    return {};
   } else {
     // Otherwise a buffer with that name already exists.
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 }
 
-int ProducerChannel::OnRemovePersistence(Message&) {
+Status<void> ProducerChannel::OnRemovePersistence(Message&) {
   if (service()->RemoveNamedBuffer(*this))
-    return 0;
+    return {};
   else
-    return -ENOENT;
+    return ErrorStatus(ENOENT);
 }
 
 void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
@@ -365,12 +368,16 @@
 }
 
 // Returns true if the given parameters match the underlying buffer parameters.
-bool ProducerChannel::CheckParameters(int width, int height, int format,
-                                      int usage, size_t meta_size_bytes,
+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].usage() == usage;
+         slices_[0].format() == format &&
+         slices_[0].producer_usage() == producer_usage &&
+         slices_[0].consumer_usage() == consumer_usage;
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index e7ca459..f04c8a5 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -30,10 +30,10 @@
   template <typename T>
   using BufferWrapper = pdx::rpc::BufferWrapper<T>;
 
-  static std::shared_ptr<ProducerChannel> Create(
-      BufferHubService* service, int channel_id, int width, int height,
-      int format, int usage, size_t meta_size_bytes, size_t slice_count,
-      int* error);
+  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);
 
   ~ProducerChannel() override;
 
@@ -42,17 +42,18 @@
 
   BufferInfo GetBufferInfo() const override;
 
-  NativeBufferHandle<BorrowedHandle> OnGetBuffer(Message& message,
-                                                 unsigned index);
-  std::vector<NativeBufferHandle<BorrowedHandle>> OnGetBuffers(
+  pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message,
+                                                              unsigned index);
+  pdx::Status<std::vector<NativeBufferHandle<BorrowedHandle>>> OnGetBuffers(
       Message& message);
 
-  RemoteChannelHandle CreateConsumer(Message& message);
-  RemoteChannelHandle OnNewConsumer(Message& message);
+  pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message);
+  pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message);
 
-  std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>> OnConsumerAcquire(
-      Message& message, std::size_t metadata_size);
-  int OnConsumerRelease(Message& message, LocalFence release_fence);
+  pdx::Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
+  OnConsumerAcquire(Message& message, std::size_t metadata_size);
+  pdx::Status<void> OnConsumerRelease(Message& message,
+                                      LocalFence release_fence);
 
   void OnConsumerIgnored();
 
@@ -60,12 +61,14 @@
   void RemoveConsumer(ConsumerChannel* channel);
 
   bool CheckAccess(int euid, int egid);
-  bool CheckParameters(int width, int height, int format, int usage,
+  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);
 
-  int OnProducerMakePersistent(Message& message, const std::string& name,
-                               int user_id, int group_id);
-  int OnRemovePersistence(Message& message);
+  pdx::Status<void> OnProducerMakePersistent(Message& message,
+                                             const std::string& name,
+                                             int user_id, int group_id);
+  pdx::Status<void> OnRemovePersistence(Message& message);
 
  private:
   std::vector<ConsumerChannel*> consumer_channels_;
@@ -91,13 +94,15 @@
 
   std::string name_;
 
-  ProducerChannel(BufferHubService* service, int channel, int width, int height,
-                  int format, int usage, size_t meta_size_bytes,
+  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);
 
-  int OnProducerPost(Message& message, LocalFence acquire_fence,
-                     BufferWrapper<std::vector<std::uint8_t>> metadata);
-  LocalFence OnProducerGain(Message& message);
+  pdx::Status<void> OnProducerPost(
+      Message& message, LocalFence acquire_fence,
+      BufferWrapper<std::vector<std::uint8_t>> metadata);
+  pdx::Status<LocalFence> OnProducerGain(Message& message);
 
   ProducerChannel(const ProducerChannel&) = delete;
   void operator=(const ProducerChannel&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 7741058..dc2a47e 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -1,5 +1,7 @@
 #include "producer_queue_channel.h"
 
+#include <inttypes.h>
+
 #include "consumer_queue_channel.h"
 #include "producer_channel.h"
 
@@ -12,16 +14,14 @@
 namespace android {
 namespace dvr {
 
-ProducerQueueChannel::ProducerQueueChannel(
-    BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-    int usage_deny_clear_mask, int* error)
+ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service,
+                                           int channel_id,
+                                           size_t meta_size_bytes,
+                                           const UsagePolicy& usage_policy,
+                                           int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerQueueType),
       meta_size_bytes_(meta_size_bytes),
-      usage_set_mask_(usage_set_mask),
-      usage_clear_mask_(usage_clear_mask),
-      usage_deny_set_mask_(usage_deny_set_mask),
-      usage_deny_clear_mask_(usage_deny_clear_mask),
+      usage_policy_(usage_policy),
       capacity_(0) {
   *error = 0;
 }
@@ -29,28 +29,34 @@
 ProducerQueueChannel::~ProducerQueueChannel() {}
 
 /* static */
-std::shared_ptr<ProducerQueueChannel> ProducerQueueChannel::Create(
+Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
     BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-    int usage_deny_clear_mask, int* error) {
+    const UsagePolicy& usage_policy) {
   // Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
   // should be mutually exclusive.
-  if (usage_deny_set_mask & usage_deny_clear_mask) {
+  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)) {
     ALOGE(
         "BufferHubService::OnCreateProducerQueue: illegal usage mask "
-        "configuration: usage_deny_set_mask=%d, usage_deny_clear_mask=%d",
-        usage_deny_set_mask, usage_deny_clear_mask);
-    *error = -EINVAL;
-    return nullptr;
+        "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);
+    return ErrorStatus(EINVAL);
   }
 
+  int error = 0;
   std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel(
-      service, channel_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
-      usage_deny_set_mask, usage_deny_clear_mask, error));
-  if (*error < 0)
-    return nullptr;
+      service, channel_id, meta_size_bytes, usage_policy, &error));
+  if (error < 0)
+    return ErrorStatus(-error);
   else
-    return producer;
+    return {std::move(producer)};
 }
 
 bool ProducerQueueChannel::HandleMessage(Message& message) {
@@ -88,8 +94,7 @@
 
 BufferHubChannel::BufferInfo ProducerQueueChannel::GetBufferInfo() const {
   return BufferInfo(channel_id(), consumer_channels_.size(), capacity_,
-                    usage_set_mask_, usage_clear_mask_, usage_deny_set_mask_,
-                    usage_deny_clear_mask_);
+                    usage_policy_);
 }
 
 Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue(
@@ -127,11 +132,10 @@
 }
 
 Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
-ProducerQueueChannel::OnProducerQueueAllocateBuffers(Message& message,
-                                                     int width, int height,
-                                                     int format, int usage,
-                                                     size_t slice_count,
-                                                     size_t buffer_count) {
+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) {
   ATRACE_NAME("ProducerQueueChannel::OnProducerQueueAllocateBuffers");
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::OnProducerQueueAllocateBuffers: "
@@ -141,31 +145,58 @@
   std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
 
   // Deny buffer allocation violating preset rules.
-  if (usage & usage_deny_set_mask_) {
+  if (producer_usage & usage_policy_.producer_deny_set_mask) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
-        "not permitted. Violating usage_deny_set_mask, the following bits "
-        "shall not be set: %d.",
-        usage, usage_deny_set_mask_);
+        "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);
     return ErrorStatus(EINVAL);
   }
 
-  if (~usage & usage_deny_clear_mask_) {
+  if (consumer_usage & usage_policy_.consumer_deny_set_mask) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
-        "not permitted. Violating usage_deny_clear_mask, the following bits "
-        "must be set: %d.",
-        usage, usage_deny_clear_mask_);
+        "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);
   }
 
-  // Force set mask and clear mask. Note that |usage_set_mask_| takes precedence
-  // and will overwrite |usage_clear_mask_|.
-  int effective_usage = (usage & ~usage_clear_mask_) | usage_set_mask_;
+  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 "
+        "bits must be set: %" PRIx64 ".",
+        producer_usage, usage_policy_.producer_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;
 
   for (size_t i = 0; i < buffer_count; i++) {
-    auto status = AllocateBuffer(message, width, height, format,
-                                 effective_usage, slice_count);
+    auto status =
+        AllocateBuffer(message, width, height, format, effective_producer_usage,
+                       effective_consumer_usage, slice_count);
     if (!status) {
       ALOGE(
           "ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to "
@@ -179,8 +210,10 @@
 }
 
 Status<std::pair<RemoteChannelHandle, size_t>>
-ProducerQueueChannel::AllocateBuffer(Message& message, int width, int height,
-                                     int format, int usage,
+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) {
   ATRACE_NAME("ProducerQueueChannel::AllocateBuffer");
   ALOGD_IF(TRACE,
@@ -205,21 +238,24 @@
   }
 
   ALOGD_IF(TRACE,
-           "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%d "
-           "height=%d format=%d usage=%d slice_count=%zu",
-           buffer_id, width, height, format, usage, slice_count);
+           "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);
   auto buffer_handle = status.take();
 
-  int error;
-  const auto producer_channel =
-      ProducerChannel::Create(service(), buffer_id, width, height, format,
-                              usage, meta_size_bytes_, slice_count, &error);
-  if (!producer_channel) {
+  auto producer_channel_status = ProducerChannel::Create(
+      service(), buffer_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes_, slice_count);
+  if (!producer_channel_status) {
     ALOGE(
-        "ProducerQueueChannel::AllocateBuffer: Failed to create "
-        "BufferHubBuffer producer!!");
+        "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
+        "buffer: %s",
+        producer_channel_status.GetErrorMessage().c_str());
     return ErrorStatus(ENOMEM);
   }
+  auto producer_channel = producer_channel_status.take();
 
   ALOGD_IF(
       TRACE,
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index a12a37d..09b0243 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -11,10 +11,9 @@
 
 class ProducerQueueChannel : public BufferHubChannel {
  public:
-  static std::shared_ptr<ProducerQueueChannel> Create(
+  static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create(
       BufferHubService* service, int channel_id, size_t meta_size_bytes,
-      int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-      int usage_deny_clear_mask, int* error);
+      const UsagePolicy& usage_policy);
   ~ProducerQueueChannel() override;
 
   bool HandleMessage(pdx::Message& message) override;
@@ -34,8 +33,10 @@
   // Allocate a new BufferHubProducer according to the input spec. Client may
   // 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, int width, int height,
-                                 int format, int usage, size_t slice_count,
+  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,
                                  size_t buffer_count);
 
   // Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
@@ -48,18 +49,17 @@
 
  private:
   ProducerQueueChannel(BufferHubService* service, int channel_id,
-                       size_t meta_size_bytes, int usage_set_mask,
-                       int usage_clear_mask, int usage_deny_set_mask,
-                       int usage_deny_clear_mask, int* error);
+                       size_t meta_size_bytes, const UsagePolicy& usage_policy,
+                       int* error);
 
   // Allocate one single producer buffer by |OnProducerQueueAllocateBuffers|.
   // Note that the newly created buffer's file handle will be pushed to client
   // and our return type is a RemoteChannelHandle.
-  // Returns the remote channdel handle and the slot number for the newly
+  // 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, int width, int height, int format, int usage,
-      size_t slice_count);
+      pdx::Message& message, uint32_t width, uint32_t height, uint32_t format,
+      uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count);
 
   // 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
@@ -68,10 +68,7 @@
 
   // A set of variables to control what |usage| bits can this ProducerQueue
   // allocate.
-  int usage_set_mask_;
-  int usage_clear_mask_;
-  int usage_deny_set_mask_;
-  int usage_deny_clear_mask_;
+  UsagePolicy usage_policy_;
 
   // Provides access to the |channel_id| of all consumer channels associated
   // with this producer.
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index b94d333..25bb30b 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -1,3 +1,51 @@
+cc_library_shared {
+  name: "libvr_hwc-hal",
+
+  srcs: [
+    "impl/vr_hwc.cpp",
+    "impl/vr_composer_client.cpp",
+  ],
+
+  static_libs: [
+    "libhwcomposer-client",
+    "libdisplay",
+    "libbufferhubqueue",
+    "libbufferhub",
+    "libpdx_default_transport",
+  ],
+
+  shared_libs: [
+    "android.frameworks.vr.composer@1.0",
+    "android.hardware.graphics.composer@2.1",
+    "libbase",
+    "libcutils",
+    "libfmq",
+    "libhardware",
+    "libhidlbase",
+    "libhidltransport",
+    "liblog",
+    "libsync",
+    "libui",
+    "libutils",
+  ],
+
+  export_static_lib_headers: [
+    "libhwcomposer-client",
+  ],
+
+  export_shared_lib_headers: [
+    "android.frameworks.vr.composer@1.0",
+    "android.hardware.graphics.composer@2.1",
+  ],
+
+  export_include_dirs: ["."],
+
+  cflags: [
+    "-DLOG_TAG=\"vr_hwc\"",
+  ],
+
+}
+
 cc_library_static {
   name: "libvr_hwc-binder",
   srcs: [
@@ -12,11 +60,12 @@
     export_aidl_headers: true,
   },
   export_include_dirs: ["aidl"],
+
   shared_libs: [
     "libbinder",
     "libui",
     "libutils",
-    "libvrhwc",
+    "libvr_hwc-hal",
   ],
 }
 
@@ -34,10 +83,10 @@
     "liblog",
     "libui",
     "libutils",
-    "libvrhwc",
+    "libvr_hwc-hal",
   ],
   export_shared_lib_headers: [
-    "libvrhwc",
+    "libvr_hwc-hal",
   ],
   cflags: [
     "-DLOG_TAG=\"vr_hwc\"",
@@ -65,7 +114,7 @@
     "libhwbinder",
     "libui",
     "libutils",
-    "libvrhwc",
+    "libvr_hwc-hal",
   ],
   cflags: [
     "-DLOG_TAG=\"vr_hwc\"",
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp
index 45eabca..db7d5dc 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp
@@ -28,6 +28,26 @@
   ret = parcel->writeBool(frame_.removed);
   if (ret != OK) return ret;
 
+  ret = parcel->writeUint32(static_cast<uint32_t>(frame_.active_config));
+  if (ret != OK) return ret;
+
+  ret = parcel->writeUint32(static_cast<uint32_t>(frame_.color_mode));
+  if (ret != OK) return ret;
+
+  ret = parcel->writeUint32(static_cast<uint32_t>(frame_.power_mode));
+  if (ret != OK) return ret;
+
+  ret = parcel->writeUint32(static_cast<uint32_t>(frame_.vsync_enabled));
+  if (ret != OK) return ret;
+
+  ret = parcel->writeInt32(frame_.color_transform_hint);
+  if (ret != OK) return ret;
+
+  for(size_t i = 0; i < 16; i++) {
+    ret = parcel->writeFloat(frame_.color_transform[i]);
+    if (ret != OK) return ret;
+  }
+
   std::vector<ParcelableComposerLayer> layers;
   for (size_t i = 0; i < frame_.layers.size(); ++i)
     layers.push_back(ParcelableComposerLayer(frame_.layers[i]));
@@ -50,6 +70,31 @@
   ret = parcel->readBool(&frame_.removed);
   if (ret != OK) return ret;
 
+  uint32_t value;
+  ret = parcel->readUint32(&value);
+  if (ret != OK) return ret;
+  frame_.active_config = static_cast<Config>(value);
+
+  ret = parcel->readUint32(&value);
+  if (ret != OK) return ret;
+  frame_.color_mode = static_cast<ColorMode>(value);
+
+  ret = parcel->readUint32(&value);
+  if (ret != OK) return ret;
+  frame_.power_mode = static_cast<IComposerClient::PowerMode>(value);
+
+  ret = parcel->readUint32(&value);
+  if (ret != OK) return ret;
+  frame_.vsync_enabled = static_cast<IComposerClient::Vsync>(value);
+
+  ret = parcel->readInt32(&frame_.color_transform_hint);
+  if (ret != OK) return ret;
+
+  for(size_t i = 0; i < 16; i++) {
+    ret = parcel->readFloat(&frame_.color_transform[i]);
+    if (ret != OK) return ret;
+  }
+
   std::vector<ParcelableComposerLayer> layers;
   ret = parcel->readParcelableVector(&layers);
   if (ret != OK) return ret;
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
index 999d71e..c3621eb 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
@@ -7,41 +7,6 @@
 
 namespace android {
 namespace dvr {
-namespace {
-
-sp<GraphicBuffer> GetBufferFromHandle(native_handle_t* handle) {
-  uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
-  uint64_t producer_usage = 0, consumer_usage = 0;
-  int32_t format = 0;
-
-  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
-  // Need to register |handle| otherwise we can't read its properties.
-  if (mapper.registerBuffer(handle) != OK) {
-    ALOGE("Failed to register buffer");
-    return nullptr;
-  }
-
-  if (mapper.getDimensions(handle, &width, &height) ||
-      mapper.getStride(handle, &stride) ||
-      mapper.getFormat(handle, &format) ||
-      mapper.getProducerUsage(handle, &producer_usage) ||
-      mapper.getConsumerUsage(handle, &consumer_usage)) {
-    ALOGE("Failed to read handle properties");
-    return nullptr;
-  }
-
-  // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
-  // capability. Otherwise assume a count of 1.
-  mapper.getLayerCount(handle, &layer_count);
-
-  sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
-      GraphicBuffer::TAKE_HANDLE, width, height, format, layer_count,
-      producer_usage, consumer_usage, stride);
-
-  return buffer;
-}
-
-}  // namespace
 
 ParcelableComposerLayer::ParcelableComposerLayer() {}
 
@@ -54,7 +19,7 @@
   status_t ret = parcel->writeUint64(layer_.id);
   if (ret != OK) return ret;
 
-  ret = parcel->writeNativeHandle(layer_.buffer->getNativeBuffer()->handle);
+  ret = parcel->write(*layer_.buffer);
   if (ret != OK) return ret;
 
   ret = parcel->writeBool(layer_.fence->isValid());
@@ -101,6 +66,50 @@
   ret = parcel->writeUint32(layer_.app_id);
   if (ret != OK) return ret;
 
+  ret = parcel->writeUint32(layer_.z_order);
+  if (ret != OK) return ret;
+
+  ret = parcel->writeInt32(layer_.cursor_x);
+  if (ret != OK) return ret;
+
+  ret = parcel->writeInt32(layer_.cursor_y);
+  if (ret != OK) return ret;
+
+  uint32_t color = layer_.color.r |
+      (static_cast<uint32_t>(layer_.color.g) << 8) |
+      (static_cast<uint32_t>(layer_.color.b) << 16) |
+      (static_cast<uint32_t>(layer_.color.a) << 24);
+  ret = parcel->writeUint32(color);
+  if (ret != OK) return ret;
+
+  ret = parcel->writeInt32(layer_.dataspace);
+  if (ret != OK) return ret;
+
+  ret = parcel->writeInt32(layer_.transform);
+  if (ret != OK) return ret;
+
+  ret = parcel->writeUint32(static_cast<uint32_t>(layer_.visible_regions.size()));
+  if (ret != OK) return ret;
+
+  for (auto& rect: layer_.visible_regions) {
+    ret = parcel->writeInt32(rect.left);
+    ret = parcel->writeInt32(rect.top);
+    ret = parcel->writeInt32(rect.right);
+    ret = parcel->writeInt32(rect.bottom);
+    if (ret != OK) return ret;
+  }
+
+  ret = parcel->writeUint32(static_cast<uint32_t>(layer_.damaged_regions.size()));
+  if (ret != OK) return ret;
+
+  for (auto& rect: layer_.damaged_regions) {
+    ret = parcel->writeInt32(rect.left);
+    ret = parcel->writeInt32(rect.top);
+    ret = parcel->writeInt32(rect.right);
+    ret = parcel->writeInt32(rect.bottom);
+    if (ret != OK) return ret;
+  }
+
   return OK;
 }
 
@@ -108,11 +117,12 @@
   status_t ret = parcel->readUint64(&layer_.id);
   if (ret != OK) return ret;
 
-  native_handle* handle = parcel->readNativeHandle();
-  if (!handle) return BAD_VALUE;
-
-  layer_.buffer = GetBufferFromHandle(handle);
-  if (!layer_.buffer.get()) return BAD_VALUE;
+  layer_.buffer = new GraphicBuffer();
+  ret = parcel->read(*layer_.buffer);
+  if (ret != OK) {
+    layer_.buffer.clear();
+    return ret;
+  }
 
   bool has_fence = 0;
   ret = parcel->readBool(&has_fence);
@@ -159,6 +169,70 @@
   ret = parcel->readUint32(&layer_.app_id);
   if (ret != OK) return ret;
 
+  ret = parcel->readUint32(&layer_.z_order);
+  if (ret != OK) return ret;
+
+  ret = parcel->readInt32(&layer_.cursor_x);
+  if (ret != OK) return ret;
+
+  ret = parcel->readInt32(&layer_.cursor_y);
+  if (ret != OK) return ret;
+
+  uint32_t color;
+  ret = parcel->readUint32(&color);
+  if (ret != OK) return ret;
+  layer_.color.r = color & 0xFF;
+  layer_.color.g = (color >> 8) & 0xFF;
+  layer_.color.b = (color >> 16) & 0xFF;
+  layer_.color.a = (color >> 24) & 0xFF;
+
+  ret = parcel->readInt32(&layer_.dataspace);
+  if (ret != OK) return ret;
+
+  ret = parcel->readInt32(&layer_.transform);
+  if (ret != OK) return ret;
+
+  uint32_t size;
+  ret = parcel->readUint32(&size);
+  if (ret != OK) return ret;
+
+  for(size_t i = 0; i < size; i++) {
+    hwc_rect_t rect;
+    ret = parcel->readInt32(&rect.left);
+    if (ret != OK) return ret;
+
+    ret = parcel->readInt32(&rect.top);
+    if (ret != OK) return ret;
+
+    ret = parcel->readInt32(&rect.right);
+    if (ret != OK) return ret;
+
+    ret = parcel->readInt32(&rect.bottom);
+    if (ret != OK) return ret;
+
+    layer_.visible_regions.push_back(rect);
+  }
+
+  ret = parcel->readUint32(&size);
+  if (ret != OK) return ret;
+
+  for(size_t i = 0; i < size; i++) {
+    hwc_rect_t rect;
+    ret = parcel->readInt32(&rect.left);
+    if (ret != OK) return ret;
+
+    ret = parcel->readInt32(&rect.top);
+    if (ret != OK) return ret;
+
+    ret = parcel->readInt32(&rect.right);
+    if (ret != OK) return ret;
+
+    ret = parcel->readInt32(&rect.bottom);
+    if (ret != OK) return ret;
+
+    layer_.damaged_regions.push_back(rect);
+  }
+
   return OK;
 }
 
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp b/services/vr/hardware_composer/impl/vr_composer_client.cpp
similarity index 63%
rename from services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
rename to services/vr/hardware_composer/impl/vr_composer_client.cpp
index acf0dac..ae54e56 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
+++ b/services/vr/hardware_composer/impl/vr_composer_client.cpp
@@ -19,8 +19,8 @@
 #include <hardware/gralloc1.h>
 #include <log/log.h>
 
-#include "vr_hwc.h"
-#include "vr_composer_client.h"
+#include "impl/vr_hwc.h"
+#include "impl/vr_composer_client.h"
 
 namespace android {
 namespace dvr {
@@ -50,6 +50,10 @@
   switch (vrCommand) {
     case IVrComposerClient::VrCommand::SET_LAYER_INFO:
       return parseSetLayerInfo(length);
+    case IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA:
+      return parseSetClientTargetMetadata(length);
+    case IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA:
+      return parseSetLayerBufferMetadata(length);
     default:
       return CommandReader::parseCommand(command, length);
   }
@@ -68,5 +72,43 @@
   return true;
 }
 
+bool VrComposerClient::VrCommandReader::parseSetClientTargetMetadata(
+    uint16_t length) {
+  if (length != 7)
+    return false;
+
+  auto err = mVrHal.setClientTargetMetadata(mDisplay, readBufferMetadata());
+  if (err != Error::NONE)
+    mWriter.setError(getCommandLoc(), err);
+
+  return true;
+}
+
+bool VrComposerClient::VrCommandReader::parseSetLayerBufferMetadata(
+    uint16_t length) {
+  if (length != 7)
+    return false;
+
+  auto err = mVrHal.setLayerBufferMetadata(mDisplay, mLayer,
+                                           readBufferMetadata());
+  if (err != Error::NONE)
+    mWriter.setError(getCommandLoc(), err);
+
+  return true;
+}
+
+IVrComposerClient::BufferMetadata
+VrComposerClient::VrCommandReader::readBufferMetadata() {
+  IVrComposerClient::BufferMetadata metadata = {
+    .width = read(),
+    .height = read(),
+    .stride = read(),
+    .layerCount = read(),
+    .format = static_cast<PixelFormat>(readSigned()),
+    .usage = read64(),
+  };
+  return metadata;
+}
+
 }  // namespace dvr
 }  // namespace android
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h b/services/vr/hardware_composer/impl/vr_composer_client.h
similarity index 80%
rename from services/vr/vr_window_manager/composer/impl/vr_composer_client.h
rename to services/vr/hardware_composer/impl/vr_composer_client.h
index 8f0c562..1236be9 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
+++ b/services/vr/hardware_composer/impl/vr_composer_client.h
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
-#define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
+#ifndef ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H
+#define ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H
 
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <ComposerClient.h>
 #include <IComposerCommandBuffer.h>
 
@@ -44,6 +45,10 @@
 
    private:
     bool parseSetLayerInfo(uint16_t length);
+    bool parseSetClientTargetMetadata(uint16_t length);
+    bool parseSetLayerBufferMetadata(uint16_t length);
+
+    IVrComposerClient::BufferMetadata readBufferMetadata();
 
     VrComposerClient& mVrClient;
     android::dvr::VrHwc& mVrHal;
@@ -63,4 +68,4 @@
 } // namespace dvr
 } // namespace android
 
-#endif  // VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
+#endif  // ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
similarity index 83%
rename from services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
rename to services/vr/hardware_composer/impl/vr_hwc.cpp
index 9ba01f9..504b26f 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -13,15 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "vr_hwc.h"
-
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
-
-#include <mutex>
+#include "impl/vr_hwc.h"
 
 #include <private/dvr/display_client.h>
+#include <ui/Fence.h>
+
+#include <mutex>
 
 #include "vr_composer_client.h"
 
@@ -43,35 +40,19 @@
 const Display kDefaultDisplayId = 1;
 const Config kDefaultConfigId = 1;
 
-sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) {
-  uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
-  uint64_t producer_usage = 0, consumer_usage = 0;
-  int32_t format = 0;
+sp<GraphicBuffer> CreateGraphicBuffer(
+    const native_handle_t* handle,
+    const IVrComposerClient::BufferMetadata& metadata) {
+   sp<GraphicBuffer> buffer = new GraphicBuffer(
+      handle, GraphicBuffer::CLONE_HANDLE, metadata.width, metadata.height,
+      static_cast<int32_t>(metadata.format), metadata.layerCount,
+      metadata.usage, metadata.stride);
+   if (buffer->initCheck() != OK) {
+     ALOGE("Failed to create graphic buffer");
+     return nullptr;
+   }
 
-  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
-  if (mapper.getDimensions(handle, &width, &height) ||
-      mapper.getStride(handle, &stride) ||
-      mapper.getFormat(handle, &format) ||
-      mapper.getProducerUsage(handle, &producer_usage) ||
-      mapper.getConsumerUsage(handle, &consumer_usage)) {
-    ALOGE("Failed to read handle properties");
-    return nullptr;
-  }
-
-  // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
-  // capability. Otherwise assume a count of 1.
-  mapper.getLayerCount(handle, &layer_count);
-
-  // NOTE: Can't re-use |handle| since we don't own it.
-  sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
-      GraphicBuffer::CLONE_HANDLE, width, height, format, layer_count,
-      producer_usage, consumer_usage, stride);
-  if (buffer->initCheck() != OK) {
-    ALOGE("Failed to register cloned buffer");
-    return nullptr;
-  }
-
-  return buffer;
+   return buffer;
 }
 
 void GetPrimaryDisplaySize(int32_t* width, int32_t* height) {
@@ -109,12 +90,17 @@
 bool HwcDisplay::SetClientTarget(const native_handle_t* handle,
                                  base::unique_fd fence) {
   if (handle)
-    buffer_ = GetBufferFromHandle(handle);
+    buffer_ = CreateGraphicBuffer(handle, buffer_metadata_);
 
   fence_ = new Fence(fence.release());
   return true;
 }
 
+void HwcDisplay::SetClientTargetMetadata(
+    const IVrComposerClient::BufferMetadata& metadata) {
+  buffer_metadata_ = metadata;
+}
+
 HwcLayer* HwcDisplay::CreateLayer() {
   uint64_t layer_id = layer_ids_++;
   layers_.push_back(HwcLayer(layer_id));
@@ -145,7 +131,7 @@
     std::vector<IComposerClient::Composition>* types) {
   std::sort(layers_.begin(), layers_.end(),
             [](const auto& lhs, const auto& rhs) {
-              return lhs.z_order < rhs.z_order;
+              return lhs.info.z_order < rhs.info.z_order;
             });
 
   int first_client_layer = -1, last_client_layer = -1;
@@ -233,6 +219,12 @@
   return last_frame_layers;
 }
 
+void HwcDisplay::SetColorTransform(const float* matrix, int32_t hint) {
+  color_transform_hint_ = hint;
+  if (matrix)
+    memcpy(color_transform_, matrix, sizeof(color_transform_));
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // VrHwcClient
 
@@ -410,40 +402,54 @@
 
 Error VrHwc::setActiveConfig(Display display, Config config) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
   if (config != kDefaultConfigId)
     return Error::BAD_CONFIG;
 
+  display_ptr->set_active_config(config);
   return Error::NONE;
 }
 
 Error VrHwc::setColorMode(Display display, ColorMode mode) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  display_ptr->set_color_mode(mode);
   return Error::NONE;
 }
 
 Error VrHwc::setPowerMode(Display display, IComposerClient::PowerMode mode) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  display_ptr->set_power_mode(mode);
   return Error::NONE;
 }
 
 Error VrHwc::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  display_ptr->set_vsync_enabled(enabled);
   return Error::NONE;
 }
 
 Error VrHwc::setColorTransform(Display display, const float* matrix,
                                int32_t hint) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  display_ptr->SetColorTransform(matrix, hint);
   return Error::NONE;
 }
 
@@ -513,6 +519,13 @@
   frame.display_id = display;
   frame.display_width = display_ptr->width();
   frame.display_height = display_ptr->height();
+  frame.active_config = display_ptr->active_config();
+  frame.power_mode = display_ptr->power_mode();
+  frame.vsync_enabled = display_ptr->vsync_enabled();
+  frame.color_transform_hint = display_ptr->color_transform_hint();
+  frame.color_mode = display_ptr->color_mode();
+  memcpy(frame.color_transform, display_ptr->color_transform(),
+         sizeof(frame.color_transform));
   if (status != Error::NONE)
     return status;
 
@@ -536,8 +549,16 @@
 Error VrHwc::setLayerCursorPosition(Display display, Layer layer, int32_t x,
                                     int32_t y) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->info.cursor_x = x;
+  hwc_layer->info.cursor_y = y;
   return Error::NONE;
 }
 
@@ -553,7 +574,8 @@
   if (!hwc_layer)
     return Error::BAD_LAYER;
 
-  hwc_layer->info.buffer = GetBufferFromHandle(buffer);
+  hwc_layer->info.buffer = CreateGraphicBuffer(
+      buffer, hwc_layer->buffer_metadata);
   hwc_layer->info.fence = new Fence(fence.release());
 
   return Error::NONE;
@@ -562,8 +584,15 @@
 Error VrHwc::setLayerSurfaceDamage(Display display, Layer layer,
                                    const std::vector<hwc_rect_t>& damage) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->info.damaged_regions = damage;
   return Error::NONE;
 }
 
@@ -586,8 +615,15 @@
 Error VrHwc::setLayerColor(Display display, Layer layer,
                            IComposerClient::Color color) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->info.color = color;
   return Error::NONE;
 }
 
@@ -610,8 +646,15 @@
 Error VrHwc::setLayerDataspace(Display display, Layer layer,
                                int32_t dataspace) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->info.dataspace = dataspace;
   return Error::NONE;
 }
 
@@ -674,16 +717,30 @@
 Error VrHwc::setLayerTransform(Display display, Layer layer,
                                int32_t transform) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->info.transform = transform;
   return Error::NONE;
 }
 
 Error VrHwc::setLayerVisibleRegion(Display display, Layer layer,
                                    const std::vector<hwc_rect_t>& visible) {
   std::lock_guard<std::mutex> guard(mutex_);
-  if (!FindDisplay(display))
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
     return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->info.visible_regions = visible;
   return Error::NONE;
 }
 
@@ -697,7 +754,7 @@
   if (!hwc_layer)
     return Error::BAD_LAYER;
 
-  hwc_layer->z_order = z;
+  hwc_layer->info.z_order = z;
 
   return Error::NONE;
 }
@@ -719,6 +776,35 @@
   return Error::NONE;
 }
 
+Error VrHwc::setClientTargetMetadata(
+    Display display, const IVrComposerClient::BufferMetadata& metadata) {
+  std::lock_guard<std::mutex> guard(mutex_);
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
+    return Error::BAD_DISPLAY;
+
+  display_ptr->SetClientTargetMetadata(metadata);
+
+  return Error::NONE;
+}
+
+Error VrHwc::setLayerBufferMetadata(
+    Display display, Layer layer,
+    const IVrComposerClient::BufferMetadata& metadata) {
+  std::lock_guard<std::mutex> guard(mutex_);
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
+    return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->buffer_metadata = metadata;
+
+  return Error::NONE;
+}
+
 Return<void> VrHwc::getCapabilities(getCapabilities_cb hidl_cb) {
   hidl_cb(hidl_vec<Capability>());
   return Void();
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
similarity index 81%
rename from services/vr/vr_window_manager/composer/impl/vr_hwc.h
rename to services/vr/hardware_composer/impl/vr_hwc.h
index bfca9a6..df04208 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -13,10 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_HWC_H_
-#define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_HWC_H_
+#ifndef ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_HWC_H
+#define ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_HWC_H
 
 #include <android-base/unique_fd.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <ComposerBase.h>
 #include <ui/Fence.h>
@@ -26,6 +27,7 @@
 #include <mutex>
 #include <unordered_map>
 
+using namespace android::frameworks::vr::composer::V1_0;
 using namespace android::hardware::graphics::common::V1_0;
 using namespace android::hardware::graphics::composer::V2_1;
 
@@ -38,7 +40,6 @@
 namespace android {
 
 class Fence;
-class GraphicBuffer;
 
 namespace dvr {
 
@@ -55,8 +56,6 @@
     using BlendMode =
         hardware::graphics::composer::V2_1::IComposerClient::BlendMode;
 
-    // TODO(dnicoara): Add all layer properties. For now just the basics to get
-    // it going.
     Layer id;
     sp<GraphicBuffer> buffer;
     sp<Fence> fence;
@@ -66,6 +65,14 @@
     float alpha;
     uint32_t type;
     uint32_t app_id;
+    uint32_t z_order;
+    int32_t cursor_x;
+    int32_t cursor_y;
+    IComposerClient::Color color;
+    int32_t dataspace;
+    int32_t transform;
+    std::vector<hwc_rect_t> visible_regions;
+    std::vector<hwc_rect_t> damaged_regions;
   };
 
   struct Frame {
@@ -76,6 +83,12 @@
     bool removed = false;
     int32_t display_width;
     int32_t display_height;
+    Config active_config;
+    ColorMode color_mode;
+    IComposerClient::PowerMode power_mode;
+    IComposerClient::Vsync vsync_enabled;
+    float color_transform[16];
+    int32_t color_transform_hint;
     std::vector<ComposerLayer> layers;
   };
 
@@ -103,8 +116,8 @@
   }
 
   Composition composition_type;
-  uint32_t z_order;
   ComposerView::ComposerLayer info;
+  IVrComposerClient::BufferMetadata buffer_metadata;
 };
 
 class HwcDisplay {
@@ -120,6 +133,8 @@
   HwcLayer* GetLayer(Layer id);
 
   bool SetClientTarget(const native_handle_t* handle, base::unique_fd fence);
+  void SetClientTargetMetadata(
+      const IVrComposerClient::BufferMetadata& metadata);
 
   void GetChangedCompositionTypes(
       std::vector<Layer>* layer_ids,
@@ -129,10 +144,28 @@
 
   std::vector<Layer> UpdateLastFrameAndGetLastFrameLayers();
 
+  Config active_config() const { return active_config_; }
+  void set_active_config(Config config) { active_config_ = config; }
+
+  ColorMode color_mode() const { return color_mode_; }
+  void set_color_mode(ColorMode mode) { color_mode_ = mode; }
+
+  IComposerClient::PowerMode power_mode() const { return power_mode_; }
+  void set_power_mode(IComposerClient::PowerMode mode) { power_mode_ = mode; }
+
+  IComposerClient::Vsync vsync_enabled() const { return vsync_enabled_; }
+  void set_vsync_enabled(IComposerClient::Vsync vsync) {
+    vsync_enabled_ = vsync;
+  }
+
+  const float* color_transform() const { return color_transform_; }
+  int32_t color_transform_hint() const { return color_transform_hint_; }
+  void SetColorTransform(const float* matrix, int32_t hint);
+
  private:
   // The client target buffer and the associated fence.
-  // TODO(dnicoara): Replace this with a list of ComposerView::ComposerLayer.
   sp<GraphicBuffer> buffer_;
+  IVrComposerClient::BufferMetadata buffer_metadata_;
   sp<Fence> fence_;
 
   // List of currently active layers.
@@ -146,6 +179,13 @@
   int32_t width_;
   int32_t height_;
 
+  Config active_config_;
+  ColorMode color_mode_;
+  IComposerClient::PowerMode power_mode_;
+  IComposerClient::Vsync vsync_enabled_;
+  float color_transform_[16];
+  int32_t color_transform_hint_;
+
   HwcDisplay(const HwcDisplay&) = delete;
   void operator=(const HwcDisplay&) = delete;
 };
@@ -159,6 +199,11 @@
 
   Error setLayerInfo(Display display, Layer layer, uint32_t type,
                      uint32_t appId);
+  Error setClientTargetMetadata(
+      Display display, const IVrComposerClient::BufferMetadata& metadata);
+  Error setLayerBufferMetadata(
+      Display display, Layer layer,
+      const IVrComposerClient::BufferMetadata& metadata);
 
   // ComposerBase
   void removeClient() override;
@@ -274,4 +319,4 @@
 }  // namespace dvr
 }  // namespace android
 
-#endif  // VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_HWC_H_
+#endif  // ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_HWC_H
diff --git a/services/vr/sensord/pose_service.cpp b/services/vr/sensord/pose_service.cpp
index e3f8171..75423bb 100644
--- a/services/vr/sensord/pose_service.cpp
+++ b/services/vr/sensord/pose_service.cpp
@@ -48,7 +48,7 @@
 static constexpr float kDefaultNeckVerticalOffset = 0.075f;    // meters
 
 static constexpr char kDisablePosePredictionProp[] =
-    "persist.dreamos.disable_predict";
+    "persist.dvr.disable_predict";
 
 // Device type property for controlling classes of behavior that differ
 // between devices. If unset, defaults to kOrientationTypeSmartphone.
@@ -182,7 +182,7 @@
     KickSensorWatchDogThread();
   }
 
-  // Read the persistent dreamos flags before using them in SetPoseMode.
+  // Read the persistent dvr flags before using them in SetPoseMode.
   enable_pose_prediction_ =
       property_get_bool(kDisablePosePredictionProp, 0) == 0;
 
@@ -467,7 +467,10 @@
                                               -kDefaultNeckHorizontalOffset);
 
       // Update the current latency model.
-      sensor_latency_.AddLatency(GetSystemClockNs() - pose_state.timestamp_ns);
+      if (pose_state.timestamp_ns != 0) {
+        sensor_latency_.AddLatency(GetSystemClockNs() -
+                                   pose_state.timestamp_ns);
+      }
 
       // Update the timestamp with the expected latency.
       WriteAsyncPoses(
diff --git a/services/vr/vr_window_manager/Android.bp b/services/vr/vr_window_manager/Android.bp
index 669426b..d7ddba1 100644
--- a/services/vr/vr_window_manager/Android.bp
+++ b/services/vr/vr_window_manager/Android.bp
@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-subdirs = [ "composer", ]
-
 native_src = [
     "application.cpp",
     "controller_mesh.cpp",
@@ -49,7 +47,6 @@
 shared_libs = [
     "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
-    "libvrhwc",
     "libbase",
     "libbinder",
     "libinput",
@@ -66,6 +63,7 @@
     "libhidlbase",
     "libhidltransport",
     "liblog",
+    "libvr_hwc-hal",
 ]
 
 cc_binary {
diff --git a/services/vr/vr_window_manager/composer/Android.bp b/services/vr/vr_window_manager/composer/Android.bp
deleted file mode 100644
index 007251f..0000000
--- a/services/vr/vr_window_manager/composer/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-cc_library_shared {
-  name: "libvrhwc",
-
-  srcs: [
-    "impl/vr_composer_view.cpp",
-    "impl/vr_hwc.cpp",
-    "impl/vr_composer_client.cpp",
-  ],
-
-  static_libs: [
-    "libhwcomposer-client",
-    "libdisplay",
-    "libpdx_default_transport",
-    "libbufferhub",
-    "libbufferhubqueue",
-  ],
-
-  shared_libs: [
-    "android.frameworks.vr.composer@1.0",
-    "android.hardware.graphics.composer@2.1",
-    "libbase",
-    "libcutils",
-    "libfmq",
-    "libhardware",
-    "libhidlbase",
-    "libhidltransport",
-    "liblog",
-    "libsync",
-    "libui",
-    "libutils",
-  ],
-
-  export_static_lib_headers: [
-    "libhwcomposer-client",
-  ],
-
-  export_shared_lib_headers: [
-    "android.hardware.graphics.composer@2.1",
-  ],
-
-  export_include_dirs: ["."],
-
-  cflags: [
-    "-DLOG_TAG=\"vrhwc\"",
-  ],
-}
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp b/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp
deleted file mode 100644
index 299e8f1..0000000
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "vr_composer_view.h"
-
-namespace android {
-namespace dvr {
-
-VrComposerView::VrComposerView(
-    std::unique_ptr<VrComposerView::Callback> callback)
-    : composer_view_(nullptr), callback_(std::move(callback)) {}
-
-VrComposerView::~VrComposerView() {
-  composer_view_->UnregisterObserver(this);
-}
-
-void VrComposerView::Initialize(ComposerView* composer_view) {
-  composer_view_ = composer_view;
-  composer_view_->RegisterObserver(this);
-}
-
-base::unique_fd VrComposerView::OnNewFrame(const ComposerView::Frame& frame) {
-  std::lock_guard<std::mutex> guard(mutex_);
-  if (!callback_.get())
-    return base::unique_fd();
-
-  return callback_->OnNewFrame(frame);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_view.h b/services/vr/vr_window_manager/composer/impl/vr_composer_view.h
deleted file mode 100644
index 8c5ee1f..0000000
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_view.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_VIEW_H_
-#define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_VIEW_H_
-
-#include <memory>
-
-#include "vr_hwc.h"
-
-namespace android {
-namespace dvr {
-
-class VrComposerView : public ComposerView::Observer {
- public:
-  class Callback {
-   public:
-    virtual ~Callback() = default;
-    virtual base::unique_fd OnNewFrame(const ComposerView::Frame& frame) = 0;
-  };
-
-  VrComposerView(std::unique_ptr<Callback> callback);
-  ~VrComposerView() override;
-
-  void Initialize(ComposerView* composer_view);
-
-  // ComposerView::Observer
-  base::unique_fd OnNewFrame(const ComposerView::Frame& frame) override;
-
- private:
-  ComposerView* composer_view_;
-  std::unique_ptr<Callback> callback_;
-  std::mutex mutex_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_VIEW_H_
diff --git a/services/vr/vr_window_manager/composer_view/Android.bp_disable b/services/vr/vr_window_manager/composer_view/Android.bp_disable
deleted file mode 100644
index 1658154..0000000
--- a/services/vr/vr_window_manager/composer_view/Android.bp_disable
+++ /dev/null
@@ -1,29 +0,0 @@
-cc_binary {
-  name: "vr_composer_view",
-
-  srcs: ["vr_composer_view.cpp"],
-
-  static_libs: [
-    "libhwcomposer-client",
-  ],
-
-  shared_libs: [
-    "android.dvr.composer@1.0",
-    "android.hardware.graphics.composer@2.1",
-    "libbase",
-    "libbinder",
-    "libhardware",
-    "libhwbinder",
-    "liblog",
-    "libutils",
-    "libvrhwc",
-  ],
-
-  cflags: [
-    "-DLOG_TAG=\"vr_composer_view\"",
-  ],
-
-  init_rc: [
-    "vr_composer_view.rc",
-  ],
-}
diff --git a/services/vr/vr_window_manager/composer_view/vr_composer_view.cpp b/services/vr/vr_window_manager/composer_view/vr_composer_view.cpp
deleted file mode 100644
index 54dff3d..0000000
--- a/services/vr/vr_window_manager/composer_view/vr_composer_view.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <binder/ProcessState.h>
-#include <hwbinder/IPCThreadState.h>
-#include <impl/vr_composer_view.h>
-#include <impl/vr_hwc.h>
-
-using namespace android;
-using namespace android::dvr;
-
-int main(int, char**) {
-  android::ProcessState::self()->startThreadPool();
-
-  const char instance[] = "vr_hwcomposer";
-  sp<IComposer> service = HIDL_FETCH_IComposer(instance);
-  LOG_ALWAYS_FATAL_IF(!service.get(), "Failed to get service");
-  LOG_ALWAYS_FATAL_IF(service->isRemote(), "Service is remote");
-
-  LOG_ALWAYS_FATAL_IF(service->registerAsService(instance) != ::android::OK,
-                      "Failed to register service");
-
-  sp<IVrComposerView> composer_view = HIDL_FETCH_IVrComposerView(
-      "DaydreamDisplay");
-  LOG_ALWAYS_FATAL_IF(!composer_view.get(),
-                      "Failed to get vr_composer_view service");
-  LOG_ALWAYS_FATAL_IF(composer_view->isRemote(),
-                      "vr_composer_view service is remote");
-
-  composer_view->registerAsService("DaydreamDisplay");
-
-  GetVrComposerViewFromIVrComposerView(composer_view.get())->Initialize(
-      GetComposerViewFromIComposer(service.get()));
-
-  android::hardware::ProcessState::self()->startThreadPool();
-  android::hardware::IPCThreadState::self()->joinThreadPool();
-
-  return 0;
-}
diff --git a/services/vr/vr_window_manager/composer_view/vr_composer_view.rc b/services/vr/vr_window_manager/composer_view/vr_composer_view.rc
deleted file mode 100644
index bd9982b..0000000
--- a/services/vr/vr_window_manager/composer_view/vr_composer_view.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-service vr_composer_view /system/bin/vr_composer_view
-  class core
-  user system
-  group system graphics
-  writepid /dev/cpuset/system/tasks
diff --git a/services/vr/vr_window_manager/hwc_callback.cpp b/services/vr/vr_window_manager/hwc_callback.cpp
index 43f5042..28e97ff 100644
--- a/services/vr/vr_window_manager/hwc_callback.cpp
+++ b/services/vr/vr_window_manager/hwc_callback.cpp
@@ -32,6 +32,15 @@
 
 }  // 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) {
 }
 
@@ -54,6 +63,11 @@
       .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,
     };
   }
 
diff --git a/services/vr/vr_window_manager/hwc_callback.h b/services/vr/vr_window_manager/hwc_callback.h
index f1f91a1..259c4ac 100644
--- a/services/vr/vr_window_manager/hwc_callback.h
+++ b/services/vr/vr_window_manager/hwc_callback.h
@@ -3,15 +3,13 @@
 
 #include <android/dvr/BnVrComposerCallback.h>
 #include <android-base/unique_fd.h>
+#include <impl/vr_hwc.h>
 
 #include <deque>
 #include <functional>
 #include <mutex>
 #include <vector>
 
-#include "impl/vr_composer_view.h"
-#include "impl/vr_hwc.h"
-
 namespace android {
 
 class Fence;
@@ -65,6 +63,8 @@
       }
     }
 
+    void PrintLayer();
+
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     Rectf crop;
@@ -73,6 +73,11 @@
     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 {
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
index aef23a1..b41de03 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ b/services/vr/vr_window_manager/surface_flinger_view.cpp
@@ -2,7 +2,6 @@
 
 #include <android/dvr/IVrComposer.h>
 #include <binder/IServiceManager.h>
-#include <impl/vr_composer_view.h>
 #include <private/dvr/native_buffer.h>
 
 #include "hwc_callback.h"
diff --git a/services/vr/vr_window_manager/vr_window_manager.cpp b/services/vr/vr_window_manager/vr_window_manager.cpp
index 9d7afe3..dd2cba7 100644
--- a/services/vr/vr_window_manager/vr_window_manager.cpp
+++ b/services/vr/vr_window_manager/vr_window_manager.cpp
@@ -2,7 +2,6 @@
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <hwbinder/IPCThreadState.h>
-#include <impl/vr_composer_view.h>
 #include <impl/vr_hwc.h>
 
 #include "shell_view.h"
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 3fd8c51..91c270e 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -26,6 +26,7 @@
 cc_library_headers {
     name: "vulkan_headers",
     export_include_dirs: ["include"],
+    vendor_available: true,
 }
 
 subdirs = [
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 9444da5..6149894 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -14,7 +14,7 @@
 
 // Headers module is in frameworks/native/vulkan/Android.bp.
 ndk_library {
-    name: "libvulkan.ndk",
+    name: "libvulkan",
     symbol_file: "libvulkan.map.txt",
     first_version: "24",
     unversioned_until: "current",
@@ -78,6 +78,7 @@
         "libutils",
         "libcutils",
         "libz",
+        "libnativewindow",
     ],
     static_libs: ["libgrallocusage"],
 }
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 5fbf5f5..f2cd8e6 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -34,6 +34,11 @@
 #include "driver.h"
 #include "stubhal.h"
 
+// TODO(b/37049319) Get this from a header once one exists
+extern "C" {
+android_namespace_t* android_get_exported_namespace(const char*);
+}
+
 // Set to true to enable exposing unratified extensions for development
 static const bool kEnableUnratifiedExtensions = false;
 
@@ -150,14 +155,12 @@
     "ro.board.platform",
 }};
 
-int LoadUpdatedDriver(const hw_module_t** module) {
+int LoadDriver(android_namespace_t* library_namespace,
+               const hwvulkan_module_t** module) {
     const android_dlextinfo dlextinfo = {
         .flags = ANDROID_DLEXT_USE_NAMESPACE,
-        .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
+        .library_namespace = library_namespace,
     };
-    if (!dlextinfo.library_namespace)
-        return -ENOENT;
-
     void* so = nullptr;
     char prop[PROPERTY_VALUE_MAX];
     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
@@ -171,7 +174,7 @@
     if (!so)
         return -ENOENT;
 
-    hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
+    auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
     if (!hmi) {
         ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
         dlclose(so);
@@ -183,11 +186,24 @@
         return -EINVAL;
     }
     hmi->dso = so;
-    *module = hmi;
-    ALOGD("loaded updated driver");
+    *module = reinterpret_cast<const hwvulkan_module_t*>(hmi);
     return 0;
 }
 
+int LoadBuiltinDriver(const hwvulkan_module_t** module) {
+    auto ns = android_get_exported_namespace("sphal");
+    if (!ns)
+        return -ENOENT;
+    return LoadDriver(ns, module);
+}
+
+int LoadUpdatedDriver(const hwvulkan_module_t** module) {
+    auto ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+    if (!ns)
+        return -ENOENT;
+    return LoadDriver(ns, module);
+}
+
 bool Hal::Open() {
     ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
 
@@ -197,9 +213,21 @@
     int result;
     const hwvulkan_module_t* module = nullptr;
 
-    result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
+    result = LoadUpdatedDriver(&module);
     if (result == -ENOENT) {
-        result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
+        result = LoadBuiltinDriver(&module);
+        if (result != 0) {
+            // -ENOENT means the sphal namespace doesn't exist, not that there
+            // is a problem with the driver.
+            ALOGW_IF(
+                result != -ENOENT,
+                "Failed to load Vulkan driver into sphal namespace. This "
+                "usually means the driver has forbidden library dependencies."
+                "Please fix, this will soon stop working.");
+            result =
+                hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
+                              reinterpret_cast<const hw_module_t**>(&module));
+        }
     }
     if (result != 0) {
         ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
@@ -789,9 +817,6 @@
     loader_extensions.push_back({
         VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
-    loader_extensions.push_back({
-        VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
-        VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
 
     if (kEnableUnratifiedExtensions) {
         // conditionally add shared_presentable_image if supportable
@@ -804,6 +829,16 @@
         }
     }
 
+    // conditionally add VK_GOOGLE_display_timing if present timestamps are
+    // supported by the driver:
+    char timestamp_property[PROPERTY_VALUE_MAX];
+    property_get("service.sf.present_timestamp", timestamp_property, "1");
+    if (strcmp(timestamp_property, "1") == 0) {
+        loader_extensions.push_back({
+                VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
+                VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
+    }
+
     // enumerate our extensions first
     if (!pLayerName && pProperties) {
         uint32_t count = std::min(
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3b785e6..caa2674 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -114,14 +114,34 @@
         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
           native_frame_id_(nativeFrameId) {}
     bool ready() const {
-        return (timestamp_desired_present_time_ &&
-                timestamp_actual_present_time_ &&
-                timestamp_render_complete_time_ &&
-                timestamp_composition_latch_time_);
+        return (timestamp_desired_present_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_actual_present_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_render_complete_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_composition_latch_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING);
     }
-    void calculate(uint64_t rdur) {
-        vals_.actualPresentTime = timestamp_actual_present_time_;
-        uint64_t margin = (timestamp_composition_latch_time_ -
+    void calculate(int64_t rdur) {
+        bool anyTimestampInvalid =
+                (timestamp_actual_present_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+                (timestamp_render_complete_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+                (timestamp_composition_latch_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID);
+        if (anyTimestampInvalid) {
+            ALOGE("Unexpectedly received invalid timestamp.");
+            vals_.actualPresentTime = 0;
+            vals_.earliestPresentTime = 0;
+            vals_.presentMargin = 0;
+            return;
+        }
+
+        vals_.actualPresentTime =
+                static_cast<uint64_t>(timestamp_actual_present_time_);
+        int64_t margin = (timestamp_composition_latch_time_ -
                            timestamp_render_complete_time_);
         // Calculate vals_.earliestPresentTime, and potentially adjust
         // vals_.presentMargin.  The initial value of vals_.earliestPresentTime
@@ -132,14 +152,14 @@
         // it did (per the extension specification).  If for some reason, we
         // can do this subtraction repeatedly, we do, since
         // vals_.earliestPresentTime really is supposed to be the "earliest".
-        uint64_t early_time = vals_.actualPresentTime;
+        int64_t early_time = timestamp_actual_present_time_;
         while ((margin > rdur) &&
                ((early_time - rdur) > timestamp_composition_latch_time_)) {
             early_time -= rdur;
             margin -= rdur;
         }
-        vals_.earliestPresentTime = early_time;
-        vals_.presentMargin = margin;
+        vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
+        vals_.presentMargin = static_cast<uint64_t>(margin);
     }
     void get_values(VkPastPresentationTimingGOOGLE* values) const {
         *values = vals_;
@@ -149,10 +169,11 @@
     VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
 
     uint64_t native_frame_id_ { 0 };
-    uint64_t timestamp_desired_present_time_ { 0 };
-    uint64_t timestamp_actual_present_time_ { 0 };
-    uint64_t timestamp_render_complete_time_ { 0 };
-    uint64_t timestamp_composition_latch_time_ { 0 };
+    int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_composition_latch_time_
+            { NATIVE_WINDOW_TIMESTAMP_PENDING };
 };
 
 // ----------------------------------------------------------------------------
@@ -187,18 +208,16 @@
           shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
                  present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
         ANativeWindow* window = surface.window.get();
-        int64_t rdur;
         native_window_get_refresh_cycle_duration(
             window,
-            &rdur);
-        refresh_duration = static_cast<uint64_t>(rdur);
+            &refresh_duration);
     }
 
     Surface& surface;
     uint32_t num_images;
     bool mailbox_mode;
     bool frame_timestamps_enabled;
-    uint64_t refresh_duration;
+    int64_t refresh_duration;
     bool shared;
 
     struct Image {
@@ -327,14 +346,10 @@
 
         // Record the timestamp(s) we received, and then see if this TimingInfo
         // is ready to be reported to the user:
-        ti.timestamp_desired_present_time_ =
-            static_cast<uint64_t>(desired_present_time);
-        ti.timestamp_actual_present_time_ =
-            static_cast<uint64_t>(actual_present_time);
-        ti.timestamp_render_complete_time_ =
-            static_cast<uint64_t>(render_complete_time);
-        ti.timestamp_composition_latch_time_ =
-               static_cast<uint64_t>(composition_latch_time);
+        ti.timestamp_desired_present_time_ = desired_present_time;
+        ti.timestamp_actual_present_time_ = actual_present_time;
+        ti.timestamp_render_complete_time_ = render_complete_time;
+        ti.timestamp_composition_latch_time_ = composition_latch_time;
 
         if (ti.ready()) {
             // The TimingInfo has received enough timestamps, and should now
@@ -1494,7 +1509,8 @@
     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
     VkResult result = VK_SUCCESS;
 
-    pDisplayTimingProperties->refreshDuration = swapchain.refresh_duration;
+    pDisplayTimingProperties->refreshDuration =
+            static_cast<uint64_t>(swapchain.refresh_duration);
 
     return result;
 }