Merge "Add android.hardware.strongbox_keystore feature." into pi-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 21d9ace..f65f4f8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -105,7 +105,6 @@
     { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
     { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
     { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
-    { "app",        "Application",      ATRACE_TAG_APP, { } },
     { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
     { "dalvik",     "Dalvik VM",        ATRACE_TAG_DALVIK, { } },
     { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index cb6d0c6..8421568 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -104,6 +104,12 @@
     chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
     chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
 
+    # graphics
+    chmod 0666 /sys/kernel/tracing/events/sde/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sde/enable
+    chmod 0666 /sys/kernel/tracing/events/mdss/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/mdss/enable
+
 # Tracing disabled by default
     write /sys/kernel/debug/tracing/tracing_on 0
     write /sys/kernel/tracing/tracing_on 0
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 19bf216..c929e35 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1432,19 +1432,40 @@
     printf("== Running Application Activities\n");
     printf("========================================================\n");
 
-    RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
+    // The following dumpsys internally collects output from running apps, so it can take a long
+    // time. So let's extend the timeout.
+
+    const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
+
+    RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
 
     printf("========================================================\n");
-    printf("== Running Application Services\n");
+    printf("== Running Application Services (platform)\n");
     printf("========================================================\n");
 
-    RunDumpsys("APP SERVICES", {"activity", "service", "all"});
+    RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform"},
+            DUMPSYS_COMPONENTS_OPTIONS);
 
     printf("========================================================\n");
-    printf("== Running Application Providers\n");
+    printf("== Running Application Services (non-platform)\n");
     printf("========================================================\n");
 
-    RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
+    RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
+            DUMPSYS_COMPONENTS_OPTIONS);
+
+    printf("========================================================\n");
+    printf("== Running Application Providers (platform)\n");
+    printf("========================================================\n");
+
+    RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
+            DUMPSYS_COMPONENTS_OPTIONS);
+
+    printf("========================================================\n");
+    printf("== Running Application Providers (non-platform)\n");
+    printf("========================================================\n");
+
+    RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
+            DUMPSYS_COMPONENTS_OPTIONS);
 
     printf("========================================================\n");
     printf("== Dropbox crashes\n");
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 833ffbf..860a68b 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -356,8 +356,8 @@
  * Ensure that we have a hard-limit quota to protect against abusive apps;
  * they should never use more than 90% of blocks or 50% of inodes.
  */
-static int prepare_app_quota(const std::unique_ptr<std::string>& uuid, const std::string& device,
-        uid_t uid) {
+static int prepare_app_quota(const std::unique_ptr<std::string>& uuid ATTRIBUTE_UNUSED,
+        const std::string& device, uid_t uid) {
     // Skip when reserved blocks are protecting us against abusive apps
     if (android::base::GetBoolProperty(kPropHasReserved, false)) return 0;
     // Skip when device no quotas present
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index c402c3c..3ae56db 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -114,14 +114,29 @@
         LOG(ERROR) << "Target slot suffix not legal: " << arg[2];
         exit(207);
     }
-    std::string vendor_partition = StringPrintf("/dev/block/bootdevice/by-name/vendor%s",
-                                                arg[2]);
-    int vendor_result = mount(vendor_partition.c_str(),
-                              "/postinstall/vendor",
-                              "ext4",
-                              MS_RDONLY,
-                              /* data */ nullptr);
-    UNUSED(vendor_result);
+    {
+      std::string vendor_partition = StringPrintf("/dev/block/bootdevice/by-name/vendor%s",
+                                                  arg[2]);
+      int vendor_result = mount(vendor_partition.c_str(),
+                                "/postinstall/vendor",
+                                "ext4",
+                                MS_RDONLY,
+                                /* data */ nullptr);
+      UNUSED(vendor_result);
+    }
+
+    // Try to mount the product partition. update_engine doesn't do this for us, but we
+    // want it for product APKs. Same notes as vendor above.
+    {
+      std::string product_partition = StringPrintf("/dev/block/bootdevice/by-name/product%s",
+                                                   arg[2]);
+      int product_result = mount(product_partition.c_str(),
+                                 "/postinstall/product",
+                                 "ext4",
+                                 MS_RDONLY,
+                                 /* data */ nullptr);
+      UNUSED(product_result);
+    }
 
     // Chdir into /postinstall.
     if (chdir("/postinstall") != 0) {
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index bbff6fb..bcdd03e 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -33,7 +33,7 @@
 #define TEST_APP_PRIVATE_DIR "/data/app-private/"
 #define TEST_APP_EPHEMERAL_DIR "/data/app-ephemeral/"
 #define TEST_ASEC_DIR "/mnt/asec/"
-#define TEST_EXPAND_DIR "/mnt/expand/"
+#define TEST_EXPAND_DIR "/mnt/expand/00000000-0000-0000-0000-000000000000/"
 
 #define TEST_SYSTEM_DIR1 "/system/app/"
 #define TEST_SYSTEM_DIR2 "/vendor/app/"
@@ -116,6 +116,41 @@
             << bad_path5 << " should be rejected as a invalid path";
 }
 
+TEST_F(UtilsTest, IsValidApkPath_TopDir) {
+    EXPECT_EQ(0, validate_apk_path(TEST_DATA_DIR "app/com.example"));
+    EXPECT_EQ(0, validate_apk_path(TEST_EXPAND_DIR "app/com.example"));
+    EXPECT_EQ(-1, validate_apk_path(TEST_DATA_DIR "data/com.example"));
+    EXPECT_EQ(-1, validate_apk_path(TEST_EXPAND_DIR "data/com.example"));
+}
+
+TEST_F(UtilsTest, IsValidApkPath_TopFile) {
+    EXPECT_EQ(0, validate_apk_path(TEST_DATA_DIR "app/com.example/base.apk"));
+    EXPECT_EQ(0, validate_apk_path(TEST_EXPAND_DIR "app/com.example/base.apk"));
+    EXPECT_EQ(-1, validate_apk_path(TEST_DATA_DIR "data/com.example/base.apk"));
+    EXPECT_EQ(-1, validate_apk_path(TEST_EXPAND_DIR "data/com.example/base.apk"));
+}
+
+TEST_F(UtilsTest, IsValidApkPath_OatDir) {
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat"));
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat"));
+    EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat"));
+    EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat"));
+}
+
+TEST_F(UtilsTest, IsValidApkPath_OatDirDir) {
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat/arm64"));
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat/arm64"));
+    EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat/arm64"));
+    EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat/arm64"));
+}
+
+TEST_F(UtilsTest, IsValidApkPath_OatDirDirFile) {
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat/arm64/base.odex"));
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat/arm64/base.odex"));
+    EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat/arm64/base.odex"));
+    EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat/arm64/base.odex"));
+}
+
 TEST_F(UtilsTest, IsValidApkPath_Private) {
     // Internal directories
     const char *private1 = TEST_APP_PRIVATE_DIR "example.apk";
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index a8c32ed..1ff45e4 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -855,21 +855,25 @@
  * that path. Returns -1 when an invalid path is encountered and 0 when a valid path
  * is encountered.
  */
-static int validate_apk_path_internal(const char *path, int maxSubdirs) {
-    std::string path_ = path;
-    if (validate_path(android_app_dir, path_, maxSubdirs) == 0) {
+static int validate_apk_path_internal(const std::string& path, int maxSubdirs) {
+    if (validate_path(android_app_dir, path, maxSubdirs) == 0) {
         return 0;
-    } else if (validate_path(android_app_private_dir, path_, maxSubdirs) == 0) {
+    } else if (validate_path(android_app_private_dir, path, maxSubdirs) == 0) {
         return 0;
-    } else if (validate_path(android_app_ephemeral_dir, path_, maxSubdirs) == 0) {
+    } else if (validate_path(android_app_ephemeral_dir, path, maxSubdirs) == 0) {
         return 0;
-    } else if (validate_path(android_asec_dir, path_, maxSubdirs) == 0) {
+    } else if (validate_path(android_asec_dir, path, maxSubdirs) == 0) {
         return 0;
-    } else if (validate_path(android_mnt_expand_dir, path_, std::max(maxSubdirs, 2)) == 0) {
-        return 0;
-    } else {
-        return -1;
+    } else if (android::base::StartsWith(path, android_mnt_expand_dir)) {
+        // Rewrite the path as if it were on internal storage, and test that
+        size_t end = path.find('/', android_mnt_expand_dir.size() + 1);
+        if (end != std::string::npos) {
+            auto modified = path;
+            modified.replace(0, end + 1, android_data_dir);
+            return validate_apk_path_internal(modified, maxSubdirs);
+        }
     }
+    return -1;
 }
 
 int validate_apk_path(const char* path) {
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index b74073c..5829c4f 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -36,7 +36,7 @@
 #define BYPASS_QUOTA 0
 #define BYPASS_SDCARDFS 0
 
-#define APPLY_HARD_QUOTAS 1
+#define APPLY_HARD_QUOTAS 0
 
 namespace android {
 namespace installd {
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 8e393c0..ff22048 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -503,7 +503,7 @@
     using namespace ::android::hidl::manager::V1_0;
     using namespace ::android::hidl::base::V1_0;
     using std::literals::chrono_literals::operator""s;
-    auto ret = timeoutIPC(2s, manager, &IServiceManager::debugDump, [&] (const auto &infos) {
+    auto ret = timeoutIPC(10s, manager, &IServiceManager::debugDump, [&] (const auto &infos) {
         std::map<std::string, TableEntry> entries;
         for (const auto &info : infos) {
             std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" +
diff --git a/data/etc/go_handheld_core_hardware.xml b/data/etc/go_handheld_core_hardware.xml
new file mode 100644
index 0000000..ffebc9f
--- /dev/null
+++ b/data/etc/go_handheld_core_hardware.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<!-- These are the hardware components that all Android Go handheld devices
+     must include. Devices with optional hardware must also include extra
+     hardware files, per the comments below.
+-->
+<permissions>
+    <!-- This is Android and fully CTS compatible.  Basically this is for CTS tests to use. -->
+    <feature name="android.software.cts" />
+
+    <feature name="android.hardware.audio.output" />
+    <feature name="android.hardware.camera" />
+    <feature name="android.hardware.location" />
+    <feature name="android.hardware.location.network" />
+    <feature name="android.hardware.sensor.compass" />
+    <feature name="android.hardware.sensor.accelerometer" />
+    <feature name="android.hardware.bluetooth" />
+    <feature name="android.hardware.touchscreen" />
+    <feature name="android.hardware.microphone" />
+    <feature name="android.hardware.screen.portrait" />
+    <feature name="android.hardware.screen.landscape" />
+
+    <!-- basic system services -->
+    <feature name="android.software.connectionservice" />
+    <feature name="android.software.backup" />
+    <feature name="android.software.home_screen" />
+    <feature name="android.software.input_methods" />
+    <feature name="android.software.print" />
+    <feature name="android.software.companion_device_setup" />
+    <feature name="android.software.autofill" />
+
+    <!-- Feature to specify if the device supports adding device admins. -->
+    <feature name="android.software.device_admin" />
+
+    <!-- Devices with all optimizations required to support VR Mode and
+         pass all CDD requirements for this feature may include
+         android.hardware.vr.high_performance -->
+    <!-- Devices that support VR headtracking features and pass all CDD
+         requirements may include
+         android.hardware.vr.headtracking -->
+
+    <!-- devices with GPS must include android.hardware.location.gps.xml -->
+    <!-- devices with an autofocus camera and/or flash must include either
+         android.hardware.camera.autofocus.xml or
+         android.hardware.camera.autofocus-flash.xml -->
+    <!-- devices with a front facing camera must include
+         android.hardware.camera.front.xml -->
+    <!-- devices with WiFi must also include android.hardware.wifi.xml -->
+    <!-- devices that support multitouch must include the most appropriate one
+         of these files:
+
+         If only partial (non-independent) pointers are supported:
+         android.hardware.touchscreen.multitouch.xml
+
+         If up to 4 independently tracked pointers are supported:
+         include android.hardware.touchscreen.multitouch.distinct.xml
+
+         If 5 or more independently tracked pointers are supported:
+         include android.hardware.touchscreen.multitouch.jazzhand.xml
+
+         ONLY ONE of the above should be included. -->
+    <!-- devices with an ambient light sensor must also include
+         android.hardware.sensor.light.xml -->
+    <!-- devices with a proximity sensor must also include
+         android.hardware.sensor.proximity.xml -->
+    <!-- GSM phones must also include android.hardware.telephony.gsm.xml -->
+    <!-- CDMA phones must also include android.hardware.telephony.cdma.xml -->
+    <!-- Devices that have low-latency audio stacks suitable for apps like
+         VoIP may include android.hardware.audio.low_latency.xml. ONLY apps
+         that meet the requirements specified in the CDD may include this. -->
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 6d739a1..c76e611 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -14,9 +14,9 @@
      limitations under the License.
 -->
 
-<!-- These are the hardware components that all handheld devices
-     must include. Devices with optional hardware must also include extra
-     hardware files, per the comments below.
+<!-- These are the hardware components that all handheld devices except Android Go
+     must include, for Android Go devices include go_handheld_core_hardware.xml.
+     Devices with optional hardware must also include extra hardware files, per the comments below.
 
      Handheld devices include phones, mobile Internet devices (MIDs),
      Personal Media Players (PMPs), small tablets (7" or less), and similar
diff --git a/headers/media_plugin/media/cas/CasAPI.h b/headers/media_plugin/media/cas/CasAPI.h
index 67f4511..4de314d 100644
--- a/headers/media_plugin/media/cas/CasAPI.h
+++ b/headers/media_plugin/media/cas/CasAPI.h
@@ -63,7 +63,7 @@
     // Construct a new instance of a CasPlugin given a CA_system_id
     virtual status_t createPlugin(
             int32_t CA_system_id,
-            uint64_t appData,
+            void *appData,
             CasPluginCallback callback,
             CasPlugin **plugin) = 0;
 
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 6103188..7c1eaaf 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -75,6 +75,28 @@
         ":libbinder_aidl",
     ],
 
+    target: {
+        vendor: {
+            exclude_srcs: [
+                "ActivityManager.cpp",
+                "AppOpsManager.cpp",
+                "IActivityManager.cpp",
+                "IAppOpsCallback.cpp",
+                "IAppOpsService.cpp",
+                "IBatteryStats.cpp",
+                "IMediaResourceMonitor.cpp",
+                "IPermissionController.cpp",
+                "IProcessInfoService.cpp",
+                "IUidObserver.cpp",
+                "PermissionCache.cpp",
+                "PermissionController.cpp",
+                "ProcessInfoService.cpp",
+                "IpPrefix.cpp",
+                ":libbinder_aidl",
+            ],
+        },
+    },
+
     aidl: {
         export_aidl_headers: true,
     },
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index ef67ab8..89ebc6c 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -49,6 +49,19 @@
         return reply.readInt32() != 0;
     }
 
+    virtual int32_t noteOp(const String16& op, int32_t uid, const String16& packageName)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor());
+        data.writeString16(op);
+        data.writeInt32(uid);
+        data.writeString16(packageName);
+        remote()->transact(NOTE_OP_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return 2; // MODE_ERRORED
+        return reply.readInt32();
+    }
+
     virtual void getPackagesForUid(const uid_t uid, Vector<String16>& packages)
     {
         Parcel data, reply;
@@ -111,6 +124,17 @@
             return NO_ERROR;
         } break;
 
+        case NOTE_OP_TRANSACTION: {
+            CHECK_INTERFACE(IPermissionController, data, reply);
+            String16 op = data.readString16();
+            int32_t uid = data.readInt32();
+            String16 packageName = data.readString16();
+            int32_t res = noteOp(op, uid, packageName);
+            reply->writeNoException();
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+
         case GET_PACKAGES_FOR_UID_TRANSACTION: {
             CHECK_INTERFACE(IPermissionController, data, reply);
             int32_t uid = data.readInt32();
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 70f5108..711143c 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -20,6 +20,9 @@
 
 #include <utils/Log.h>
 #include <binder/IPCThreadState.h>
+#ifndef __ANDROID_VNDK__
+#include <binder/IPermissionController.h>
+#endif
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 #include <utils/SystemClock.h>
@@ -48,6 +51,9 @@
     return gDefaultServiceManager;
 }
 
+#ifndef __ANDROID_VNDK__
+// IPermissionController is not accessible to vendors
+
 bool checkCallingPermission(const String16& permission)
 {
     return checkCallingPermission(permission, NULL, NULL);
@@ -122,6 +128,8 @@
     }
 }
 
+#endif //__ANDROID_VNDK__
+
 // ----------------------------------------------------------------------
 
 class BpServiceManager : public BpInterface<IServiceManager>
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2d196c1..2e7edd7 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -433,6 +433,7 @@
 
     mDataPos = pos;
     mNextObjectHint = 0;
+    mObjectsSorted = false;
 }
 
 status_t Parcel::setDataCapacity(size_t size)
@@ -1469,6 +1470,59 @@
     LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!");
 }
 
+status_t Parcel::validateReadData(size_t upperBound) const
+{
+    // Don't allow non-object reads on object data
+    if (mObjectsSorted || mObjectsSize <= 1) {
+data_sorted:
+        // Expect to check only against the next object
+        if (mNextObjectHint < mObjectsSize && upperBound > mObjects[mNextObjectHint]) {
+            // For some reason the current read position is greater than the next object
+            // hint. Iterate until we find the right object
+            size_t nextObject = mNextObjectHint;
+            do {
+                if (mDataPos < mObjects[nextObject] + sizeof(flat_binder_object)) {
+                    // Requested info overlaps with an object
+                    ALOGE("Attempt to read from protected data in Parcel %p", this);
+                    return PERMISSION_DENIED;
+                }
+                nextObject++;
+            } while (nextObject < mObjectsSize && upperBound > mObjects[nextObject]);
+            mNextObjectHint = nextObject;
+        }
+        return NO_ERROR;
+    }
+    // Quickly determine if mObjects is sorted.
+    binder_size_t* currObj = mObjects + mObjectsSize - 1;
+    binder_size_t* prevObj = currObj;
+    while (currObj > mObjects) {
+        prevObj--;
+        if(*prevObj > *currObj) {
+            goto data_unsorted;
+        }
+        currObj--;
+    }
+    mObjectsSorted = true;
+    goto data_sorted;
+
+data_unsorted:
+    // Insertion Sort mObjects
+    // Great for mostly sorted lists. If randomly sorted or reverse ordered mObjects become common,
+    // switch to std::sort(mObjects, mObjects + mObjectsSize);
+    for (binder_size_t* iter0 = mObjects + 1; iter0 < mObjects + mObjectsSize; iter0++) {
+        binder_size_t temp = *iter0;
+        binder_size_t* iter1 = iter0 - 1;
+        while (iter1 >= mObjects && *iter1 > temp) {
+            *(iter1 + 1) = *iter1;
+            iter1--;
+        }
+        *(iter1 + 1) = temp;
+    }
+    mNextObjectHint = 0;
+    mObjectsSorted = true;
+    goto data_sorted;
+}
+
 status_t Parcel::read(void* outData, size_t len) const
 {
     if (len > INT32_MAX) {
@@ -1479,6 +1533,15 @@
 
     if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
             && len <= pad_size(len)) {
+        if (mObjectsSize > 0) {
+            status_t err = validateReadData(mDataPos + pad_size(len));
+            if(err != NO_ERROR) {
+                // Still increment the data position by the expected length
+                mDataPos += pad_size(len);
+                ALOGV("read Setting data pos of %p to %zu", this, mDataPos);
+                return err;
+            }
+        }
         memcpy(outData, mData+mDataPos, len);
         mDataPos += pad_size(len);
         ALOGV("read Setting data pos of %p to %zu", this, mDataPos);
@@ -1497,6 +1560,16 @@
 
     if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
             && len <= pad_size(len)) {
+        if (mObjectsSize > 0) {
+            status_t err = validateReadData(mDataPos + pad_size(len));
+            if(err != NO_ERROR) {
+                // Still increment the data position by the expected length
+                mDataPos += pad_size(len);
+                ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
+                return NULL;
+            }
+        }
+
         const void* data = mData+mDataPos;
         mDataPos += pad_size(len);
         ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
@@ -1510,6 +1583,15 @@
     COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
 
     if ((mDataPos+sizeof(T)) <= mDataSize) {
+        if (mObjectsSize > 0) {
+            status_t err = validateReadData(mDataPos + sizeof(T));
+            if(err != NO_ERROR) {
+                // Still increment the data position by the expected length
+                mDataPos += sizeof(T);
+                return err;
+            }
+        }
+
         const void* data = mData+mDataPos;
         mDataPos += sizeof(T);
         *pArg =  *reinterpret_cast<const T*>(data);
@@ -2366,6 +2448,7 @@
     mObjects = const_cast<binder_size_t*>(objects);
     mObjectsSize = mObjectsCapacity = objectsCount;
     mNextObjectHint = 0;
+    mObjectsSorted = false;
     mOwner = relFunc;
     mOwnerCookie = relCookie;
     for (size_t i = 0; i < mObjectsSize; i++) {
@@ -2524,6 +2607,7 @@
     mObjects = NULL;
     mObjectsSize = mObjectsCapacity = 0;
     mNextObjectHint = 0;
+    mObjectsSorted = false;
     mHasFds = false;
     mFdsKnown = true;
     mAllowFds = true;
@@ -2610,6 +2694,7 @@
         mDataCapacity = desired;
         mObjectsSize = mObjectsCapacity = objectsSize;
         mNextObjectHint = 0;
+        mObjectsSorted = false;
 
     } else if (mData) {
         if (objectsSize < mObjectsSize) {
@@ -2631,6 +2716,7 @@
             }
             mObjectsSize = objectsSize;
             mNextObjectHint = 0;
+            mObjectsSorted = false;
         }
 
         // We own the data, so we can just do a realloc().
@@ -2703,6 +2789,7 @@
     mObjectsSize = 0;
     mObjectsCapacity = 0;
     mNextObjectHint = 0;
+    mObjectsSorted = false;
     mHasFds = false;
     mFdsKnown = true;
     mAllowFds = true;
diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp
index 25748ca..96df33c 100644
--- a/libs/binder/PermissionController.cpp
+++ b/libs/binder/PermissionController.cpp
@@ -59,6 +59,12 @@
     return service != NULL ? service->checkPermission(permission, pid, uid) : false;
 }
 
+int32_t PermissionController::noteOp(const String16& op, int32_t uid, const String16& packageName)
+{
+    sp<IPermissionController> service = getService();
+    return service != NULL ? service->noteOp(op, uid, packageName) : MODE_ERRORED;
+}
+
 void PermissionController::getPackagesForUid(const uid_t uid, Vector<String16> &packages)
 {
     sp<IPermissionController> service = getService();
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index f0613d1..9899b65 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -94,6 +94,8 @@
 
 Mutex gDefaultServiceManagerLock;
 sp<IServiceManager> gDefaultServiceManager;
+#ifndef __ANDROID_VNDK__
 sp<IPermissionController> gPermissionController;
+#endif
 
 }   // namespace android
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 3090cae..b8db091 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_ACTIVITY_MANAGER_H
 #define ANDROID_ACTIVITY_MANAGER_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IActivityManager.h>
 
 #include <utils/threads.h>
@@ -64,4 +66,8 @@
 
 }; // namespace android
 // ---------------------------------------------------------------------------
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_ACTIVITY_MANAGER_H
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index a44d270..c5b57c7 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_APP_OPS_MANAGER_H
 #define ANDROID_APP_OPS_MANAGER_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IAppOpsService.h>
 
 #include <utils/threads.h>
@@ -117,4 +119,8 @@
 
 }; // namespace android
 // ---------------------------------------------------------------------------
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_APP_OPS_MANAGER_H
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index 6607c0e..f34969b 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_IACTIVITY_MANAGER_H
 #define ANDROID_IACTIVITY_MANAGER_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IInterface.h>
 #include <binder/IUidObserver.h>
 
@@ -49,4 +51,8 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_IACTIVITY_MANAGER_H
diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/binder/include/binder/IAppOpsCallback.h
index b62e9e2..e5b12a9 100644
--- a/libs/binder/include/binder/IAppOpsCallback.h
+++ b/libs/binder/include/binder/IAppOpsCallback.h
@@ -18,6 +18,8 @@
 #ifndef ANDROID_IAPP_OPS_CALLBACK_H
 #define ANDROID_IAPP_OPS_CALLBACK_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IInterface.h>
 
 namespace android {
@@ -51,5 +53,9 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_IAPP_OPS_CALLBACK_H
 
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index ecba5d6..f0c5e17 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -18,6 +18,8 @@
 #ifndef ANDROID_IAPP_OPS_SERVICE_H
 #define ANDROID_IAPP_OPS_SERVICE_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IAppOpsCallback.h>
 #include <binder/IInterface.h>
 
@@ -75,4 +77,8 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_IAPP_OPS_SERVICE_H
diff --git a/libs/binder/include/binder/IBatteryStats.h b/libs/binder/include/binder/IBatteryStats.h
index e15d6f0..59e806c 100644
--- a/libs/binder/include/binder/IBatteryStats.h
+++ b/libs/binder/include/binder/IBatteryStats.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_IBATTERYSTATS_H
 #define ANDROID_IBATTERYSTATS_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IInterface.h>
 
 namespace android {
@@ -76,4 +78,8 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_IBATTERYSTATS_H
diff --git a/libs/binder/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
index b21047f..213ee63 100644
--- a/libs/binder/include/binder/IMediaResourceMonitor.h
+++ b/libs/binder/include/binder/IMediaResourceMonitor.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_I_MEDIA_RESOURCE_MONITOR_H
 #define ANDROID_I_MEDIA_RESOURCE_MONITOR_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IInterface.h>
 
 namespace android {
@@ -52,4 +54,8 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_I_MEDIA_RESOURCE_MONITOR_H
diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
index 2f63677..3ec459f 100644
--- a/libs/binder/include/binder/IPermissionController.h
+++ b/libs/binder/include/binder/IPermissionController.h
@@ -18,6 +18,8 @@
 #ifndef ANDROID_IPERMISSION_CONTROLLER_H
 #define ANDROID_IPERMISSION_CONTROLLER_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IInterface.h>
 #include <stdlib.h>
 
@@ -32,6 +34,8 @@
 
     virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid) = 0;
 
+    virtual int32_t noteOp(const String16& op, int32_t uid, const String16& packageName) = 0;
+
     virtual void getPackagesForUid(const uid_t uid, Vector<String16> &packages) = 0;
 
     virtual bool isRuntimePermission(const String16& permission) = 0;
@@ -40,9 +44,10 @@
 
     enum {
         CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
-        GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
-        IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2,
-        GET_PACKAGE_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 3
+        NOTE_OP_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
+        GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2,
+        IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 3,
+        GET_PACKAGE_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 4
     };
 };
 
@@ -61,5 +66,9 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_IPERMISSION_CONTROLLER_H
 
diff --git a/libs/binder/include/binder/IProcessInfoService.h b/libs/binder/include/binder/IProcessInfoService.h
index 2669f91..033c145 100644
--- a/libs/binder/include/binder/IProcessInfoService.h
+++ b/libs/binder/include/binder/IProcessInfoService.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_I_PROCESS_INFO_SERVICE_H
 #define ANDROID_I_PROCESS_INFO_SERVICE_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IInterface.h>
 
 namespace android {
@@ -46,4 +48,8 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_I_PROCESS_INFO_SERVICE_H
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index cf4c08a..197026d 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -19,7 +19,6 @@
 #define ANDROID_ISERVICE_MANAGER_H
 
 #include <binder/IInterface.h>
-#include <binder/IPermissionController.h>
 #include <utils/Vector.h>
 #include <utils/String16.h>
 
diff --git a/libs/binder/include/binder/IUidObserver.h b/libs/binder/include/binder/IUidObserver.h
index fd4d8a6..d81789e 100644
--- a/libs/binder/include/binder/IUidObserver.h
+++ b/libs/binder/include/binder/IUidObserver.h
@@ -18,6 +18,8 @@
 #ifndef ANDROID_IUID_OBSERVER_H
 #define ANDROID_IUID_OBSERVER_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IInterface.h>
 
 namespace android {
@@ -55,4 +57,8 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_IUID_OBSERVER_H
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
index 96ebaac..dd5bc3a 100644
--- a/libs/binder/include/binder/IpPrefix.h
+++ b/libs/binder/include/binder/IpPrefix.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_IP_PREFIX_H
 #define ANDROID_IP_PREFIX_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <netinet/in.h>
 
 #include <binder/Parcelable.h>
@@ -85,4 +87,8 @@
 
 }  // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif  // ANDROID_IP_PREFIX_H
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 5d36526..dede78f 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -417,6 +417,7 @@
     void                freeDataNoInit();
     void                initState();
     void                scanForFds() const;
+    status_t            validateReadData(size_t len) const;
                         
     template<class T>
     status_t            readAligned(T *pArg) const;
@@ -463,6 +464,7 @@
     size_t              mObjectsSize;
     size_t              mObjectsCapacity;
     mutable size_t      mNextObjectHint;
+    mutable bool        mObjectsSorted;
 
     mutable bool        mFdsKnown;
     mutable bool        mHasFds;
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index bcdf0c2..95eabff 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -17,6 +17,8 @@
 #ifndef BINDER_PERMISSION_H
 #define BINDER_PERMISSION_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <stdint.h>
 #include <unistd.h>
 
@@ -77,4 +79,8 @@
 // ---------------------------------------------------------------------------
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif /* BINDER_PERMISSION_H */
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
index c4c98d0..d81f514 100644
--- a/libs/binder/include/binder/PermissionController.h
+++ b/libs/binder/include/binder/PermissionController.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_PERMISSION_CONTROLLER_H
 #define ANDROID_PERMISSION_CONTROLLER_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IPermissionController.h>
 
 #include <utils/threads.h>
@@ -35,9 +37,17 @@
         MATCH_INSTANT = 1<<23
     };
 
+    enum {
+        MODE_ALLOWED = 0,
+        MODE_IGNORED = 1,
+        MODE_ERRORED = 2,
+        MODE_DEFAULT = 3,
+    };
+
     PermissionController();
 
     bool checkPermission(const String16& permission, int32_t pid, int32_t uid);
+    int32_t noteOp(const String16& op, int32_t uid, const String16& packageName);
     void getPackagesForUid(const uid_t uid, Vector<String16>& packages);
     bool isRuntimePermission(const String16& permission);
     int getPackageUid(const String16& package, int flags);
@@ -52,4 +62,8 @@
 
 }; // namespace android
 // ---------------------------------------------------------------------------
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_PERMISSION_CONTROLLER_H
diff --git a/libs/binder/include/binder/ProcessInfoService.h b/libs/binder/include/binder/ProcessInfoService.h
index 0da61ee..a03aae9 100644
--- a/libs/binder/include/binder/ProcessInfoService.h
+++ b/libs/binder/include/binder/ProcessInfoService.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_PROCESS_INFO_SERVICE_H
 #define ANDROID_PROCESS_INFO_SERVICE_H
 
+#ifndef __ANDROID_VNDK__
+
 #include <binder/IProcessInfoService.h>
 #include <utils/Errors.h>
 #include <utils/Singleton.h>
@@ -78,5 +80,9 @@
 
 }; // namespace android
 
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
+
 #endif // ANDROID_PROCESS_INFO_SERVICE_H
 
diff --git a/libs/binder/include/private/binder/Static.h b/libs/binder/include/private/binder/Static.h
index 3d10456..f04bcae 100644
--- a/libs/binder/include/private/binder/Static.h
+++ b/libs/binder/include/private/binder/Static.h
@@ -21,7 +21,9 @@
 
 #include <binder/IBinder.h>
 #include <binder/ProcessState.h>
+#ifndef __ANDROID_VNDK__
 #include <binder/IPermissionController.h>
+#endif
 #include <binder/IServiceManager.h>
 
 namespace android {
@@ -36,6 +38,8 @@
 // For IServiceManager.cpp
 extern Mutex gDefaultServiceManagerLock;
 extern sp<IServiceManager> gDefaultServiceManager;
+#ifndef __ANDROID_VNDK__
 extern sp<IPermissionController> gPermissionController;
+#endif
 
 }   // namespace android
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 835da20..8f6b1bd 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -47,6 +47,7 @@
         "android.hardware.drm@1.0::IDrmFactory",
         "android.hardware.graphics.composer@2.1::IComposer",
         "android.hardware.media.omx@1.0::IOmx",
+        "android.hardware.media.omx@1.0::IOmxStore",
         "android.hardware.sensors@1.0::ISensors",
         "android.hardware.vr@1.0::IVr",
         NULL,
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 17cf677..d70e142 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -35,7 +35,9 @@
 #include <gui/IProducerListener.h>
 
 #include <binder/IPCThreadState.h>
+#ifndef __ANDROID_VNDK__
 #include <binder/PermissionCache.h>
+#endif
 
 #include <system/window.h>
 
@@ -757,12 +759,18 @@
     }
 
     const IPCThreadState* ipc = IPCThreadState::self();
-    const pid_t pid = ipc->getCallingPid();
     const uid_t uid = ipc->getCallingUid();
+#ifndef __ANDROID_VNDK__
+    // permission check can't be done for vendors as vendors have no access to
+    // the PermissionController
+    const pid_t pid = ipc->getCallingPid();
     if ((uid != shellUid) &&
         !PermissionCache::checkPermission(String16("android.permission.DUMP"), pid, uid)) {
         outResult->appendFormat("Permission Denial: can't dump BufferQueueConsumer "
                 "from pid=%d, uid=%d\n", pid, uid);
+#else
+    if (uid != shellUid) {
+#endif
         android_errorWriteWithInfoLog(0x534e4554, "27046057",
                 static_cast<int32_t>(uid), NULL, 0);
         return PERMISSION_DENIED;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index cc67aca..78cec41 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -214,7 +214,7 @@
  * Allocates a buffer that backs an AHardwareBuffer using the passed
  * AHardwareBuffer_Desc.
  *
- * \return NO_ERROR on success, or an error number of the allocation fails for
+ * \return 0 on success, or an error number of the allocation fails for
  * any reason. The returned buffer has a reference count of 1.
  */
 int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
@@ -267,7 +267,7 @@
  * may return an error or leave the buffer's content into an indeterminate
  * state.
  *
- * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL or if the usage
+ * \return 0 on success, -EINVAL if \a buffer is NULL or if the usage
  * flags are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or an error
  * number of the lock fails for any reason.
  */
@@ -281,7 +281,7 @@
  * completed. The caller is responsible for closing the fence when it is no
  * longer needed.
  *
- * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL, or an error
+ * \return 0 on success, -EINVAL if \a buffer is NULL, or an error
  * number if the unlock fails for any reason.
  */
 int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence);
@@ -289,7 +289,7 @@
 /**
  * Send the AHardwareBuffer to an AF_UNIX socket.
  *
- * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL, or an error
+ * \return 0 on success, -EINVAL if \a buffer is NULL, or an error
  * number if the operation fails for any reason.
  */
 int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd);
@@ -297,7 +297,7 @@
 /**
  * Receive the AHardwareBuffer from an AF_UNIX socket.
  *
- * \return NO_ERROR on success, BAD_VALUE if \a outBuffer is NULL, or an error
+ * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
  * number if the operation fails for any reason.
  */
 int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer);
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index 6fe72a1..b9ae524 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -27,6 +27,7 @@
 #include <utils/Singleton.h>
 
 #include <binder/IBinder.h>
+#include <binder/IPermissionController.h>
 #include <binder/IServiceManager.h>
 
 #include <sensor/ISensorServer.h>
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
index 755e60c..50f9bf1 100644
--- a/libs/ui/HdrCapabilities.cpp
+++ b/libs/ui/HdrCapabilities.cpp
@@ -33,7 +33,7 @@
             sizeof(mMaxAverageLuminance) +
             sizeof(mMinLuminance) +
             sizeof(int32_t) +
-            mSupportedHdrTypes.size() * sizeof(int32_t);
+            mSupportedHdrTypes.size() * sizeof(ui::Hdr);
 }
 
 status_t HdrCapabilities::flatten(void* buffer, size_t size) const {
@@ -48,7 +48,7 @@
     reinterpret_cast<float&>(buf[2]) = mMinLuminance;
     buf[3] = static_cast<int32_t>(mSupportedHdrTypes.size());
     for (size_t i = 0, c = mSupportedHdrTypes.size(); i < c; ++i) {
-        buf[4 + i] = mSupportedHdrTypes[i];
+        buf[4 + i] = static_cast<int32_t>(mSupportedHdrTypes[i]);
     }
     return NO_ERROR;
 }
@@ -78,7 +78,7 @@
     if (itemCount) {
         mSupportedHdrTypes.resize(itemCount);
         for (size_t i = 0; i < itemCount; ++i) {
-            mSupportedHdrTypes[i] = buf[4 + i];
+            mSupportedHdrTypes[i] = static_cast<ui::Hdr>(buf[4 + i]);
         }
     }
     return NO_ERROR;
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 36da084..fe4ae6c 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -838,6 +838,11 @@
 }
 
 Region::const_iterator Region::end() const {
+    // Workaround for b/77643177
+    // mStorage should never be empty, but somehow it is and it's causing
+    // an abort in ubsan
+    if (mStorage.isEmpty()) return mStorage.array();
+
     size_t numRects = isRect() ? 1 : mStorage.size() - 1;
     return mStorage.array() + numRects;
 }
diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h
index bd5722f..0fa819d 100644
--- a/libs/ui/include/ui/GraphicTypes.h
+++ b/libs/ui/include/ui/GraphicTypes.h
@@ -24,6 +24,7 @@
 namespace android {
 namespace ui {
 
+using android::hardware::graphics::common::V1_0::Hdr;
 using android::hardware::graphics::common::V1_1::ColorMode;
 using android::hardware::graphics::common::V1_1::Dataspace;
 using android::hardware::graphics::common::V1_1::PixelFormat;
diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
index 925aa1b..4e98c28 100644
--- a/libs/ui/include/ui/HdrCapabilities.h
+++ b/libs/ui/include/ui/HdrCapabilities.h
@@ -21,6 +21,7 @@
 
 #include <vector>
 
+#include <ui/GraphicTypes.h>
 #include <utils/Flattenable.h>
 
 namespace android {
@@ -28,7 +29,7 @@
 class HdrCapabilities : public LightFlattenable<HdrCapabilities>
 {
 public:
-    HdrCapabilities(const std::vector<int32_t /*android_hdr_t*/>& types,
+    HdrCapabilities(const std::vector<ui::Hdr>& types,
             float maxLuminance, float maxAverageLuminance, float minLuminance)
       : mSupportedHdrTypes(types),
         mMaxLuminance(maxLuminance),
@@ -47,7 +48,7 @@
 
     ~HdrCapabilities();
 
-    const std::vector<int32_t /*android_hdr_t*/>& getSupportedHdrTypes() const {
+    const std::vector<ui::Hdr>& getSupportedHdrTypes() const {
         return mSupportedHdrTypes;
     }
     float getDesiredMaxLuminance() const { return mMaxLuminance; }
@@ -61,7 +62,7 @@
     status_t unflatten(void const* buffer, size_t size);
 
 private:
-    std::vector<int32_t /*android_hdr_t*/> mSupportedHdrTypes;
+    std::vector<ui::Hdr> mSupportedHdrTypes;
     float mMaxLuminance;
     float mMaxAverageLuminance;
     float mMinLuminance;
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 7d4e2d1..d14f040 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -41,10 +41,19 @@
     }                                                          \
   } while (0)
 
+#define DVR_V1_API_ENTRY_DEPRECATED(name)                      \
+  do {                                                         \
+    if ((offsetof(DvrApi_v1, name) + sizeof(dvr_api->name)) <= \
+        clamped_struct_size) {                                 \
+      dvr_api->name = nullptr;                                 \
+    }                                                          \
+  } while (0)
+
 #include "include/dvr/dvr_api_entries.h"
 
 // Undefine macro definitions to play nice with Google3 style rules.
 #undef DVR_V1_API_ENTRY
+#undef DVR_V1_API_ENTRY_DEPRECATED
 
     return 0;
   }
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 1a99234..baf1f2f 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -38,17 +38,13 @@
 
 extern "C" {
 
-void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer) {
-  if (write_buffer)
-    *write_buffer = new DvrWriteBuffer;
-}
-
 void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
   if (write_buffer != nullptr) {
     ALOGW_IF(
         write_buffer->slot != -1,
         "dvrWriteBufferDestroy: Destroying a buffer associated with a valid "
-        "buffer queue slot. This may indicate possible leaks.");
+        "buffer queue slot. This may indicate possible leaks, buffer_id=%d.",
+        dvrWriteBufferGetId(write_buffer));
     delete write_buffer;
   }
 }
@@ -57,14 +53,6 @@
   return write_buffer && write_buffer->write_buffer;
 }
 
-int dvrWriteBufferClear(DvrWriteBuffer* write_buffer) {
-  if (!write_buffer)
-    return -EINVAL;
-
-  write_buffer->write_buffer = nullptr;
-  return 0;
-}
-
 int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
   if (!write_buffer || !write_buffer->write_buffer)
     return -EINVAL;
@@ -81,44 +69,13 @@
       write_buffer->write_buffer->buffer()->buffer().get(), hardware_buffer);
 }
 
-int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
-                       const void* meta, size_t meta_size_bytes) {
-  if (!write_buffer || !write_buffer->write_buffer)
-    return -EINVAL;
-
-  pdx::LocalHandle fence(ready_fence_fd);
-  int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
-  return result;
-}
-
-int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
-  if (!write_buffer || !write_buffer->write_buffer || !release_fence_fd)
-    return -EINVAL;
-
-  pdx::LocalHandle release_fence;
-  int result = write_buffer->write_buffer->Gain(&release_fence);
-  *release_fence_fd = release_fence.Release();
-  return result;
-}
-
-int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
-  if (!write_buffer || !write_buffer->write_buffer)
-    return -EINVAL;
-
-  return write_buffer->write_buffer->GainAsync();
-}
-
-void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer) {
-  if (read_buffer)
-    *read_buffer = new DvrReadBuffer;
-}
-
 void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) {
   if (read_buffer != nullptr) {
     ALOGW_IF(
         read_buffer->slot != -1,
         "dvrReadBufferDestroy: Destroying a buffer associated with a valid "
-        "buffer queue slot. This may indicate possible leaks.");
+        "buffer queue slot. This may indicate possible leaks, buffer_id=%d.",
+        dvrReadBufferGetId(read_buffer));
     delete read_buffer;
   }
 }
