Merge "Support halt the trace when schd-dbg hit deadline" into oc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 5421a75..5dad511 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1062,13 +1062,9 @@
     RunCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
                CommandOptions::WithTimeout(20).Build());
 
-    DumpFile("INTERRUPTS (1)", "/proc/interrupts");
-
     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
                CommandOptions::WithTimeout(10).Build());
 
-    DumpFile("INTERRUPTS (2)", "/proc/interrupts");
-
     RunCommand("SYSTEM PROPERTIES", {"getprop"});
 
     RunCommand("VOLD DUMP", {"vdc", "dump"});
@@ -1152,6 +1148,13 @@
 
     RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
 
+    printf("========================================================\n");
+    printf("== Dropbox crashes\n");
+    printf("========================================================\n");
+
+    RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
+    RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
+
     // DumpModemLogs adds the modem logs if available to the bugreport.
     // Do this at the end to allow for sufficient time for the modem logs to be
     // collected.
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index cc4144a..f5dca47 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -836,7 +836,7 @@
                 continue;
             }
 
-            if (!should_dump_hal_interface(info.interfaceName)) {
+            if (!should_dump_hal_interface(info.interfaceName.c_str())) {
                 continue;
             }
 
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 20b960d..e9a135c 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1729,7 +1729,8 @@
         const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
         int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
         const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
-        const std::unique_ptr<std::string>& sharedLibraries) {
+        const std::unique_ptr<std::string>& sharedLibraries,
+        const std::unique_ptr<std::string>& seInfo) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     if (packageName && *packageName != "*") {
@@ -1744,9 +1745,9 @@
     const char* compiler_filter = compilerFilter.c_str();
     const char* volume_uuid = uuid ? uuid->c_str() : nullptr;
     const char* shared_libraries = sharedLibraries ? sharedLibraries->c_str() : nullptr;
-
+    const char* se_info = seInfo ? seInfo->c_str() : nullptr;
     int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
-            oat_dir, dexFlags, compiler_filter, volume_uuid, shared_libraries);
+            oat_dir, dexFlags, compiler_filter, volume_uuid, shared_libraries, se_info);
     return res ? error(res, "Failed to dexopt") : ok();
 }
 
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index f5b7142..fe8aa14 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -82,7 +82,8 @@
             const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
             int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
             const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
-            const std::unique_ptr<std::string>& sharedLibraries);
+            const std::unique_ptr<std::string>& sharedLibraries,
+            const std::unique_ptr<std::string>& seInfo);
 
     binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
 
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 03ff96e..e738b81 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -50,7 +50,8 @@
             @utf8InCpp String instructionSet, int dexoptNeeded,
             @nullable @utf8InCpp String outputPath, int dexFlags,
             @utf8InCpp String compilerFilter, @nullable @utf8InCpp String uuid,
-            @nullable @utf8InCpp String sharedLibraries);
+            @nullable @utf8InCpp String sharedLibraries,
+            @nullable @utf8InCpp String seInfo);
 
     void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f7e8d13..63afdcd 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -36,6 +36,7 @@
 #include <cutils/sched_policy.h>
 #include <log/log.h>               // TODO: Move everything to base/logging.
 #include <private/android_filesystem_config.h>
+#include <selinux/android.h>
 #include <system/thread_defs.h>
 
 #include "dexopt.h"
@@ -1302,17 +1303,9 @@
     }
     std::string dex_dir = dex_path.substr(0, dirIndex);
 
-    // Assign the gid to the cache gid so that the oat file storage
-    // is counted towards the app cache.
-    int32_t cache_gid = multiuser_get_cache_gid(
-            multiuser_get_user_id(uid), multiuser_get_app_id(uid));
-    // If UID doesn't have a specific cache GID, use UID value
-    if (cache_gid == -1) {
-        cache_gid = uid;
-    }
-
     // Create oat file output directory.
-    if (prepare_app_cache_dir(dex_dir, "oat", 02711, uid, cache_gid) != 0) {
+    mode_t oat_dir_mode = S_IRWXU | S_IRWXG | S_IXOTH;
+    if (prepare_app_cache_dir(dex_dir, "oat", oat_dir_mode, uid, uid) != 0) {
         LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
         return false;
     }
@@ -1322,7 +1315,7 @@
     oat_dir_out->assign(oat_dir);
 
     // Create oat/isa output directory.
-    if (prepare_app_cache_dir(*oat_dir_out, instruction_set, 02711, uid, cache_gid) != 0) {
+    if (prepare_app_cache_dir(*oat_dir_out, instruction_set, oat_dir_mode, uid, uid) != 0) {
         LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
         return false;
     }
@@ -1366,12 +1359,15 @@
 // Processes the dex_path as a secondary dex files and return true if the path dex file should
 // be compiled. Returns false for errors (logged) or true if the secondary dex path was process
 // successfully.
-// When returning true, dexopt_needed_out is assigned a valid OatFileAsssitant::DexOptNeeded
-// code and oat_dir_out is assigned the oat dir path where the oat file should be stored.
+// When returning true, the output parameters will be:
+//   - is_public_out: whether or not the oat file should not be made public
+//   - dexopt_needed_out: valid OatFileAsssitant::DexOptNeeded
+//   - oat_dir_out: the oat dir path where the oat file should be stored
+//   - dex_path_out: the real path of the dex file
 static bool process_secondary_dex_dexopt(const char* original_dex_path, const char* pkgname,
         int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
-        const char* compiler_filter, int* dexopt_needed_out, std::string* oat_dir_out,
-        std::string* dex_path_out) {
+        const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
+        std::string* oat_dir_out, std::string* dex_path_out) {
     int storage_flag;
 
     if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
@@ -1407,7 +1403,8 @@
     }
 
     // Check if the path exist. If not, there's nothing to do.
-    if (access(dex_path.c_str(), F_OK) != 0) {
+    struct stat dex_path_stat;
+    if (stat(dex_path.c_str(), &dex_path_stat) != 0) {
         if (errno == ENOENT) {
             // Secondary dex files might be deleted any time by the app.
             // Nothing to do if that's the case
@@ -1418,6 +1415,11 @@
         }
     }
 
+    // Check if we should make the oat file public.
+    // Note that if the dex file is not public the compiled code cannot be made public.
+    *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) &&
+            ((dex_path_stat.st_mode & S_IROTH) != 0);
+
     // Prepare the oat directories.
     if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, oat_dir_out)) {
         return false;
@@ -1458,14 +1460,14 @@
 
 int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
-        const char* volume_uuid, const char* shared_libraries) {
+        const char* volume_uuid, const char* shared_libraries, const char* se_info) {
     CHECK(pkgname != nullptr);
     CHECK(pkgname[0] != 0);
     if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
         LOG_FATAL("dexopt flags contains unknown fields\n");
     }
 
-    bool is_public = ((dexopt_flags & DEXOPT_PUBLIC) != 0);
+    bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
     bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
     bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
     bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
@@ -1477,7 +1479,8 @@
     std::string dex_real_path;
     if (is_secondary_dex) {
         if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
-                instruction_set, compiler_filter, &dexopt_needed, &oat_dir_str, &dex_real_path)) {
+                instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
+                &dex_real_path)) {
             oat_dir = oat_dir_str.c_str();
             dex_path = dex_real_path.c_str();
             if (dexopt_needed == NO_DEXOPT_NEEDED) {
@@ -1516,6 +1519,19 @@
         return -1;
     }
 
+    // Ensure that the oat dir and the compiler artifacts of secondary dex files have the correct
+    // selinux context (we generate them on the fly during the dexopt invocation and they don't
+    // fully inherit their parent context).
+    // Note that for primary apk the oat files are created before, in a separate installd
+    // call which also does the restorecon. TODO(calin): unify the paths.
+    if (is_secondary_dex) {
+        if (selinux_android_restorecon_pkgdir(oat_dir, se_info, uid,
+                SELINUX_ANDROID_RESTORECON_RECURSE)) {
+            LOG(ERROR) << "Failed to restorecon " << oat_dir;
+            return -1;
+        }
+    }
+
     // Create a swap file if necessary.
     unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
 
@@ -1857,8 +1873,9 @@
                   atoi(params[6]),              // dexopt_flags
                   params[7],                    // compiler_filter
                   parse_null(params[8]),        // volume_uuid
-                  parse_null(params[9]));       // shared_libraries
-    static_assert(DEXOPT_PARAM_COUNT == 10U, "Unexpected dexopt param count");
+                  parse_null(params[9]),        // shared_libraries
+                  parse_null(params[10]));       // se_info
+    static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param count");
 }
 
 }  // namespace installd
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index dbf3fae..88144b7 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -60,10 +60,10 @@
 
 int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
-        const char* volume_uuid, const char* shared_libraries);
+        const char* volume_uuid, const char* shared_libraries, const char* se_info);
 
