Merge "Sensor: Limit delay to maximum possible value before sending to HAL" into oc-dev
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index 6c5869a..4f1065f 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -16,6 +16,9 @@
         "libz",
         "libbase",
     ],
+    static_libs: [
+        "libpdx_default_transport",
+    ],
 
     init_rc: ["atrace.rc"],
 
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 6cfbed9..f8e0ad5 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -41,6 +41,7 @@
 #include <hidl/ServiceManagement.h>
 #include <cutils/properties.h>
 
+#include <pdx/default_transport/service_utility.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/Tokenizer.h>
@@ -48,6 +49,7 @@
 #include <android-base/file.h>
 
 using namespace android;
+using pdx::default_transport::ServiceUtility;
 
 using std::string;
 #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
@@ -814,6 +816,7 @@
     ok &= setAppCmdlineProperty(&packageList[0]);
     ok &= pokeBinderServices();
     pokeHalServices();
+    ok &= ServiceUtility::PokeServices();
 
     // Disable all the sysfs enables.  This is done as a separate loop from
     // the enables to allow the same enable to exist in multiple categories.
@@ -851,6 +854,7 @@
     setTagsProperty(0);
     clearAppProperties();
     pokeBinderServices();
+    ServiceUtility::PokeServices();
 
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
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/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 989fcda..70acb07 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1122,65 +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;
+            }
         }
     }
 
-#if HACK_FOR_37193650
-    extStats->dataSize = extStats->dataSize;
-#else
-    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;
+            }
         }
-    }
-#endif
 
-    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;
+            }
         }
     }
 }
@@ -1256,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);
@@ -1357,25 +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();
-
-#if HACK_FOR_37193650
-        ATRACE_BEGIN("external");
-        for (size_t i = 0; i < packageNames.size(); i++) {
-            const char* pkgname = packageNames[i].c_str();
-            auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
-            calculate_tree_size(extPath, &extStats.dataSize);
-            auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
-            calculate_tree_size(mediaPath, &extStats.dataSize);
-        }
-        ATRACE_END();
-#endif
     } else {
         ATRACE_BEGIN("code");
         for (auto codePath : codePaths) {
@@ -1414,7 +1419,7 @@
 
         if (!uuid) {
             ATRACE_BEGIN("dalvik");
-            int32_t sharedGid = multiuser_get_shared_gid(userId, appId);
+            int32_t sharedGid = multiuser_get_shared_gid(0, appId);
             if (sharedGid != -1) {
                 calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
                         sharedGid, -1);
@@ -1464,12 +1469,6 @@
         flags &= ~FLAG_USE_QUOTA;
     }
 
-#if HACK_FOR_37193650
-    if (userId != 0) {
-        flags &= ~FLAG_USE_QUOTA;
-    }
-#endif
-
     if (flags & FLAG_USE_QUOTA) {
         struct dqblk dq;
 
@@ -1532,6 +1531,7 @@
         }
 
         ATRACE_BEGIN("quota");
+        int64_t dataSize = extStats.dataSize;
         for (auto appId : appIds) {
             if (appId >= AID_APP_START) {
                 collectQuotaStats(device, userId, appId, &stats, &extStats);
@@ -1542,6 +1542,7 @@
 #endif
             }
         }
+        extStats.dataSize = dataSize;
         ATRACE_END();
     } else {
         ATRACE_BEGIN("obb");
@@ -1601,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
@@ -1620,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()) {
@@ -1629,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) {
@@ -1637,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;
         }
@@ -1646,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;
         }
@@ -1654,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;
         }
@@ -1662,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);
@@ -1700,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;
@@ -1712,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/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index ae4c797..ff838ce 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -313,8 +313,7 @@
                                         + 1   // filter
                                         + 1   // volume
                                         + 1   // libs
-                                        + 1   // seinfo
-                                        + 1;  // null
+                                        + 1;  // seinfo
             if (argc == kV2ArgCount) {
                 return ReadArgumentsV2(argc, argv, false);
             } else {
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 5db547e..dd94da9 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -32,7 +32,6 @@
 
 #define MEASURE_DEBUG 0
 #define FIXUP_DEBUG 0
-#define HACK_FOR_37193650 1
 
 namespace android {
 namespace installd {
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/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 c4cbfc4..fe99de1 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -49,7 +49,7 @@
     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);
 
@@ -65,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;
     };
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 49552dc..cddb1fd 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -503,7 +503,7 @@
     if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
         BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
         sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
-                width, height, format, BQ_LAYER_COUNT, usage, usage,
+                width, height, format, BQ_LAYER_COUNT, usage,
                 {mConsumerName.string(), mConsumerName.size()});
 
         status_t error = graphicBuffer->initCheck();