@@ -127,14 +84,6 @@
   return read_buffer && read_buffer->read_buffer;
 }
 
-int dvrReadBufferClear(DvrReadBuffer* read_buffer) {
-  if (!read_buffer)
-    return -EINVAL;
-
-  read_buffer->read_buffer = nullptr;
-  return 0;
-}
-
 int dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
   if (!read_buffer || !read_buffer->read_buffer)
     return -EINVAL;
@@ -151,34 +100,6 @@
       read_buffer->read_buffer->buffer()->buffer().get(), hardware_buffer);
 }
 
-int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
-                         void* meta, size_t meta_size_bytes) {
-  if (!read_buffer || !read_buffer->read_buffer)
-    return -EINVAL;
-
-  pdx::LocalHandle ready_fence;
-  int result =
-      read_buffer->read_buffer->Acquire(&ready_fence, meta, meta_size_bytes);
-  *ready_fence_fd = ready_fence.Release();
-  return result;
-}
-
-int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
-  if (!read_buffer || !read_buffer->read_buffer)
-    return -EINVAL;
-
-  pdx::LocalHandle fence(release_fence_fd);
-  int result = read_buffer->read_buffer->Release(fence);
-  return result;
-}
-
-int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
-  if (!read_buffer || !read_buffer->read_buffer)
-    return -EINVAL;
-
-  return read_buffer->read_buffer->ReleaseAsync();
-}
-
 void dvrBufferDestroy(DvrBuffer* buffer) { delete buffer; }
 
 int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