-static constexpr size_t DEXOPT_PARAM_COUNT = 10U;
-static_assert(DEXOPT_PARAM_COUNT == 10U, "Unexpected dexopt param size");
+static constexpr size_t DEXOPT_PARAM_COUNT = 11U;
+static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param size");
 
 // Helper for the above, converting arguments.
 int dexopt(const char* const params[DEXOPT_PARAM_COUNT]);
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 420ec3c..4c57361 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -301,7 +301,6 @@
                 if (!manifest.add(vintf::ManifestHal{
                     .format = vintf::HalFormat::HIDL,
                     .name = fqName.package(),
-                    .impl = {.implLevel = vintf::ImplLevel::GENERIC, .impl = ""},
                     .transportArch = {transport, arch}
                 })) {
                     mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 428b87c..09921e4 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -68,18 +68,12 @@
 
 int main(int argc, char* const argv[])
 {
-    sp<IServiceManager> sm = defaultServiceManager();
-    fflush(stdout);
-    if (sm == NULL) {
-        aerr << "service: Unable to get default service manager!" << endl;
-        return 20;
-    }
-    
     bool wantsUsage = false;
+    bool wantsVendorServices = false;
     int result = 0;
     
     while (1) {
-        int ic = getopt(argc, argv, "h?");
+        int ic = getopt(argc, argv, "vh?");
         if (ic < 0)
             break;
 
@@ -88,6 +82,9 @@
         case '?':
             wantsUsage = true;
             break;
+        case 'v':
+            wantsVendorServices = true;
+            break;
         default:
             aerr << "service: Unknown option -" << ic << endl;
             wantsUsage = true;
@@ -95,6 +92,16 @@
             break;
         }
     }
+
+    if (wantsVendorServices) {
+        ProcessState::initWithDriver("/dev/vndbinder");
+    }
+    sp<IServiceManager> sm = defaultServiceManager();
+    fflush(stdout);
+    if (sm == NULL) {
+        aerr << "service: Unable to get default service manager!" << endl;
+        return 20;
+    }
     
     if (optind >= argc) {
         wantsUsage = true;
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 45bb1d0..1f56a47 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -65,7 +65,11 @@
 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/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h
index cb9b373..9557b4f 100644
--- a/include/gui/DisplayEventReceiver.h
+++ b/include/gui/DisplayEventReceiver.h
@@ -32,9 +32,12 @@
 
 // ----------------------------------------------------------------------------
 
-class BitTube;
 class IDisplayEventConnection;
 
+namespace gui {
+class BitTube;
+} // namespace gui
+
 static inline constexpr uint32_t fourcc(char c1, char c2, char c3, char c4) {
     return static_cast<uint32_t>(c1) << 24 |
         static_cast<uint32_t>(c2) << 16 |
@@ -108,15 +111,13 @@
      * should be destroyed and getEvents() shouldn't be called again.
      */
     ssize_t getEvents(Event* events, size_t count);
-    static ssize_t getEvents(const sp<BitTube>& dataChannel,
-            Event* events, size_t count);
+    static ssize_t getEvents(gui::BitTube* dataChannel, Event* events, size_t count);
 
     /*
      * sendEvents write events to the queue and returns how many events were
      * written.
      */
-    static ssize_t sendEvents(const sp<BitTube>& dataChannel,
-            Event const* events, size_t count);
+    static ssize_t sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count);
 
     /*
      * setVsyncRate() sets the Event::VSync delivery rate. A value of
@@ -134,7 +135,7 @@
 
 private:
     sp<IDisplayEventConnection> mEventConnection;
-    sp<BitTube> mDataChannel;
+    std::unique_ptr<gui::BitTube> mDataChannel;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 51d7666..2cf6162 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -23,6 +23,7 @@
 #include <gui/BufferQueueDefs.h>
 #include <gui/ConsumerBase.h>
 
+#include <ui/FenceTime.h>
 #include <ui/GraphicBuffer.h>
 
 #include <utils/String8.h>
diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h
index a3c7d64..c082882 100644
--- a/include/gui/IConsumerListener.h
+++ b/include/gui/IConsumerListener.h
@@ -14,103 +14,84 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_GUI_ICONSUMERLISTENER_H
-#define ANDROID_GUI_ICONSUMERLISTENER_H
+#pragma once
 
-#include <stdint.h>
-#include <sys/types.h>
+#include <binder/IInterface.h>
+#include <binder/SafeInterface.h>
 
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
-#include <binder/IInterface.h>
-
-#include <gui/FrameTimestamps.h>
+#include <cstdint>
 
 namespace android {
-// ----------------------------------------------------------------------------
 
 class BufferItem;
+class FrameEventHistoryDelta;
+struct NewFrameEventsEntry;
 
-// ConsumerListener is the interface through which the BufferQueue notifies
-// the consumer of events that the consumer may wish to react to.  Because
-// the consumer will generally have a mutex that is locked during calls from
-// the consumer to the BufferQueue, these calls from the BufferQueue to the
+// ConsumerListener is the interface through which the BufferQueue notifies the consumer of events
+// that the consumer may wish to react to. Because the consumer will generally have a mutex that is
+// locked during calls from the consumer to the BufferQueue, these calls from the BufferQueue to the
 // consumer *MUST* be called only when the BufferQueue mutex is NOT locked.
 
 class ConsumerListener : public virtual RefBase {
 public:
-    ConsumerListener() { }
+    ConsumerListener() {}
     virtual ~ConsumerListener();
 
     // onDisconnect is called when a producer disconnects from the BufferQueue.
     virtual void onDisconnect() {} /* Asynchronous */
 
-    // onFrameAvailable is called from queueBuffer each time an additional
-    // frame becomes available for consumption. This means that frames that
-    // are queued while in asynchronous mode only trigger the callback if no
-    // previous frames are pending. Frames queued while in synchronous mode
-    // always trigger the callback. The item passed to the callback will contain
-    // all of the information about the queued frame except for its
-    // GraphicBuffer pointer, which will always be null (except if the consumer
-    // is SurfaceFlinger).
+    // onFrameAvailable is called from queueBuffer each time an additional frame becomes available
+    // for consumption. This means that frames that are queued while in asynchronous mode only
+    // trigger the callback if no previous frames are pending. Frames queued while in synchronous
+    // mode always trigger the callback. The item passed to the callback will contain all of the
+    // information about the queued frame except for its GraphicBuffer pointer, which will always be
+    // null (except if the consumer is SurfaceFlinger).
     //
-    // This is called without any lock held and can be called concurrently
-    // by multiple threads.
+    // This is called without any lock held and can be called concurrently by multiple threads.
     virtual void onFrameAvailable(const BufferItem& item) = 0; /* Asynchronous */
 
-    // onFrameReplaced is called from queueBuffer if the frame being queued is
-    // replacing an existing slot in the queue. Any call to queueBuffer that
-    // doesn't call onFrameAvailable will call this callback instead. The item
-    // passed to the callback will contain all of the information about the
-    // queued frame except for its GraphicBuffer pointer, which will always be
-    // null.
+    // onFrameReplaced is called from queueBuffer if the frame being queued is replacing an existing
+    // slot in the queue. Any call to queueBuffer that doesn't call onFrameAvailable will call this
+    // callback instead. The item passed to the callback will contain all of the information about
+    // the queued frame except for its GraphicBuffer pointer, which will always be null.
     //
-    // This is called without any lock held and can be called concurrently
-    // by multiple threads.
+    // This is called without any lock held and can be called concurrently by multiple threads.
     virtual void onFrameReplaced(const BufferItem& /* item */) {} /* Asynchronous */
 
-    // onBuffersReleased is called to notify the buffer consumer that the
-    // BufferQueue has released its references to one or more GraphicBuffers
-    // contained in its slots.  The buffer consumer should then call
-    // BufferQueue::getReleasedBuffers to retrieve the list of buffers
+    // onBuffersReleased is called to notify the buffer consumer that the BufferQueue has released
+    // its references to one or more GraphicBuffers contained in its slots. The buffer consumer
+    // should then call BufferQueue::getReleasedBuffers to retrieve the list of buffers.
     //
-    // This is called without any lock held and can be called concurrently
-    // by multiple threads.
+    // This is called without any lock held and can be called concurrently by multiple threads.
     virtual void onBuffersReleased() = 0; /* Asynchronous */
 
-    // onSidebandStreamChanged is called to notify the buffer consumer that the
-    // BufferQueue's sideband buffer stream has changed. This is called when a
-    // stream is first attached and when it is either detached or replaced by a
-    // different stream.
+    // onSidebandStreamChanged is called to notify the buffer consumer that the BufferQueue's
+    // sideband buffer stream has changed. This is called when a stream is first attached and when
+    // it is either detached or replaced by a different stream.
     virtual void onSidebandStreamChanged() = 0; /* Asynchronous */
 
-    // Notifies the consumer of any new producer-side timestamps and
-    // returns the combined frame history that hasn't already been retrieved.
-    virtual void addAndGetFrameTimestamps(
-            const NewFrameEventsEntry* /*newTimestamps*/,
-            FrameEventHistoryDelta* /*outDelta*/) {}
+    // Notifies the consumer of any new producer-side timestamps and returns the combined frame
+    // history that hasn't already been retrieved.
+    //
+    // WARNING: This method can only be called when the BufferQueue is in the consumer's process.
+    virtual void addAndGetFrameTimestamps(const NewFrameEventsEntry* /*newTimestamps*/,
+                                          FrameEventHistoryDelta* /*outDelta*/) {}
 };
 
-
-class IConsumerListener : public ConsumerListener, public IInterface
-{
+class IConsumerListener : public ConsumerListener, public IInterface {
 public:
     DECLARE_META_INTERFACE(ConsumerListener)
 };
 
-// ----------------------------------------------------------------------------
-
-class BnConsumerListener : public BnInterface<IConsumerListener>
-{
+class BnConsumerListener : public SafeBnInterface<IConsumerListener> {
 public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
+    BnConsumerListener() : SafeBnInterface<IConsumerListener>("BnConsumerListener") {}
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                        uint32_t flags = 0) override;
 };
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_ICONSUMERLISTENER_H
+} // namespace android
diff --git a/include/gui/IDisplayEventConnection.h b/include/gui/IDisplayEventConnection.h
index 848368c..d783f74 100644
--- a/include/gui/IDisplayEventConnection.h
+++ b/include/gui/IDisplayEventConnection.h
@@ -14,60 +14,52 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
-#define ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
+#pragma once
 
 #include <binder/IInterface.h>
+#include <binder/SafeInterface.h>
+
+#include <utils/Errors.h>
+
+#include <cstdint>
 
 namespace android {
-// ----------------------------------------------------------------------------
 
+namespace gui {
 class BitTube;
+} // namespace gui
 
-class IDisplayEventConnection : public IInterface
-{
+class IDisplayEventConnection : public IInterface {
 public:
-
     DECLARE_META_INTERFACE(DisplayEventConnection)
 
     /*
-     * getDataChannel() returns a BitTube where to receive the events from
+     * stealReceiveChannel() returns a BitTube to receive events from. Only the receive file
+     * descriptor of outChannel will be initialized, and this effectively "steals" the receive
+     * channel from the remote end (such that the remote end can only use its send channel).
      */
-    virtual sp<BitTube> getDataChannel() const = 0;
+    virtual status_t stealReceiveChannel(gui::BitTube* outChannel) = 0;
 
     /*
-     * setVsyncRate() sets the vsync event delivery rate. A value of
-     * 1 returns every vsync events. A value of 2 returns every other events,
-     * etc... a value of 0 returns no event unless  requestNextVsync() has
-     * been called.
+     * setVsyncRate() sets the vsync event delivery rate. A value of 1 returns every vsync event.
+     * A value of 2 returns every other event, etc. A value of 0 returns no event unless
+     * requestNextVsync() has been called.
      */
-    virtual void setVsyncRate(uint32_t count) = 0;
+    virtual status_t setVsyncRate(uint32_t count) = 0;
 
     /*
-     * requestNextVsync() schedules the next vsync event. It has no effect
-     * if the vsync rate is > 0.
+     * requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0.
      */
-    virtual void requestNextVsync() = 0;    // asynchronous
+    virtual void requestNextVsync() = 0; // Asynchronous
 };
 
-// ----------------------------------------------------------------------------
-
-class BnDisplayEventConnection : public BnInterface<IDisplayEventConnection>
-{
+class BnDisplayEventConnection : public SafeBnInterface<IDisplayEventConnection> {
 public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
+    BnDisplayEventConnection()
+          : SafeBnInterface<IDisplayEventConnection>("BnDisplayEventConnection") {}
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                        uint32_t flags = 0) override;
 };
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
+} // namespace android
diff --git a/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h
index a680bc6..2c613ea 100644
--- a/include/gui/ISurfaceComposerClient.h
+++ b/include/gui/ISurfaceComposerClient.h
@@ -29,14 +29,6 @@
 public:
     DECLARE_META_INTERFACE(SurfaceComposerClient)
 
-    enum class Tag : uint32_t {
-        CreateSurface = IBinder::FIRST_CALL_TRANSACTION,
-        DestroySurface,
-        ClearLayerFrameStats,
-        GetLayerFrameStats,
-        Last,
-    };
-
     // flags for createSurface()
     enum { // (keep in sync with Surface.java)
         eHidden = 0x00000004,
diff --git a/include/private/gui/BitTube.h b/include/private/gui/BitTube.h
deleted file mode 100644
index 9d65fad..0000000
--- a/include/private/gui/BitTube.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GUI_SENSOR_CHANNEL_H
-#define ANDROID_GUI_SENSOR_CHANNEL_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <android/log.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-class Parcel;
-
-class BitTube : public RefBase
-{
-public:
-
-    // creates a BitTube with a default (4KB) send buffer
-    BitTube();
-
-    // creates a BitTube with a a specified send and receive buffer size
-    explicit BitTube(size_t bufsize);
-
-    explicit BitTube(const Parcel& data);
-    virtual ~BitTube();
-
-    // check state after construction
-    status_t initCheck() const;
-
-    // get receive file-descriptor
-    int getFd() const;
-
-    // get the send file-descriptor.
-    int getSendFd() const;
-
-    // send objects (sized blobs). All objects are guaranteed to be written or the call fails.
-    template <typename T>
-    static ssize_t sendObjects(const sp<BitTube>& tube,
-            T const* events, size_t count) {
-        return sendObjects(tube, events, count, sizeof(T));
-    }
-
-    // receive objects (sized blobs). If the receiving buffer isn't large enough,
-    // excess messages are silently discarded.
-    template <typename T>
-    static ssize_t recvObjects(const sp<BitTube>& tube,
-            T* events, size_t count) {
-        return recvObjects(tube, events, count, sizeof(T));
-    }
-
-    // parcels this BitTube
-    status_t writeToParcel(Parcel* reply) const;
-
-private:
-    void init(size_t rcvbuf, size_t sndbuf);
-
-    // send a message. The write is guaranteed to send the whole message or fail.
-    ssize_t write(void const* vaddr, size_t size);
-
-    // receive a message. the passed buffer must be at least as large as the
-    // write call used to send the message, excess data is silently discarded.
-    ssize_t read(void* vaddr, size_t size);
-
-    int mSendFd;
-    mutable int mReceiveFd;
-
-    static ssize_t sendObjects(const sp<BitTube>& tube,
-            void const* events, size_t count, size_t objSize);
-
-    static ssize_t recvObjects(const sp<BitTube>& tube,
-            void* events, size_t count, size_t objSize);
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_SENSOR_CHANNEL_H
diff --git a/include/ui/DebugUtils.h b/include/ui/DebugUtils.h
new file mode 100644
index 0000000..8483808
--- /dev/null
+++ b/include/ui/DebugUtils.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <system/graphics.h>
+
+#include <string>
+
+std::string decodeStandard(android_dataspace dataspace);
+std::string decodeTransfer(android_dataspace dataspace);
+std::string decodeRange(android_dataspace dataspace);
+std::string dataspaceDetails(android_dataspace dataspace);
+std::string decodeColorMode(android_color_mode colormode);
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index 0e723c5..44c1352 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -45,6 +45,16 @@
         return callParcel("writeBool", [&]() { return parcel->writeBool(b); });
     }
     template <typename T>
+    typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
+            const Parcel& parcel, T* t) const {
+        return callParcel("read(Flattenable)", [&]() { return parcel.read(*t); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write(
+            Parcel* parcel, const T& t) const {
+        return callParcel("write(Flattenable)", [&]() { return parcel->write(t); });
+    }
+    template <typename T>
     typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type read(
             const Parcel& parcel, T* t) const {
         return callParcel("read(LightFlattenable)", [&]() { return parcel.read(*t); });
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index ac2f4d5..d1f63a7 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -65,6 +65,25 @@
     uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
 };
 
+struct TestFlattenable : Flattenable<TestFlattenable> {
+    TestFlattenable() = default;
+    explicit TestFlattenable(int32_t v) : value(v) {}
+
+    // Flattenable protocol
+    size_t getFlattenedSize() const { return sizeof(value); }
+    size_t getFdCount() const { return 0; }
+    status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
+        FlattenableUtils::write(buffer, size, value);
+        return NO_ERROR;
+    }
+    status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
+        FlattenableUtils::read(buffer, size, value);
+        return NO_ERROR;
+    }
+
+    int32_t value = 0;
+};
+
 struct TestLightFlattenable : LightFlattenablePod<TestLightFlattenable> {
     TestLightFlattenable() = default;
     explicit TestLightFlattenable(int32_t v) : value(v) {}
@@ -142,6 +161,7 @@
         SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
         ReturnsNoMemory,
         LogicalNot,
+        IncrementFlattenable,
         IncrementLightFlattenable,
         IncrementNoCopyNoMove,
         ToUpper,
@@ -161,6 +181,7 @@
 
     // These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
     virtual status_t logicalNot(bool a, bool* notA) const = 0;
+    virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
     virtual status_t increment(const TestLightFlattenable& a,
                                TestLightFlattenable* aPlusOne) const = 0;
     virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
@@ -192,6 +213,12 @@
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
     }
+    status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
+        using Signature =
+                status_t (ISafeInterfaceTest::*)(const TestFlattenable&, TestFlattenable*) const;
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemote<Signature>(Tag::IncrementFlattenable, a, aPlusOne);
+    }
     status_t increment(const TestLightFlattenable& a,
                        TestLightFlattenable* aPlusOne) const override {
         using Signature = status_t (ISafeInterfaceTest::*)(const TestLightFlattenable&,
@@ -263,6 +290,11 @@
         *notA = !a;
         return NO_ERROR;
     }
+    status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        aPlusOne->value = a.value + 1;
+        return NO_ERROR;
+    }
     status_t increment(const TestLightFlattenable& a,
                        TestLightFlattenable* aPlusOne) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
@@ -317,6 +349,11 @@
             case ISafeInterfaceTest::Tag::LogicalNot: {
                 return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
             }
+            case ISafeInterfaceTest::Tag::IncrementFlattenable: {
+                using Signature = status_t (ISafeInterfaceTest::*)(const TestFlattenable& a,
+                                                                   TestFlattenable* aPlusOne) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
             case ISafeInterfaceTest::Tag::IncrementLightFlattenable: {
                 using Signature =
                         status_t (ISafeInterfaceTest::*)(const TestLightFlattenable& a,
@@ -428,6 +465,14 @@
     ASSERT_EQ(!b, notB);
 }
 
+TEST_F(SafeInterfaceTest, TestIncrementFlattenable) {
+    const TestFlattenable a{1};
+    TestFlattenable aPlusOne{0};
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(a.value + 1, aPlusOne.value);
+}
+
 TEST_F(SafeInterfaceTest, TestIncrementLightFlattenable) {
     const TestLightFlattenable a{1};
     TestLightFlattenable aPlusOne{0};
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 28c2a48..90ab286 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -126,6 +126,10 @@
         "android.hidl.token@1.0-utils",
         "android.hardware.graphics.bufferqueue@1.0",
     ],
+
+    export_include_dirs: [
+        "include",
+    ],
 }
 
 subdirs = ["tests"]
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index 51a8d67..ef7a6f5 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -17,8 +17,8 @@
 #include <private/gui/BitTube.h>
 
 #include <stdint.h>
-#include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 
 #include <fcntl.h>
 #include <unistd.h>
@@ -27,45 +27,21 @@
 
 #include <binder/Parcel.h>
 
-
 namespace android {
-// ----------------------------------------------------------------------------
+namespace gui {
 
-// Socket buffer size.  The default is typically about 128KB, which is much larger than
-// we really need.  So we make it smaller.
+// Socket buffer size.  The default is typically about 128KB, which is much larger than we really
+// need. So we make it smaller.
 static const size_t DEFAULT_SOCKET_BUFFER_SIZE = 4 * 1024;
 
-
-BitTube::BitTube()
-    : mSendFd(-1), mReceiveFd(-1)
-{
-    init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);
-}
-
-BitTube::BitTube(size_t bufsize)
-    : mSendFd(-1), mReceiveFd(-1)
-{
+BitTube::BitTube(size_t bufsize) {
     init(bufsize, bufsize);
 }
 
-BitTube::BitTube(const Parcel& data)
-    : mSendFd(-1), mReceiveFd(-1)
-{
-    mReceiveFd = dup(data.readFileDescriptor());
-    if (mReceiveFd < 0) {
-        mReceiveFd = -errno;
-        ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",
-                strerror(-mReceiveFd));
-    }
-}
+BitTube::BitTube(DefaultSizeType) : BitTube(DEFAULT_SOCKET_BUFFER_SIZE) {}
 
-BitTube::~BitTube()
-{
-    if (mSendFd >= 0)
-        close(mSendFd);
-
-    if (mReceiveFd >= 0)
-        close(mReceiveFd);
+BitTube::BitTube(const Parcel& data) {
+    readFromParcel(&data);
 }
 
 void BitTube::init(size_t rcvbuf, size_t sndbuf) {
@@ -74,39 +50,43 @@
         size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
         setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
         setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
-        // sine we don't use the "return channel", we keep it small...
+        // since we don't use the "return channel", we keep it small...
         setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
         setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
         fcntl(sockets[0], F_SETFL, O_NONBLOCK);
         fcntl(sockets[1], F_SETFL, O_NONBLOCK);
-        mReceiveFd = sockets[0];
-        mSendFd = sockets[1];
+        mReceiveFd.reset(sockets[0]);
+        mSendFd.reset(sockets[1]);
     } else {
-        mReceiveFd = -errno;
-        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
+        mReceiveFd.reset();
+        ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
     }
 }
 
-status_t BitTube::initCheck() const
-{
+status_t BitTube::initCheck() const {
     if (mReceiveFd < 0) {
         return status_t(mReceiveFd);
     }
     return NO_ERROR;
 }
 
-int BitTube::getFd() const
-{
+int BitTube::getFd() const {
     return mReceiveFd;
 }
 
-int BitTube::getSendFd() const
-{
+int BitTube::getSendFd() const {
     return mSendFd;
 }
 
-ssize_t BitTube::write(void const* vaddr, size_t size)
-{
+base::unique_fd BitTube::moveReceiveFd() {
+    return std::move(mReceiveFd);
+}
+
+void BitTube::setReceiveFd(base::unique_fd&& receiveFd) {
+    mReceiveFd = std::move(receiveFd);
+}
+
+ssize_t BitTube::write(void const* vaddr, size_t size) {
     ssize_t err, len;
     do {
         len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
@@ -116,62 +96,66 @@
     return err == 0 ? len : -err;
 }
 
-ssize_t BitTube::read(void* vaddr, size_t size)
-{
+ssize_t BitTube::read(void* vaddr, size_t size) {
     ssize_t err, len;
     do {
         len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
         err = len < 0 ? errno : 0;
     } while (err == EINTR);
     if (err == EAGAIN || err == EWOULDBLOCK) {
-        // EAGAIN means that we have non-blocking I/O but there was
-        // no data to be read. Nothing the client should care about.
+        // EAGAIN means that we have non-blocking I/O but there was no data to be read. Nothing the
+        // client should care about.
         return 0;
     }
     return err == 0 ? len : -err;
 }
 
-status_t BitTube::writeToParcel(Parcel* reply) const
-{
-    if (mReceiveFd < 0)
-        return -EINVAL;
+status_t BitTube::writeToParcel(Parcel* reply) const {
+    if (mReceiveFd < 0) return -EINVAL;
 
     status_t result = reply->writeDupFileDescriptor(mReceiveFd);
-    close(mReceiveFd);
-    mReceiveFd = -1;
+    mReceiveFd.reset();
     return result;
 }
 
+status_t BitTube::readFromParcel(const Parcel* parcel) {
+    mReceiveFd.reset(dup(parcel->readFileDescriptor()));
+    if (mReceiveFd < 0) {
+        mReceiveFd.reset();
+        int error = errno;
+        ALOGE("BitTube::readFromParcel: can't dup file descriptor (%s)", strerror(error));
+        return -error;
+    }
+    return NO_ERROR;
+}
 
-ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
-        void const* events, size_t count, size_t objSize)
-{
+ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
     const char* vaddr = reinterpret_cast<const char*>(events);
-    ssize_t size = tube->write(vaddr, count*objSize);
+    ssize_t size = tube->write(vaddr, count * objSize);
 
     // should never happen because of SOCK_SEQPACKET
     LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
-            "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
-            count, objSize, size);
+                        "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were "
+                        "sent!)",
+                        count, objSize, size);
 
-    //ALOGE_IF(size<0, "error %d sending %d events", size, count);
+    // ALOGE_IF(size<0, "error %d sending %d events", size, count);
     return size < 0 ? size : size / static_cast<ssize_t>(objSize);
 }
 
-ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
-        void* events, size_t count, size_t objSize)
-{
+ssize_t BitTube::recvObjects(BitTube* tube, void* events, size_t count, size_t objSize) {
     char* vaddr = reinterpret_cast<char*>(events);
-    ssize_t size = tube->read(vaddr, count*objSize);
+    ssize_t size = tube->read(vaddr, count * objSize);
 
     // should never happen because of SOCK_SEQPACKET
     LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
-            "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were received!)",
-            count, objSize, size);
+                        "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were "
+                        "received!)",
+                        count, objSize, size);
 
-    //ALOGE_IF(size<0, "error %d receiving %d events", size, count);
+    // ALOGE_IF(size<0, "error %d receiving %d events", size, count);
     return size < 0 ? size : size / static_cast<ssize_t>(objSize);
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace gui
+} // namespace android
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 07e07e0..1507d51 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -37,7 +37,8 @@
     if (sf != NULL) {
         mEventConnection = sf->createDisplayEventConnection();
         if (mEventConnection != NULL) {
-            mDataChannel = mEventConnection->getDataChannel();
+            mDataChannel = std::make_unique<gui::BitTube>();
+            mEventConnection->stealReceiveChannel(mDataChannel.get());
         }
     }
 }
@@ -80,19 +81,19 @@
 
 ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
         size_t count) {
-    return DisplayEventReceiver::getEvents(mDataChannel, events, count);
+    return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count);
 }
 
-ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
+ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel,
         Event* events, size_t count)
 {
-    return BitTube::recvObjects(dataChannel, events, count);
+    return gui::BitTube::recvObjects(dataChannel, events, count);
 }
 
-ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
+ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
         Event const* events, size_t count)
 {
-    return BitTube::sendObjects(dataChannel, events, count);
+    return gui::BitTube::sendObjects(dataChannel, events, count);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 8cadc4d..85ac304 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -14,98 +14,86 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
 #include <gui/IConsumerListener.h>
+
 #include <gui/BufferItem.h>
 
-// ---------------------------------------------------------------------------
 namespace android {
-// ---------------------------------------------------------------------------
 
-enum {
+namespace { // Anonymous
+
+enum class Tag : uint32_t {
     ON_DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
     ON_FRAME_AVAILABLE,
-    ON_BUFFER_RELEASED,
+    ON_FRAME_REPLACED,
+    ON_BUFFERS_RELEASED,
     ON_SIDEBAND_STREAM_CHANGED,
-    GET_FRAME_TIMESTAMPS
+    LAST = ON_SIDEBAND_STREAM_CHANGED,
 };
 
-class BpConsumerListener : public BpInterface<IConsumerListener>
-{
+} // Anonymous namespace
+
+class BpConsumerListener : public SafeBpInterface<IConsumerListener> {
 public:
     explicit BpConsumerListener(const sp<IBinder>& impl)
-        : BpInterface<IConsumerListener>(impl) {
+          : SafeBpInterface<IConsumerListener>(impl, "BpConsumerListener") {}
+
+    ~BpConsumerListener() override;
+
+    void onDisconnect() override {
+        callRemoteAsync<decltype(&IConsumerListener::onDisconnect)>(Tag::ON_DISCONNECT);
     }
 
-    virtual ~BpConsumerListener();
-
-    virtual void onDisconnect() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
-        remote()->transact(ON_DISCONNECT, data, &reply, IBinder::FLAG_ONEWAY);
+    void onFrameAvailable(const BufferItem& item) override {
+        callRemoteAsync<decltype(&IConsumerListener::onFrameAvailable)>(Tag::ON_FRAME_AVAILABLE,
+                                                                        item);
     }
 
-    virtual void onFrameAvailable(const BufferItem& item) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
-        data.write(item);
-        remote()->transact(ON_FRAME_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY);
+    void onFrameReplaced(const BufferItem& item) override {
+        callRemoteAsync<decltype(&IConsumerListener::onFrameReplaced)>(Tag::ON_FRAME_REPLACED,
+                                                                       item);
     }
 
-    virtual void onBuffersReleased() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
-        remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY);
+    void onBuffersReleased() override {
+        callRemoteAsync<decltype(&IConsumerListener::onBuffersReleased)>(Tag::ON_BUFFERS_RELEASED);
     }
 
-    virtual void onSidebandStreamChanged() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
-        remote()->transact(ON_SIDEBAND_STREAM_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+    void onSidebandStreamChanged() override {
+        callRemoteAsync<decltype(&IConsumerListener::onSidebandStreamChanged)>(
+                Tag::ON_SIDEBAND_STREAM_CHANGED);
+    }
+
+    void addAndGetFrameTimestamps(const NewFrameEventsEntry* /*newTimestamps*/,
+                                  FrameEventHistoryDelta* /*outDelta*/) override {
+        LOG_ALWAYS_FATAL("IConsumerListener::addAndGetFrameTimestamps cannot be proxied");
     }
 };
 
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpConsumerListener::~BpConsumerListener() {}
+// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see
+// clang warning -Wweak-vtables)
+BpConsumerListener::~BpConsumerListener() = default;
+ConsumerListener::~ConsumerListener() = default;
 
 IMPLEMENT_META_INTERFACE(ConsumerListener, "android.gui.IConsumerListener");
 
-// ----------------------------------------------------------------------
-
-status_t BnConsumerListener::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case ON_DISCONNECT: {
-            CHECK_INTERFACE(IConsumerListener, data, reply);
-            onDisconnect();
-            return NO_ERROR; }
-        case ON_FRAME_AVAILABLE: {
-            CHECK_INTERFACE(IConsumerListener, data, reply);
-            BufferItem item;
-            data.read(item);
-            onFrameAvailable(item);
-            return NO_ERROR; }
-        case ON_BUFFER_RELEASED: {
-            CHECK_INTERFACE(IConsumerListener, data, reply);
-            onBuffersReleased();
-            return NO_ERROR; }
-        case ON_SIDEBAND_STREAM_CHANGED: {
-            CHECK_INTERFACE(IConsumerListener, data, reply);
-            onSidebandStreamChanged();
-            return NO_ERROR; }
+status_t BnConsumerListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                        uint32_t flags) {
+    if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
+        return BBinder::onTransact(code, data, reply, flags);
     }
-    return BBinder::onTransact(code, data, reply, flags);
+    auto tag = static_cast<Tag>(code);
+    switch (tag) {
+        case Tag::ON_DISCONNECT:
+            return callLocalAsync(data, reply, &IConsumerListener::onDisconnect);
+        case Tag::ON_FRAME_AVAILABLE:
+            return callLocalAsync(data, reply, &IConsumerListener::onFrameAvailable);
+        case Tag::ON_FRAME_REPLACED:
+            return callLocalAsync(data, reply, &IConsumerListener::onFrameReplaced);
+        case Tag::ON_BUFFERS_RELEASED:
+            return callLocalAsync(data, reply, &IConsumerListener::onBuffersReleased);
+        case Tag::ON_SIDEBAND_STREAM_CHANGED:
+            return callLocalAsync(data, reply, &IConsumerListener::onSidebandStreamChanged);
+    }
 }
 
-ConsumerListener::~ConsumerListener() = default;
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
+} // namespace android
diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp
index e5c3c48..c0e246f 100644
--- a/libs/gui/IDisplayEventConnection.cpp
+++ b/libs/gui/IDisplayEventConnection.cpp
@@ -14,89 +14,67 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-#include <binder/Parcel.h>
-
 #include <gui/IDisplayEventConnection.h>
 
 #include <private/gui/BitTube.h>
 
 namespace android {
-// ----------------------------------------------------------------------------
 
-enum {
-    GET_DATA_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
+namespace { // Anonymous
+
+enum class Tag : uint32_t {
+    STEAL_RECEIVE_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
     SET_VSYNC_RATE,
-    REQUEST_NEXT_VSYNC
+    REQUEST_NEXT_VSYNC,
+    LAST = REQUEST_NEXT_VSYNC,
 };
 
-class BpDisplayEventConnection : public BpInterface<IDisplayEventConnection>
-{
+} // Anonymous namespace
+
+class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
 public:
     explicit BpDisplayEventConnection(const sp<IBinder>& impl)
-        : BpInterface<IDisplayEventConnection>(impl)
-    {
+          : SafeBpInterface<IDisplayEventConnection>(impl, "BpDisplayEventConnection") {}
+
+    ~BpDisplayEventConnection() override;
+
+    status_t stealReceiveChannel(gui::BitTube* outChannel) override {
+        return callRemote<decltype(
+                &IDisplayEventConnection::stealReceiveChannel)>(Tag::STEAL_RECEIVE_CHANNEL,
+                                                                outChannel);
     }
 
-    virtual ~BpDisplayEventConnection();
-
-    virtual sp<BitTube> getDataChannel() const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
-        remote()->transact(GET_DATA_CHANNEL, data, &reply);
-        return new BitTube(reply);
+    status_t setVsyncRate(uint32_t count) override {
+        return callRemote<decltype(&IDisplayEventConnection::setVsyncRate)>(Tag::SET_VSYNC_RATE,
+                                                                            count);
     }
 
-    virtual void setVsyncRate(uint32_t count) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
-        data.writeUint32(count);
-        remote()->transact(SET_VSYNC_RATE, data, &reply);
-    }
-
-    virtual void requestNextVsync() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
-        remote()->transact(REQUEST_NEXT_VSYNC, data, &reply, IBinder::FLAG_ONEWAY);
+    void requestNextVsync() override {
+        callRemoteAsync<decltype(&IDisplayEventConnection::requestNextVsync)>(
+                Tag::REQUEST_NEXT_VSYNC);
     }
 };
 
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpDisplayEventConnection::~BpDisplayEventConnection() {}
+// Out-of-line virtual method definition to trigger vtable emission in this translation unit (see
+// clang warning -Wweak-vtables)
+BpDisplayEventConnection::~BpDisplayEventConnection() = default;
 
 IMPLEMENT_META_INTERFACE(DisplayEventConnection, "android.gui.DisplayEventConnection");
 
-// ----------------------------------------------------------------------------
-
-status_t BnDisplayEventConnection::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case GET_DATA_CHANNEL: {
-            CHECK_INTERFACE(IDisplayEventConnection, data, reply);
-            sp<BitTube> channel(getDataChannel());
-            channel->writeToParcel(reply);
-            return NO_ERROR;
-        }
-        case SET_VSYNC_RATE: {
-            CHECK_INTERFACE(IDisplayEventConnection, data, reply);
-            setVsyncRate(data.readUint32());
-            return NO_ERROR;
-        }
-        case REQUEST_NEXT_VSYNC: {
-            CHECK_INTERFACE(IDisplayEventConnection, data, reply);
-            requestNextVsync();
-            return NO_ERROR;
-        }
+status_t BnDisplayEventConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                              uint32_t flags) {
+    if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
+        return BBinder::onTransact(code, data, reply, flags);
     }
-    return BBinder::onTransact(code, data, reply, flags);
+    auto tag = static_cast<Tag>(code);
+    switch (tag) {
+        case Tag::STEAL_RECEIVE_CHANNEL:
+            return callLocal(data, reply, &IDisplayEventConnection::stealReceiveChannel);
+        case Tag::SET_VSYNC_RATE:
+            return callLocal(data, reply, &IDisplayEventConnection::setVsyncRate);
+        case Tag::REQUEST_NEXT_VSYNC:
+            return callLocalAsync(data, reply, &IDisplayEventConnection::requestNextVsync);
+    }
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 2d2146b..679f44b 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -17,24 +17,28 @@
 // tag as surfaceflinger
 #define LOG_TAG "SurfaceFlinger"
 
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/types.h>
+#include <gui/ISurfaceComposerClient.h>
 
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
+#include <gui/IGraphicBufferProducer.h>
+
 #include <binder/SafeInterface.h>
 
 #include <ui/FrameStats.h>
-#include <ui/Point.h>
-#include <ui/Rect.h>
-
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/ISurfaceComposerClient.h>
 
 namespace android {
 
+namespace { // Anonymous
+
+enum class Tag : uint32_t {
+    CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
+    DESTROY_SURFACE,
+    CLEAR_LAYER_FRAME_STATS,
+    GET_LAYER_FRAME_STATS,
+    LAST = GET_LAYER_FRAME_STATS,
+};
+
+} // Anonymous namespace
+
 class BpSurfaceComposerClient : public SafeBpInterface<ISurfaceComposerClient> {
 public:
     explicit BpSurfaceComposerClient(const sp<IBinder>& impl)
@@ -46,7 +50,7 @@
                            uint32_t flags, const sp<IBinder>& parent, uint32_t windowType,
                            uint32_t ownerUid, sp<IBinder>* handle,
                            sp<IGraphicBufferProducer>* gbp) override {
-        return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CreateSurface,
+        return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,
                                                                             name, width, height,
                                                                             format, flags, parent,
                                                                             windowType, ownerUid,
@@ -54,18 +58,19 @@
     }
 
     status_t destroySurface(const sp<IBinder>& handle) override {
-        return callRemote<decltype(&ISurfaceComposerClient::destroySurface)>(Tag::DestroySurface,
+        return callRemote<decltype(&ISurfaceComposerClient::destroySurface)>(Tag::DESTROY_SURFACE,
                                                                              handle);
     }
 
     status_t clearLayerFrameStats(const sp<IBinder>& handle) const override {
         return callRemote<decltype(
-                &ISurfaceComposerClient::clearLayerFrameStats)>(Tag::ClearLayerFrameStats, handle);
+                &ISurfaceComposerClient::clearLayerFrameStats)>(Tag::CLEAR_LAYER_FRAME_STATS,
+                                                                handle);
     }
 
     status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const override {
         return callRemote<decltype(
-                &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GetLayerFrameStats, handle,
+                &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GET_LAYER_FRAME_STATS, handle,
                                                               outStats);
     }
 };
@@ -80,26 +85,19 @@
 
 status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                              uint32_t flags) {
-    if (code < IBinder::FIRST_CALL_TRANSACTION || code >= static_cast<uint32_t>(Tag::Last)) {
+    if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
         return BBinder::onTransact(code, data, reply, flags);
     }
     auto tag = static_cast<Tag>(code);
     switch (tag) {
-        case Tag::CreateSurface: {
+        case Tag::CREATE_SURFACE:
             return callLocal(data, reply, &ISurfaceComposerClient::createSurface);
-        }
-        case Tag::DestroySurface: {
+        case Tag::DESTROY_SURFACE:
             return callLocal(data, reply, &ISurfaceComposerClient::destroySurface);
-        }
-        case Tag::ClearLayerFrameStats: {
+        case Tag::CLEAR_LAYER_FRAME_STATS:
             return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats);
-        }
-        case Tag::GetLayerFrameStats: {
+        case Tag::GET_LAYER_FRAME_STATS:
             return callLocal(data, reply, &ISurfaceComposerClient::getLayerFrameStats);
-        }
-        case Tag::Last:
-            // Should not be possible because of the check at the beginning of the method
-            return BBinder::onTransact(code, data, reply, flags);
     }
 }
 
diff --git a/libs/gui/include/private/gui/BitTube.h b/libs/gui/include/private/gui/BitTube.h
new file mode 100644
index 0000000..13c0162
--- /dev/null
+++ b/libs/gui/include/private/gui/BitTube.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/Parcelable.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class Parcel;
+
+namespace gui {
+
+class BitTube : public Parcelable {
+public:
+    // creates an uninitialized BitTube (to unparcel into)
+    BitTube() = default;
+
+    // creates a BitTube with a a specified send and receive buffer size
+    explicit BitTube(size_t bufsize);
+
+    // creates a BitTube with a default (4KB) send buffer
+    struct DefaultSizeType {};
+    static constexpr DefaultSizeType DefaultSize{};
+    explicit BitTube(DefaultSizeType);
+
+    explicit BitTube(const Parcel& data);
+
+    virtual ~BitTube() = default;
+
+    // check state after construction
+    status_t initCheck() const;
+
+    // get receive file-descriptor
+    int getFd() const;
+
+    // get the send file-descriptor.
+    int getSendFd() const;
+
+    // moves the receive file descriptor out of this BitTube
+    base::unique_fd moveReceiveFd();
+
+    // resets this BitTube's receive file descriptor to receiveFd
+    void setReceiveFd(base::unique_fd&& receiveFd);
+
+    // send objects (sized blobs). All objects are guaranteed to be written or the call fails.
+    template <typename T>
+    static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) {
+        return sendObjects(tube, events, count, sizeof(T));
+    }
+
+    // receive objects (sized blobs). If the receiving buffer isn't large enough, excess messages
+    // are silently discarded.
+    template <typename T>
+    static ssize_t recvObjects(BitTube* tube, T* events, size_t count) {
+        return recvObjects(tube, events, count, sizeof(T));
+    }
+
+    // implement the Parcelable protocol. Only parcels the receive file descriptor
+    status_t writeToParcel(Parcel* reply) const;
+    status_t readFromParcel(const Parcel* parcel);
+
+private:
+    void init(size_t rcvbuf, size_t sndbuf);
+
+    // send a message. The write is guaranteed to send the whole message or fail.
+    ssize_t write(void const* vaddr, size_t size);
+
+    // receive a message. the passed buffer must be at least as large as the write call used to send
+    // the message, excess data is silently discarded.
+    ssize_t read(void* vaddr, size_t size);
+
+    base::unique_fd mSendFd;
+    mutable base::unique_fd mReceiveFd;
+
+    static ssize_t sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize);
+
+    static ssize_t recvObjects(BitTube* tube, void* events, size_t count, size_t objSize);
+};
+
+} // namespace gui
+} // namespace android
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 3a99147..192bfc8 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -27,6 +27,8 @@
     ],
 
     shared_libs: [
+        "android.hardware.configstore@1.0",
+        "android.hardware.configstore-utils",
         "liblog",
         "libEGL",
         "libGLESv1_CM",
@@ -34,6 +36,8 @@
         "libbinder",
         "libcutils",
         "libgui",
+        "libhidlbase",
+        "libhidltransport",
         "libui",
         "libutils",
         "libnativewindow"
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3932b92..ce11486 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -18,7 +18,9 @@
 
 #include <gtest/gtest.h>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <binder/ProcessState.h>
+#include <configstore/Utils.h>
 #include <cutils/properties.h>
 #include <gui/BufferItemConsumer.h>
 #include <gui/IDisplayEventConnection.h>
@@ -35,6 +37,12 @@
 namespace android {
 
 using namespace std::chrono_literals;
+// retrieve wide-color and hdr settings from configstore
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
+static bool hasWideColorDisplay =
+        getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
 
 class FakeSurfaceComposer;
 class FakeProducerFrameEventHistory;
@@ -271,17 +279,19 @@
     bool supported;
     surface->getWideColorSupport(&supported);
 
-    // TODO(courtneygo): How can we know what device we are on to
-    // verify that this is correct?
-    char product[PROPERTY_VALUE_MAX] = "0";
-    property_get("ro.build.product", product, "0");
-    std::cerr << "[          ] product = " << product << std::endl;
-
-    if (strcmp("marlin", product) == 0 || strcmp("sailfish", product) == 0) {
-        ASSERT_EQ(true, supported);
-    } else {
-        ASSERT_EQ(false, supported);
-    }
+    // NOTE: This test assumes that device that supports
+    // wide-color (as indicated by BoardConfig) must also
+    // have a wide-color primary display.
+    // That assumption allows this test to cover devices
+    // that advertised a wide-color color mode without
+    // actually supporting wide-color to pass this test
+    // as well as the case of a device that does support
+    // wide-color (via BoardConfig) and has a wide-color
+    // primary display.
+    // NOT covered at this time is a device that supports
+    // wide color in the BoardConfig but does not support
+    // a wide-color color mode on the primary display.
+    ASSERT_EQ(hasWideColorDisplay, supported);
 }
 
 TEST_F(SurfaceTest, DynamicSetBufferCount) {
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index f41f187..74186df 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -40,6 +40,7 @@
     ENABLE_DATA_INJECTION,
     GET_DYNAMIC_SENSOR_LIST,
     CREATE_SENSOR_DIRECT_CONNECTION,
+    SET_OPERATION_PARAMETER,
 };
 
 class BpSensorServer : public BpInterface<ISensorServer>
@@ -117,6 +118,23 @@
         remote()->transact(CREATE_SENSOR_DIRECT_CONNECTION, data, &reply);
         return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
     }