@@ -1342,7 +1342,7 @@
         for (size_t i = 0; i <  newBufferCount; ++i) {
             sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
                     allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
-                    allocUsage, allocUsage, {mConsumerName.string(), mConsumerName.size()});
+                    allocUsage, {mConsumerName.string(), mConsumerName.size()});
 
             status_t result = graphicBuffer->initCheck();
 
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 35b76c7..e2647be 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -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();
@@ -358,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;
@@ -372,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/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 02838d4..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
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index b0cb012..ee85c9b 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -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()
@@ -129,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;
@@ -148,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;
@@ -163,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;
@@ -184,16 +184,14 @@
 
 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)
 {
     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;
 
@@ -203,7 +201,7 @@
         buffer_handle_t importedHandle;
         status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
         if (err != NO_ERROR) {
-            initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0, 0);
+            initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
 
             return err;
         }
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 9beed0e..eaba1ed 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -64,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;
@@ -95,8 +93,8 @@
 }
 
 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,
+        PixelFormat format, uint32_t layerCount, uint64_t usage,
+        buffer_handle_t* handle, uint32_t* stride,
         uint64_t /*graphicBufferId*/, std::string requestorName)
 {
     ATRACE_CALL();
@@ -115,8 +113,7 @@
     info.height = height;
     info.layerCount = layerCount;
     info.format = static_cast<Gralloc2::PixelFormat>(format);
-    info.usage = static_cast<uint64_t>(android_convertGralloc1To0Usage(
-                producerUsage, consumerUsage));
+    info.usage = usage;
 
     Gralloc2::Error error = mAllocator->allocate(info, stride, handle);
     if (error == Gralloc2::Error::NONE) {
@@ -129,14 +126,17 @@
         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;
     } else {
+        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
+                "usage %" PRIx64 ": %d",
+                width, height, layerCount, format, usage,
+                error);
         return NO_MEMORY;
     }
 }
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/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index df9ae81..0a6996e 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -2,6 +2,7 @@
 
 #include <log/log.h>
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <grallocusage/GrallocUsageConversion.h>
 #include <utils/Trace.h>
 
 #include <mutex>
@@ -99,9 +100,10 @@
       " consumer_usage=%" PRIx64,
       width, height, format, producer_usage, consumer_usage);
 
-  sp<GraphicBuffer> buffer =
-      new GraphicBuffer(width, height, format, kDefaultGraphicBufferLayerCount,
-                        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;
@@ -144,9 +146,12 @@
       "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
       handle, width, height, stride, format, producer_usage, consumer_usage);
   FreeHandle();
-  sp<GraphicBuffer> buffer = new GraphicBuffer(
-      handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
-      kDefaultGraphicBufferLayerCount, producer_usage, consumer_usage, stride);
+  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;
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/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/libeds/Android.bp b/libs/vr/libeds/Android.bp
index 85e43cc..a149853 100644
--- a/libs/vr/libeds/Android.bp
+++ b/libs/vr/libeds/Android.bp
@@ -19,7 +19,6 @@
     "display_metrics.cpp",
     "distortion_renderer.cpp",
     "device_metrics.cpp",
-    "lookup_radial_distortion.cpp",
     "polynomial_radial_distortion.cpp",
 ]
 
diff --git a/libs/vr/libeds/device_metrics.cpp b/libs/vr/libeds/device_metrics.cpp
index 50c3e54..68ee186 100644
--- a/libs/vr/libeds/device_metrics.cpp
+++ b/libs/vr/libeds/device_metrics.cpp
@@ -3,14 +3,12 @@
 #include <cutils/properties.h>
 #include <private/dvr/head_mount_metrics.h>
 #include <private/dvr/identity_distortion.h>
-#include <private/dvr/lookup_radial_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 kRGBPolynomialOffset[] = "persist.dvr.rgb_poly_offset";
 static constexpr char kRPolynomial[] = "persist.dvr.r_poly";
 static constexpr char kGPolynomial[] = "persist.dvr.g_poly";
 static constexpr char kBPolynomial[] = "persist.dvr.b_poly";
@@ -68,7 +66,9 @@
 
 float GetDisplayGap() { return GetProperty(kDisplayGap, 0.0f); }
 