@@ -196,27 +117,4 @@
   return android::dvr::kSharedBufferLayoutVersion;
 }
 
-const struct native_handle* dvrWriteBufferGetNativeHandle(
-    DvrWriteBuffer* write_buffer) {
-  if (!write_buffer || !write_buffer->write_buffer)
-    return nullptr;
-
-  return write_buffer->write_buffer->native_handle();
-}
-
-const struct native_handle* dvrReadBufferGetNativeHandle(
-    DvrReadBuffer* read_buffer) {
-  if (!read_buffer || !read_buffer->read_buffer)
-    return nullptr;
-
-  return read_buffer->read_buffer->native_handle();
-}
-
-const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer) {
-  if (!buffer || !buffer->buffer)
-    return nullptr;
-
-  return buffer->buffer->handle();
-}
-
 }  // extern "C"
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index c36d190..74cee3f 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -273,14 +273,6 @@
   return write_queue->id();
 }
 
-int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
-                                          ANativeWindow** out_window) {
-  ALOGW(
-      "dvrWriteBufferQueueGetExternalSurface: This API has been deprecated and "
-      "renamed to dvrWriteBufferQueueGetANativeWindow.");
-  return dvrWriteBufferQueueGetANativeWindow(write_queue, out_window);
-}
-
 int dvrWriteBufferQueueGetANativeWindow(DvrWriteBufferQueue* write_queue,
                                         ANativeWindow** out_window) {
   if (!write_queue || !out_window)
@@ -297,15 +289,6 @@
   return write_queue->CreateReadQueue(out_read_queue);
 }
 
-int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
-                               DvrWriteBuffer* write_buffer,
-                               int* out_fence_fd) {
-  if (!write_queue || !write_buffer || !out_fence_fd)
-    return -EINVAL;
-
-  return write_queue->Dequeue(timeout, write_buffer, out_fence_fd);
-}
-
 int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout,
                                   DvrWriteBuffer** out_write_buffer,
                                   DvrNativeBufferMetadata* out_meta,
@@ -355,34 +338,6 @@
   return 0;
 }
 
-int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer,
-                                int* out_fence_fd, void* out_meta,
-                                size_t meta_size_bytes) {
-  if (meta_size_bytes != consumer_queue_->metadata_size()) {
-    ALOGE(
-        "DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), "
-        "but actual (%zu).",
-        consumer_queue_->metadata_size(), meta_size_bytes);
-    return -EINVAL;
-  }
-
-  size_t slot;
-  pdx::LocalHandle acquire_fence;
-  auto buffer_status = consumer_queue_->Dequeue(
-      timeout, &slot, out_meta, meta_size_bytes, &acquire_fence);
-  if (!buffer_status) {
-    ALOGE_IF(buffer_status.error() != ETIMEDOUT,
-             "dvrReadBufferQueueDequeue: Failed to dequeue buffer: %s",
-             buffer_status.GetErrorMessage().c_str());
-    return -buffer_status.error();
-  }
-
-  read_buffer->read_buffer = buffer_status.take();
-  *out_fence_fd = acquire_fence.Release();
-
-  return 0;
-}
-
 int DvrReadBufferQueue::AcquireBuffer(int timeout,
                                       DvrReadBuffer** out_read_buffer,
                                       DvrNativeBufferMetadata* out_meta,
@@ -434,12 +389,22 @@
     return -EINVAL;
   }
   if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) {
-    ALOGE(
-        "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not "
-        "belong to this buffer queue. Releasing buffer: id=%d, buffer in "
-        "queue: id=%d",
-        read_buffer->read_buffer->id(), consumer_queue_->GetBufferId(slot));
-    return -EINVAL;
+    if (consumer_queue_->GetBufferId(slot) > 0) {
+      ALOGE(
+          "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released may not "
+          "belong to this queue (queue_id=%d): attempting to release buffer "
+          "(buffer_id=%d) at slot %d which holds a different buffer "
+          "(buffer_id=%d).",
+          consumer_queue_->id(), read_buffer->read_buffer->id(),
+          static_cast<int>(slot), consumer_queue_->GetBufferId(slot));
+    } else {
+      ALOGI(
+          "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released may not "
+          "belong to this queue (queue_id=%d): attempting to release buffer "
+          "(buffer_id=%d) at slot %d which is empty.",
+          consumer_queue_->id(), read_buffer->read_buffer->id(),
+          static_cast<int>(slot));
+    }
   }
 
   pdx::LocalHandle fence(release_fence_fd);
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 499b7c1..80ffc82 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -443,11 +443,13 @@
 struct DvrApi_v1 {
 // Defines an API entry for V1 (no version suffix).
 #define DVR_V1_API_ENTRY(name) Dvr##name##Ptr name
+#define DVR_V1_API_ENTRY_DEPRECATED(name) Dvr##name##Ptr name
 
 #include "dvr_api_entries.h"
 
 // Undefine macro definitions to play nice with Google3 style rules.
 #undef DVR_V1_API_ENTRY
+#undef DVR_V1_API_ENTRY_DEPRECATED
 };
 
 int dvrGetApi(void* api, size_t struct_size, int version);
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index cce8c7e..f0d8ec6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -8,6 +8,10 @@
 #error Do not include this header directly.
 #endif
 
+#ifndef DVR_V1_API_ENTRY_DEPRECATED
+#error Do not include this header directly.
+#endif
+
 // Do not delete this line: BEGIN CODEGEN OUTPUT
 // Display manager client
 DVR_V1_API_ENTRY(DisplayManagerCreate);
@@ -32,42 +36,42 @@
 DVR_V1_API_ENTRY(SurfaceStateGetAttributes);
 
 // Write buffer