+
+    virtual int setOperationParameter(
+            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+        data.writeInt32(type);
+        data.writeUint32(static_cast<uint32_t>(floats.size()));
+        for (auto i : floats) {
+            data.writeFloat(i);
+        }
+        data.writeUint32(static_cast<uint32_t>(ints.size()));
+        for (auto i : ints) {
+            data.writeInt32(i);
+        }
+        remote()->transact(SET_OPERATION_PARAMETER, data, &reply);
+        return reply.readInt32();
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -183,6 +201,26 @@
             reply->writeStrongBinder(IInterface::asBinder(ch));
             return NO_ERROR;
         }
+        case SET_OPERATION_PARAMETER: {
+            CHECK_INTERFACE(ISensorServer, data, reply);
+            int32_t type;
+            Vector<float> floats;
+            Vector<int32_t> ints;
+
+            type = data.readInt32();
+            floats.resize(data.readUint32());
+            for (auto &i : floats) {
+                i = data.readFloat();
+            }
+            ints.resize(data.readUint32());
+            for (auto &i : ints) {
+                i = data.readInt32();
+            }
+
+            int32_t ret = setOperationParameter(type, floats, ints);
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index d6d3304..3fbc5eb 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -304,5 +304,14 @@
     return ret;
 }
 
+int SensorManager::setOperationParameter(
+        int type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+    Mutex::Autolock _l(mLock);
+    if (assertStateLocked() != NO_ERROR) {
+        return NO_INIT;
+    }
+    return mSensorServer->setOperationParameter(type, floats, ints);
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/sensor/include/sensor/ISensorServer.h b/libs/sensor/include/sensor/ISensorServer.h
index f922307..8d50062 100644
--- a/libs/sensor/include/sensor/ISensorServer.h
+++ b/libs/sensor/include/sensor/ISensorServer.h
@@ -50,6 +50,9 @@
 
     virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
             uint32_t size, int32_t type, int32_t format, const native_handle_t *resource) = 0;