-float GetVEyeToDisplay() { return GetProperty(kVEyeToDisplay, 0.035f); }
+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};
@@ -110,33 +110,23 @@
 HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov,
                                         const FieldOfView& r_fov) {
   static const std::vector<float> default_r = {
-      -4.08519004f,  34.70282075f, -67.37781249f, 56.97304235f,
-      -23.35768685f, 4.7199597f,   0.63198082f};
+      0.00103f, 2.63917f, -7.14427f, 8.98036f, -4.10586f, 0.83705f, 0.00130f};
   static const std::vector<float> default_g = {
-      4.43078318f, 3.47806617f, -20.58017398f, 20.85880414f,
-      -8.4046504f, 1.61284685f, 0.8881761f};
+      0.08944f, 2.26005f, -6.30924f, 7.94561f, -3.22788f, 0.45577f, 0.07300f};
   static const std::vector<float> default_b = {
-      12.04141265f, -21.98112491f, 14.06758389f, -3.15245629f,
-      0.36549102f,  0.05252705f,   0.99844279f};
-  static const std::vector<float> default_offsets = {
-      0.20971645238f, 0.15189450000f, 1.00096958278f};
-
-  std::vector<float> poly_offsets =
-      GetProperty(kRGBPolynomialOffset, default_offsets);
+      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);
-  if (poly_offsets.size() != 3)
-    poly_offsets = default_offsets;
 
   std::shared_ptr<ColorChannelDistortion> distortion_r(
-      new PolynomialRadialDistortion(poly_offsets[0], poly_r));
+      new PolynomialRadialDistortion(poly_r));
   std::shared_ptr<ColorChannelDistortion> distortion_g(
-      new PolynomialRadialDistortion(poly_offsets[1], poly_g));
+      new PolynomialRadialDistortion(poly_g));
   std::shared_ptr<ColorChannelDistortion> distortion_b(
-      new PolynomialRadialDistortion(poly_offsets[2], poly_b));
+      new PolynomialRadialDistortion(poly_b));
 
-  return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(),
+  return HeadMountMetrics(GetInterLensDistance(), GetTrayToLensDistance(),
                           GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
                           r_fov, distortion_r, distortion_g, distortion_b,
                           HeadMountMetrics::EyeOrientation::kCCW0Degrees,
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/polynomial_radial_distortion.h b/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h
index c1f1ce9..8f080aa 100644
--- a/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h
+++ b/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h
@@ -28,8 +28,7 @@
   // in the distortion equation: coefficients[0] is K1, coefficients[1] is K2,
   // etc.  Thus the polynomial used for distortion has degree
   // (2 * coefficients.size()).
-  explicit PolynomialRadialDistortion(float polynomial_offset,
-                                      const std::vector<float>& coefficients);
+  explicit PolynomialRadialDistortion(const std::vector<float>& coefficients);
 
   // Given a radius (measuring distance from the optical axis of the lens),
   // returns the distortion factor for that radius.
@@ -52,10 +51,6 @@
   const std::vector<float>& GetCoefficients() const;
 
  private:
-  // This is makes the polynomial work nicer with a specific lens that doesn't
-  // fit nicely to a lower order polynomial.  It's basically piecewise
-  // line->poly.
-  float polynomial_offset_;
   std::vector<float> coefficients_;
 };
 
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/polynomial_radial_distortion.cpp b/libs/vr/libeds/polynomial_radial_distortion.cpp
index a0c6ea3..fa01bb4 100644
--- a/libs/vr/libeds/polynomial_radial_distortion.cpp
+++ b/libs/vr/libeds/polynomial_radial_distortion.cpp
@@ -4,13 +4,10 @@
 namespace dvr {
 
 PolynomialRadialDistortion::PolynomialRadialDistortion(
-    float polynomial_offset, const std::vector<float>& coefficients)
-    : polynomial_offset_(polynomial_offset), coefficients_(coefficients) {}
+    const std::vector<float>& coefficients)
+    : coefficients_(coefficients) {}
 
 float PolynomialRadialDistortion::DistortionFactor(float r_squared) const {
-  if (r_squared < polynomial_offset_)
-    return 1.0f;
-
   float r_factor = 1.0f;
   float distortion_factor = 1.0f;
 
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/private/pdx/default_transport/service_utility.h b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
index 22c6b3f..81bb17b 100644
--- a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
+++ b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
@@ -1,6 +1,8 @@
 #ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
 #define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_
 
+#include <ftw.h>
+
 #include <pdx/client.h>
 #include <pdx/default_transport/client_channel_factory.h>
 #include <pdx/service.h>
@@ -25,15 +27,59 @@
     return ClientChannelFactory::GetEndpointPath(endpoint_path);
   }
 