-DVR_V1_API_ENTRY(WriteBufferCreateEmpty);
+DVR_V1_API_ENTRY_DEPRECATED(WriteBufferCreateEmpty);
 DVR_V1_API_ENTRY(WriteBufferDestroy);
 DVR_V1_API_ENTRY(WriteBufferIsValid);
-DVR_V1_API_ENTRY(WriteBufferClear);
+DVR_V1_API_ENTRY_DEPRECATED(WriteBufferClear);
 DVR_V1_API_ENTRY(WriteBufferGetId);
 DVR_V1_API_ENTRY(WriteBufferGetAHardwareBuffer);
-DVR_V1_API_ENTRY(WriteBufferPost);
-DVR_V1_API_ENTRY(WriteBufferGain);
-DVR_V1_API_ENTRY(WriteBufferGainAsync);
-DVR_V1_API_ENTRY(WriteBufferGetNativeHandle);
+DVR_V1_API_ENTRY_DEPRECATED(WriteBufferPost);
+DVR_V1_API_ENTRY_DEPRECATED(WriteBufferGain);
+DVR_V1_API_ENTRY_DEPRECATED(WriteBufferGainAsync);
+DVR_V1_API_ENTRY_DEPRECATED(WriteBufferGetNativeHandle);
 
 // Read buffer
-DVR_V1_API_ENTRY(ReadBufferCreateEmpty);
+DVR_V1_API_ENTRY_DEPRECATED(ReadBufferCreateEmpty);
 DVR_V1_API_ENTRY(ReadBufferDestroy);
 DVR_V1_API_ENTRY(ReadBufferIsValid);
-DVR_V1_API_ENTRY(ReadBufferClear);
+DVR_V1_API_ENTRY_DEPRECATED(ReadBufferClear);
 DVR_V1_API_ENTRY(ReadBufferGetId);
 DVR_V1_API_ENTRY(ReadBufferGetAHardwareBuffer);
-DVR_V1_API_ENTRY(ReadBufferAcquire);
-DVR_V1_API_ENTRY(ReadBufferRelease);
-DVR_V1_API_ENTRY(ReadBufferReleaseAsync);
-DVR_V1_API_ENTRY(ReadBufferGetNativeHandle);
+DVR_V1_API_ENTRY_DEPRECATED(ReadBufferAcquire);
+DVR_V1_API_ENTRY_DEPRECATED(ReadBufferRelease);
+DVR_V1_API_ENTRY_DEPRECATED(ReadBufferReleaseAsync);
+DVR_V1_API_ENTRY_DEPRECATED(ReadBufferGetNativeHandle);
 
 // Buffer
 DVR_V1_API_ENTRY(BufferDestroy);
 DVR_V1_API_ENTRY(BufferGetAHardwareBuffer);
-DVR_V1_API_ENTRY(BufferGetNativeHandle);
+DVR_V1_API_ENTRY_DEPRECATED(BufferGetNativeHandle);
 DVR_V1_API_ENTRY(BufferGlobalLayoutVersionGet);
 
 // Write buffer queue
 DVR_V1_API_ENTRY(WriteBufferQueueDestroy);
 DVR_V1_API_ENTRY(WriteBufferQueueGetCapacity);
 DVR_V1_API_ENTRY(WriteBufferQueueGetId);
-DVR_V1_API_ENTRY(WriteBufferQueueGetExternalSurface);  // deprecated
+DVR_V1_API_ENTRY_DEPRECATED(WriteBufferQueueGetExternalSurface);
 DVR_V1_API_ENTRY(WriteBufferQueueCreateReadQueue);
-DVR_V1_API_ENTRY(WriteBufferQueueDequeue);
+DVR_V1_API_ENTRY_DEPRECATED(WriteBufferQueueDequeue);
 DVR_V1_API_ENTRY(WriteBufferQueueResizeBuffer);
 
 // Read buffer queue
@@ -75,7 +79,7 @@
 DVR_V1_API_ENTRY(ReadBufferQueueGetCapacity);
 DVR_V1_API_ENTRY(ReadBufferQueueGetId);
 DVR_V1_API_ENTRY(ReadBufferQueueCreateReadQueue);
-DVR_V1_API_ENTRY(ReadBufferQueueDequeue);
+DVR_V1_API_ENTRY_DEPRECATED(ReadBufferQueueDequeue);
 DVR_V1_API_ENTRY(ReadBufferQueueSetBufferAvailableCallback);
 DVR_V1_API_ENTRY(ReadBufferQueueSetBufferRemovedCallback);
 DVR_V1_API_ENTRY(ReadBufferQueueHandleEvents);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index 935a7b2..4234844 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -14,20 +14,12 @@
 typedef struct AHardwareBuffer AHardwareBuffer;
 struct native_handle;
 
-// Creates an empty write buffer that may be filled with an acutal buffer by
-// other functions.
-void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer);
-
 // Destroys the write buffer.
 void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
 
 // Returns 1 if the given write buffer object contains a buffer, 0 otherwise.
 int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer);
 
-// Clears the contents of the buffer object. After a call to this function
-// dvrWriteBufferIsValid on the same buffer object returns 0.
-int dvrWriteBufferClear(DvrWriteBuffer* write_buffer);
-
 // Returns the global BufferHub id of this buffer.
 int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
 
@@ -36,34 +28,12 @@
 int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer);
 
-// Posts the buffer, notifying any connected read buffers. Takes ownership of
-// |ready_fence_fd|.
-int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
-                       const void* meta, size_t meta_size_bytes);
-
-// Gains a buffer that has been released by all connected read buffers.
-int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
-int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
-
-// TODO(eieio): Switch to return int and take an out parameter for the native
-// handle.
-const struct native_handle* dvrWriteBufferGetNativeHandle(
-    DvrWriteBuffer* write_buffer);
-
-// Creates an empty read buffer that may be filled with and actual buffer by
-// other functions.
-void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer);
-
 // Destroys the read buffer.
 void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
 
 // Returns 1 if the given write buffer object contains a buffer, 0 otherwise.
 int dvrReadBufferIsValid(DvrReadBuffer* read_buffer);
 
-// Clears the contents of the buffer object. After a call to this function
-// dvrReadBufferIsValid on the same buffer object returns 0.
-int dvrReadBufferClear(DvrReadBuffer* read_buffer);
-
 // Returns the global BufferHub id of this buffer.
 int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
 
@@ -72,21 +42,6 @@
 int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer);
 
-// Acquires the read buffer after it has been posted by the write buffer it is
-// connected to.
-int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
-                         void* meta, size_t meta_size_bytes);
-
-// Releases the read buffer, notifying the write buffer it is connected to.
-// Takes ownership of |release_fence_fd|.
-int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
-int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
-
-// TODO(eieio): Switch to return int and take an out parameter for the native
-// handle.
-const struct native_handle* dvrReadBufferGetNativeHandle(
-    DvrReadBuffer* read_buffer);
-
 // Destroys the buffer.
 void dvrBufferDestroy(DvrBuffer* buffer);
 
@@ -98,10 +53,6 @@
 // Retrieve the shared buffer layout version defined in dvr_shared_buffers.h.
 int dvrBufferGlobalLayoutVersionGet();
 
-// TODO(eieio): Switch to return int and take an out parameter for the native
-// handle.
-const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer);
-
 __END_DECLS
 
 #endif  // ANDROID_DVR_BUFFER_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index bf695c7..ac789da 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -76,10 +76,6 @@
 int dvrWriteBufferQueueGetANativeWindow(DvrWriteBufferQueue* write_queue,
                                         ANativeWindow** out_window);
 
-// @deprecated Please use dvrWriteBufferQueueGetANativeWindow instead.
-int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
-                                          ANativeWindow** out_window);
-
 // Create a read buffer queue from an existing write buffer queue.
 //
 // @param write_queue The DvrWriteBufferQueue of interest.
@@ -89,10 +85,6 @@
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue);
 
-// @deprecated Please use dvrWriteBufferQueueGainBuffer instead.
-int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
-                               DvrWriteBuffer* out_buffer, int* out_fence_fd);
-
 // Gains a buffer to write into.
 //
 // @param write_queue The DvrWriteBufferQueue to gain buffer from.
@@ -176,11 +168,6 @@
 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
                                       DvrReadBufferQueue** out_read_queue);
 
-// @deprecated Please use dvrReadBufferQueueAcquireBuffer instead.
-int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
-                              DvrReadBuffer* out_buffer, int* out_fence_fd,
-                              void* out_meta, size_t meta_size_bytes);
-
 // Dequeues a buffer to read from.
 //
 // @param read_queue The DvrReadBufferQueue to acquire buffer from.
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index 5d9d8b5..2d5f004 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -525,4 +525,55 @@
   }
 }
 
+TEST_F(DvrBufferQueueTest, ConsumerReleaseAfterProducerDestroy) {
+  int ret = api_.WriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(ret, 0);
+
+  DvrReadBufferQueue* read_queue = nullptr;
+  DvrReadBuffer* rb = nullptr;
+  DvrWriteBuffer* wb = nullptr;
+  DvrNativeBufferMetadata meta1;
+  DvrNativeBufferMetadata meta2;
+  int fence_fd = -1;
+
+  ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+  ASSERT_EQ(ret, 0);
+
+  api_.ReadBufferQueueSetBufferAvailableCallback(
+      read_queue, &BufferAvailableCallback, this);
+
+  // Gain buffer for writing.
+  ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb,
+                                        &meta1, &fence_fd);
+  ASSERT_EQ(ret, 0);
+  close(fence_fd);
+
+  // Post buffer to the read_queue.
+  ret = api_.WriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1);
+  ASSERT_EQ(ret, 0);
+  wb = nullptr;
+
+  // Acquire buffer for reading.
+  ret = api_.ReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10, &rb,
+                                          &meta2, &fence_fd);
+  ASSERT_EQ(ret, 0);
+  close(fence_fd);
+
+  // Destroy the write buffer queue and make sure the reader queue is picking
+  // these events up.
+  api_.WriteBufferQueueDestroy(write_queue_);
+  ret = api_.ReadBufferQueueHandleEvents(read_queue);
+  ASSERT_EQ(0, ret);
+
+  // Release buffer to the write_queue.
+  ret = api_.ReadBufferQueueReleaseBuffer(read_queue, rb, &meta2,
+                                          /*release_fence_fd=*/-1);
+  ASSERT_EQ(ret, 0);
+  rb = nullptr;
+
+  api_.ReadBufferQueueDestroy(read_queue);
+}
+
 }  // namespace
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
index f83b26e..c9a5c09 100644
--- a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -845,10 +845,10 @@
   ASSERT_NE(nullptr, write_queue.get());
 
   DvrWriteBuffer* buffer = nullptr;
-  dvrWriteBufferCreateEmpty(&buffer);
+  DvrNativeBufferMetadata metadata;
   int fence_fd = -1;
-  int error =
-      dvrWriteBufferQueueDequeue(write_queue.get(), 1000, buffer, &fence_fd);
+  int error = dvrWriteBufferQueueGainBuffer(write_queue.get(), /*timeout=*/1000,
+                                            &buffer, &metadata, &fence_fd);
   ASSERT_EQ(0, error);
 
   AHardwareBuffer* hardware_buffer = nullptr;
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index 0d30614..13aa3e9 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -589,6 +589,14 @@
   }
 
   /*
+   * Return true if a channel with the given ID exists in the Channel map.
+   */
+  bool HasChannelId(int channel_id) const {
+    std::lock_guard<std::mutex> autolock(channels_mutex_);
+    return channels_.find(channel_id) != channels_.end();
+  }
+
+  /*
    * Subclasses of Service may override this method to provide a text string
    * describing the state of the service. This method is called by
    * HandleSystemMessage in response to the standard
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index ef8cca3..34b3b0a 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -45,6 +45,14 @@
   const int user_id = message.GetEffectiveUserId();
   const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
 
+  // Check if the display_manager_ has a defunct channel.
+  if (display_manager_ && !HasChannelId(display_manager_->channel_id())) {
+    ALOGE("DisplayManagerService::OnChannelOpen: Found defunct channel %d with "
+          "no OnChannelClose, clearing prior display manager.",
+          display_manager_->channel_id());
+    display_manager_ = nullptr;
+  }
+
   // Prevent more than one display manager from registering at a time or
   // untrusted UIDs from connecting.
   if (display_manager_ || !trusted) {
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
index 3ad39d9..e8d7515 100644
--- a/opengl/include/GLES2/gl2ext.h
+++ b/opengl/include/GLES2/gl2ext.h
@@ -3612,17 +3612,6 @@
 #define GL_SHADER_BINARY_VIV              0x8FC4
 #endif /* GL_VIV_shader_binary */
 