+
+    virtual int setOperationParameter(
+            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index 92c9823..5fc85d3 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -64,6 +64,7 @@
     int createDirectChannel(size_t size, int channelType, const native_handle_t *channelData);
     void destroyDirectChannel(int channelNativeHandle);
     int configureDirectChannel(int channelNativeHandle, int sensorHandle, int rateLevel);
+    int setOperationParameter(int type, const Vector<float> &floats, const Vector<int32_t> &ints);
 
 private:
     // DeathRecipient interface
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 80fb064..310d25e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -45,6 +45,7 @@
 
     srcs: [
         "ColorSpace.cpp",
+        "DebugUtils.cpp",
         "Fence.cpp",
         "FenceTime.cpp",
         "FrameStats.cpp",
@@ -66,6 +67,9 @@
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.configstore@1.0",
+	"android.hardware.configstore-utils",
+        "libbase",
         "libnativeloader",
         "libcutils",
         "libhardware",
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
new file mode 100644
index 0000000..882bd7c
--- /dev/null
+++ b/libs/ui/DebugUtils.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/DebugUtils.h>
+
+#include <android-base/stringprintf.h>
+#include <string>
+
+std::string decodeStandard(android_dataspace dataspace) {
+    const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK);
+    switch (dataspaceSelect) {
+        case HAL_DATASPACE_STANDARD_BT709:
+            return std::string("BT709");
+
+        case HAL_DATASPACE_STANDARD_BT601_625:
+            return std::string("BT601_625");
+
+        case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+            return std::string("BT601_625_UNADJUSTED");
+
+        case HAL_DATASPACE_STANDARD_BT601_525:
+            return std::string("BT601_525");
+
+        case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+            return std::string("BT601_525_UNADJUSTED");
+
+        case HAL_DATASPACE_STANDARD_BT2020:
+            return std::string("BT2020");
+
+        case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+            return std::string("BT2020 (constant luminance)");
+
+        case HAL_DATASPACE_STANDARD_BT470M:
+            return std::string("BT470M");
+
+        case HAL_DATASPACE_STANDARD_FILM:
+            return std::string("FILM");
+
+        case HAL_DATASPACE_STANDARD_DCI_P3:
+            return std::string("DCI-P3");
+
+        case HAL_DATASPACE_STANDARD_ADOBE_RGB:
+            return std::string("AdobeRGB");
+
+        case 0:
+            switch (dataspace & 0xffff) {
+                case HAL_DATASPACE_JFIF:
+                    return std::string("(deprecated) JFIF (BT601_625, SMPTE_170M Full range)");
+
+                case HAL_DATASPACE_BT601_625:
+                    return std::string("(deprecated) BT601_625 (BT601_625, SMPTE_170M Limited "
+                                       "range)");
+
+                case HAL_DATASPACE_BT601_525:
+                    return std::string("(deprecated) BT601_525 (BT601_525, SMPTE_170M Limited "
+                                       "range)");
+
+                case HAL_DATASPACE_SRGB_LINEAR:
+                    return std::string("(deprecated) SRGB Linear Full range");
+
+                case HAL_DATASPACE_SRGB:
+                    return std::string("(deprecated) sRGB");
+
+                case HAL_DATASPACE_V0_BT709:
+                    return std::string("(deprecated) BT709 (BT709, SMPTE_170M Limited range)");
+
+                case HAL_DATASPACE_ARBITRARY:
+                    return std::string("ARBITRARY");
+
+                case HAL_DATASPACE_UNKNOWN:
+                // Fallthrough
+                default:
+                    return android::base::StringPrintf("Unknown deprecated dataspace code %d",
+                                                       dataspaceSelect);
+            }
+    }
+
+    return android::base::StringPrintf("Unknown dataspace code %d", dataspaceSelect);
+}
+
+std::string decodeTransfer(android_dataspace dataspace) {
+    const uint32_t dataspaceTransfer = (dataspace & HAL_DATASPACE_TRANSFER_MASK);
+    switch (dataspaceTransfer) {
+        case HAL_DATASPACE_TRANSFER_UNSPECIFIED:
+            return std::string("Unspecified");
+
+        case HAL_DATASPACE_TRANSFER_LINEAR:
+            return std::string("Linear");
+
+        case HAL_DATASPACE_TRANSFER_SRGB:
+            return std::string("sRGB");
+
+        case HAL_DATASPACE_TRANSFER_SMPTE_170M:
+            return std::string("SMPTE_170M");
+
+        case HAL_DATASPACE_TRANSFER_GAMMA2_2:
+            return std::string("gamma 2.2");
+
+        case HAL_DATASPACE_TRANSFER_GAMMA2_6:
+            return std::string("gamma 2.6");
+
+        case HAL_DATASPACE_TRANSFER_GAMMA2_8:
+            return std::string("gamma 2.8");
+
+        case HAL_DATASPACE_TRANSFER_ST2084:
+            return std::string("SMPTE 2084");
+
+        case HAL_DATASPACE_TRANSFER_HLG:
+            return std::string("STD-B67");
+    }
+
+    return android::base::StringPrintf("Unknown dataspace transfer %d", dataspaceTransfer);
+}
+
+std::string decodeRange(android_dataspace dataspace) {
+    const uint32_t dataspaceRange = (dataspace & HAL_DATASPACE_RANGE_MASK);
+    switch (dataspaceRange) {
+        case HAL_DATASPACE_RANGE_UNSPECIFIED:
+            return std::string("Range Unspecified");
+
+        case HAL_DATASPACE_RANGE_FULL:
+            return std::string("Full range");
+
+        case HAL_DATASPACE_RANGE_LIMITED:
+            return std::string("Limited range");
+
+        case HAL_DATASPACE_RANGE_EXTENDED:
+            return std::string("Extended range");
+    }
+
+    return android::base::StringPrintf("Unknown dataspace range %d", dataspaceRange);
+}
+
+std::string dataspaceDetails(android_dataspace dataspace) {
+    return android::base::StringPrintf("%s %s %s", decodeStandard(dataspace).c_str(),
+                                       decodeTransfer(dataspace).c_str(),
+                                       decodeRange(dataspace).c_str());
+}
+
+std::string decodeColorMode(android_color_mode colorMode) {
+    switch (colorMode) {
+        case HAL_COLOR_MODE_NATIVE:
+            return std::string("HAL_COLOR_MODE_NATIVE");
+
+        case HAL_COLOR_MODE_STANDARD_BT601_625:
+            return std::string("HAL_COLOR_MODE_BT601_625");
+
+        case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED:
+            return std::string("HAL_COLOR_MODE_BT601_625_UNADJUSTED");
+
+        case HAL_COLOR_MODE_STANDARD_BT601_525:
+            return std::string("HAL_COLOR_MODE_BT601_525");
+
+        case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED:
+            return std::string("HAL_COLOR_MODE_BT601_525_UNADJUSTED");
+
+        case HAL_COLOR_MODE_STANDARD_BT709:
+            return std::string("HAL_COLOR_MODE_BT709");
+
+        case HAL_COLOR_MODE_DCI_P3:
+            return std::string("HAL_COLOR_MODE_DCI_P3");
+
+        case HAL_COLOR_MODE_SRGB:
+            return std::string("HAL_COLOR_MODE_SRGB");
+
+        case HAL_COLOR_MODE_ADOBE_RGB:
+            return std::string("HAL_COLOR_MODE_ADOBE_RGB");
+
+        case HAL_COLOR_MODE_DISPLAY_P3:
+            return std::string("HAL_COLOR_MODE_DISPLAY_P3");
+    }
+
+    return android::base::StringPrintf("Unknown color mode %d", colorMode);
+}
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index a020dca..37cd8c7 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -381,6 +381,7 @@
 
 struct DvrWriteBufferQueue {
   std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+  ANativeWindow* native_window_{nullptr};
 };
 
 struct DvrReadBufferQueue {
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
index 3c6934b..1050283 100644
--- a/libs/vr/libdvr/Android.mk
+++ b/libs/vr/libdvr/Android.mk
@@ -49,7 +49,6 @@
 LOCAL_SHARED_LIBRARIES := \
     android.hardware.graphics.bufferqueue@1.0 \
     android.hidl.token@1.0-utils \
-    libandroid_runtime \
     libbase \
     libnativewindow \
 
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 4ce0b22..dfde21d 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -1,11 +1,10 @@
 #include "include/dvr/dvr_buffer_queue.h"
 
+#include <android/native_window.h>
 #include <gui/Surface.h>
 #include <private/dvr/buffer_hub_queue_client.h>
 #include <private/dvr/buffer_hub_queue_producer.h>
 
-#include <android_runtime/android_view_Surface.h>
-
 #define CHECK_PARAM(param)                                               \
   LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
                       __FUNCTION__)
@@ -15,6 +14,9 @@
 extern "C" {
 
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
+  if (write_queue != nullptr && write_queue->native_window_ != nullptr) {
+    ANativeWindow_release(write_queue->native_window_);
+  }
   delete write_queue;
 }
 
@@ -23,16 +25,30 @@
   return write_queue->producer_queue_->capacity();
 }
 
-jobject dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
-                                              JNIEnv* env) {
-  CHECK_PARAM(env);
+int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+                                          ANativeWindow** out_window) {
   CHECK_PARAM(write_queue);
+  CHECK_PARAM(out_window);
 
-  std::shared_ptr<dvr::BufferHubQueueCore> core =
-      dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+  // Lazy creation of |native_window_|.
+  if (write_queue->native_window_ == nullptr) {
+    std::shared_ptr<dvr::BufferHubQueueCore> core =
+        dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+    if (core == nullptr) {
+      ALOGE(
+          "dvrWriteBufferQueueGetExternalSurface: Failed to create native "
+          "window.");
+      return -ENOMEM;
+    }
 
-  return android_view_Surface_createFromIGraphicBufferProducer(
-      env, new dvr::BufferHubQueueProducer(core));
+    sp<IGraphicBufferProducer> gbp = new dvr::BufferHubQueueProducer(core);
+    sp<Surface> surface = new Surface(gbp, true);
+    write_queue->native_window_ = static_cast<ANativeWindow*>(surface.get());
+    ANativeWindow_acquire(write_queue->native_window_);
+  }
+
+  *out_window = write_queue->native_window_;
+  return 0;
 }
 
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 053382f..a4fef19 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -6,12 +6,13 @@
 #include <stdint.h>
 
 #include <dvr/dvr_hardware_composer_defs.h>
-#include <jni.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+typedef struct ANativeWindow ANativeWindow;
+
 typedef struct DvrPoseAsync DvrPoseAsync;
 
 typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
@@ -89,8 +90,8 @@
 typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
 typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
     DvrWriteBufferQueue* write_queue);
-typedef jobject (*DvrWriteBufferQueueGetExternalSurfacePtr)(
-    DvrWriteBufferQueue* write_queue, JNIEnv* env);
+typedef int (*DvrWriteBufferQueueGetExternalSurfacePtr)(
+    DvrWriteBufferQueue* write_queue, ANativeWindow** out_window);
 typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
     DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
 typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index 80c9779..ba39513 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -2,12 +2,13 @@
 #define ANDROID_DVR_BUFFER_QUEUE_H_
 
 #include <dvr/dvr_buffer.h>
-#include <jni.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+typedef struct ANativeWindow ANativeWindow;
+
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 typedef struct DvrReadBufferQueue DvrReadBufferQueue;
 
@@ -15,10 +16,12 @@
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
 size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
 
-// Returns ANativeWindow in the form of jobject. Can be casted to ANativeWindow
-// using ANativeWindow_fromSurface NDK API.
-jobject dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
-                                              JNIEnv* env);
+// Returns ANativeWindow. Can be casted to a Java Surface using
+// ANativeWindow_toSurface NDK API. Note that this method does not acquire an
+// additional reference to the ANativeWindow returned, don't call
+// ANativeWindow_release on it.
+int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+                                          ANativeWindow** out_window);
 
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue);
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
index 158d58f..75e2a7d 100644
--- a/libs/vr/libdvr/tests/Android.mk
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -9,6 +9,7 @@
     libhardware \
     libui \
     libutils \
+    libnativewindow \
 
 static_libraries := \
     libdvr \
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index f344a24..1c9eadd 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -1,4 +1,5 @@
 #include <dvr/dvr_buffer_queue.h>
+#include <gui/Surface.h>
 #include <private/dvr/buffer_hub_queue_client.h>
 
 #include <base/logging.h>
@@ -143,6 +144,17 @@
   dvrReadBufferQueueDestroy(read_queue);
 }
 
+TEST_F(DvrBufferQueueTest, TestGetExternalSurface) {
+  ANativeWindow* window = nullptr;
+  int ret = dvrWriteBufferQueueGetExternalSurface(write_queue_, &window);
+
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, window);
+
+  sp<Surface> surface = static_cast<Surface*>(window);
+  ASSERT_TRUE(Surface::isValid(surface));
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index 655adb8..8cfa86f 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -57,6 +57,7 @@
         "pdx_benchmarks.cpp",
     ],
     shared_libs: [
+        "libbase",
         "libchrome",
         "libcutils",
         "liblog",
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index 9f308ec..a73ba34 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -20,6 +20,8 @@
         "service_endpoint.cpp",
     ],
     static_libs: [
+        "libcutils",
+        "libbase",
         "libpdx",
     ],
 }
diff --git a/libs/vr/libpdx_uds/channel_event_set.cpp b/libs/vr/libpdx_uds/channel_event_set.cpp
index f8baeab..ac4dea9 100644
--- a/libs/vr/libpdx_uds/channel_event_set.cpp
+++ b/libs/vr/libpdx_uds/channel_event_set.cpp
@@ -12,7 +12,7 @@
   const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
   LocalHandle epoll_fd, event_fd;
 
-  if (!SetupHandle(epoll_create(1), &epoll_fd, "epoll") ||
+  if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll") ||
       !SetupHandle(eventfd(0, flags), &event_fd, "event")) {
     return;
   }
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 4cbdb94..924335f 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -67,7 +67,7 @@
   ResponseHeader<LocalHandle> response;
 };
 
-Status<void> ReadAndDiscardData(int socket_fd, size_t size) {
+Status<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
   while (size > 0) {
     // If there is more data to read in the message than the buffers provided
     // by the caller, read and discard the extra data from the socket.
@@ -83,9 +83,10 @@
   return ErrorStatus(EIO);
 }
 
-Status<void> SendRequest(int socket_fd, TransactionState* transaction_state,
-                         int opcode, const iovec* send_vector,
-                         size_t send_count, size_t max_recv_len) {
+Status<void> SendRequest(const BorrowedHandle& socket_fd,
+                         TransactionState* transaction_state, int opcode,
+                         const iovec* send_vector, size_t send_count,
+                         size_t max_recv_len) {
   size_t send_len = CountVectorSize(send_vector, send_count);
   InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
               false);
@@ -95,7 +96,8 @@
   return status;
 }
 
-Status<void> ReceiveResponse(int socket_fd, TransactionState* transaction_state,
+Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
+                             TransactionState* transaction_state,
                              const iovec* receive_vector, size_t receive_count,
                              size_t max_recv_len) {
   auto status = ReceiveData(socket_fd, &transaction_state->response);
@@ -164,7 +166,7 @@
 
   InitRequest(&request, opcode, length, 0, true);
   memcpy(request.impulse_payload.data(), buffer, length);
-  return SendData(channel_handle_.value(), request);
+  return SendData(BorrowedHandle{channel_handle_.value()}, request);
 }
 
 Status<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
@@ -182,11 +184,11 @@
   auto* state = static_cast<TransactionState*>(transaction_state);
   size_t max_recv_len = CountVectorSize(receive_vector, receive_count);
 
-  auto status = SendRequest(channel_handle_.value(), state, opcode, send_vector,
-                            send_count, max_recv_len);
+  auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
+                            opcode, send_vector, send_count, max_recv_len);
   if (status) {
-    status = ReceiveResponse(channel_handle_.value(), state, receive_vector,
-                             receive_count, max_recv_len);
+    status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
+                             receive_vector, receive_count, max_recv_len);
   }
   if (!result.PropagateError(status)) {
     const int return_code = state->response.ret_code;
diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp
index f059453..323236d 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -111,11 +111,11 @@
         remote.sun_path);
   RequestHeader<BorrowedHandle> request;
   InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false);