+  // Traverses the PDX service path space and sends a message to reload system
+  // properties to each service endpoint it finds along the way.
+  // NOTE: This method is used by atrace to poke PDX services. Please avoid
+  // unnecessary changes to this mechanism to minimize impact on atrace.
+  static bool PokeServices() {
+    const int kMaxDepth = 16;
+    const int result =
+        nftw(GetRootEndpointPath().c_str(), PokeService, kMaxDepth, FTW_PHYS);
+    return result == 0 ? true : false;
+  }
+
  private:
   friend BASE;
 
   ServiceUtility(const std::string& endpoint_path, int* error = nullptr)
-      : BASE(ClientChannelFactory::Create(endpoint_path)) {
+      : BASE(ClientChannelFactory::Create(endpoint_path), 0) {
     if (error)
       *error = Client::error();
   }
 
+  // Sends the sysprop_change message to the service at fpath, so it re-reads
+  // its system properties. Returns 0 on success or a negated errno code on
+  // failure.
+  // NOTE: This method is used by atrace to poke PDX services. Please avoid
+  // unnecessary changes to this mechanism to minimize impact on atrace.
+  static int PokeService(const char* fpath, const struct stat* /*sb*/,
+                         int typeflag, struct FTW* /*ftwbuf*/) {
+    const bool kIgnoreErrors = true;
+
+    if (typeflag == FTW_F) {
+      int error;
+      auto utility = ServiceUtility::Create(fpath, &error);
+      if (!utility) {
+        if (error != -ECONNREFUSED) {
+          ALOGE("ServiceUtility::PokeService: Failed to open %s: %s.", fpath,
+                strerror(-error));
+        }
+        return kIgnoreErrors ? 0 : error;
+      }
+
+      auto status = utility->ReloadSystemProperties();
+      if (!status) {
+        ALOGE(
+            "ServiceUtility::PokeService: Failed to send sysprop change to %s: "
+            "%s",
+            fpath, status.GetErrorMessage().c_str());
+        return kIgnoreErrors ? 0 : -status.error();
+      }
+    }
+
+    return 0;
+  }
+
   ServiceUtility(const ServiceUtility&) = delete;
   void operator=(const ServiceUtility&) = delete;
 };
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index f2bcc0c..cfc2022 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -35,6 +35,7 @@
         "-Werror",
     ],
     srcs: [
+        "client_channel_tests.cpp",
         "ipc_helper_tests.cpp",
         "remote_method_tests.cpp",
         "service_framework_tests.cpp",
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 9202cd5..850c6d3 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -39,32 +39,42 @@
 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;
@@ -74,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)
@@ -81,7 +95,7 @@
 
     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));
@@ -107,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;
@@ -129,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 b675894..d75ce86 100644
--- a/libs/vr/libpdx_uds/ipc_helper.cpp
+++ b/libs/vr/libpdx_uds/ipc_helper.cpp
@@ -275,6 +275,7 @@
     return ret;
 
   if (preamble.magic != kMagicPreamble) {
+    ALOGE("ReceivePayload::Receive: Message header is invalid");
     ret.SetError(EIO);
     return ret;
   }
@@ -319,8 +320,10 @@
     cmsg = CMSG_NXTHDR(&msg, cmsg);
   }
 