-/* Temporary hack to allow frameworks/base/libs/hwui/debug to build.
- * This function was removed from the Khronos version of the headers
- * (it is specified with the EXT prefix, not OES). */
-#ifndef GL_ANDROID_draw_elements_base_vertex_backwards_compatibility
-#define GL_ANDROID_draw_elements_base_vertex_backwards_compatibility 1
-typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexOES (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
-#endif
-#endif /* GL_ANDROID_draw_elements_base_vertex_backwards_compatibility */
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index f3a9ad8..d6c254d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -489,6 +489,9 @@
     bool haveColorSpaceSupport = dp->haveExtension("EGL_KHR_gl_colorspace");
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        // RGB_888 is never returned by getNativePixelFormat, but is included here for completeness.
+        case HAL_PIXEL_FORMAT_RGB_888:
             if (haveColorSpaceSupport) {
                 // Spec says:
                 //     [fn1] Only OpenGL and OpenGL ES contexts which support sRGB
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 2aa4cd3..57f474b 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -515,7 +515,27 @@
         recomputeVisibleRegions = true;
     }
 
-    setDataSpace(mConsumer->getCurrentDataSpace());
+    // Dataspace::V0_SRGB and Dataspace::V0_SRGB_LINEAR are not legacy
+    // data space, however since framework doesn't distinguish them out of
+    // legacy SRGB, we have to treat them as the same for now.
+    // UNKNOWN is treated as legacy SRGB when the connected api is EGL.
+    ui::Dataspace dataSpace = mConsumer->getCurrentDataSpace();
+    switch (dataSpace) {
+        case ui::Dataspace::V0_SRGB:
+            dataSpace = ui::Dataspace::SRGB;
+            break;
+        case ui::Dataspace::V0_SRGB_LINEAR:
+            dataSpace = ui::Dataspace::SRGB_LINEAR;
+            break;
+        case ui::Dataspace::UNKNOWN:
+            if (mConsumer->getCurrentApi() == NATIVE_WINDOW_API_EGL) {
+                dataSpace = ui::Dataspace::SRGB;
+            }
+            break;
+        default:
+            break;
+    }
+    setDataSpace(dataSpace);
 
     Rect crop(mConsumer->getCurrentCrop());
     const uint32_t transform(mConsumer->getCurrentTransform());
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 58a774b..cd41662 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -55,6 +55,8 @@
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 using android::ui::ColorMode;
+using android::ui::Hdr;
+using android::ui::RenderIntent;
 
 /*
  * Initialize the display to the specified values.
@@ -75,8 +77,8 @@
         std::unique_ptr<RE::Surface> renderSurface,
         int displayWidth,
         int displayHeight,
-        bool supportWideColor,
-        bool supportHdr,
+        bool hasWideColorGamut,
+        const HdrCapabilities& hdrCapabilities,
         int initialPowerMode)
     : lastCompositionHadVisibleLayers(false),
       mFlinger(flinger),
@@ -98,10 +100,27 @@
       mActiveConfig(0),
       mActiveColorMode(ColorMode::NATIVE),
       mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY),
-      mDisplayHasWideColor(supportWideColor),
-      mDisplayHasHdr(supportHdr)
+      mHasWideColorGamut(hasWideColorGamut),
+      mHasHdr10(false),
+      mHasHLG(false),
+      mHasDolbyVision(false)
 {
     // clang-format on
+    for (Hdr hdrType : hdrCapabilities.getSupportedHdrTypes()) {
+        switch (hdrType) {
+            case Hdr::HDR10:
+                mHasHdr10 = true;
+                break;
+            case Hdr::HLG:
+                mHasHLG = true;
+                break;
+            case Hdr::DOLBY_VISION:
+                mHasDolbyVision = true;
+                break;
+            default:
+                ALOGE("UNKNOWN HDR capability: %d", static_cast<int32_t>(hdrType));
+        }
+    }
 
     // initialize the display orientation transform.
     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
@@ -268,6 +287,14 @@
     return mActiveColorMode;
 }
 
+RenderIntent DisplayDevice::getActiveRenderIntent() const {
+    return mActiveRenderIntent;
+}
+
+void DisplayDevice::setActiveRenderIntent(RenderIntent renderIntent) {
+    mActiveRenderIntent = renderIntent;
+}
+
 void DisplayDevice::setColorTransform(const mat4& transform) {
     const bool isIdentity = (transform == mat4());
     mColorTransform =
@@ -279,10 +306,15 @@
 }
 
 void DisplayDevice::setCompositionDataSpace(ui::Dataspace dataspace) {
+    mCompositionDataSpace = dataspace;
     ANativeWindow* const window = mNativeWindow.get();
     native_window_set_buffers_data_space(window, static_cast<android_dataspace>(dataspace));
 }
 
+ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
+    return mCompositionDataSpace;
+}
+
 // ----------------------------------------------------------------------------
 
 void DisplayDevice::setLayerStack(uint32_t stack) {
@@ -464,8 +496,8 @@
                         tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
     auto const surface = static_cast<Surface*>(window);
     ui::Dataspace dataspace = surface->getBuffersDataSpace();
-    result.appendFormat("   wideColor=%d, hdr=%d, colorMode=%s, dataspace: %s (%d)\n",
-                        mDisplayHasWideColor, mDisplayHasHdr,
+    result.appendFormat("   wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n",
+                        mHasWideColorGamut, mHasHdr10,
                         decodeColorMode(mActiveColorMode).c_str(),
                         dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(), dataspace);
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e844d11..cd0bed6 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -84,8 +84,8 @@
             std::unique_ptr<RE::Surface> renderSurface,
             int displayWidth,
             int displayHeight,
-            bool supportWideColor,
-            bool supportHdr,
+            bool hasWideColorGamut,
+            const HdrCapabilities& hdrCapabilities,
             int initialPowerMode);
     // clang-format on
 
@@ -135,8 +135,10 @@
     // machine happy without actually queueing a buffer if nothing has changed
     status_t beginFrame(bool mustRecompose) const;
     status_t prepareFrame(HWComposer& hwc);
-    bool getWideColorSupport() const { return mDisplayHasWideColor; }
-    bool getHdrSupport() const { return mDisplayHasHdr; }
+    bool hasWideColorGamut() const { return mHasWideColorGamut; }
+    bool hasHDR10Support() const { return mHasHdr10; }
+    bool hasHLGSupport() const { return mHasHLG; }
+    bool hasDolbyVisionSupport() const { return mHasDolbyVision; }
 
     void swapBuffers(HWComposer& hwc) const;
 
@@ -165,9 +167,12 @@
 
     ui::ColorMode getActiveColorMode() const;
     void setActiveColorMode(ui::ColorMode mode);
+    ui::RenderIntent getActiveRenderIntent() const;
+    void setActiveRenderIntent(ui::RenderIntent renderIntent);
     android_color_transform_t getColorTransform() const;
     void setColorTransform(const mat4& transform);
     void setCompositionDataSpace(ui::Dataspace dataspace);
+    ui::Dataspace getCompositionDataSpace() const;
 
     /* ------------------------------------------------------------------------
      * Display active config management.
@@ -241,14 +246,19 @@
     int mActiveConfig;
     // current active color mode
     ui::ColorMode mActiveColorMode;
+    // Current active render intent.
+    ui::RenderIntent mActiveRenderIntent;
+    ui::Dataspace mCompositionDataSpace;
     // Current color transform
     android_color_transform_t mColorTransform;
 
     // 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;
-    bool mDisplayHasHdr;
+    bool mHasWideColorGamut;
+    bool mHasHdr10;
+    bool mHasHLG;
+    bool mHasDolbyVision;
 };
 
 struct DisplayDeviceState {
@@ -281,7 +291,8 @@
                               rotation) {}
     DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqHeight,
                       uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
-          : RenderArea(reqHeight, reqWidth, rotation), mDevice(device), mSourceCrop(sourceCrop) {}
+          : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device),
+                              mSourceCrop(sourceCrop) {}
 
     const Transform& getTransform() const override { return mDevice->getTransform(); }
     Rect getBounds() const override { return mDevice->getBounds(); }
@@ -290,9 +301,9 @@
     bool isSecure() const override { return mDevice->isSecure(); }
     bool needsFiltering() const override { return mDevice->needsFiltering(); }
     Rect getSourceCrop() const override { return mSourceCrop; }
-    bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); }
-    ui::ColorMode getActiveColorMode() const override {
-        return mDevice->getActiveColorMode();
+    bool getWideColorSupport() const override { return mDevice->hasWideColorGamut(); }
+    ui::Dataspace getDataSpace() const override {
+        return mDevice->getCompositionDataSpace();
     }
 
 private:
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 5f94bb4..0667f8d 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -448,26 +448,21 @@
     return Error::None;
 }
 
-Error Display::getHdrCapabilities(
-        std::unique_ptr<HdrCapabilities>* outCapabilities) const
+Error Display::getHdrCapabilities(HdrCapabilities* outCapabilities) const
 {
     float maxLuminance = -1.0f;
     float maxAverageLuminance = -1.0f;
     float minLuminance = -1.0f;
-    std::vector<Hwc2::Hdr> intTypes;
-    auto intError = mComposer.getHdrCapabilities(mId, &intTypes,
+    std::vector<Hwc2::Hdr> types;
+    auto intError = mComposer.getHdrCapabilities(mId, &types,
             &maxLuminance, &maxAverageLuminance, &minLuminance);
     auto error = static_cast<HWC2::Error>(intError);
 
-    std::vector<int32_t> types;
-    for (auto type : intTypes) {
-        types.push_back(static_cast<int32_t>(type));
-    }
     if (error != Error::None) {
         return error;
     }
 
-    *outCapabilities = std::make_unique<HdrCapabilities>(std::move(types),
+    *outCapabilities = HdrCapabilities(std::move(types),
             maxLuminance, maxAverageLuminance, minLuminance);
     return Error::None;
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index e5779d4..aa907ea 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -228,7 +228,7 @@
     [[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
     [[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
     [[clang::warn_unused_result]] Error getHdrCapabilities(
-            std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
+            android::HdrCapabilities* outCapabilities) const;
     [[clang::warn_unused_result]] Error getReleaseFences(
             std::unordered_map<Layer*,
                     android::sp<android::Fence>>* outFences) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 8db8aa6..0a3ac84 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -824,24 +824,22 @@
     mDisplayData[displayId].releaseFences.clear();
 }
 
-std::unique_ptr<HdrCapabilities> HWComposer::getHdrCapabilities(
-        int32_t displayId) {
+status_t HWComposer::getHdrCapabilities(
+        int32_t displayId, HdrCapabilities* outCapabilities) {
     if (!isValidDisplay(displayId)) {
         ALOGE("getHdrCapabilities: Display %d is not valid", displayId);
-        return nullptr;
+        return BAD_INDEX;
     }
 
     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
-    std::unique_ptr<HdrCapabilities> capabilities;
-    auto error = hwcDisplay->getHdrCapabilities(&capabilities);
+    auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
     if (error != HWC2::Error::None) {
         ALOGE("getOutputCapabilities: Failed to get capabilities on display %d:"
-                " %s (%d)", displayId, to_string(error).c_str(),
-                static_cast<int32_t>(error));
-        return nullptr;
+              " %s (%d)", displayId, to_string(error).c_str(),
+              static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
     }
-
-    return capabilities;
+    return NO_ERROR;
 }
 
 std::vector<ui::RenderIntent> HWComposer::getRenderIntents(int32_t displayId,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index e86d621..138e1f1 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -134,8 +134,8 @@
     // it can call this to clear the shared pointers in the release fence map
     void clearReleaseFences(int32_t displayId);
 
-    // Returns the HDR capabilities of the given display
-    std::unique_ptr<HdrCapabilities> getHdrCapabilities(int32_t displayId);
+    // Fetches the HDR capabilities of the given display
+    status_t getHdrCapabilities(int32_t displayId, HdrCapabilities* outCapabilities);
 
     // Returns the available RenderIntent of the given display.
     std::vector<ui::RenderIntent> getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9d356d8..66ad2f6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -23,6 +23,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <algorithm>
 
 #include <cutils/compiler.h>
 #include <cutils/native_handle.h>
@@ -1643,6 +1644,11 @@
     return true;
 }
 
+bool Layer::isLegacySrgbDataSpace() const {
+    return mDrawingState.dataSpace == ui::Dataspace::SRGB ||
+        mDrawingState.dataSpace == ui::Dataspace::SRGB_LINEAR;
+}
+
 void Layer::setParent(const sp<Layer>& layer) {
     mCurrentParent = layer;
 }
@@ -1772,29 +1778,81 @@
     }
 }
 
-/**
- * Traverse only children in z order, ignoring relative layers.
- */
-void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet,
-                                     const LayerVector::Visitor& visitor) {
+LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet,
+                                             const std::vector<Layer*>& layersInTree) {
+    LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid,
+                        "makeTraversalList received invalid stateSet");
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
+
+    LayerVector traverse;
+    for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
+        sp<Layer> strongRelative = weakRelative.promote();
+        // Only add relative layers that are also descendents of the top most parent of the tree.
+        // If a relative layer is not a descendent, then it should be ignored.
+        if (std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) {
+            traverse.add(strongRelative);
+        }
+    }
+
+    for (const sp<Layer>& child : children) {
+        const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
+        // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a
+        // descendent of the top most parent of the tree. If it's not a descendent, then just add
+        // the child here since it won't be added later as a relative.
+        if (std::binary_search(layersInTree.begin(), layersInTree.end(),
+                               childState.zOrderRelativeOf.promote().get())) {
+            continue;
+        }
+        traverse.add(child);
+    }
+
+    return traverse;
+}
+
+void Layer::traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree,
+                                          LayerVector::StateSet stateSet,
+                                          const LayerVector::Visitor& visitor) {
+    const LayerVector list = makeChildrenTraversalList(stateSet, layersInTree);
 
     size_t i = 0;
-    for (; i < children.size(); i++) {
-        const auto& relative = children[i];
+    for (; i < list.size(); i++) {
+        const auto& relative = list[i];
         if (relative->getZ() >= 0) {
             break;
         }
-        relative->traverseChildrenInZOrder(stateSet, visitor);
+        relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor);
     }
+
     visitor(this);
-    for (; i < children.size(); i++) {
-        const auto& relative = children[i];
-        relative->traverseChildrenInZOrder(stateSet, visitor);
+    for (; i < list.size(); i++) {
+        const auto& relative = list[i];
+        relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor);
     }
 }
 
+std::vector<Layer*> Layer::getLayersInTree(LayerVector::StateSet stateSet) {
+    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+    const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
+
+    std::vector<Layer*> layersInTree = {this};
+    for (size_t i = 0; i < children.size(); i++) {
+        const auto& child = children[i];
+        std::vector<Layer*> childLayers = child->getLayersInTree(stateSet);
+        layersInTree.insert(layersInTree.end(), childLayers.cbegin(), childLayers.cend());
+    }
+
+    return layersInTree;
+}
+
+void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet,
+                                     const LayerVector::Visitor& visitor) {
+    std::vector<Layer*> layersInTree = getLayersInTree(stateSet);
+    std::sort(layersInTree.begin(), layersInTree.end());
+    traverseChildrenInZOrderInner(layersInTree, stateSet, visitor);
+}
+
 Transform Layer::getTransform() const {
     Transform t;
     const auto& p = mDrawingParent.promote();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8d2a048..be3967b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -51,6 +51,7 @@
 #include "RenderEngine/Texture.h"
 
 #include <math/vec4.h>
+#include <vector>
 
 using namespace android::surfaceflinger;
 
@@ -297,6 +298,13 @@
     bool reparent(const sp<IBinder>& newParentHandle);
     bool detachChildren();
 
+    // Before color management is introduced, contents on Android have to be
+    // desaturated in order to match what they appears like visually.
+    // With color management, these contents will appear desaturated, thus
+    // needed to be saturated so that they match what they are designed for
+    // visually. When returns true, legacy SRGB data space is passed to HWC.
+    bool isLegacySrgbDataSpace() const;
+
     // If we have received a new buffer this frame, we will pass its surface
     // damage down to hardware composer. Otherwise, we must send a region with
     // one empty rect.
@@ -557,6 +565,10 @@
                                  const LayerVector::Visitor& visitor);
     void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor);
 
+    /**
+     * Traverse only children in z order, ignoring relative layers that are not children of the
+     * parent.
+     */
     void traverseChildrenInZOrder(LayerVector::StateSet stateSet,
                                   const LayerVector::Visitor& visitor);
 
@@ -771,6 +783,22 @@
     wp<Layer> mDrawingParent;
 
     mutable LayerBE mBE;
+
+private:
+    /**
+     * Returns an unsorted vector of all layers that are part of this tree.
+     * That includes the current layer and all its descendants.
+     */
+    std::vector<Layer*> getLayersInTree(LayerVector::StateSet stateSet);
+    /**
+     * Traverses layers that are part of this tree in the correct z order.
+     * layersInTree must be sorted before calling this method.
+     */
+    void traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree,
+                                       LayerVector::StateSet stateSet,
+                                       const LayerVector::Visitor& visitor);
+    LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet,
+                                          const std::vector<Layer*>& layersInTree);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index 38ea6ed..04ab121 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -57,11 +57,12 @@
 }
 
 void LayerStats::traverseLayerTreeStatsLocked(
-        std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
-        const LayerProtoParser::LayerGlobal* layerGlobal, std::vector<std::string>& layerShapeVec) {
-    for (std::unique_ptr<LayerProtoParser::Layer>& layer : layerTree) {
+        const std::vector<std::unique_ptr<LayerProtoParser::Layer>>& layerTree,
+        const LayerProtoParser::LayerGlobal& layerGlobal,
+        std::vector<std::string>* const outLayerShapeVec) {
+    for (const auto& layer : layerTree) {
         if (!layer) continue;
-        traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal, layerShapeVec);
+        traverseLayerTreeStatsLocked(layer->children, layerGlobal, outLayerShapeVec);
         std::string key = "";
         base::StringAppendF(&key, ",%s", layer->type.c_str());
         base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
@@ -70,21 +71,21 @@
         base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format));
         base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
         base::StringAppendF(&key, ",%s",
-                            destinationLocation(layer->hwcFrame.left, layerGlobal->resolution[0],
+                            destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0],
                                                 true));
         base::StringAppendF(&key, ",%s",
-                            destinationLocation(layer->hwcFrame.top, layerGlobal->resolution[1],
+                            destinationLocation(layer->hwcFrame.top, layerGlobal.resolution[1],
                                                 false));
         base::StringAppendF(&key, ",%s",
                             destinationSize(layer->hwcFrame.right - layer->hwcFrame.left,
-                                            layerGlobal->resolution[0], true));
+                                            layerGlobal.resolution[0], true));
         base::StringAppendF(&key, ",%s",
                             destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
-                                            layerGlobal->resolution[1], false));
+                                            layerGlobal.resolution[1], false));
         base::StringAppendF(&key, ",%s", scaleRatioWH(layer.get()).c_str());
         base::StringAppendF(&key, ",%s", alpha(static_cast<float>(layer->color.a)));
 
-        layerShapeVec.push_back(key);
+        outLayerShapeVec->push_back(key);
         ALOGV("%s", key.c_str());
     }
 }
@@ -97,7 +98,7 @@
     std::vector<std::string> layerShapeVec;
 
     std::lock_guard<std::mutex> lock(mMutex);
-    traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal, layerShapeVec);
+    traverseLayerTreeStatsLocked(layerTree, layerGlobal, &layerShapeVec);
 
     std::string layerShapeKey =
             base::StringPrintf("%d,%s,%s,%s", static_cast<int32_t>(layerShapeVec.size()),
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 7871fc6..7a190fd 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -38,9 +38,9 @@
 private:
     // Traverse layer tree to get all visible layers' stats
     void traverseLayerTreeStatsLocked(
-            std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
-            const LayerProtoParser::LayerGlobal* layerGlobal,
-            std::vector<std::string>& layerShapeVec);
+            const std::vector<std::unique_ptr<LayerProtoParser::Layer>>& layerTree,
+            const LayerProtoParser::LayerGlobal& layerGlobal,
+            std::vector<std::string>* const outLayerShapeVec);
     // Convert layer's top-left position into 8x8 percentage of the display
     static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal);
     // Convert layer's size into 8x8 percentage of the display
diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
index 6225df1..46ec8e6 100644
--- a/services/surfaceflinger/RenderArea.cpp
+++ b/services/surfaceflinger/RenderArea.cpp
@@ -2,6 +2,15 @@
 
 namespace android {
 
+float RenderArea::getCaptureFillValue(CaptureFill captureFill) {
+    switch(captureFill) {
+        case CaptureFill::CLEAR:
+            return 0.0f;
+        case CaptureFill::OPAQUE:
+        default:
+            return 1.0f;
+    }
+}
 /*
  * Checks that the requested width and height are valid and updates them to the render area
  * dimensions if they are set to 0
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index bf0707f..3630677 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -9,10 +9,15 @@
 namespace android {
 
 class RenderArea {
+
 public:
-    RenderArea(uint32_t reqHeight, uint32_t reqWidth,
+    enum class CaptureFill {CLEAR, OPAQUE};
+
+    static float getCaptureFillValue(CaptureFill captureFill);
+
+    RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill,
                ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
-          : mReqHeight(reqHeight), mReqWidth(reqWidth) {
+          : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) {
         mRotationFlags = Transform::fromRotation(rotation);
     }
 
@@ -25,21 +30,23 @@
     virtual bool isSecure() const = 0;
     virtual bool needsFiltering() const = 0;
     virtual Rect getSourceCrop() const = 0;
+    virtual bool getWideColorSupport() const = 0;
+    virtual ui::Dataspace getDataSpace() const = 0;
 
     virtual void render(std::function<void()> drawLayers) { drawLayers(); }
 
     int getReqHeight() const { return mReqHeight; };
     int getReqWidth() const { return mReqWidth; };
     Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
-    virtual bool getWideColorSupport() const = 0;
-    virtual ui::ColorMode getActiveColorMode() const = 0;
-
     status_t updateDimensions();
 
+    CaptureFill getCaptureFill() const { return mCaptureFill; };
+
 private:
     uint32_t mReqHeight;
     uint32_t mReqWidth;
     Transform::orientation_flags mRotationFlags;
+    CaptureFill mCaptureFill;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 5e79e7a..323bdb2 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -73,8 +73,4 @@
     mOutputTransferFunction = transferFunction;
 }
 
-void Description::enableToneMapping(bool enable) {
-    mToneMappingEnabled = enable;
-}
-
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 75c1981..5854ba4 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -51,12 +51,11 @@
         LINEAR,
         SRGB,
         ST2084,
+        HLG,  // Hybrid Log-Gamma for HDR.
     };
     void setInputTransferFunction(TransferFunction transferFunction);
     void setOutputTransferFunction(TransferFunction transferFunction);
 
-    void enableToneMapping(bool enable);
-
 private:
     friend class Program;
     friend class ProgramCache;
@@ -84,9 +83,6 @@
     // transfer functions for the input/output
     TransferFunction mInputTransferFunction = TransferFunction::LINEAR;
     TransferFunction mOutputTransferFunction = TransferFunction::LINEAR;
-
-    // tone-map the color
-    bool mToneMappingEnabled = false;
 };
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 0fb3d28..6e0fa32 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -316,15 +316,26 @@
                 wideColorState.setColorMatrix(mState.getColorMatrix() * mBt2020ToDisplayP3);
                 wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084);
                 wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
-                wideColorState.enableToneMapping(true);
+                break;
+            case Dataspace::BT2020_HLG:
+            case Dataspace::BT2020_ITU_HLG:
+                wideColorState.setColorMatrix(mState.getColorMatrix() * mBt2020ToDisplayP3);
+                wideColorState.setInputTransferFunction(Description::TransferFunction::HLG);
+                wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
                 break;
             default:
                 // treat all other dataspaces as sRGB
                 wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
-                if ((mDataSpace & Dataspace::TRANSFER_MASK) & Dataspace::TRANSFER_LINEAR) {
-                    wideColorState.setInputTransferFunction(Description::TransferFunction::LINEAR);
-                } else {
-                    wideColorState.setInputTransferFunction(Description::TransferFunction::SRGB);
+                switch (static_cast<Dataspace>(mDataSpace & Dataspace::TRANSFER_MASK)) {
+                    case Dataspace::TRANSFER_LINEAR:
+                        wideColorState.setInputTransferFunction(
+                                Description::TransferFunction::LINEAR);
+                        break;
+                    default:
+                        // treat all other transfer functions as sRGB
+                        wideColorState.setInputTransferFunction(
+                                Description::TransferFunction::SRGB);
+                        break;
                 }
                 wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
                 ALOGV("drawMesh: gamut transform applied");
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 6a34981..d1887ee 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -143,6 +143,9 @@
             case Description::TransferFunction::ST2084:
                 needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_ST2084);
                 break;
+            case Description::TransferFunction::HLG:
+                needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_HLG);
+                break;
         }
 
         switch (description.mOutputTransferFunction) {
@@ -156,10 +159,10 @@
             case Description::TransferFunction::ST2084:
                 needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_ST2084);
                 break;
+            case Description::TransferFunction::HLG:
+                needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_HLG);
+                break;
         }
-
-        needs.set(Key::TONE_MAPPING_MASK,
-                  description.mToneMappingEnabled ? Key::TONE_MAPPING_ON : Key::TONE_MAPPING_OFF);
     }
 
     return needs;
@@ -220,6 +223,8 @@
     if (needs.hasColorMatrix()) {
         fs << "uniform mat4 colorMatrix;";
 
+        // Generate EOTF that converts signal values to relative display light,
+        // both normalized to [0, 1].
         switch (needs.getInputTF()) {
             case Key::INPUT_TF_LINEAR:
             default:
@@ -259,8 +264,123 @@
                     }
                     )__SHADER__";
                 break;
+          case Key::INPUT_TF_HLG:
+              fs << R"__SHADER__(
+                  highp float EOTF_channel(const highp float channel) {
+                      const highp float a = 0.17883277;
+                      const highp float b = 0.28466892;
+                      const highp float c = 0.55991073;
+                      return channel <= 0.5 ? channel * channel / 3.0 :
+                              (exp((channel - c) / a) + b) / 12.0;
+                  }
+
+                  vec3 EOTF(const highp vec3 color) {
+                      return vec3(EOTF_channel(color.r), EOTF_channel(color.g),
+                              EOTF_channel(color.b));
+                  }
+                  )__SHADER__";
+              break;
         }
 
+        fs << R"__SHADER__(
+            highp float CalculateY(const highp vec3 color) {
+                // BT2020 standard uses the unadjusted KR = 0.2627,
+                // KB = 0.0593 luminance interpretation for RGB conversion.
+                return color.r * 0.262700 + color.g * 0.677998 +
+                        color.b * 0.059302;
+            }
+        )__SHADER__";
+
+        // Generate OOTF that modifies the relative display light.
+        switch(needs.getInputTF()) {
+            case Key::INPUT_TF_ST2084:
+                fs << R"__SHADER__(
+                    highp vec3 OOTF(const highp vec3 color) {
+                        const float maxLumi = 10000.0;
+                        const float maxMasteringLumi = 1000.0;
+                        const float maxContentLumi = 1000.0;
+                        const float maxInLumi = min(maxMasteringLumi, maxContentLumi);
+                        const float maxOutLumi = 500.0;
+
+                        // Calculate Y value in XYZ color space.
+                        float colorY = CalculateY(color);
+
+                        // convert to nits first
+                        float nits = colorY * maxLumi;
+
+                        // clamp to max input luminance
+                        nits = clamp(nits, 0.0, maxInLumi);
+
+                        // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
+                        if (maxInLumi <= maxOutLumi) {
+                            nits *= maxOutLumi / maxInLumi;
+                        } else {
+                            // three control points
+                            const float x0 = 10.0;
+                            const float y0 = 17.0;
+                            const float x1 = maxOutLumi * 0.75;
+                            const float y1 = x1;
+                            const float x2 = x1 + (maxInLumi - x1) / 2.0;
+                            const float y2 = y1 + (maxOutLumi - y1) * 0.75;
+
+                            // horizontal distances between the last three control points
+                            const float h12 = x2 - x1;
+                            const float h23 = maxInLumi - x2;
+                            // tangents at the last three control points
+                            const float m1 = (y2 - y1) / h12;
+                            const float m3 = (maxOutLumi - y2) / h23;
+                            const float m2 = (m1 + m3) / 2.0;
+
+                            if (nits < x0) {
+                                // scale [0.0, x0] to [0.0, y0] linearly
+                                const float slope = y0 / x0;
+                                nits *= slope;
+                            } else if (nits < x1) {
+                                // scale [x0, x1] to [y0, y1] linearly
+                                const float slope = (y1 - y0) / (x1 - x0);
+                                nits = y0 + (nits - x0) * slope;
+                            } else if (nits < x2) {
+                                // scale [x1, x2] to [y1, y2] using Hermite interp
+                                float t = (nits - x1) / h12;
+                                nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +
+                                       (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
+                            } else {
+                                // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
+                                float t = (nits - x2) / h23;
+                                nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +
+                                       (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t;
+                            }
+                        }
+
+                        // convert back to [0.0, 1.0]
+                        float targetY = nits / maxOutLumi;
+                        return color * (targetY / max(1e-6, colorY));
+                    }
+                )__SHADER__";
+                break;
+            case Key::INPUT_TF_HLG:
+                fs << R"__SHADER__(
+                    highp vec3 OOTF(const highp vec3 color) {
+                        const float maxOutLumi = 500.0;
+                        const float gamma = 1.2 + 0.42 * log(maxOutLumi / 1000.0) / log(10.0);
+                        // The formula is:
+                        // alpha * pow(Y, gamma - 1.0) * color + beta;
+                        // where alpha is 1.0, beta is 0.0 as recommended in
+                        // Rec. ITU-R BT.2100-1 TABLE 5.
+                        return pow(CalculateY(color), gamma - 1.0) * color;
+                    }
+                )__SHADER__";
+                break;
+            default:
+                fs << R"__SHADER__(
+                    highp vec3 OOTF(const highp vec3 color) {
+                        return color;
+                    }
+                )__SHADER__";
+        }
+
+        // Generate OETF that converts relative display light to signal values,
+        // both normalized to [0, 1]
         switch (needs.getOutputTF()) {
             case Key::OUTPUT_TF_LINEAR:
             default:
@@ -301,84 +421,22 @@
                     }
                 )__SHADER__";
                 break;
-        }
-
-        if (needs.hasToneMapping()) {
-            fs << R"__SHADER__(
-                float CalculateY(const vec3 color) {
-                    // BT2020 standard uses the unadjusted KR = 0.2627,
-                    // KB = 0.0593 luminance interpretation for RGB conversion.
-                    return color.r * 0.262700 + color.g * 0.677998 +
-                            color.b * 0.059302;
-                }
-                vec3 ToneMap(const vec3 color) {
-                    const float maxLumi = 10000.0;
-                    const float maxMasteringLumi = 1000.0;
-                    const float maxContentLumi = 1000.0;
-                    const float maxInLumi = min(maxMasteringLumi, maxContentLumi);
-                    const float maxOutLumi = 500.0;
-
-                    // Calculate Y value in XYZ color space.
-                    float colorY = CalculateY(color);
-
-                    // convert to nits first
-                    float nits = colorY * maxLumi;
-
-                    // clamp to max input luminance
-                    nits = clamp(nits, 0.0, maxInLumi);
-
-                    // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
-                    if (maxInLumi <= maxOutLumi) {
-                        nits *= maxOutLumi / maxInLumi;
-                    } else {
-                        // three control points
-                        const float x0 = 10.0;
-                        const float y0 = 17.0;
-                        const float x1 = maxOutLumi * 0.75;
-                        const float y1 = x1;
-                        const float x2 = x1 + (maxInLumi - x1) / 2.0;
-                        const float y2 = y1 + (maxOutLumi - y1) * 0.75;
-
-                        // horizontal distances between the last three control points
-                        const float h12 = x2 - x1;
-                        const float h23 = maxInLumi - x2;
-                        // tangents at the last three control points
-                        const float m1 = (y2 - y1) / h12;
-                        const float m3 = (maxOutLumi - y2) / h23;
-                        const float m2 = (m1 + m3) / 2.0;
-
-                        if (nits < x0) {
-                            // scale [0.0, x0] to [0.0, y0] linearly
-                            const float slope = y0 / x0;
-                            nits *= slope;
-                        } else if (nits < x1) {
-                            // scale [x0, x1] to [y0, y1] linearly
-                            const float slope = (y1 - y0) / (x1 - x0);
-                            nits = y0 + (nits - x0) * slope;
-                        } else if (nits < x2) {
-                            // scale [x1, x2] to [y1, y2] using Hermite interp
-                            float t = (nits - x1) / h12;
-                            nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +
-                                   (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
-                        } else {
-                            // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
-                            float t = (nits - x2) / h23;
-                            nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +
-                                   (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t;
-                        }
+            case Key::OUTPUT_TF_HLG:
+                fs << R"__SHADER__(
+                    highp float OETF_channel(const highp float channel) {
+                        const highp float a = 0.17883277;
+                        const highp float b = 0.28466892;
+                        const highp float c = 0.55991073;
+                        return channel <= 1.0 / 12.0 ? sqrt(3.0 * channel) :
+                                a * log(12.0 * channel - b) + c;
                     }
 
-                    // convert back to [0.0, 1.0]
-                    float targetY = nits / maxOutLumi;
-                    return color * (targetY / max(1e-6, colorY));
-                }
-            )__SHADER__";
-        } else {
-            fs << R"__SHADER__(
-                vec3 ToneMap(const vec3 color) {
-                    return color;
-                }
-            )__SHADER__";
+                    vec3 OETF(const highp vec3 color) {
+                        return vec3(OETF_channel(color.r), OETF_channel(color.g),
+                                OETF_channel(color.b));
+                    }
+                )__SHADER__";
+                break;
         }
     }
 
@@ -411,7 +469,7 @@
             // avoid divide by 0 by adding 0.5/256 to the alpha channel
             fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);";
         }
-        fs << "vec4 transformed = colorMatrix * vec4(ToneMap(EOTF(gl_FragColor.rgb)), 1);";
+        fs << "vec4 transformed = colorMatrix * vec4(OOTF(EOTF(gl_FragColor.rgb)), 1);";
         // the transformation from a wider colorspace to a narrower one can
         // result in >1.0 or <0.0 pixel values
         fs << "transformed.rgb = clamp(transformed.rgb, 0.0, 1.0);";
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index dcc8cc6..f67e132 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -81,19 +81,16 @@
             INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT,
             INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT,
             INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT,
+            INPUT_TF_HLG = 3 << INPUT_TF_SHIFT,
 
             OUTPUT_TF_SHIFT = 8,
             OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT,
             OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT,
             OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT,
             OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT,
+            OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT,
 
-            TONE_MAPPING_SHIFT = 10,
-            TONE_MAPPING_MASK = 1 << TONE_MAPPING_SHIFT,
-            TONE_MAPPING_OFF = 0 << TONE_MAPPING_SHIFT,
-            TONE_MAPPING_ON = 1 << TONE_MAPPING_SHIFT,
-
-            Y410_BT2020_SHIFT = 11,
+            Y410_BT2020_SHIFT = 10,
             Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT,
             Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT,
             Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT,
@@ -115,7 +112,6 @@
         inline bool hasColorMatrix() const { return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON; }
         inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
         inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
-        inline bool hasToneMapping() const { return (mKey & TONE_MAPPING_MASK) == TONE_MAPPING_ON; }
         inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; }
 
         // this is the definition of a friend function -- not a method of class Needs
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 183c1eb..58e4fbe 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -106,6 +106,7 @@
 using namespace android::hardware::configstore::V1_0;
 using ui::ColorMode;
 using ui::Dataspace;
+using ui::Hdr;
 using ui::RenderIntent;
 
 namespace {
@@ -157,6 +158,31 @@
     return std::string(value) == "true";
 }
 
+DisplayColorSetting toDisplayColorSetting(int value) {
+    switch(value) {
+        case 0:
+            return DisplayColorSetting::MANAGED;
+        case 1:
+            return DisplayColorSetting::UNMANAGED;
+        case 2:
+            return DisplayColorSetting::ENHANCED;
+        default:
+            return DisplayColorSetting::MANAGED;
+    }
+}
+
+std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) {
+    switch(displayColorSetting) {
+        case DisplayColorSetting::MANAGED:
+            return std::string("Natural Mode");
+        case DisplayColorSetting::UNMANAGED:
+            return std::string("Saturated Mode");
+        case DisplayColorSetting::ENHANCED:
+            return std::string("Auto Color Mode");
+    }
+    return std::string("Unknown Display Color Setting");
+}
+
 NativeWindowSurface::~NativeWindowSurface() = default;
 
 namespace impl {
@@ -690,6 +716,9 @@
         ALOGE("Run StartPropertySetThread failed!");
     }
 
+    mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
+            Dataspace::SRGB_LINEAR);
+
     ALOGV("Done initializing");
 }
 
@@ -697,14 +726,13 @@
     char value[PROPERTY_VALUE_MAX];
 
     property_get("persist.sys.sf.color_saturation", value, "1.0");
-    mSaturation = atof(value);
-    ALOGV("Saturation is set to %.2f", mSaturation);
+    mGlobalSaturationFactor = atof(value);
+    ALOGV("Saturation is set to %.2f", mGlobalSaturationFactor);
 
     property_get("persist.sys.sf.native_mode", value, "0");
-    mForceNativeColorMode = atoi(value) == 1;
-    if (mForceNativeColorMode) {
-        ALOGV("Forcing native color mode");
-    }
+    mDisplayColorSetting = toDisplayColorSetting(atoi(value));
+    ALOGV("Display Color Setting is set to %s.",
+          decodeDisplayColorSetting(mDisplayColorSetting).c_str());
 }
 
 void SurfaceFlinger::startBootAnim() {
@@ -989,11 +1017,29 @@
 }
 
 void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
-        ColorMode mode) {
+                                                ColorMode mode, Dataspace dataSpace) {
     int32_t type = hw->getDisplayType();
     ColorMode currentMode = hw->getActiveColorMode();
+    Dataspace currentDataSpace = hw->getCompositionDataSpace();
+    RenderIntent currentRenderIntent = hw->getActiveRenderIntent();
 
-    if (mode == currentMode) {
+    // Natural Mode means it's color managed and the color must be right,
+    // thus we pick RenderIntent::COLORIMETRIC as render intent.
+    // Native Mode means the display is not color managed, and whichever
+    // render intent is picked doesn't matter, thus return
+    // RenderIntent::COLORIMETRIC as default here.
+    RenderIntent renderIntent = RenderIntent::COLORIMETRIC;
+
+    // In Auto Color Mode, we want to strech to panel color space, right now
+    // only the built-in display supports it.
+    if (mDisplayColorSetting == DisplayColorSetting::ENHANCED &&
+        mBuiltinDisplaySupportsEnhance &&
+        hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
+        renderIntent = RenderIntent::ENHANCE;
+    }
+
+    if (mode == currentMode && dataSpace == currentDataSpace &&
+        renderIntent == currentRenderIntent) {
         return;
     }
 
@@ -1002,11 +1048,15 @@
         return;
     }
 
-    ALOGD("Set active color mode: %s (%d), type=%d", decodeColorMode(mode).c_str(), mode,
-          hw->getDisplayType());
-
     hw->setActiveColorMode(mode);
-    getHwComposer().setActiveColorMode(type, mode, RenderIntent::COLORIMETRIC);
+    hw->setCompositionDataSpace(dataSpace);
+    hw->setActiveRenderIntent(renderIntent);
+    getHwComposer().setActiveColorMode(type, mode, renderIntent);
+
+    ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), type=%d",
+          decodeColorMode(mode).c_str(), mode,
+          decodeRenderIntent(renderIntent).c_str(), renderIntent,
+          hw->getDisplayType());
 }
 
 
@@ -1037,7 +1087,7 @@
                 ALOGW("Attempt to set active color mode %s %d for virtual display",
                       decodeColorMode(mMode).c_str(), mMode);
             } else {
-                mFlinger.setActiveColorModeInternal(hw, mMode);
+                mFlinger.setActiveColorModeInternal(hw, mMode, Dataspace::UNKNOWN);
             }
             return true;
         }
@@ -1069,21 +1119,23 @@
         return BAD_VALUE;
     }
 
-    std::unique_ptr<HdrCapabilities> capabilities =
-            getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId());
-    if (capabilities) {
-        if (displayDevice->getWideColorSupport() && !displayDevice->getHdrSupport()) {
+    HdrCapabilities capabilities;
+    int status = getBE().mHwc->getHdrCapabilities(
+        displayDevice->getHwcDisplayId(), &capabilities);
+    if (status == NO_ERROR) {
+        if (displayDevice->hasWideColorGamut() &&
+            !displayDevice->hasHDR10Support()) {
             // insert HDR10 as we will force client composition for HDR10
             // layers
-            std::vector<int32_t> types = capabilities->getSupportedHdrTypes();
-            types.push_back(HAL_HDR_HDR10);
+            std::vector<Hdr> types = capabilities.getSupportedHdrTypes();
+            types.push_back(Hdr::HDR10);
 
             *outCapabilities = HdrCapabilities(types,
-                    capabilities->getDesiredMaxLuminance(),
-                    capabilities->getDesiredMaxAverageLuminance(),
-                    capabilities->getDesiredMinLuminance());
+                    capabilities.getDesiredMaxLuminance(),
+                    capabilities.getDesiredMaxAverageLuminance(),
+                    capabilities.getDesiredMinLuminance());
         } else {
-            *outCapabilities = std::move(*capabilities);
+            *outCapabilities = std::move(capabilities);
         }
     } else {
         return BAD_VALUE;
@@ -1338,7 +1390,7 @@
     if (sequenceId != getBE().mComposerSequenceId) {
         return;
     }
-    repaintEverythingLocked();
+    repaintEverything();
 }
 
 void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
@@ -1821,73 +1873,78 @@
 }
 
 mat4 SurfaceFlinger::computeSaturationMatrix() const {
-    if (mSaturation == 1.0f) {
+    if (mGlobalSaturationFactor == 1.0f) {
         return mat4();
     }
 
     // Rec.709 luma coefficients
     float3 luminance{0.213f, 0.715f, 0.072f};
-    luminance *= 1.0f - mSaturation;
+    luminance *= 1.0f - mGlobalSaturationFactor;
     return mat4(
-        vec4{luminance.r + mSaturation, luminance.r, luminance.r, 0.0f},
-        vec4{luminance.g, luminance.g + mSaturation, luminance.g, 0.0f},
-        vec4{luminance.b, luminance.b, luminance.b + mSaturation, 0.0f},
+        vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
+        vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
+        vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
         vec4{0.0f, 0.0f, 0.0f, 1.0f}
     );
 }
 
-// pickColorMode translates a given dataspace into the best available color mode.
-// Currently only support sRGB and Display-P3.
-ColorMode SurfaceFlinger::pickColorMode(Dataspace dataSpace) const {
-    if (mForceNativeColorMode) {
-        return ColorMode::NATIVE;
+// Returns a dataspace that fits all visible layers.  The returned dataspace
+// can only be one of
+//
+//  - Dataspace::V0_SRGB
+//  - Dataspace::DISPLAY_P3
+//  - Dataspace::V0_SCRGB_LINEAR
+// TODO(b/73825729) Add BT2020 data space.
+ui::Dataspace SurfaceFlinger::getBestDataspace(
+        const sp<const DisplayDevice>& displayDevice) const {
+    Dataspace bestDataspace = Dataspace::V0_SRGB;
+    for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+        switch (layer->getDataSpace()) {
+            case Dataspace::V0_SCRGB:
+            case Dataspace::V0_SCRGB_LINEAR:
+                // return immediately
+                return Dataspace::V0_SCRGB_LINEAR;
+            case Dataspace::BT2020_PQ:
+            case Dataspace::BT2020_ITU_PQ:
+                // Historically, HDR dataspaces are ignored by SurfaceFlinger. But
+                // since SurfaceFlinger simulates HDR support now, it should honor
+                // them unless there is also native support.
+                if (!displayDevice->hasHDR10Support()) {
+                    return Dataspace::V0_SCRGB_LINEAR;
+                }
+                break;
+            case Dataspace::DISPLAY_P3:
+                bestDataspace = Dataspace::DISPLAY_P3;
+                break;
+            default:
+                break;
+        }
     }
 
-    switch (dataSpace) {
-        // treat Unknown as regular SRGB buffer, since that's what the rest of the
-        // system expects.
-        case Dataspace::UNKNOWN:
-        case Dataspace::SRGB:
-        case Dataspace::V0_SRGB:
-            return ColorMode::SRGB;
-            break;
-
-        case Dataspace::DISPLAY_P3:
-            return ColorMode::DISPLAY_P3;
-            break;
-
-        default:
-            // TODO (courtneygo): Do we want to assert an error here?
-            ALOGE("No color mode mapping for %s (%#x)",
-                  dataspaceDetails(static_cast<android_dataspace>(dataSpace)).c_str(),
-                  dataSpace);
-            return ColorMode::SRGB;
-            break;
-    }
+    return bestDataspace;
 }
 
-Dataspace SurfaceFlinger::bestTargetDataSpace(
-        Dataspace a, Dataspace b, bool hasHdr) const {
-    // Only support sRGB and Display-P3 right now.
-    if (a == Dataspace::DISPLAY_P3 || b == Dataspace::DISPLAY_P3) {
-        return Dataspace::DISPLAY_P3;
-    }
-    if (a == Dataspace::V0_SCRGB_LINEAR || b == Dataspace::V0_SCRGB_LINEAR) {
-        return Dataspace::DISPLAY_P3;
-    }
-    if (a == Dataspace::V0_SCRGB || b == Dataspace::V0_SCRGB) {
-        return Dataspace::DISPLAY_P3;
-    }
-    if (!hasHdr) {
-        if (a == Dataspace::BT2020_PQ || b == Dataspace::BT2020_PQ) {
-            return Dataspace::DISPLAY_P3;
-        }
-        if (a == Dataspace::BT2020_ITU_PQ || b == Dataspace::BT2020_ITU_PQ) {
-            return Dataspace::DISPLAY_P3;
-        }
+// Pick the ColorMode / Dataspace for the display device.
+// TODO(b/73825729) Add BT2020 color mode.
+void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& displayDevice,
+        ColorMode* outMode, Dataspace* outDataSpace) const {
+    if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) {
+        *outMode = ColorMode::NATIVE;
+        *outDataSpace = Dataspace::UNKNOWN;
+        return;
     }
 
-    return Dataspace::V0_SRGB;
+    switch (getBestDataspace(displayDevice)) {
+        case Dataspace::DISPLAY_P3:
+        case Dataspace::V0_SCRGB_LINEAR:
+            *outMode = ColorMode::DISPLAY_P3;
+            *outDataSpace = Dataspace::DISPLAY_P3;
+            break;
+        default:
+            *outMode = ColorMode::SRGB;
+            *outDataSpace = Dataspace::V0_SRGB;
+            break;
+    }
 }
 
 void SurfaceFlinger::setUpHWComposer() {
@@ -1895,7 +1952,7 @@
     ALOGV("setUpHWComposer");
 
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
+        bool dirty = !mDisplays[dpy]->getDirtyRegion(mRepaintEverything).isEmpty();
         bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
         bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
 
@@ -1970,7 +2027,7 @@
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
                  layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
-                    !displayDevice->getHdrSupport()) {
+                    !displayDevice->hasHDR10Support()) {
                 layer->forceClientComposition(hwcId);
             }
 
@@ -1984,19 +2041,10 @@
         }
 
         if (hasWideColorDisplay) {
-            ColorMode newColorMode;
-            Dataspace newDataSpace = Dataspace::V0_SRGB;
-
-            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
-                newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace,
-                        displayDevice->getHdrSupport());
-                ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
-                      layer->getName().string(), dataspaceDetails(static_cast<android_dataspace>(layer->getDataSpace())).c_str(),
-                      layer->getDataSpace(), dataspaceDetails(static_cast<android_dataspace>(newDataSpace)).c_str(), newDataSpace);
-            }
-            newColorMode = pickColorMode(newDataSpace);
-
-            setActiveColorModeInternal(displayDevice, newColorMode);
+            ColorMode colorMode;
+            Dataspace dataSpace;
+            pickColorMode(displayDevice, &colorMode, &dataSpace);
+            setActiveColorModeInternal(displayDevice, colorMode, dataSpace);
         }
     }
 
@@ -2121,7 +2169,7 @@
     // with mStateLock held to guarantee that mCurrentState won't change
     // until the transaction is committed.
 
-    mVsyncModulator.setTransactionStart(VSyncModulator::TransactionStart::NORMAL);
+    mVsyncModulator.onTransactionHandled();
     transactionFlags = getTransactionFlags(eTransactionMask);
     handleTransactionLocked(transactionFlags);
 
@@ -2204,30 +2252,36 @@
 sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
         const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state,
         const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
-    bool hasWideColorSupport = false;
+    bool hasWideColorGamut = false;
     if (hasWideColorDisplay) {
-        std::vector<ColorMode> modes = getHwComposer().getColorModes(state.type);
+        std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId);
         for (ColorMode colorMode : modes) {
             switch (colorMode) {
                 case ColorMode::DISPLAY_P3:
                 case ColorMode::ADOBE_RGB:
                 case ColorMode::DCI_P3:
-                    hasWideColorSupport = true;
+                    hasWideColorGamut = true;
                     break;
+                // TODO(lpy) Handle BT2020, BT2100_PQ and BT2100_HLG properly.
                 default:
                     break;
             }
+
+            std::vector<RenderIntent> renderIntents = getHwComposer().getRenderIntents(hwcId,
+                                                                                       colorMode);
+            if (state.type == DisplayDevice::DISPLAY_PRIMARY) {
+                for (auto intent : renderIntents) {
+                    if (intent == RenderIntent::ENHANCE) {
+                        mBuiltinDisplaySupportsEnhance = true;
+                        break;
+                    }
+                }
+            }
         }
     }
 
-    bool hasHdrSupport = false;
-    std::unique_ptr<HdrCapabilities> hdrCapabilities =
-            getHwComposer().getHdrCapabilities(state.type);
-    if (hdrCapabilities) {
-        const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
-        auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
-        hasHdrSupport = iter != types.cend();
-    }
+    HdrCapabilities hdrCapabilities;
+    getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities);
 
     auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
     auto nativeWindow = nativeWindowSurface->getNativeWindow();
@@ -2260,18 +2314,19 @@
     sp<DisplayDevice> hw =
             new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
                               dispSurface, std::move(renderSurface), displayWidth, displayHeight,
-                              hasWideColorSupport, hasHdrSupport, initialPowerMode);
+                              hasWideColorGamut, hdrCapabilities, initialPowerMode);
 
     if (maxFrameBufferAcquiredBuffers >= 3) {
         nativeWindowSurface->preallocateBuffers();
     }
 
     ColorMode defaultColorMode = ColorMode::NATIVE;
-    if (hasWideColorSupport) {
+    Dataspace defaultDataSpace = Dataspace::UNKNOWN;
+    if (hasWideColorGamut) {
         defaultColorMode = ColorMode::SRGB;
+        defaultDataSpace = Dataspace::V0_SRGB;
     }
-    setActiveColorModeInternal(hw, defaultColorMode);
-    hw->setCompositionDataSpace(Dataspace::UNKNOWN);
+    setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace);
     hw->setLayerStack(state.layerStack);
     hw->setProjection(state.orientation, state.viewport, state.frame);
     hw->setDisplayName(state.displayName);
@@ -2822,23 +2877,27 @@
     const Region bounds(displayDevice->bounds());
     const DisplayRenderArea renderArea(displayDevice);
     const auto hwcId = displayDevice->getHwcDisplayId();
+    const bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId);
+    const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId);
+    const bool skipClientColorTransform = getBE().mHwc->hasCapability(
+        HWC2::Capability::SkipClientColorTransform);
+    ATRACE_INT("hasClientComposition", hasClientComposition);
 
     mat4 oldColorMatrix;
-    const bool applyColorMatrix = !getBE().mHwc->hasDeviceComposition(hwcId) &&
-            !getBE().mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform);
+    mat4 legacySrgbSaturationMatrix = mLegacySrgbSaturationMatrix;
+    const bool applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
     if (applyColorMatrix) {
-        mat4 colorMatrix = mColorMatrix * mDaltonizer();
+        mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
         oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix);
+        legacySrgbSaturationMatrix = colorMatrix * legacySrgbSaturationMatrix;
     }
 
-    bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId);
     if (hasClientComposition) {
         ALOGV("hasClientComposition");
 
         Dataspace outputDataspace = Dataspace::UNKNOWN;
-        if (displayDevice->getWideColorSupport() &&
-              displayDevice->getActiveColorMode() == ColorMode::DISPLAY_P3) {
-            outputDataspace = Dataspace::DISPLAY_P3;
+        if (displayDevice->hasWideColorGamut()) {
+            outputDataspace = displayDevice->getCompositionDataSpace();
         }
         getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
 
@@ -2855,7 +2914,6 @@
         }
 
         // Never touch the framebuffer if we don't have any framebuffer layers
-        const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId);
         if (hasDeviceComposition) {
             // when using overlays, we assume a fully transparent framebuffer
             // NOTE: we could reduce how much we need to clear, for instance
@@ -2930,7 +2988,20 @@
                         break;
                     }
                     case HWC2::Composition::Client: {
+                        // Only apply saturation matrix layer that is legacy SRGB dataspace
+                        // when auto color mode is on.
+                        bool restore = false;
+                        mat4 savedMatrix;
+                        if (mDisplayColorSetting == DisplayColorSetting::ENHANCED &&
+                            layer->isLegacySrgbDataSpace()) {
+                            savedMatrix =
+                                getRenderEngine().setupColorTransform(legacySrgbSaturationMatrix);
+                            restore = true;
+                        }
                         layer->draw(renderArea, clip);
+                        if (restore) {
+                            getRenderEngine().setupColorTransform(savedMatrix);
+                        }
                         break;
                     }
                     default:
@@ -3643,7 +3714,7 @@
 
         mVisibleRegionsDirty = true;
         mHasPoweredOff = true;
-        repaintEverythingLocked();
+        repaintEverything();
 
         struct sched_param param = {0};
         param.sched_priority = 1;
@@ -4004,7 +4075,7 @@
 
 void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
     result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
-    result.appendFormat("forceNativeColorMode: %d\n", mForceNativeColorMode);
+    result.appendFormat("DisplayColorSetting: %d\n", mDisplayColorSetting);
 
     // TODO: print out if wide-color mode is active or not
 
@@ -4500,15 +4571,22 @@
                 return NO_ERROR;
             }
             case 1022: { // Set saturation boost
-                mSaturation = std::max(0.0f, std::min(data.readFloat(), 2.0f));
+                mGlobalSaturationFactor = std::max(0.0f, std::min(data.readFloat(), 2.0f));
 
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
             }
             case 1023: { // Set native mode
-                mForceNativeColorMode = data.readInt32() == 1;
+                int32_t value = data.readInt32();
+                if (value > 2) {
+                    return BAD_VALUE;
+                }
+                if (value == 2 && !mBuiltinDisplaySupportsEnhance) {
+                    return BAD_VALUE;
+                }
 
+                mDisplayColorSetting = toDisplayColorSetting(value);
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
@@ -4535,25 +4613,31 @@
                 reply->writeBool(mTracing.isEnabled());
                 return NO_ERROR;
             }
+            // Is a DisplayColorSetting supported?
+            case 1027: {
+                int32_t value = data.readInt32();
+                switch (value) {
+                    case 0:
+                        reply->writeBool(hasWideColorDisplay);
+                        return NO_ERROR;
+                    case 1:
+                        reply->writeBool(true);
+                        return NO_ERROR;
+                    case 2:
+                        reply->writeBool(mBuiltinDisplaySupportsEnhance);
+                        return NO_ERROR;
+                    default:
+                        return BAD_VALUE;
+                }
+            }
         }
     }
     return err;
 }
 
-void SurfaceFlinger::repaintEverythingLocked() {
-    android_atomic_or(1, &mRepaintEverything);
-    for (size_t dpy = 0; dpy < mDisplays.size(); dpy++) {
-        const sp<DisplayDevice>& displayDevice(mDisplays[dpy]);
-        const Rect bounds(displayDevice->getBounds());
-        displayDevice->dirtyRegion.orSelf(Region(bounds));
-    }
-    signalTransaction();
-}
-
 void SurfaceFlinger::repaintEverything() {
-    ConditionalLock _l(mStateLock,
-            std::this_thread::get_id() != mMainThreadId);
-    repaintEverythingLocked();
+    android_atomic_or(1, &mRepaintEverything);
+    signalTransaction();
 }
 
 // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
@@ -4597,11 +4681,12 @@
     public:
         LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop,
                         int32_t reqWidth, int32_t reqHeight, bool childrenOnly)
-              : RenderArea(reqHeight, reqWidth),
+              : RenderArea(reqHeight, reqWidth, CaptureFill::CLEAR),
                 mLayer(layer),
                 mCrop(crop),
                 mFlinger(flinger),
                 mChildrenOnly(childrenOnly) {}
+        const Transform& getTransform() const override { return mTransform; }
         Rect getBounds() const override {
             const Layer::State& layerState(mLayer->getDrawingState());
             return Rect(layerState.active.w, layerState.active.h);
@@ -4610,7 +4695,15 @@
         int getWidth() const override { return mLayer->getDrawingState().active.w; }
         bool isSecure() const override { return false; }
         bool needsFiltering() const override { return false; }
-        const Transform& getTransform() const { return mTransform; }
+        Rect getSourceCrop() const override {
+            if (mCrop.isEmpty()) {
+                return getBounds();
+            } else {
+                return mCrop;
+            }
+        }
+        bool getWideColorSupport() const override { return false; }
+        Dataspace getDataSpace() const override { return Dataspace::UNKNOWN; }
 
         class ReparentForDrawing {
         public:
@@ -4639,16 +4732,6 @@
             }
         }
 
-        Rect getSourceCrop() const override {
-            if (mCrop.isEmpty()) {
-                return getBounds();
-            } else {
-                return mCrop;
-            }
-        }
-        bool getWideColorSupport() const override { return false; }
-        ColorMode getActiveColorMode() const override { return ColorMode::NATIVE; }
-
     private:
         const sp<Layer> mLayer;
         const Rect mCrop;
@@ -4820,9 +4903,8 @@
     }
 
     Dataspace outputDataspace = Dataspace::UNKNOWN;
-    if (renderArea.getWideColorSupport() &&
-          renderArea.getActiveColorMode() == ColorMode::DISPLAY_P3) {
-        outputDataspace = Dataspace::DISPLAY_P3;
+    if (renderArea.getWideColorSupport()) {
+        outputDataspace = renderArea.getDataSpace();
     }
     getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
 
@@ -4834,8 +4916,9 @@
                                     renderArea.getRotationFlags());
     engine.disableTexturing();
 
+    const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
     // redraw the screen entirely...
-    engine.clearWithColor(0, 0, 0, 1);
+    engine.clearWithColor(0, 0, 0, alpha);
 
     traverseLayers([&](Layer* layer) {
         if (filtering) layer->setFiltering(true);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a29d1d7..33706da 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -123,6 +123,12 @@
     eTransactionMask          = 0x0f,
 };
 
+enum class DisplayColorSetting : int32_t {
+    MANAGED = 0,
+    UNMANAGED = 1,
+    ENHANCED = 2,
+};
+
 // A thin interface to abstract creating instances of Surface (gui/Surface.h) to
 // use as a NativeWindow.
 class NativeWindowSurface {
@@ -306,8 +312,6 @@
 
     // force full composition on all displays
     void repaintEverything();
-    // Can only be called from the main thread or with mStateLock held
-    void repaintEverythingLocked();
 
     // returns the default Display
     sp<const DisplayDevice> getDefaultDisplayDevice() const {
@@ -467,7 +471,9 @@
                               bool stateLockHeld);
 
     // Called on the main thread in response to setActiveColorMode()
-    void setActiveColorModeInternal(const sp<DisplayDevice>& hw, ui::ColorMode colorMode);
+    void setActiveColorModeInternal(const sp<DisplayDevice>& hw,
+                                    ui::ColorMode colorMode,
+                                    ui::Dataspace dataSpace);
 
     // Returns whether the transaction actually modified any state
     bool handleMessageTransaction();
@@ -641,9 +647,10 @@
 
     // Given a dataSpace, returns the appropriate color_mode to use
     // to display that dataSpace.
-    ui::ColorMode pickColorMode(ui::Dataspace dataSpace) const;
-    ui::Dataspace bestTargetDataSpace(ui::Dataspace a, ui::Dataspace b,
-            bool hasHdr) const;
+    ui::Dataspace getBestDataspace(const sp<const DisplayDevice>& displayDevice) const;
+    void pickColorMode(const sp<DisplayDevice>& displayDevice,
+                       ui::ColorMode* outMode,
+                       ui::Dataspace* outDataSpace) const;
 
     mat4 computeSaturationMatrix() const;
 
@@ -846,7 +853,6 @@
 
     size_t mNumLayers;
 
-
     // Verify that transaction is being called by an approved process:
     // either AID_GRAPHICS or AID_SYSTEM.
     status_t CheckTransactCodeCredentials(uint32_t code);
@@ -856,8 +862,12 @@
     static bool useVrFlinger;
     std::thread::id mMainThreadId;
 
-    float mSaturation = 1.0f;
-    bool mForceNativeColorMode = false;
+    DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED;
+    // Applied on sRGB layers when the render intent is non-colorimetric.
+    mat4 mLegacySrgbSaturationMatrix;
+    // Applied globally.
+    float mGlobalSaturationFactor = 1.0f;
+    bool mBuiltinDisplaySupportsEnhance = false;
 
     using CreateBufferQueueFunction =
             std::function<void(sp<IGraphicBufferProducer>* /* outProducer */,
diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h
index 3126deb..3e5800e 100644
--- a/services/surfaceflinger/VSyncModulator.h
+++ b/services/surfaceflinger/VSyncModulator.h
@@ -55,11 +55,20 @@
     }
 
     void setTransactionStart(TransactionStart transactionStart) {
-        if (transactionStart == mTransactionStart) return;
+        // An early transaction stays an early transaction.
+        if (transactionStart == mTransactionStart || mTransactionStart == TransactionStart::EARLY) {
+            return;
+        }
         mTransactionStart = transactionStart;
         updatePhaseOffsets();
     }
 