-  status = SendData(socket_fd.Get(), request);
+  status = SendData(socket_fd.Borrow(), request);
   if (!status)
     return ErrorStatus(status.error());
   ResponseHeader<LocalHandle> response;
-  status = ReceiveData(socket_fd.Get(), &response);
+  status = ReceiveData(socket_fd.Borrow(), &response);
   if (!status)
     return ErrorStatus(status.error());
   int ref = response.ret_code;
diff --git a/libs/vr/libpdx_uds/ipc_helper.cpp b/libs/vr/libpdx_uds/ipc_helper.cpp
index fe5c986..d604f62 100644
--- a/libs/vr/libpdx_uds/ipc_helper.cpp
+++ b/libs/vr/libpdx_uds/ipc_helper.cpp
@@ -26,18 +26,19 @@
   uint32_t fd_count{0};
 };
 
-Status<void> SendPayload::Send(int socket_fd) {
+Status<void> SendPayload::Send(const BorrowedHandle& socket_fd) {
   return Send(socket_fd, nullptr);
 }
 
-Status<void> SendPayload::Send(int socket_fd, const ucred* cred) {
+Status<void> SendPayload::Send(const BorrowedHandle& socket_fd,
+                               const ucred* cred) {
   MessagePreamble preamble;
   preamble.magic = kMagicPreamble;
   preamble.data_size = buffer_.size();
   preamble.fd_count = file_handles_.size();
 
-  ssize_t ret =
-      RETRY_EINTR(send(socket_fd, &preamble, sizeof(preamble), MSG_NOSIGNAL));
+  ssize_t ret = RETRY_EINTR(
+      send(socket_fd.Get(), &preamble, sizeof(preamble), MSG_NOSIGNAL));
   if (ret < 0)
     return ErrorStatus(errno);
   if (ret != sizeof(preamble))
@@ -71,7 +72,7 @@
     }
   }
 
-  ret = RETRY_EINTR(sendmsg(socket_fd, &msg, MSG_NOSIGNAL));
+  ret = RETRY_EINTR(sendmsg(socket_fd.Get(), &msg, MSG_NOSIGNAL));
   if (ret < 0)
     return ErrorStatus(errno);
   if (static_cast<size_t>(ret) != buffer_.size())
@@ -125,14 +126,15 @@
   return ErrorStatus{EOPNOTSUPP};
 }
 
-Status<void> ReceivePayload::Receive(int socket_fd) {
+Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd) {
   return Receive(socket_fd, nullptr);
 }
 
-Status<void> ReceivePayload::Receive(int socket_fd, ucred* cred) {
+Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd,
+                                     ucred* cred) {
   MessagePreamble preamble;
-  ssize_t ret =
-      RETRY_EINTR(recv(socket_fd, &preamble, sizeof(preamble), MSG_WAITALL));
+  ssize_t ret = RETRY_EINTR(
+      recv(socket_fd.Get(), &preamble, sizeof(preamble), MSG_WAITALL));
   if (ret < 0)
     return ErrorStatus(errno);
   else if (ret == 0)
@@ -157,7 +159,7 @@
     msg.msg_control = alloca(msg.msg_controllen);
   }
 
-  ret = RETRY_EINTR(recvmsg(socket_fd, &msg, MSG_WAITALL));
+  ret = RETRY_EINTR(recvmsg(socket_fd.Get(), &msg, MSG_WAITALL));
   if (ret < 0)
     return ErrorStatus(errno);
   else if (ret == 0)
@@ -219,8 +221,10 @@
   return false;
 }
 
-Status<void> SendData(int socket_fd, const void* data, size_t size) {
-  ssize_t size_written = RETRY_EINTR(send(socket_fd, data, size, MSG_NOSIGNAL));
+Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
+                      size_t size) {
+  ssize_t size_written =
+      RETRY_EINTR(send(socket_fd.Get(), data, size, MSG_NOSIGNAL));
   if (size_written < 0)
     return ErrorStatus(errno);
   if (static_cast<size_t>(size_written) != size)
@@ -228,11 +232,13 @@
   return {};
 }
 
-Status<void> SendDataVector(int socket_fd, const iovec* data, size_t count) {
+Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
+                            size_t count) {
   msghdr msg = {};
   msg.msg_iov = const_cast<iovec*>(data);
   msg.msg_iovlen = count;
-  ssize_t size_written = RETRY_EINTR(sendmsg(socket_fd, &msg, MSG_NOSIGNAL));
+  ssize_t size_written =
+      RETRY_EINTR(sendmsg(socket_fd.Get(), &msg, MSG_NOSIGNAL));
   if (size_written < 0)
     return ErrorStatus(errno);
   if (static_cast<size_t>(size_written) != CountVectorSize(data, count))
@@ -240,8 +246,10 @@
   return {};
 }
 
-Status<void> ReceiveData(int socket_fd, void* data, size_t size) {
-  ssize_t size_read = RETRY_EINTR(recv(socket_fd, data, size, MSG_WAITALL));
+Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
+                         size_t size) {
+  ssize_t size_read =
+      RETRY_EINTR(recv(socket_fd.Get(), data, size, MSG_WAITALL));
   if (size_read < 0)
     return ErrorStatus(errno);
   else if (size_read == 0)
@@ -251,11 +259,12 @@
   return {};
 }
 
-Status<void> ReceiveDataVector(int socket_fd, const iovec* data, size_t count) {
+Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
+                               const iovec* data, size_t count) {
   msghdr msg = {};
   msg.msg_iov = const_cast<iovec*>(data);
   msg.msg_iovlen = count;
-  ssize_t size_read = RETRY_EINTR(recvmsg(socket_fd, &msg, MSG_WAITALL));
+  ssize_t size_read = RETRY_EINTR(recvmsg(socket_fd.Get(), &msg, MSG_WAITALL));
   if (size_read < 0)
     return ErrorStatus(errno);
   else if (size_read == 0)
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 80530bf..82950a2 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -25,8 +25,8 @@
 
 class SendPayload : public MessageWriter, public OutputResourceMapper {
  public:
-  Status<void> Send(int socket_fd);
-  Status<void> Send(int socket_fd, const ucred* cred);
+  Status<void> Send(const BorrowedHandle& socket_fd);
+  Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred);
 
   // MessageWriter
   void* GetNextWriteBufferSection(size_t size) override;
@@ -50,8 +50,8 @@
 
 class ReceivePayload : public MessageReader, public InputResourceMapper {
  public:
-  Status<void> Receive(int socket_fd);
-  Status<void> Receive(int socket_fd, ucred* cred);
+  Status<void> Receive(const BorrowedHandle& socket_fd);
+  Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred);
 
   // MessageReader
   BufferSection GetNextReadBufferSection() override;
@@ -111,25 +111,27 @@
 };
 
 template <typename T>
-inline Status<void> SendData(int socket_fd, const T& data) {
+inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data) {
   SendPayload payload;
   rpc::Serialize(data, &payload);
   return payload.Send(socket_fd);
 }
 
 template <typename FileHandleType>
-inline Status<void> SendData(int socket_fd,
+inline Status<void> SendData(const BorrowedHandle& socket_fd,
                              const RequestHeader<FileHandleType>& request) {
   SendPayload payload;
   rpc::Serialize(request, &payload);
   return payload.Send(socket_fd, &request.cred);
 }
 
-Status<void> SendData(int socket_fd, const void* data, size_t size);
-Status<void> SendDataVector(int socket_fd, const iovec* data, size_t count);
+Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
+                      size_t size);
+Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
+                            size_t count);
 
 template <typename T>
-inline Status<void> ReceiveData(int socket_fd, T* data) {
+inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, T* data) {
   ReceivePayload payload;
   Status<void> status = payload.Receive(socket_fd);
   if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR)
@@ -138,7 +140,7 @@
 }
 
 template <typename FileHandleType>
-inline Status<void> ReceiveData(int socket_fd,
+inline Status<void> ReceiveData(const BorrowedHandle& socket_fd,
                                 RequestHeader<FileHandleType>* request) {
   ReceivePayload payload;
   Status<void> status = payload.Receive(socket_fd, &request->cred);
@@ -147,8 +149,10 @@
   return status;
 }
 
-Status<void> ReceiveData(int socket_fd, void* data, size_t size);
-Status<void> ReceiveDataVector(int socket_fd, const iovec* data, size_t count);
+Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
+                         size_t size);
+Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
+                               const iovec* data, size_t count);
 
 size_t CountVectorSize(const iovec* data, size_t count);
 void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index 9d038cb..f747abc 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -107,7 +107,8 @@
   };
 
   // This class must be instantiated using Create() static methods above.
-  Endpoint(const std::string& endpoint_path, bool blocking);
+  Endpoint(const std::string& endpoint_path, bool blocking,
+           bool use_init_socket_fd = true);
 
   Endpoint(const Endpoint&) = delete;
   void operator=(const Endpoint&) = delete;
@@ -116,18 +117,20 @@
     return next_message_id_.fetch_add(1, std::memory_order_relaxed);
   }
 
-  void BuildCloseMessage(int channel_id, Message* message);
+  void BuildCloseMessage(int32_t channel_id, Message* message);
 
   Status<void> AcceptConnection(Message* message);
-  Status<void> ReceiveMessageForChannel(int channel_id, Message* message);
+  Status<void> ReceiveMessageForChannel(const BorrowedHandle& channel_fd,
+                                        Message* message);
   Status<void> OnNewChannel(LocalHandle channel_fd);
-  Status<ChannelData*> OnNewChannelLocked(LocalHandle channel_fd,
-                                          Channel* channel_state);
-  Status<void> CloseChannelLocked(int channel_id);
-  Status<void> ReenableEpollEvent(int fd);
-  Channel* GetChannelState(int channel_id);
-  int GetChannelSocketFd(int channel_id);
-  int GetChannelEventFd(int channel_id);
+  Status<std::pair<int32_t, ChannelData*>> OnNewChannelLocked(
+      LocalHandle channel_fd, Channel* channel_state);
+  Status<void> CloseChannelLocked(int32_t channel_id);
+  Status<void> ReenableEpollEvent(const BorrowedHandle& channel_fd);
+  Channel* GetChannelState(int32_t channel_id);
+  BorrowedHandle GetChannelSocketFd(int32_t channel_id);
+  BorrowedHandle GetChannelEventFd(int32_t channel_id);
+  int32_t GetChannelId(const BorrowedHandle& channel_fd);
 
   std::string endpoint_path_;
   bool is_blocking_;
@@ -136,7 +139,9 @@
   LocalHandle epoll_fd_;
 
   mutable std::mutex channel_mutex_;
-  std::map<int, ChannelData> channels_;
+  std::map<int32_t, ChannelData> channels_;
+  std::map<int, int32_t> channel_fd_to_id_;
+  int32_t last_channel_id_{0};
 
   Service* service_{nullptr};
   std::atomic<uint32_t> next_message_id_;
diff --git a/libs/vr/libpdx_uds/service_dispatcher.cpp b/libs/vr/libpdx_uds/service_dispatcher.cpp
index fa98f26..2c52578 100644
--- a/libs/vr/libpdx_uds/service_dispatcher.cpp
+++ b/libs/vr/libpdx_uds/service_dispatcher.cpp
@@ -30,7 +30,7 @@
     return;
   }
 
-  epoll_fd_.Reset(epoll_create(1));  // Size arg is ignored, but must be > 0.
+  epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
   if (!epoll_fd_) {
     ALOGE("Failed to create epoll fd because: %s\n", strerror(errno));
     return;
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index f89b8a8..65fd59f 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -7,6 +7,9 @@
 #include <sys/un.h>
 #include <algorithm>  // std::min
 
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <cutils/sockets.h>
 #include <pdx/service.h>
 #include <uds/channel_manager.h>
 #include <uds/client_channel_factory.h>
@@ -124,43 +127,50 @@
 namespace pdx {
 namespace uds {
 
-Endpoint::Endpoint(const std::string& endpoint_path, bool blocking)
+Endpoint::Endpoint(const std::string& endpoint_path, bool blocking,
+                   bool use_init_socket_fd)
     : endpoint_path_{ClientChannelFactory::GetEndpointPath(endpoint_path)},
       is_blocking_{blocking} {
-  LocalHandle fd{socket(AF_UNIX, SOCK_STREAM, 0)};
-  if (!fd) {
-    ALOGE("Endpoint::Endpoint: Failed to create socket: %s", strerror(errno));
-    return;
-  }
+  LocalHandle fd;
+  if (use_init_socket_fd) {
+    // Cut off the /dev/socket/ prefix from the full socket path and use the
+    // resulting "name" to retrieve the file descriptor for the socket created
+    // by the init process.
+    constexpr char prefix[] = "/dev/socket/";
+    CHECK(android::base::StartsWith(endpoint_path_, prefix))
+        << "Endpoint::Endpoint: Socket name '" << endpoint_path_
+        << "' must begin with '" << prefix << "'";
+    std::string socket_name = endpoint_path_.substr(sizeof(prefix) - 1);
+    fd.Reset(android_get_control_socket(socket_name.c_str()));
+    CHECK(fd.IsValid())
+        << "Endpoint::Endpoint: Unable to obtain the control socket fd for '"
+        << socket_name << "'";
+    fcntl(fd.Get(), F_SETFD, FD_CLOEXEC);
+  } else {
+    fd.Reset(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
+    CHECK(fd.IsValid()) << "Endpoint::Endpoint: Failed to create socket: "
+                        << strerror(errno);
 
-  sockaddr_un local;
-  local.sun_family = AF_UNIX;
-  strncpy(local.sun_path, endpoint_path_.c_str(), sizeof(local.sun_path));
-  local.sun_path[sizeof(local.sun_path) - 1] = '\0';
+    sockaddr_un local;
+    local.sun_family = AF_UNIX;
+    strncpy(local.sun_path, endpoint_path_.c_str(), sizeof(local.sun_path));
+    local.sun_path[sizeof(local.sun_path) - 1] = '\0';
 
-  unlink(local.sun_path);
-  if (bind(fd.Get(), (struct sockaddr*)&local, sizeof(local)) == -1) {
-    ALOGE("Endpoint::Endpoint: bind error: %s", strerror(errno));
-    return;
+    unlink(local.sun_path);
+    int ret =
+        bind(fd.Get(), reinterpret_cast<sockaddr*>(&local), sizeof(local));
+    CHECK_EQ(ret, 0) << "Endpoint::Endpoint: bind error: " << strerror(errno);
   }
-  if (listen(fd.Get(), kMaxBackLogForSocketListen) == -1) {
-    ALOGE("Endpoint::Endpoint: listen error: %s", strerror(errno));
-    return;
-  }
+  CHECK_EQ(listen(fd.Get(), kMaxBackLogForSocketListen), 0)
+      << "Endpoint::Endpoint: listen error: " << strerror(errno);
 
   cancel_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
-  if (!cancel_event_fd_) {
-    ALOGE("Endpoint::Endpoint: Failed to create event fd: %s\n",
-          strerror(errno));
-    return;
-  }
+  CHECK(cancel_event_fd_.IsValid())
+      << "Endpoint::Endpoint: Failed to create event fd: " << strerror(errno);
 
-  epoll_fd_.Reset(epoll_create(1));  // Size arg is ignored, but must be > 0.
-  if (!epoll_fd_) {
-    ALOGE("Endpoint::Endpoint: Failed to create epoll fd: %s\n",
-          strerror(errno));
-    return;
-  }
+  epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
+  CHECK(epoll_fd_.IsValid())
+      << "Endpoint::Endpoint: Failed to create epoll fd: " << strerror(errno);
 
   epoll_event socket_event;
   socket_event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
@@ -170,16 +180,16 @@
   cancel_event.events = EPOLLIN;
   cancel_event.data.fd = cancel_event_fd_.Get();
 
-  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd.Get(), &socket_event) < 0 ||
-      epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, cancel_event_fd_.Get(),
-                &cancel_event) < 0) {
-    ALOGE("Endpoint::Endpoint: Failed to add event fd to epoll fd: %s\n",
-          strerror(errno));
-    cancel_event_fd_.Close();
-    epoll_fd_.Close();
-  } else {
-    socket_fd_ = std::move(fd);
-  }
+  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);
+  CHECK_EQ(ret, 0)
+      << "Endpoint::Endpoint: Failed to add cancel event fd to epoll fd: "
+      << strerror(errno);
+  socket_fd_ = std::move(fd);
 }
 
 void* Endpoint::AllocateMessageState() { return new MessageState; }
@@ -191,8 +201,9 @@
 Status<void> Endpoint::AcceptConnection(Message* message) {
   sockaddr_un remote;
   socklen_t addrlen = sizeof(remote);
-  LocalHandle channel_fd{
-      accept(socket_fd_.Get(), reinterpret_cast<sockaddr*>(&remote), &addrlen)};
+  LocalHandle channel_fd{accept4(socket_fd_.Get(),
+                                 reinterpret_cast<sockaddr*>(&remote), &addrlen,
+                                 SOCK_CLOEXEC)};
   if (!channel_fd) {
     ALOGE("Endpoint::AcceptConnection: failed to accept connection: %s",
           strerror(errno));
@@ -209,9 +220,11 @@
     return ErrorStatus(errno);
   }
 
-  auto status = ReceiveMessageForChannel(channel_fd.Get(), message);
+  // Borrow the channel handle before we pass (move) it into OnNewChannel().
+  BorrowedHandle borrowed_channel_handle = channel_fd.Borrow();
+  auto status = OnNewChannel(std::move(channel_fd));
   if (status)
-    status = OnNewChannel(std::move(channel_fd));
+    status = ReceiveMessageForChannel(borrowed_channel_handle, message);
   return status;
 }
 
@@ -236,7 +249,7 @@
   return status;
 }
 