-  if (cred && !cred_available)
+  if (cred && !cred_available) {
+    ALOGE("ReceivePayload::Receive: Failed to obtain message credentials");
     ret.SetError(EIO);
+  }
 
   return ret;
 }
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/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/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 07e4a8b..d1d4f45 100644
--- a/libs/vr/libvrflinger/compositor.cpp
+++ b/libs/vr/libvrflinger/compositor.cpp
@@ -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;
@@ -429,6 +431,7 @@
 }
 
 void Compositor::Shutdown() {
+  glFinish();
   render_target_[0].Destroy();
   render_target_[1].Destroy();
   layers_.clear();
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 971345b..d3d50d0 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -209,16 +209,16 @@
   // We should always have a red distortion.
   LOG_FATAL_IF(view_params.distortion_coefficients_r.empty());
   red_distortion = std::make_shared<PolynomialRadialDistortion>(
-      0.0f, view_params.distortion_coefficients_r);
+      view_params.distortion_coefficients_r);
 
   if (!view_params.distortion_coefficients_g.empty()) {
     green_distortion = std::make_shared<PolynomialRadialDistortion>(
-        0.0f, view_params.distortion_coefficients_g);
+        view_params.distortion_coefficients_g);
   }
 
   if (!view_params.distortion_coefficients_b.empty()) {
     blue_distortion = std::make_shared<PolynomialRadialDistortion>(
-        0.0f, view_params.distortion_coefficients_b);
+        view_params.distortion_coefficients_b);
   }
 
   HeadMountMetrics::EyeOrientation left_orientation =
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 6602d78..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.
diff --git a/opengl/tests/gl2_basic/gl2_basic.cpp b/opengl/tests/gl2_basic/gl2_basic.cpp
index cdbf1cf..9f8d166 100644
--- a/opengl/tests/gl2_basic/gl2_basic.cpp
+++ b/opengl/tests/gl2_basic/gl2_basic.cpp
@@ -44,6 +44,11 @@
     fprintf(stderr, "GL %s = %s\n", name, v);
 }
 
+static void printEGLString(EGLDisplay dpy, const char *name, GLenum s) {
+    const char *v = (const char *) eglQueryString(dpy, s);
+    fprintf(stderr, "GL %s = %s\n", name, v);
+}
+
 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
     if (returnVal != EGL_TRUE) {
         fprintf(stderr, "%s() returned %d\n", op, returnVal);
@@ -341,6 +346,7 @@
     printGLString("Vendor", GL_VENDOR);
     printGLString("Renderer", GL_RENDERER);
     printGLString("Extensions", GL_EXTENSIONS);
+    printEGLString(dpy, "EGL Extensions", EGL_EXTENSIONS);
 
     if(!setupGraphics(w, h)) {
         fprintf(stderr, "Could not set up graphics.\n");
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/hidl/EventQueue.cpp b/services/sensorservice/hidl/EventQueue.cpp
index c0365e5..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,7 +36,11 @@
 
         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);
@@ -47,7 +52,7 @@
     }
 
 private:
-    sp<EventQueue> mQueue;
+    wp<::android::SensorEventQueue> mQueue;
     sp<IEventQueueCallback> mCallback;
 };
 
@@ -58,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/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d044f37..0e7c214 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -287,6 +287,14 @@
 // the layer has been remove from the current state list (and just before
 // it's removed from the drawing state list)
 void Layer::onRemoved() {
+    if (mCurrentState.zOrderRelativeOf != nullptr) {
+        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+        if (strongRelative != nullptr) {
+            strongRelative->removeZOrderRelative(this);
+        }
+        mCurrentState.zOrderRelativeOf = nullptr;
+    }
+
     mSurfaceFlingerConsumer->abandon();
     for (const auto& child : mCurrentChildren) {
         child->onRemoved();
@@ -2555,11 +2563,6 @@
         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);
         }
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 746d3d9..9cd1214 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2371,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.
@@ -2398,6 +2399,9 @@
         const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
         layer->useSurfaceDamage();
         invalidateLayerStack(layer->getLayerStack(), dirty);
+        if (!dirty.isEmpty()) {
+            newDataLatched = true;
+        }
     }
 
     mVisibleRegionsDirty |= visibleRegions;
@@ -2410,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()
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index 41b6225..1c0427d 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -5,6 +5,6 @@
     onrestart restart zygote
     writepid /dev/stune/foreground/tasks
     socket pdx/system/vr/display/client stream 0666 system graphics
-    socket pdx/system/vr/display/manager stream 0660 system graphics
+    socket pdx/system/vr/display/manager stream 0666 system graphics
     socket pdx/system/vr/display/screenshot stream 0660 system graphics
     socket pdx/system/vr/display/vsync stream 0666 system graphics
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 25bb30b..5cb201d 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -17,6 +17,7 @@
   shared_libs: [
     "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
+    "android.hardware.graphics.mapper@2.0",
     "libbase",
     "libcutils",
     "libfmq",
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index 29983a7..504b26f 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -46,7 +46,7 @@
    sp<GraphicBuffer> buffer = new GraphicBuffer(
       handle, GraphicBuffer::CLONE_HANDLE, metadata.width, metadata.height,
       static_cast<int32_t>(metadata.format), metadata.layerCount,
-      metadata.usage, metadata.usage, metadata.stride);
+      metadata.usage, metadata.stride);
    if (buffer->initCheck() != OK) {
      ALOGE("Failed to create graphic buffer");
      return nullptr;
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(