+    void onTransactionHandled() {
+        if (mTransactionStart == TransactionStart::NORMAL) return;
+        mTransactionStart = TransactionStart::NORMAL;
+        updatePhaseOffsets();
+    }
+
     void setLastFrameUsedRenderEngine(bool re) {
         if (re == mLastFrameUsedRenderEngine) return;
         mLastFrameUsedRenderEngine = re;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 176c691..5108279 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2358,6 +2358,76 @@
     mCapture->expectChildColor(0, 0);
 }
 
+TEST_F(ScreenCaptureTest, CaptureTransparent) {
+    sp<SurfaceControl> child =
+            mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+                                           0, mFGSurfaceControl.get());
+
+    fillSurfaceRGBA8(child, 200, 200, 200);
+
+    SurfaceComposerClient::Transaction().show(child).apply(true);
+
+    auto childHandle = child->getHandle();
+
+    // Captures child
+    ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20});
+    mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255});
+    // Area outside of child's bounds is transparent.
+    mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0});
+}
+
+TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) {
+    auto fgHandle = mFGSurfaceControl->getHandle();
+
+    sp<SurfaceControl> child =
+            mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> relative = mComposerClient->createSurface(String8("Relative surface"), 10,
+                                                                 10, PIXEL_FORMAT_RGBA_8888, 0);
+    fillSurfaceRGBA8(child, 200, 200, 200);
+    fillSurfaceRGBA8(relative, 100, 100, 100);
+
+    SurfaceComposerClient::Transaction()
+            .show(child)
+            // Set relative layer above fg layer so should be shown above when computing all layers.
+            .setRelativeLayer(relative, fgHandle, 1)
+            .show(relative)
+            .apply(true);
+
+    // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured.
+    ScreenCapture::captureLayers(&mCapture, fgHandle);
+    mCapture->expectFGColor(10, 10);
+    mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureRelativeInTree) {
+    auto fgHandle = mFGSurfaceControl->getHandle();
+
+    sp<SurfaceControl> child =
+            mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+                                           0, mFGSurfaceControl.get());
+    sp<SurfaceControl> relative =
+            mComposerClient->createSurface(String8("Relative surface"), 10, 10,
+                                           PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child, 200, 200, 200);
+    fillSurfaceRGBA8(relative, 100, 100, 100);
+
+    SurfaceComposerClient::Transaction()
+            .show(child)
+            // Set relative layer below fg layer but relative to child layer so it should be shown
+            // above child layer.
+            .setLayer(relative, -1)
+            .setRelativeLayer(relative, child->getHandle(), 1)
+            .show(relative)
+            .apply(true);
+
+    // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its
+    // relative value should be taken into account, placing it above child layer.
+    ScreenCapture::captureLayers(&mCapture, fgHandle);
+    mCapture->expectFGColor(10, 10);
+    // Relative layer is showing on top of child layer
+    mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255});
+}
 
 // In the following tests we verify successful skipping of a parent layer,
 // so we use the same verification logic and only change how we mutate
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 0705b5c..2551a9c 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -81,7 +81,7 @@
         sp<DisplayDevice> build() {
             return new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, false, mDisplayToken,
                                      mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0,
-                                     0, false, false, HWC_POWER_MODE_NORMAL);
+                                     0, false, {}, HWC_POWER_MODE_NORMAL);
         }
 
         FakeDisplayDeviceFactory& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index 11ffc3f..4af47d2 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -251,20 +251,22 @@
 bool VrHwc::hasCapability(hwc2_capability_t /* capability */) { return false; }
 
 void VrHwc::registerEventCallback(EventCallback* callback) {
-  event_callback_ = callback;
-
-  if (client_ != nullptr) {
-    {
-      int32_t width, height;
-      GetPrimaryDisplaySize(&width, &height);
-      std::lock_guard<std::mutex> guard(mutex_);
-      // Create the primary display late to avoid initialization issues between
-      // VR HWC and SurfaceFlinger.
-      displays_[kDefaultDisplayId].reset(new HwcDisplay(width, height));
-    }
-    event_callback_->onHotplug(kDefaultDisplayId,
-                               IComposerCallback::Connection::CONNECTED);
+  {
+    std::lock_guard<std::mutex> guard(mutex_);
+    event_callback_ = callback;
+    int32_t width, height;
+    GetPrimaryDisplaySize(&width, &height);
+    // Create the primary display late to avoid initialization issues between
+    // VR HWC and SurfaceFlinger.
+    displays_[kDefaultDisplayId].reset(new HwcDisplay(width, height));
   }
+  event_callback_->onHotplug(kDefaultDisplayId,
+                             IComposerCallback::Connection::CONNECTED);
+}
+
+void VrHwc::unregisterEventCallback() {
+  std::lock_guard<std::mutex> guard(mutex_);
+  event_callback_ = nullptr;
 }
 
 uint32_t VrHwc::getMaxVirtualDisplayCount() { return 1; }
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index d5d5f55..85e587a 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -213,7 +213,7 @@
 
   std::string dumpDebugInfo() override { return {}; }
   void registerEventCallback(EventCallback* callback) override;
-  void unregisterEventCallback() override {}
+  void unregisterEventCallback() override;
 
   uint32_t getMaxVirtualDisplayCount() override;
   Error createVirtualDisplay(uint32_t width, uint32_t height,
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index 84644a9..1f4df1e 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -983,6 +983,7 @@
     {{else if eq $.Name "vkDestroyImage"}}true
 
     {{else if eq $.Name "vkGetPhysicalDeviceProperties"}}true
+    {{else if eq $.Name "vkGetPhysicalDeviceProperties2"}}true
     {{else if eq $.Name "vkGetPhysicalDeviceProperties2KHR"}}true
     {{end}}
 
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 741fbb8..56bc35e 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -848,7 +848,8 @@
     const InstanceData& data = GetData(physicalDevice);
 
     // GPDP2 must be present and enabled on the instance.
-    if (!data.driver.GetPhysicalDeviceProperties2KHR)
+    if (!data.driver.GetPhysicalDeviceProperties2KHR &&
+        !data.driver.GetPhysicalDeviceProperties2)
         return false;
 
     // Request the android-specific presentation properties via GPDP2
@@ -866,8 +867,12 @@
     presentation_properties->pNext = nullptr;
     presentation_properties->sharedImage = VK_FALSE;
 
-    data.driver.GetPhysicalDeviceProperties2KHR(physicalDevice,
-                                                &properties);
+    if (data.driver.GetPhysicalDeviceProperties2KHR) {
+        data.driver.GetPhysicalDeviceProperties2KHR(physicalDevice,
+                                                    &properties);
+    } else {
+        data.driver.GetPhysicalDeviceProperties2(physicalDevice, &properties);
+    }
 
     return true;
 }
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 51e3abf..ec98b9f 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -494,6 +494,7 @@
     INIT_PROC(true, instance, CreateDevice);
     INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
     INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
+    INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
     INIT_PROC_EXT(EXT_debug_report, true, instance, CreateDebugReportCallbackEXT);
     INIT_PROC_EXT(EXT_debug_report, true, instance, DestroyDebugReportCallbackEXT);
     INIT_PROC_EXT(EXT_debug_report, true, instance, DebugReportMessageEXT);
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 99dc889..14c3aba 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -69,6 +69,7 @@
     PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
     PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
+    PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
     PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
     PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
     PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 6f3790b..6fb3351 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -580,7 +580,7 @@
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
-    capabilities->minImageCount = 2;
+    capabilities->minImageCount = max_buffer_count == 1 ? 1 : 2;
     capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
 
     capabilities->currentExtent =