-Status<Endpoint::ChannelData*> Endpoint::OnNewChannelLocked(
+Status<std::pair<int32_t, Endpoint::ChannelData*>> Endpoint::OnNewChannelLocked(
     LocalHandle channel_fd, Channel* channel_state) {
   epoll_event event;
   event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
@@ -248,19 +261,28 @@
     return ErrorStatus(errno);
   }
   ChannelData channel_data;
-  const int channel_id = channel_fd.Get();
   channel_data.event_set.AddDataFd(channel_fd);
   channel_data.data_fd = std::move(channel_fd);
   channel_data.channel_state = channel_state;
-  auto pair = channels_.emplace(channel_id, std::move(channel_data));
-  return &pair.first->second;
+  for (;;) {
+    // Try new channel IDs until we find one which is not already in the map.
+    if (last_channel_id_++ == std::numeric_limits<int32_t>::max())
+      last_channel_id_ = 1;
+    auto iter = channels_.lower_bound(last_channel_id_);
+    if (iter == channels_.end() || iter->first != last_channel_id_) {
+      channel_fd_to_id_.emplace(channel_data.data_fd.Get(), last_channel_id_);
+      iter = channels_.emplace_hint(iter, last_channel_id_,
+                                    std::move(channel_data));
+      return std::make_pair(last_channel_id_, &iter->second);
+    }
+  }
 }
 
-Status<void> Endpoint::ReenableEpollEvent(int fd) {
+Status<void> Endpoint::ReenableEpollEvent(const BorrowedHandle& fd) {
   epoll_event event;
   event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
-  event.data.fd = fd;
-  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd, &event) < 0) {
+  event.data.fd = fd.Get();
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd.Get(), &event) < 0) {
     ALOGE(
         "Endpoint::ReenableEpollEvent: Failed to re-enable channel to "
         "endpoint: %s\n",
@@ -275,16 +297,17 @@
   return CloseChannelLocked(channel_id);
 }
 
-Status<void> Endpoint::CloseChannelLocked(int channel_id) {
+Status<void> Endpoint::CloseChannelLocked(int32_t channel_id) {
   ALOGD_IF(TRACE, "Endpoint::CloseChannelLocked: channel_id=%d", channel_id);
 
-  auto channel_data = channels_.find(channel_id);
-  if (channel_data == channels_.end())
+  auto iter = channels_.find(channel_id);
+  if (iter == channels_.end())
     return ErrorStatus{EINVAL};
 
+  int channel_fd = iter->second.data_fd.Get();
   Status<void> status;
   epoll_event dummy;  // See BUGS in man 2 epoll_ctl.
-  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_id, &dummy) < 0) {
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_fd, &dummy) < 0) {
     status.SetError(errno);
     ALOGE(
         "Endpoint::CloseChannelLocked: Failed to remove channel from endpoint: "
@@ -294,7 +317,8 @@
     status.SetValue();
   }
 
-  channels_.erase(channel_data);
+  channel_fd_to_id_.erase(channel_fd);
+  channels_.erase(iter);
   return status;
 }
 
@@ -317,7 +341,7 @@
                                                   Channel* channel,
                                                   int* channel_id) {
   int channel_pair[2] = {};
-  if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel_pair) == -1) {
+  if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, channel_pair) == -1) {
     ALOGE("Endpoint::PushChannel: Failed to create a socket pair: %s",
           strerror(errno));
     return ErrorStatus(errno);
@@ -337,10 +361,10 @@
   }
 
   std::lock_guard<std::mutex> autolock(channel_mutex_);
-  *channel_id = local_socket.Get();
   auto channel_data = OnNewChannelLocked(std::move(local_socket), channel);
   if (!channel_data)
     return channel_data.error_status();
+  *channel_id = channel_data.get().first;
 
   // Flags are ignored for now.
   // TODO(xiaohuit): Implement those.
@@ -348,7 +372,7 @@
   auto* state = static_cast<MessageState*>(message->GetState());
   Status<ChannelReference> ref = state->PushChannelHandle(
       remote_socket.Borrow(),
-      channel_data.get()->event_set.event_fd().Borrow());
+      channel_data.get().second->event_set.event_fd().Borrow());
   if (!ref)
     return ref.error_status();
   state->sockets_to_close.push_back(std::move(remote_socket));
@@ -362,32 +386,42 @@
   return ErrorStatus(EFAULT);
 }
 
-Channel* Endpoint::GetChannelState(int channel_id) {
+Channel* Endpoint::GetChannelState(int32_t channel_id) {
   std::lock_guard<std::mutex> autolock(channel_mutex_);
   auto channel_data = channels_.find(channel_id);
   return (channel_data != channels_.end()) ? channel_data->second.channel_state
                                            : nullptr;
 }
 
-int Endpoint::GetChannelSocketFd(int channel_id) {
+BorrowedHandle Endpoint::GetChannelSocketFd(int32_t channel_id) {
   std::lock_guard<std::mutex> autolock(channel_mutex_);
+  BorrowedHandle handle;
   auto channel_data = channels_.find(channel_id);
-  return (channel_data != channels_.end()) ? channel_data->second.data_fd.Get()
-                                           : -1;
+  if (channel_data != channels_.end())
+    handle = channel_data->second.data_fd.Borrow();
+  return handle;
 }
 
-int Endpoint::GetChannelEventFd(int channel_id) {
+BorrowedHandle Endpoint::GetChannelEventFd(int32_t channel_id) {
   std::lock_guard<std::mutex> autolock(channel_mutex_);
+  BorrowedHandle handle;
   auto channel_data = channels_.find(channel_id);
-  return (channel_data != channels_.end())
-             ? channel_data->second.event_set.event_fd().Get()
-             : -1;
+  if (channel_data != channels_.end())
+    handle = channel_data->second.event_set.event_fd().Borrow();
+  return handle;
 }
 
-Status<void> Endpoint::ReceiveMessageForChannel(int channel_id,
-                                                Message* message) {
+int32_t Endpoint::GetChannelId(const BorrowedHandle& channel_fd) {
+  std::lock_guard<std::mutex> autolock(channel_mutex_);
+  auto iter = channel_fd_to_id_.find(channel_fd.Get());
+  return (iter != channel_fd_to_id_.end()) ? iter->second : -1;
+}
+
+Status<void> Endpoint::ReceiveMessageForChannel(
+    const BorrowedHandle& channel_fd, Message* message) {
   RequestHeader<LocalHandle> request;
-  auto status = ReceiveData(channel_id, &request);
+  int32_t channel_id = GetChannelId(channel_fd);
+  auto status = ReceiveData(channel_fd.Borrow(), &request);
   if (!status) {
     if (status.error() == ESHUTDOWN) {
       BuildCloseMessage(channel_id, message);
@@ -423,12 +457,12 @@
   state->request = std::move(request);
   if (request.send_len > 0 && !request.is_impulse) {
     state->request_data.resize(request.send_len);
-    status = ReceiveData(channel_id, state->request_data.data(),
+    status = ReceiveData(channel_fd, state->request_data.data(),
                          state->request_data.size());
   }
 
   if (status && request.is_impulse)
-    status = ReenableEpollEvent(channel_id);
+    status = ReenableEpollEvent(channel_fd);
 
   if (!status) {
     if (status.error() == ESHUTDOWN) {
@@ -443,7 +477,7 @@
   return status;
 }
 
-void Endpoint::BuildCloseMessage(int channel_id, Message* message) {
+void Endpoint::BuildCloseMessage(int32_t channel_id, Message* message) {
   ALOGD_IF(TRACE, "Endpoint::BuildCloseMessage: channel_id=%d", channel_id);
   MessageInfo info;
   info.pid = -1;
@@ -485,22 +519,22 @@
     auto status = AcceptConnection(message);
     if (!status)
       return status;
-    return ReenableEpollEvent(socket_fd_.Get());
+    return ReenableEpollEvent(socket_fd_.Borrow());
   }
 
-  int channel_id = event.data.fd;
+  BorrowedHandle channel_fd{event.data.fd};
   if (event.events & (EPOLLRDHUP | EPOLLHUP)) {
-    BuildCloseMessage(channel_id, message);
+    BuildCloseMessage(GetChannelId(channel_fd), message);
     return {};
   }
 
-  return ReceiveMessageForChannel(channel_id, message);
+  return ReceiveMessageForChannel(channel_fd, message);
 }
 
 Status<void> Endpoint::MessageReply(Message* message, int return_code) {
-  const int channel_id = message->GetChannelId();
-  const int channel_socket = GetChannelSocketFd(channel_id);
-  if (channel_socket < 0)
+  const int32_t channel_id = message->GetChannelId();
+  auto channel_socket = GetChannelSocketFd(channel_id);
+  if (!channel_socket)
     return ErrorStatus{EBADF};
 
   auto* state = static_cast<MessageState*>(message->GetState());
@@ -513,8 +547,7 @@
         return CloseChannel(channel_id);
       } else {
         // Reply with the event fd.
-        auto push_status = state->PushFileHandle(
-            BorrowedHandle{GetChannelEventFd(channel_socket)});
+        auto push_status = state->PushFileHandle(GetChannelEventFd(channel_id));
         state->response_data.clear();  // Just in case...
         if (!push_status)
           return push_status.error_status();
@@ -643,10 +676,8 @@
 
 std::unique_ptr<Endpoint> Endpoint::CreateAndBindSocket(
     const std::string& endpoint_path, bool blocking) {
-  // TODO(avakulenko): When Endpoint can differentiate between absolute paths
-  // and relative paths/socket names created by the init process, change this
-  // code to reflect the fact that we want to use absolute paths here.
-  return std::unique_ptr<Endpoint>(new Endpoint(endpoint_path, blocking));
+  return std::unique_ptr<Endpoint>(
+      new Endpoint(endpoint_path, blocking, false));
 }
 
 }  // namespace uds
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 3f79a7b..0daab64 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -47,7 +47,6 @@
 ]
 
 sharedLibraries = [
-    "android.dvr.composer@1.0",
     "android.hardware.graphics.allocator@2.0",
     "android.hardware.graphics.composer@2.1",
     "libbinder",
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 3750ea3..bb8613c 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -361,10 +361,10 @@
 }
 
 int DisplayService::IsVrAppRunning(pdx::Message& message) {
-  bool visible = true;
+  bool visible = false;
   ForEachDisplaySurface([&visible](const std::shared_ptr<DisplaySurface>& surface) {
-    if (surface->client_z_order() == 0 && !surface->IsVisible())
-      visible = false;
+    if (surface->client_z_order() == 0 && surface->IsVisible())
+      visible = true;
   });
 
   REPLY_SUCCESS_RETURN(message, visible, 0);
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
index b772450..5620496 100644
--- a/opengl/tests/EGLTest/Android.mk
+++ b/opengl/tests/EGLTest/Android.mk
@@ -12,12 +12,17 @@
     EGL_test.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
+	android.hardware.configstore@1.0 \
+	android.hardware.configstore-utils \
 	libEGL \
 	libcutils \
 	libbinder \
+	libhidlbase \
+	libhidltransport \
 	libutils \
 	libgui \
 	libbase \
+	liblog \
 
 LOCAL_C_INCLUDES := \
     bionic/libc/private \
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 1b3086b..94de5af 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -16,6 +16,9 @@
 
 #include <gtest/gtest.h>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+
+#include <configstore/Utils.h>
 #include <utils/String8.h>
 
 #include <EGL/egl.h>
@@ -25,10 +28,31 @@
 #include <gui/IGraphicBufferConsumer.h>
 #include <gui/BufferQueue.h>
 
+#define PIXEL_FORMAT_FLOAT "EGL_EXT_pixel_format_float"
+
+bool hasEglPixelFormatFloat() {
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+    size_t cropExtLen = strlen(PIXEL_FORMAT_FLOAT);
+    size_t extsLen = strlen(exts);
+    bool equal = !strcmp(PIXEL_FORMAT_FLOAT, exts);
+    bool atStart = !strncmp(PIXEL_FORMAT_FLOAT " ", exts, cropExtLen + 1);
+    bool atEnd = (cropExtLen + 1) < extsLen &&
+            !strcmp(" " PIXEL_FORMAT_FLOAT, exts + extsLen - (cropExtLen + 1));
+    bool inMiddle = strstr(exts, " " PIXEL_FORMAT_FLOAT " ");
+    return equal || atStart || atEnd || inMiddle;
+}
+
 namespace android {
 
 #define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
 
+// retrieve wide-color setting from configstore
+using namespace android::hardware::configstore;
+
+static bool hasWideColorDisplay =
+        getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+
 class EGLTest : public ::testing::Test {
 protected:
     EGLDisplay mEglDisplay;
@@ -169,5 +193,75 @@
     EXPECT_GE(components[3], 8);
 }
 
+TEST_F(EGLTest, EGLConfigFP16) {
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
 
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        return;
+    }
+
+    ASSERT_TRUE(hasEglPixelFormatFloat());
+
+    EGLint attrs[] = {EGL_SURFACE_TYPE,
+                      EGL_WINDOW_BIT,
+                      EGL_RENDERABLE_TYPE,
+                      EGL_OPENGL_ES2_BIT,
+                      EGL_RED_SIZE,
+                      16,
+                      EGL_GREEN_SIZE,
+                      16,
+                      EGL_BLUE_SIZE,
+                      16,
+                      EGL_ALPHA_SIZE,
+                      16,
+                      EGL_COLOR_COMPONENT_TYPE_EXT,
+                      EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+                      EGL_NONE};
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(1, numConfigs);
+
+    EGLint components[4];
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_GE(components[0], 16);
+    EXPECT_GE(components[1], 16);
+    EXPECT_GE(components[2], 16);
+    EXPECT_GE(components[3], 16);
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
+    // Create a EGLSurface
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    consumer->consumerConnect(new DummyConsumer, false);
+    sp<Surface> mSTC = new Surface(producer);
+    sp<ANativeWindow> mANW = mSTC;
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
 }
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 8fc4921..4d76272 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -13,23 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#include <cutils/properties.h>
-
 #include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
-
 #include <cutils/ashmem.h>
-#include <sensor/SensorEventQueue.h>
-
+#include <cutils/properties.h>
 #include <hardware/sensors.h>
 #include <hardware_legacy/power.h>
-
 #include <openssl/digest.h>
 #include <openssl/hmac.h>
 #include <openssl/rand.h>
+#include <sensor/SensorEventQueue.h>
+#include <utils/SystemClock.h>
 
 #include "BatteryService.h"
 #include "CorrectedGyroSensor.h"
@@ -77,7 +73,8 @@
 #define SENSOR_SERVICE_SCHED_FIFO_PRIORITY 10
 
 // Permissions.
-static const String16 sDump("android.permission.DUMP");
+static const String16 sDumpPermission("android.permission.DUMP");
+static const String16 sLocationHardwarePermission("android.permission.LOCATION_HARDWARE");
 
 SensorService::SensorService()
     : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
@@ -319,7 +316,7 @@
 
 status_t SensorService::dump(int fd, const Vector<String16>& args) {
     String8 result;
-    if (!PermissionCache::checkCallingPermission(sDump)) {
+    if (!PermissionCache::checkCallingPermission(sDumpPermission)) {
         result.appendFormat("Permission Denial: can't dump SensorService from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
                 IPCThreadState::self()->getCallingUid());
@@ -1032,6 +1029,84 @@
     return conn;
 }
 
+int SensorService::setOperationParameter(
+            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+    Mutex::Autolock _l(mLock);
+
+    // check permission
+    int32_t uid;
+    bool hasPermission = checkCallingPermission(sLocationHardwarePermission, nullptr, &uid);
+    if (!hasPermission || (uid != 1000 && uid != 0)) {
+        return PERMISSION_DENIED;
+    }
+
+    bool isFloat = true;
+    size_t expectSize = INT32_MAX;
+    switch (type) {
+        case AINFO_LOCAL_GEOMAGNETIC_FIELD:
+            isFloat = true;
+            expectSize = 3;
+            break;
+        case AINFO_LOCAL_GRAVITY:
+            isFloat = true;
+            expectSize = 1;
+            break;
+        case AINFO_DOCK_STATE:
+        case AINFO_HIGH_PERFORMANCE_MODE:
+        case AINFO_MAGNETIC_FIELD_CALIBRATION:
+            isFloat = false;
+            expectSize = 1;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    // three events: first one is begin tag, last one is end tag, the one in the middle
+    // is the payload.
+    sensors_event_t event[3];
+    int64_t timestamp = elapsedRealtimeNano();
+    for (sensors_event_t* i = event; i < event + 3; i++) {
+        *i = (sensors_event_t) {
+            .version = sizeof(sensors_event_t),
+            .sensor = 0,
+            .type = SENSOR_TYPE_ADDITIONAL_INFO,
+            .timestamp = timestamp++,
+            .additional_info = (additional_info_event_t) {
+                .serial = 0
+            }
+        };
+    }
+
+    event[0].additional_info.type = AINFO_BEGIN;
+    event[1].additional_info.type = type;
+    event[2].additional_info.type = AINFO_END;
+
+    if (isFloat) {
+        if (floats.size() != expectSize) {
+            return BAD_VALUE;
+        }
+        for (size_t i = 0; i < expectSize; ++i) {
+            event[1].additional_info.data_float[i] = floats[i];
+        }
+    } else {
+        if (ints.size() != expectSize) {
+            return BAD_VALUE;
+        }
+        for (size_t i = 0; i < expectSize; ++i) {
+            event[1].additional_info.data_int32[i] = ints[i];
+        }
+    }
+
+    SensorDevice& dev(SensorDevice::getInstance());
+    for (sensors_event_t* i = event; i < event + 3; i++) {
+        int ret = dev.injectSensorData(i);
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+    }
+    return NO_ERROR;
+}
+
 status_t SensorService::resetToNormalMode() {
     Mutex::Autolock _l(mLock);
     return resetToNormalModeLocked();
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index d0be121..2a9d6e8 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -158,6 +158,8 @@
     virtual int isDataInjectionEnabled();
     virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
             uint32_t size, int32_t type, int32_t format, const native_handle *resource);
+    virtual int setOperationParameter(
+            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints);
     virtual status_t dump(int fd, const Vector<String16>& args);
 
     String8 getSensorName(int handle) const;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index ebf72bc..76baa01 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -74,7 +74,7 @@
     libvrflinger
 
 LOCAL_SHARED_LIBRARIES := \
-    android.dvr.composer@1.0 \
+    android.frameworks.vr.composer@1.0 \
     android.hardware.graphics.allocator@2.0 \
     android.hardware.graphics.composer@2.1 \
     android.hardware.configstore@1.0 \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index c3b48ca..b5ffc60 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -80,6 +80,7 @@
 
 uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
 
+// clang-format off
 DisplayDevice::DisplayDevice(
         const sp<SurfaceFlinger>& flinger,
         DisplayType type,
@@ -91,7 +92,8 @@
         const wp<IBinder>& displayToken,
         const sp<DisplaySurface>& displaySurface,
         const sp<IGraphicBufferProducer>& producer,
-        EGLConfig config)
+        EGLConfig config,
+        bool supportWideColor)
     : lastCompositionHadVisibleLayers(false),
       mFlinger(flinger),
       mType(type),
@@ -113,12 +115,16 @@
       mPowerMode(HWC_POWER_MODE_OFF),
       mActiveConfig(0)
 {
+    // clang-format on
     Surface* surface;
     mNativeWindow = surface = new Surface(producer, false);
     ANativeWindow* const window = mNativeWindow.get();
 
 #ifdef USE_HWC2
     mActiveColorMode = static_cast<android_color_mode_t>(-1);
+    mDisplayHasWideColor = supportWideColor;
+#else
+    (void) supportWideColor;
 #endif
     /*
      * Create our display's surface
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index caa7adc..e2852a7 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -83,6 +83,7 @@
         NO_LAYER_STACK = 0xFFFFFFFF,
     };
 
+    // clang-format off
     DisplayDevice(
             const sp<SurfaceFlinger>& flinger,
             DisplayType type,
@@ -94,7 +95,9 @@
             const wp<IBinder>& displayToken,
             const sp<DisplaySurface>& displaySurface,
             const sp<IGraphicBufferProducer>& producer,
-            EGLConfig config);
+            EGLConfig config,
+            bool supportWideColor);
+    // clang-format on
 
     ~DisplayDevice();
 
@@ -146,6 +149,7 @@
     status_t beginFrame(bool mustRecompose) const;
 #ifdef USE_HWC2
     status_t prepareFrame(HWComposer& hwc);
+    bool getWideColorSupport() const { return mDisplayHasWideColor; }
 #else
     status_t prepareFrame(const HWComposer& hwc) const;
 #endif
@@ -264,6 +268,11 @@
 #ifdef USE_HWC2
     // current active color mode
     android_color_mode_t mActiveColorMode;
+
+    // Need to know if display is wide-color capable or not.
+    // Initialized by SurfaceFlinger when the DisplayDevice is created.
+    // Fed to RenderEngine during composition.
+    bool mDisplayHasWideColor;
 #endif
 };
 
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index d9bddb5..33aa759 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -17,7 +17,7 @@
 #undef LOG_TAG
 #define LOG_TAG "HwcComposer"
 
-#include <android/dvr/composer/1.0/IVrComposerClient.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <inttypes.h>
 #include <log/log.h>
 #include <gui/BufferQueue.h>
@@ -26,7 +26,7 @@
 
 namespace android {
 
-using dvr::composer::V1_0::IVrComposerClient;
+using frameworks::vr::composer::V1_0::IVrComposerClient;
 using hardware::Return;
 using hardware::hidl_vec;
 using hardware::hidl_handle;
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 486bce4..a9bb2ba 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -21,7 +21,6 @@
 
 #include <cutils/compiler.h>
 
-#include <private/gui/BitTube.h>
 #include <gui/IDisplayEventConnection.h>
 #include <gui/DisplayEventReceiver.h>
 
@@ -389,7 +388,7 @@
 
 EventThread::Connection::Connection(
         const sp<EventThread>& eventThread)
-    : count(-1), mEventThread(eventThread), mChannel(new BitTube())
+    : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize)
 {
 }
 
@@ -403,12 +402,14 @@
     mEventThread->registerDisplayEventConnection(this);
 }
 
-sp<BitTube> EventThread::Connection::getDataChannel() const {
-    return mChannel;
+status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
+    outChannel->setReceiveFd(mChannel.moveReceiveFd());
+    return NO_ERROR;
 }
 
-void EventThread::Connection::setVsyncRate(uint32_t count) {
+status_t EventThread::Connection::setVsyncRate(uint32_t count) {
     mEventThread->setVsyncRate(count, this);
+    return NO_ERROR;
 }
 
 void EventThread::Connection::requestNextVsync() {
@@ -417,7 +418,7 @@
 
 status_t EventThread::Connection::postEvent(
         const DisplayEventReceiver::Event& event) {
-    ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
+    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
 
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 3f1d0bb..6a59fbb 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <private/gui/BitTube.h>
 #include <gui/DisplayEventReceiver.h>
 #include <gui/IDisplayEventConnection.h>
 
@@ -68,11 +69,11 @@
     private:
         virtual ~Connection();
         virtual void onFirstRef();
-        virtual sp<BitTube> getDataChannel() const;
-        virtual void setVsyncRate(uint32_t count);
-        virtual void requestNextVsync();    // asynchronous
+        status_t stealReceiveChannel(gui::BitTube* outChannel) override;
+        status_t setVsyncRate(uint32_t count) override;
+        void requestNextVsync() override;    // asynchronous
         sp<EventThread> const mEventThread;
-        sp<BitTube> const mChannel;
+        gui::BitTube mChannel;
     };
 
 public:
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 16d8160..c211c7b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1011,6 +1011,9 @@
     return inverse(tr);
 }
 
+/*
+ * onDraw will draw the current layer onto the presentable buffer
+ */
 void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
         bool useIdentityTransform) const
 {
@@ -1172,6 +1175,9 @@
 
     RenderEngine& engine(mFlinger->getRenderEngine());
     engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
+#ifdef USE_HWC2
+    engine.setSourceDataSpace(mCurrentState.dataSpace);
+#endif
     engine.drawMesh(mMesh);
     engine.disableBlending();
 }
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index debea58..bca3430 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -25,7 +25,6 @@
 #include <utils/Log.h>
 
 #include <gui/IDisplayEventConnection.h>
-#include <private/gui/BitTube.h>
 
 #include "MessageQueue.h"
 #include "EventThread.h"
@@ -94,8 +93,8 @@
 {
     mEventThread = eventThread;
     mEvents = eventThread->createEventConnection();
-    mEventTube = mEvents->getDataChannel();
-    mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,
+    mEvents->stealReceiveChannel(&mEventTube);
+    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
             MessageQueue::cb_eventReceiver, this);
 }
 
@@ -150,7 +149,7 @@
 int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
     ssize_t n;
     DisplayEventReceiver::Event buffer[8];
-    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
+    while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
         for (int i=0 ; i<n ; i++) {
             if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                 mHandler->dispatchInvalidate();
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index aed0aa9..85a33c8 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -25,6 +25,7 @@
 #include <utils/Timers.h>
 #include <utils/Looper.h>
 
+#include <private/gui/BitTube.h>
 #include <gui/DisplayEventReceiver.h>
 
 #include "Barrier.h"
@@ -81,7 +82,7 @@
     sp<Looper> mLooper;
     sp<EventThread> mEventThread;
     sp<IDisplayEventConnection> mEvents;
-    sp<BitTube> mEventTube;
+    gui::BitTube mEventTube;
     sp<Handler> mHandler;
 
 
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 406e611..04fe182 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -14,11 +14,16 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "RenderEngine"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include <ui/ColorSpace.h>
+#include <ui/DebugUtils.h>
 #include <ui/Rect.h>
 
 #include <utils/String8.h>
@@ -35,6 +40,73 @@
 #include "Mesh.h"
 #include "Texture.h"
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
+#include <fstream>
+
+// ---------------------------------------------------------------------------
+#ifdef USE_HWC2
+bool checkGlError(const char* op, int lineNumber) {
+    bool errorFound = false;
+    GLint error = glGetError();
+    while (error != GL_NO_ERROR) {
+        errorFound = true;
+        error = glGetError();
+        ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error);
+    }
+    return errorFound;
+}
+
+static constexpr bool outputDebugPPMs = false;
+
+void writePPM(const char* basename, GLuint width, GLuint height) {
+    ALOGV("writePPM #%s: %d x %d", basename, width, height);
+
+    std::vector<GLubyte> pixels(width * height * 4);
+    std::vector<GLubyte> outBuffer(width * height * 3);
+
+    // TODO(courtneygo): We can now have float formats, need
+    // to remove this code or update to support.
+    // Make returned pixels fit in uint32_t, one byte per component
+    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+    if (checkGlError(__FUNCTION__, __LINE__)) {
+        return;
+    }
+
+    std::string filename(basename);
+    filename.append(".ppm");
+    std::ofstream file(filename.c_str(), std::ios::binary);
+    if (!file.is_open()) {
+        ALOGE("Unable to open file: %s", filename.c_str());
+        ALOGE("You may need to do: \"adb shell setenforce 0\" to enable "
+              "surfaceflinger to write debug images");
+        return;
+    }
+
+    file << "P6\n";
+    file << width << "\n";
+    file << height << "\n";
+    file << 255 << "\n";
+
+    auto ptr = reinterpret_cast<char*>(pixels.data());
+    auto outPtr = reinterpret_cast<char*>(outBuffer.data());
+    for (int y = height - 1; y >= 0; y--) {
+        char* data = ptr + y * width * sizeof(uint32_t);
+
+        for (GLuint x = 0; x < width; x++) {
+            // Only copy R, G and B components
+            outPtr[0] = data[0];
+            outPtr[1] = data[1];
+            outPtr[2] = data[2];
+            data += sizeof(uint32_t);
+            outPtr += 3;
+        }
+    }
+    file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
+}
+#endif
+
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
@@ -59,6 +131,28 @@
             GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
 
     //mColorBlindnessCorrection = M;
+
+#ifdef USE_HWC2
+    // retrieve wide-color and hdr settings from configstore
+    using namespace android::hardware::configstore;
+    using namespace android::hardware::configstore::V1_0;
+
+    mPlatformHasWideColor =
+            getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+    if (mPlatformHasWideColor) {
+        // Compute sRGB to DisplayP3 color transform
+        // NOTE: For now, we are limiting wide-color support to
+        // Display-P3 only.
+        mat3 srgbToP3 = ColorSpace::DisplayP3().getXYZtoRGB() * ColorSpace::sRGB().getRGBtoXYZ();
+
+        // color transform needs to be transposed and expanded to 4x4
+        // to be what the shader wants
+        // mat has an initializer that expands mat3 to mat4, but
+        // not an assignment operator
+        mat4 gamutTransform(transpose(srgbToP3));
+        mSrgbToDisplayP3 = gamutTransform;
+    }
+#endif
 }
 
 GLES20RenderEngine::~GLES20RenderEngine() {
@@ -170,6 +264,42 @@
     }
 }
 
+#ifdef USE_HWC2
+void GLES20RenderEngine::setColorMode(android_color_mode mode) {
+    ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode);
+
+    if (mColorMode == mode) return;
+
+    if (!mPlatformHasWideColor || !mDisplayHasWideColor || mode == HAL_COLOR_MODE_SRGB ||
+        mode == HAL_COLOR_MODE_NATIVE) {
+        // We are returning back to our default color_mode
+        mUseWideColor = false;
+        mWideColorFrameCount = 0;
+    } else {
+        mUseWideColor = true;
+    }
+
+    mColorMode = mode;
+}
+
+void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) {
+    if (source == HAL_DATASPACE_UNKNOWN) {
+        // Treat UNKNOWN as SRGB
+        source = HAL_DATASPACE_V0_SRGB;
+    }
+    mDataSpace = source;
+}
+
+void GLES20RenderEngine::setWideColor(bool hasWideColor) {
+    ALOGV("setWideColor: %s", hasWideColor ? "true" : "false");
+    mDisplayHasWideColor = hasWideColor;
+}
+
+bool GLES20RenderEngine::usesWideColor() {
+    return mUseWideColor;
+}
+#endif
+
 void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
     GLuint target = texture.getTextureTarget();
     glBindTexture(target, texture.getTextureName());
@@ -242,8 +372,6 @@
 
 void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
 
-    ProgramCache::getInstance().useProgram(mState);
-
     if (mesh.getTexCoordsSize()) {
         glEnableVertexAttribArray(Program::texCoords);
         glVertexAttribPointer(Program::texCoords,
@@ -259,7 +387,32 @@
             mesh.getByteStride(),
             mesh.getPositions());
 
+#ifdef USE_HWC2
+    if (usesWideColor()) {
+        Description wideColorState = mState;
+        if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
+            wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+            ALOGV("drawMesh: gamut transform applied");
+        }
+        ProgramCache::getInstance().useProgram(wideColorState);
+
+        glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+
+        if (outputDebugPPMs) {
+            std::ostringstream out;
+            out << "/data/texture_out" << mWideColorFrameCount++;
+            writePPM(out.str().c_str(), mVpWidth, mVpHeight);
+        }
+    } else {
+        ProgramCache::getInstance().useProgram(mState);
+
+        glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+    }
+#else
+    ProgramCache::getInstance().useProgram(mState);
+
     glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+#endif
 
     if (mesh.getTexCoordsSize()) {
         glDisableVertexAttribArray(Program::texCoords);
@@ -268,6 +421,13 @@
 
 void GLES20RenderEngine::dump(String8& result) {
     RenderEngine::dump(result);
+#ifdef USE_HWC2
+    if (usesWideColor()) {
+        result.append("Wide-color: On\n");
+    } else {
+        result.append("Wide-color: Off\n");
+    }
+#endif
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 7c3f9b5..19cbb60 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -72,6 +72,27 @@
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
             float alpha) override;
     virtual void setupDimLayerBlending(float alpha) override;
+
+    // Color management related functions and state
+    void setColorMode(android_color_mode mode);
+    void setSourceDataSpace(android_dataspace source);
+    void setWideColor(bool hasWideColor);
+    bool usesWideColor();
+
+    // Current color mode of display using the render engine
+    android_color_mode mColorMode = HAL_COLOR_MODE_NATIVE;
+
+    // Current dataspace of layer being rendered
+    android_dataspace mDataSpace = HAL_DATASPACE_V0_SRGB;
+
+    // Indicate if wide-color mode is needed or not
+    bool mPlatformHasWideColor = false;
+    bool mDisplayHasWideColor = false;
+    bool mUseWideColor = false;
+    uint64_t mWideColorFrameCount = 0;
+
+    // Currently only supporting sRGB and DisplayP3 color spaces
+    mat4 mSrgbToDisplayP3;
 #else
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
             int alpha);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index d19137b..8b031bc 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -98,6 +98,10 @@
 #ifdef USE_HWC2
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0;
     virtual void setupDimLayerBlending(float alpha) = 0;
+    virtual void setColorMode(android_color_mode mode) = 0;
+    virtual void setSourceDataSpace(android_dataspace source) = 0;
+    virtual void setWideColor(bool hasWideColor) = 0;
+    virtual bool usesWideColor() = 0;
 #else
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
     virtual void setupDimLayerBlending(int alpha) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 834c1c4..26baaae 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -37,6 +37,7 @@
 
 #include <dvr/vr_flinger.h>
 
+#include <ui/DebugUtils.h>
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayStatInfo.h>
 
@@ -119,6 +120,7 @@
 bool SurfaceFlinger::hasSyncFramework;
 bool SurfaceFlinger::useVrFlinger;
 int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
+bool SurfaceFlinger::hasWideColorDisplay;
 
 SurfaceFlinger::SurfaceFlinger()
     :   BnSurfaceComposer(),
@@ -189,6 +191,9 @@
     maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
             &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
 
+    hasWideColorDisplay =
+            getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+
     // debugging stuff...
     char value[PROPERTY_VALUE_MAX];
 
@@ -867,13 +872,10 @@
 
 void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
         android_color_mode_t mode) {
-    ALOGD("Set active color mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
-          this);
     int32_t type = hw->getDisplayType();
     android_color_mode_t currentMode = hw->getActiveColorMode();
 
     if (mode == currentMode) {
-        ALOGD("Screen type=%d is already in color mode=%d", hw->getDisplayType(), mode);
         return;
     }
 
@@ -882,6 +884,9 @@
         return;
     }
 
+    ALOGD("Set active color mode: %s (%d), type=%d", decodeColorMode(mode).c_str(), mode,
+          hw->getDisplayType());
+
     hw->setActiveColorMode(mode);
     getHwComposer().setActiveColorMode(type, mode);
 }
@@ -902,17 +907,17 @@
             mFlinger.getDisplayColorModes(mDisplay, &modes);
             bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
             if (mMode < 0 || !exists) {
-                ALOGE("Attempt to set invalid active color mode = %d for display %p", mMode,
-                        mDisplay.get());
+                ALOGE("Attempt to set invalid active color mode %s (%d) for display %p",
+                      decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
                 return true;
             }
             sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
             if (hw == nullptr) {
-                ALOGE("Attempt to set active color mode = %d for null display %p",
-                        mMode, mDisplay.get());
+                ALOGE("Attempt to set active color mode %s (%d) for null display %p",
+                      decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
             } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
-                ALOGW("Attempt to set active color mode= %d for virtual display",
-                        mMode);
+                ALOGW("Attempt to set active color mode %s %d for virtual display",
+                      decodeColorMode(mMode).c_str(), mMode);
             } else {
                 mFlinger.setActiveColorModeInternal(hw, mMode);
             }
@@ -1144,10 +1149,30 @@
 
         sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
                 DisplayDevice::DISPLAY_PRIMARY, consumer);
-        sp<DisplayDevice> hw = new DisplayDevice(this,
-                DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
-                producer, mRenderEngine->getEGLConfig());
+
+        bool hasWideColorModes = false;
+        std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
+        for (android_color_mode_t colorMode : modes) {
+            switch (colorMode) {
+                case HAL_COLOR_MODE_DISPLAY_P3:
+                case HAL_COLOR_MODE_ADOBE_RGB:
+                case HAL_COLOR_MODE_DCI_P3:
+                    hasWideColorModes = true;
+                    break;
+                default:
+                    break;
+            }
+        }
+        sp<DisplayDevice> hw =
+                new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
+                                  producer, mRenderEngine->getEGLConfig(),
+                                  hasWideColorModes && hasWideColorDisplay);
         mDisplays.add(token, hw);
+        android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
+        if (hasWideColorModes && hasWideColorDisplay) {
+            defaultColorMode = HAL_COLOR_MODE_SRGB;
+        }
+        setActiveColorModeInternal(hw, defaultColorMode);
     } else {
         auto type = DisplayDevice::DISPLAY_EXTERNAL;
         Mutex::Autolock _l(mStateLock);
@@ -1591,6 +1616,39 @@
     }
 }
 
+// pickColorMode translates a given dataspace into the best available color mode.
+// Currently only support sRGB and Display-P3.
+android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) {
+    switch (dataSpace) {
+        // treat Unknown as regular SRGB buffer, since that's what the rest of the
+        // system expects.
+        case HAL_DATASPACE_UNKNOWN:
+        case HAL_DATASPACE_SRGB:
+        case HAL_DATASPACE_V0_SRGB:
+            return HAL_COLOR_MODE_SRGB;
+            break;
+
+        case HAL_DATASPACE_DISPLAY_P3:
+            return HAL_COLOR_MODE_DISPLAY_P3;
+            break;
+
+        default:
+            // TODO (courtneygo): Do we want to assert an error here?
+            ALOGE("No color mode mapping for %s (%#x)", dataspaceDetails(dataSpace).c_str(),
+                  dataSpace);
+            return HAL_COLOR_MODE_SRGB;
+            break;
+    }
+}
+
+android_dataspace SurfaceFlinger::bestTargetDataSpace(android_dataspace a, android_dataspace b) {
+    // Only support sRGB and Display-P3 right now.
+    if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    }
+    return HAL_DATASPACE_V0_SRGB;
+}
+
 void SurfaceFlinger::setUpHWComposer() {
     ATRACE_CALL();
     ALOGV("setUpHWComposer");
@@ -1661,6 +1719,7 @@
     for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
         auto& displayDevice = mDisplays[displayId];
         const auto hwcId = displayDevice->getHwcDisplayId();
+
         if (hwcId < 0) {
             continue;
         }
@@ -1672,6 +1731,21 @@
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             layer->setPerFrameData(displayDevice);
         }
+
+        if (hasWideColorDisplay) {
+            android_color_mode newColorMode;
+            android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
+
+            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+                newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace);
+                ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
+                      layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
+                      layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
+            }
+            newColorMode = pickColorMode(newDataSpace);
+
+            setActiveColorModeInternal(displayDevice, newColorMode);
+        }
     }
 
     mPreviousColorMatrix = colorMatrix;
@@ -1950,10 +2024,11 @@
 
                     const wp<IBinder>& display(curr.keyAt(i));
                     if (dispSurface != NULL) {
-                        sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, hwcId, state.isSecure, display,
-                                dispSurface, producer,
-                                mRenderEngine->getEGLConfig());
+                        sp<DisplayDevice> hw =
+                                new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
+                                                  dispSurface, producer,
+                                                  mRenderEngine->getEGLConfig(),
+                                                  hasWideColorDisplay);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
@@ -2369,6 +2444,10 @@
     if (hasClientComposition) {
         ALOGV("hasClientComposition");
 
+#ifdef USE_HWC2
+        mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
+        mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
+#endif
         if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                   displayDevice->getDisplayName().string());
@@ -3014,7 +3093,6 @@
     int currentMode = hw->getPowerMode();
 
     if (mode == currentMode) {
-        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
         return;
     }
 
@@ -3171,6 +3249,12 @@
                 dumpFrameEventsLocked(result);
                 dumpAll = false;
             }
+
+            if ((index < numArgs) && (args[index] == String16("--wide-color"))) {
+                index++;
+                dumpWideColorInfo(result);
+                dumpAll = false;
+            }
         }
 
         if (dumpAll) {
@@ -3341,6 +3425,30 @@
     result.append("\n");
 }
 
+void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
+    result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
+
+    // TODO: print out if wide-color mode is active or not
+
+    for (size_t d = 0; d < mDisplays.size(); d++) {
+        const sp<const DisplayDevice>& displayDevice(mDisplays[d]);
+        int32_t hwcId = displayDevice->getHwcDisplayId();
+        if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+            continue;
+        }
+
+        result.appendFormat("Display %d color modes:\n", hwcId);
+        std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(hwcId);
+        for (auto&& mode : modes) {
+            result.appendFormat("    %s (%d)\n", decodeColorMode(mode).c_str(), mode);
+        }
+
+        android_color_mode_t currentMode = displayDevice->getActiveColorMode();
+        result.appendFormat("    Current color mode: %s (%d)\n",
+                            decodeColorMode(currentMode).c_str(), currentMode);
+    }
+    result.append("\n");
+}
 
 void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
         String8& result) const
@@ -3373,6 +3481,9 @@
     appendGuiConfigString(result);
     result.append("\n");
 
+    result.append("\nWide-Color information:\n");
+    dumpWideColorInfo(result);
+
     colorizer.bold(result);
     result.append("Sync configuration: ");
     colorizer.reset(result);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4ecbddd..46121cf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -151,6 +151,13 @@
     // FramebufferSurface
     static int64_t maxFrameBufferAcquiredBuffers;
 
+    // Indicate if platform supports color management on its
+    // wide-color display. This is typically found on devices
+    // with wide gamut (e.g. Display-P3) display.
+    // This also allows devices with wide-color displays that don't
+    // want to support color management to disable color management.
+    static bool hasWideColorDisplay;
+
     static char const* getServiceName() ANDROID_API {
         return "SurfaceFlinger";
     }
@@ -472,6 +479,12 @@
             nsecs_t vsyncPhase, nsecs_t vsyncInterval,
             nsecs_t compositeToPresentLatency);
     void rebuildLayerStacks();
+
+    // Given a dataSpace, returns the appropriate color_mode to use
+    // to display that dataSpace.
+    android_color_mode pickColorMode(android_dataspace dataSpace);
+    android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b);
+
     void setUpHWComposer();
     void doComposition();
     void doDebugFlashRegions();
@@ -522,6 +535,7 @@
     void recordBufferingStats(const char* layerName,
             std::vector<OccupancyTracker::Segment>&& history);
     void dumpBufferingStats(String8& result) const;
+    void dumpWideColorInfo(String8& result) const;
 
     bool isLayerTripleBufferingDisabled() const {
         return this->mLayerTripleBufferingDisabled;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index a6c0b9c..e640ef7 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -570,7 +570,7 @@
             sp<DisplayDevice> hw = new DisplayDevice(this,
                     type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                     fbs, producer,
-                    mRenderEngine->getEGLConfig());
+                    mRenderEngine->getEGLConfig(), false);
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
                 // FIXME: currently we don't get blank/unblank requests
                 // for displays other than the main display, so we always
@@ -1740,7 +1740,7 @@
                                 state.type, hwcDisplayId,
                                 mHwc->getFormat(hwcDisplayId), state.isSecure,
                                 display, dispSurface, producer,
-                                mRenderEngine->getEGLConfig());
+                                mRenderEngine->getEGLConfig(), false);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index 0b482f7..41b6225 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -4,3 +4,7 @@
     group graphics drmrpc readproc
     onrestart restart zygote
     writepid /dev/stune/foreground/tasks
+    socket pdx/system/vr/display/client stream 0666 system graphics
+    socket pdx/system/vr/display/manager stream 0660 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/bufferhubd/Android.mk b/services/vr/bufferhubd/Android.mk
index b3d777e..97f0332 100644
--- a/services/vr/bufferhubd/Android.mk
+++ b/services/vr/bufferhubd/Android.mk
@@ -37,8 +37,6 @@
         libui
 
 include $(CLEAR_VARS)
-# Don't strip symbols so we see stack traces in logcat.
-LOCAL_STRIP_MODULE := false
 LOCAL_SRC_FILES := $(sourceFiles)
 LOCAL_CFLAGS := -DLOG_TAG=\"bufferhubd\"
 LOCAL_CFLAGS += -DTRACE=0
diff --git a/services/vr/bufferhubd/bufferhubd.rc b/services/vr/bufferhubd/bufferhubd.rc
index 65b7293..8d57723 100644
--- a/services/vr/bufferhubd/bufferhubd.rc
+++ b/services/vr/bufferhubd/bufferhubd.rc
@@ -3,4 +3,4 @@
   user system
   group system
   writepid /dev/cpuset/tasks
-
+  socket pdx/system/buffer_hub/client stream 0660 system system
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 629d65b..b94d333 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -56,7 +56,7 @@
     "libvr_hwc-binder",
   ],
   shared_libs: [
-    "android.dvr.composer@1.0",
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
     "libbase",
     "libbinder",
diff --git a/services/vr/performanced/performanced.rc b/services/vr/performanced/performanced.rc
index 5042982..6283f37 100644
--- a/services/vr/performanced/performanced.rc
+++ b/services/vr/performanced/performanced.rc
@@ -3,3 +3,4 @@
   user root
   group system readproc
   writepid /dev/cpuset/tasks
+  socket pdx/system/performance/client stream 0666 system system
diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk
index ba0821b..638c9a8 100644
--- a/services/vr/sensord/Android.mk
+++ b/services/vr/sensord/Android.mk
@@ -51,8 +51,6 @@
           -DTRACE=0
 
 include $(CLEAR_VARS)
-# Don't strip symbols so we see stack traces in logcat.
-LOCAL_STRIP_MODULE := false
 LOCAL_SRC_FILES := $(sourceFiles)
 LOCAL_CFLAGS := $(cFlags)
 LOCAL_STATIC_LIBRARIES := $(staticLibraries)
diff --git a/services/vr/sensord/sensord.rc b/services/vr/sensord/sensord.rc
index f8d28fd..36cd377 100644
--- a/services/vr/sensord/sensord.rc
+++ b/services/vr/sensord/sensord.rc
@@ -7,3 +7,5 @@
   user system
   group system camera sdcard_rw
   writepid /dev/cpuset/system/tasks
+  socket pdx/system/vr/sensors/client stream 0666 system system
+  socket pdx/system/vr/pose/client stream 0666 system system
diff --git a/services/vr/vr_window_manager/Android.bp b/services/vr/vr_window_manager/Android.bp
index 0406331..669426b 100644
--- a/services/vr/vr_window_manager/Android.bp
+++ b/services/vr/vr_window_manager/Android.bp
@@ -47,7 +47,7 @@
 ]
 
 shared_libs = [
-    "android.dvr.composer@1.0",
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
     "libvrhwc",
     "libbase",
diff --git a/services/vr/vr_window_manager/application.cpp b/services/vr/vr_window_manager/application.cpp
index b2f02e5..8b4460a 100644
--- a/services/vr/vr_window_manager/application.cpp
+++ b/services/vr/vr_window_manager/application.cpp
@@ -206,8 +206,9 @@
     if (fade_value_ > 1.0f)
       fade_value_ = 1.0f;
 
-    controller_position_ = elbow_model_.Update(delta, last_pose_.GetRotation(),
-                                               controller_orientation_, false);
+    controller_position_ =
+        elbow_model_.Update(delta, last_pose_.GetRotation(),
+                            controller_orientation_, should_recenter_);
 
     dvrBeginRenderFrameEds(graphics_context_, pose.orientation,
                            pose.translation);
@@ -233,6 +234,7 @@
     OnEndFrame();
 
     dvrPresent(graphics_context_);
+    should_recenter_ = false;
   }
 }
 
diff --git a/services/vr/vr_window_manager/application.h b/services/vr/vr_window_manager/application.h
index 4b36ecc..ed99157 100644
--- a/services/vr/vr_window_manager/application.h
+++ b/services/vr/vr_window_manager/application.h
@@ -80,6 +80,9 @@
   bool shmem_controller_active_ = false;
   uint64_t shmem_controller_buttons_;
 
+  // Used to center the scene when the shell becomes visible.
+  bool should_recenter_ = true;
+
   bool is_visible_ = false;
   std::chrono::time_point<std::chrono::system_clock> visibility_button_press_;
   bool debug_mode_ = false;
diff --git a/services/vr/vr_window_manager/composer/1.0/Android.bp b/services/vr/vr_window_manager/composer/1.0/Android.bp
deleted file mode 100644
index 58f83f8..0000000
--- a/services/vr/vr_window_manager/composer/1.0/Android.bp
+++ /dev/null
@@ -1,54 +0,0 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
-
-genrule {
-    name: "android.dvr.composer@1.0_genc++",
-    tools: ["hidl-gen"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hidl:system/libhidl/transport -randroid.hardware:hardware/interfaces/ -randroid.dvr:frameworks/native/services/vr/vr_window_manager android.dvr.composer@1.0",
-    srcs: [
-        "IVrComposerClient.hal",
-    ],
-    out: [
-        "android/dvr/composer/1.0/VrComposerClientAll.cpp",
-    ],
-}
-
-genrule {
-    name: "android.dvr.composer@1.0_genc++_headers",
-    tools: ["hidl-gen"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hidl:system/libhidl/transport -randroid.hardware:hardware/interfaces/ -randroid.dvr:frameworks/native/services/vr/vr_window_manager android.dvr.composer@1.0",
-    srcs: [
-        "IVrComposerClient.hal",
-    ],
-    out: [
-        "android/dvr/composer/1.0/IVrComposerClient.h",
-        "android/dvr/composer/1.0/IHwVrComposerClient.h",
-        "android/dvr/composer/1.0/BnHwVrComposerClient.h",
-        "android/dvr/composer/1.0/BpHwVrComposerClient.h",
-        "android/dvr/composer/1.0/BsVrComposerClient.h",
-    ],
-}
-
-cc_library_shared {
-    name: "android.dvr.composer@1.0",
-    generated_sources: ["android.dvr.composer@1.0_genc++"],
-    generated_headers: ["android.dvr.composer@1.0_genc++_headers"],
-    export_generated_headers: ["android.dvr.composer@1.0_genc++_headers"],
-    shared_libs: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "liblog",
-        "libutils",
-        "libcutils",
-        "android.hardware.graphics.composer@2.1",
-        "android.hidl.base@1.0",
-    ],
-    export_shared_lib_headers: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libutils",
-        "android.hardware.graphics.composer@2.1",
-        "android.hidl.base@1.0",
-    ],
-}
diff --git a/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal b/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal
deleted file mode 100644
index 230a68a..0000000
--- a/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.dvr.composer@1.0;
-
-import android.hardware.graphics.composer@2.1::IComposerClient;
-
-interface IVrComposerClient
-    extends android.hardware.graphics.composer@2.1::IComposerClient {
-    /*
-     * Used to annotate the layer with additional information, which will be
-     * used to describe the content of the layer (ie: notification, permission,
-     * etc) which allows VR window manager to treat certain layer types
-     * specially.
-     *
-     * @param display is the display on which the layer was created.
-     * @param layer is the layer affected by the change.
-     * @param layer_type the type of the layer as described by the window
-     * manager.
-     * @param application_id the application id the layer belongs to.
-     * @return error is NONE upon success. Otherwise,
-     *         BAD_DISPLAY when an invalid display handle was passed in.
-     *         BAD_LAYER when an invalid layer handle was passed in.
-     *
-     * setLayerInfo(Display display,
-     *              Layer layer,
-     *              uint32_t layer_type,
-     *              uint32_t application_id)
-     *     generates(Error error);
-     */
-
-    enum VrCommand : int32_t {
-        OPCODE_SHIFT         = android.hardware.graphics.composer@2.1::IComposerClient.Command:OPCODE_SHIFT,
-
-        SET_LAYER_INFO = 0x800 << OPCODE_SHIFT,
-    };
-};
diff --git a/services/vr/vr_window_manager/composer/Android.bp b/services/vr/vr_window_manager/composer/Android.bp
index f28818a..007251f 100644
--- a/services/vr/vr_window_manager/composer/Android.bp
+++ b/services/vr/vr_window_manager/composer/Android.bp
@@ -1,7 +1,3 @@
-subdirs = [
-  "1.0",
-]
-
 cc_library_shared {
   name: "libvrhwc",
 
@@ -20,7 +16,7 @@
   ],
 
   shared_libs: [
-    "android.dvr.composer@1.0",
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
     "libbase",
     "libcutils",
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
index 367acb7..acf0dac 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <android/dvr/composer/1.0/IVrComposerClient.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <hardware/gralloc.h>
 #include <hardware/gralloc1.h>
 #include <log/log.h>
@@ -26,7 +26,7 @@
 namespace dvr {
 
 using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::dvr::composer::V1_0::IVrComposerClient;
+using android::frameworks::vr::composer::V1_0::IVrComposerClient;
 
 VrComposerClient::VrComposerClient(dvr::VrHwc& hal)
     : ComposerClient(hal), mVrHal(hal) {}
diff --git a/services/vr/vr_window_manager/display_view.cpp b/services/vr/vr_window_manager/display_view.cpp
index 52984b7..88768a0 100644
--- a/services/vr/vr_window_manager/display_view.cpp
+++ b/services/vr/vr_window_manager/display_view.cpp
@@ -219,6 +219,11 @@
       visibility = ViewMode::Hidden;
       current_vr_app_ = app;
     }
+  } else if ((use_2dmode_ || !is_vr_active) && app != 0 &&
+             visibility == ViewMode::Hidden) {
+    // This is the case for the VR app launching a 2D intent of itself on some
+    // display.
+    visibility = ViewMode::App;
   } else if (!current_vr_app_) {
     // The VR app is running.
     current_vr_app_ = app;
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 850f604..2b53cd6 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -327,7 +327,6 @@
     // Position the quad horizontally aligned in the direction the user
     // is facing, effectively taking out head roll.
     displays_[0]->Recenter(GetHorizontallyAlignedMatrixFromPose(last_pose_));
-    should_recenter_ = false;
   }
 
   for (auto& display : displays_) {
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index be2ae58..d90e833 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -84,9 +84,6 @@
   bool is_touching_ = false;
   int touchpad_buttons_ = 0;
 
-  // Used to center the scene when the shell becomes visible.
-  bool should_recenter_ = true;
-
   std::mutex display_frame_mutex_;
 
   std::vector<std::unique_ptr<DisplayView>> displays_;