Merge sc-dev-plus-aosp-without-vendor@7634622

Merged-In: I1a17b0b27568a8e44a1b41b6336b39b064e66f24
Change-Id: Ic2c3f7fb5d5107f5abaef402f7ed69d6d675e00c
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 7dc2de6..e3eda5b 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -5,6 +5,9 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.graphics.composer@2.2-service)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.graphics.composer@2.2-service.rc)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/lib64/hw/android.hardware.graphics.composer@2.2-impl.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.graphics.composer@2.3-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.graphics.composer@2.3-service.rc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/lib64/hw/android.hardware.graphics.composer@2.3-impl.so)
 
 
 # Clean old target objs
@@ -38,3 +41,6 @@
 
 # Clean old allocator rc file
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/vendor.qti.hardware.display.allocator@1.0-service.rc)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/lib/hw/android.hardware.graphics.mapper@2.0-impl-qti-display.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl-qti-display.so)
diff --git a/common.mk b/common.mk
index d10ba96..e4d34df 100644
--- a/common.mk
+++ b/common.mk
@@ -75,5 +75,6 @@
 # If the macro is not present, the headers are picked from $(QC_HARDWARE_ROOT)/msmXXXX
 # failing which, they are picked from bionic.
     common_deps += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
-    kernel_includes += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+    kernel_includes += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
+                       $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/display
 endif
diff --git a/config/display-board.mk b/config/display-board.mk
index 29f540b..db15d83 100644
--- a/config/display-board.mk
+++ b/config/display-board.mk
@@ -17,3 +17,4 @@
 SF_WCG_COMPOSITION_DATA_SPACE := 143261696
 TARGET_USES_QTI_MAPPER_2_0 := true
 TARGET_USES_QTI_MAPPER_EXTENSIONS_1_1 := true
+TARGET_USES_GRALLOC4 := true
diff --git a/config/display-product.mk b/config/display-product.mk
index b770afe..774261a 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -1,13 +1,12 @@
 # Display product definitions
 PRODUCT_PACKAGES += \
-    android.hardware.graphics.composer@2.3-impl \
-    android.hardware.graphics.composer@2.3-service \
+    android.hardware.graphics.composer@2.4-impl \
+    android.hardware.graphics.composer@2.4-service \
     android.hardware.graphics.mapper@3.0-impl-qti-display \
+    android.hardware.graphics.mapper@4.0-impl-qti-display \
     vendor.qti.hardware.display.allocator-service \
     android.hardware.memtrack@1.0-impl \
     android.hardware.memtrack@1.0-service \
-    android.hardware.light@2.0-impl \
-    android.hardware.light@2.0-service \
     gralloc.$(TARGET_BOARD_PLATFORM) \
     lights.$(TARGET_BOARD_PLATFORM) \
     hwcomposer.$(TARGET_BOARD_PLATFORM) \
@@ -25,8 +24,8 @@
     vendor.display.config@1.8.vendor \
     vendor.display.config@1.9.vendor \
     vendor.display.config@1.10.vendor \
-    vendor.qti.hardware.display.mapper@2.0.vendor \
-    vendor.qti.hardware.display.mapper@3.0.vendor \
+    vendor.qti.hardware.display.mapper@3.0 \
+    vendor.qti.hardware.display.mapper@4.0.vendor \
     modetest
 
 #QDCM calibration xml file for 2k panel
@@ -76,6 +75,18 @@
 #QDCM calibration xml file base on Rennell FHD+ visionox panel
 PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_rm69299_amoled_fhd+_video_mode_dsi_visionox_panel.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_rm69299_amoled_fhd+_video_mode_dsi_visionox_panel.xml
 PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_rm69299_amoled_fhd+_video_mode_dsi_visionox_panel.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_rm69299_amoled_fhd+_cmd_mode_dsi_visionox_panel.xml
+#QDCM calibration xml file for sharp 120hz panel etc
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_sharp_1080p_120hz_dual_dsi_cmd_mode_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Dual_s6e3ha3_amoled_cmd_mode_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Dual_nt36850_cmd_mode_dsi_truly_panel_without_DSC.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_nt36672c_fhd_plus_video_mode_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_rm69298_amoled_fhd+_video_mode_dsi_truly_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_rm69298_amoled_fhd+_cmd_mode_dsi_truly_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_2k_cmd_mode_qsync_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_2k_video_mode_qsync_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_fhd_video_mode_qsync_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_fhd_cmd_mode_qsync_dsi_panel.xml
+
 
 PRODUCT_PROPERTY_OVERRIDES += \
     persist.demo.hdmirotationlock=false \
@@ -90,20 +101,33 @@
     vendor.display.disable_decimation=1 \
     vendor.display.enable_null_display=0 \
     vendor.display.disable_excl_rect=0 \
+    vendor.display.disable_excl_rect_partial_fb=1 \
     vendor.display.comp_mask=0 \
     vendor.display.enable_default_color_mode=1 \
     vendor.display.enable_optimize_refresh=1 \
     vendor.display.disable_ui_3d_tonemap=1
 
+ifeq ($(TARGET_BOARD_PLATFORM), msmnile)
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.protected_contents=true
+endif
+
 #Set WCG properties
-ifeq ($(TARGET_BOARD_PLATFORM), sm8150)
+ifeq ($(TARGET_BOARD_PLATFORM),$(TRINKET))
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_wide_color_display=false
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_HDR_display=false
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.use_color_management=false
+else
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_wide_color_display=true
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_HDR_display=true
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.use_color_management=true
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.wcg_composition_dataspace=143261696
-PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.protected_contents=true
 endif
 
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.force_hwc_copy_for_virtual_displays=true
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.max_frame_buffer_acquired_buffers=3
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.max_virtual_display_dimension=4096
+
+
 ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
 # Recovery is enabled, logging is enabled
 PRODUCT_PROPERTY_OVERRIDES += \
diff --git a/config/talos.mk b/config/talos.mk
index 93c1cf9..3c5bace 100644
--- a/config/talos.mk
+++ b/config/talos.mk
@@ -1,8 +1,8 @@
 #Display related packages and configuration
 
 PRODUCT_PACKAGES += \
-    android.hardware.graphics.composer@2.3-impl \
-    android.hardware.graphics.composer@2.3-service \
+    android.hardware.graphics.composer@2.4-impl \
+    android.hardware.graphics.composer@2.4-service \
     android.hardware.graphics.mapper@2.0-impl-qti-display \
     vendor.qti.hardware.display.allocator-service \
     android.hardware.memtrack@1.0-impl \
diff --git a/gralloc/Android.bp b/gralloc/Android.bp
new file mode 100644
index 0000000..f4ebf61
--- /dev/null
+++ b/gralloc/Android.bp
@@ -0,0 +1,35 @@
+package {
+    default_applicable_licenses: ["hardware_qcom_sm8150_display_license"],
+}
+
+cc_library_shared {
+    name: "libgrallocutils",
+    vendor: true,
+    defaults: ["display_go_defaults"],
+    srcs: [
+        "gr_utils.cpp",
+        "gr_adreno_info.cpp",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"qdgralloc\"",
+        "-Wno-sign-conversion",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
+        "libcutils",
+        "libdl",
+        "liblog",
+        "//vendor/qcom/sm8150:libqdMetaData",
+    ],
+    header_libs: [
+        "display_headers",
+        "device_kernel_headers",
+    ],
+    export_header_lib_headers: [
+        "device_kernel_headers",
+    ],
+    export_include_dirs: ["."],
+}
diff --git a/gralloc/Android.mk b/gralloc/Android.mk
index 0a55f64..99343e6 100644
--- a/gralloc/Android.mk
+++ b/gralloc/Android.mk
@@ -20,32 +20,15 @@
                                  libgralloccore \
                                  android.hardware.graphics.mapper@2.0 \
                                  android.hardware.graphics.mapper@2.1 \
-                                 android.hardware.graphics.mapper@3.0
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wall -Werror
+                                 android.hardware.graphics.mapper@3.0 \
+                                 android.hardware.graphics.mapper@4.0
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wall -Werror \
+                                 -D__QTI_DISPLAY_GRALLOC__
 LOCAL_CLANG                   := true
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := gr_device_impl.cpp
 include $(BUILD_SHARED_LIBRARY)
 
-#libgrallocutils
-include $(CLEAR_VARS)
-LOCAL_MODULE                  := libgrallocutils
-LOCAL_LICENSE_KINDS           := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
-LOCAL_LICENSE_CONDITIONS      := by_exception_only not_allowed notice
-LOCAL_NOTICE_FILE             := $(LOCAL_PATH)/../LICENSE
-LOCAL_VENDOR_MODULE           := true
-LOCAL_MODULE_TAGS             := optional
-LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_HEADER_LIBRARIES        := display_headers
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdMetaData libdl  \
-                                  android.hardware.graphics.mapper@2.0 \
-                                  android.hardware.graphics.mapper@2.1 \
-                                  android.hardware.graphics.mapper@3.0
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES               := gr_utils.cpp gr_adreno_info.cpp
-include $(BUILD_SHARED_LIBRARY)
-
 #libgralloccore
 include $(CLEAR_VARS)
 LOCAL_MODULE                  := libgralloccore
@@ -59,13 +42,20 @@
                                  $(kernel_includes)
 
 LOCAL_HEADER_LIBRARIES        := display_headers
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdMetaData libdl libgrallocutils libion \
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdMetaData libdl libgrallocutils libion libgralloctypes \
+                                  libgralloc.qti libhidlbase \
                                   android.hardware.graphics.mapper@2.1 \
-                                  android.hardware.graphics.mapper@3.0
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
+                                  android.hardware.graphics.mapper@3.0 \
+                                  android.hardware.graphics.mapper@4.0
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion \
+                                 -D__QTI_DISPLAY_GRALLOC__
 ifeq ($(ENABLE_HYP),true)
 LOCAL_CFLAGS += -DHYPERVISOR
 endif
+
+ifneq ($(TARGET_USES_GRALLOC4),false)
+LOCAL_CFLAGS                  += -DTARGET_USES_GRALLOC4
+endif
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := gr_allocator.cpp gr_buf_mgr.cpp gr_ion_alloc.cpp
 include $(BUILD_SHARED_LIBRARY)
@@ -91,13 +81,50 @@
                                   vendor.qti.hardware.display.mapperextensions@1.0 \
                                   android.hardware.graphics.mapper@2.0 \
                                   android.hardware.graphics.mapper@2.1 \
-                                  android.hardware.graphics.mapper@3.0 \
-				  vendor.qti.hardware.display.mapperextensions@1.1
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
+                                  vendor.qti.hardware.display.mapperextensions@1.1 \
+                                  android.hardware.graphics.mapper@3.0
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion \
+                                 -D__QTI_DISPLAY_GRALLOC__
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := QtiMapper.cpp QtiMapperExtensions.cpp
+#LOCAL_VINTF_FRAGMENTS         := android.hardware.graphics.mapper-impl-qti-display.xml
 include $(BUILD_SHARED_LIBRARY)
 
+ifneq ($(TARGET_USES_GRALLOC4),false)
+include $(CLEAR_VARS)
+LOCAL_MODULE                  := android.hardware.graphics.mapper@4.0-impl-qti-display
+LOCAL_SANITIZE                := integer_overflow
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_SHARED_LIBRARIES        := $(common_libs) \
+                                  libhidlbase \
+                                  libhidltransport \
+                                  libqdMetaData \
+                                  libgrallocutils \
+                                  libgralloccore \
+                                  libsync \
+                                  libgralloctypes \
+                                  vendor.qti.hardware.display.mapper@4.0 \
+                                  vendor.qti.hardware.display.mapperextensions@1.0 \
+                                  android.hardware.graphics.mapper@2.0 \
+                                  android.hardware.graphics.mapper@2.1 \
+                                  vendor.qti.hardware.display.mapperextensions@1.1 \
+                                  android.hardware.graphics.mapper@3.0 \
+                                  android.hardware.graphics.mapper@4.0
+LOCAL_CFLAGS                  := $(common_flags) $(qmaa_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion \
+                                 -D__QTI_DISPLAY_GRALLOC__
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES               := QtiMapper4.cpp QtiMapperExtensions.cpp
+#LOCAL_VINTF_FRAGMENTS         := android.hardware.graphics.mapper-impl-qti-display.xml
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../LICENSE
+include $(BUILD_SHARED_LIBRARY)
+endif
+
 #allocator
 include $(CLEAR_VARS)
 LOCAL_MODULE                  := vendor.qti.hardware.display.allocator-service
@@ -113,13 +140,25 @@
                                  libqdMetaData \
                                  libgrallocutils \
                                  libgralloccore \
+                                 libgralloctypes \
+                                 vendor.qti.hardware.display.allocator@4.0 \
                                  vendor.qti.hardware.display.allocator@3.0 \
+                                 vendor.qti.hardware.display.mapper@4.0 \
+                                 vendor.qti.hardware.display.mapper@3.0 \
+                                 android.hardware.graphics.mapper@4.0 \
                                  android.hardware.graphics.mapper@3.0 \
                                  android.hardware.graphics.mapper@2.1 \
-                                 android.hardware.graphics.allocator@3.0
+                                 android.hardware.graphics.allocator@4.0 \
+                                 android.hardware.graphics.allocator@3.0 \
+                                 vendor.qti.hardware.display.mapperextensions@1.0 \
+                                 vendor.qti.hardware.display.mapperextensions@1.1
 LOCAL_CFLAGS                  := -DLOG_TAG=\"qdgralloc\" $(common_flags)
+ifneq ($(TARGET_USES_GRALLOC4),false)
+LOCAL_CFLAGS                  += -DTARGET_USES_GRALLOC4
+endif
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SRC_FILES               := QtiAllocator.cpp service.cpp
 LOCAL_INIT_RC                 := vendor.qti.hardware.display.allocator-service.rc
+#LOCAL_VINTF_FRAGMENTS         := vendor.qti.hardware.display.allocator-service.xml
 include $(BUILD_EXECUTABLE)
diff --git a/gralloc/QtiAllocator.cpp b/gralloc/QtiAllocator.cpp
index 44612c0..35145dc 100644
--- a/gralloc/QtiAllocator.cpp
+++ b/gralloc/QtiAllocator.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,11 +30,26 @@
 #define DEBUG 0
 #include "QtiAllocator.h"
 
+#include <cutils/properties.h>
 #include <log/log.h>
+#include <vendor/qti/hardware/display/mapper/3.0/IQtiMapper.h>
+#include <vendor/qti/hardware/display/mapper/4.0/IQtiMapper.h>
+
 #include <vector>
 
+#include "QtiMapper.h"
+#include "QtiMapper4.h"
 #include "gr_utils.h"
 
+static void get_properties(gralloc::GrallocProperties *props) {
+  props->use_system_heap_for_sensors =
+      property_get_bool("vendor.gralloc.use_system_heap_for_sensors", 1);
+
+  props->ubwc_disable = property_get_bool("vendor.gralloc.disable_ubwc", 0);
+
+  props->ahardware_buffer_disable = property_get_bool("vendor.gralloc.disable_ahardware_buffer", 0);
+}
+
 namespace vendor {
 namespace qti {
 namespace hardware {
@@ -45,9 +60,14 @@
 
 using android::hardware::hidl_handle;
 using gralloc::BufferDescriptor;
+using IMapper_3_0_Error = android::hardware::graphics::mapper::V3_0::Error;
+using gralloc::Error;
 
 QtiAllocator::QtiAllocator() {
+  gralloc::GrallocProperties properties;
+  get_properties(&properties);
   buf_mgr_ = BufferManager::GetInstance();
+  buf_mgr_->SetGrallocDebugProperties(properties);
 }
 
 // Methods from ::android::hardware::graphics::allocator::V2_0::IAllocator follow.
@@ -65,9 +85,10 @@
   ALOGD_IF(DEBUG, "Allocating buffers count: %d", count);
   gralloc::BufferDescriptor desc;
 
-  auto err = desc.Decode(descriptor);
+  auto err = ::vendor::qti::hardware::display::mapper::V3_0::implementation::QtiMapper::Decode(
+      descriptor, &desc);
   if (err != Error::NONE) {
-    hidl_cb(err, 0, hidl_vec<hidl_handle>());
+    hidl_cb(static_cast<IMapper_3_0_Error>(err), 0, hidl_vec<hidl_handle>());
     return Void();
   }
 
@@ -89,7 +110,7 @@
     stride = static_cast<uint32_t>(PRIV_HANDLE_CONST(buffers[0].getNativeHandle())->width);
     hidl_buffers.setToExternal(buffers.data(), buffers.size());
   }
-  hidl_cb(err, stride, hidl_buffers);
+  hidl_cb(static_cast<IMapper_3_0_Error>(err), stride, hidl_buffers);
 
   for (const auto &b : buffers) {
     buf_mgr_->ReleaseBuffer(PRIV_HANDLE_CONST(b.getNativeHandle()));
@@ -98,14 +119,75 @@
   return Void();
 }
 
-// Methods from ::android::hidl::base::V1_0::IBase follow.
+}  // namespace implementation
+}  // namespace V3_0
+}  // namespace allocator
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
 
-IQtiAllocator *HIDL_FETCH_IQtiAllocator(const char * /* name */) {
-  return new QtiAllocator();
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace allocator {
+namespace V4_0 {
+namespace implementation {
+
+using android::hardware::hidl_handle;
+using gralloc::BufferDescriptor;
+using IMapper_4_0_Error = android::hardware::graphics::mapper::V4_0::Error;
+using gralloc::Error;
+
+QtiAllocator::QtiAllocator() {
+  gralloc::GrallocProperties properties;
+  get_properties(&properties);
+  buf_mgr_ = BufferManager::GetInstance();
+  buf_mgr_->SetGrallocDebugProperties(properties);
+}
+
+Return<void> QtiAllocator::allocate(const hidl_vec<uint8_t> &descriptor, uint32_t count,
+                                    allocate_cb hidl_cb) {
+  ALOGD_IF(DEBUG, "Allocating buffers count: %d", count);
+  gralloc::BufferDescriptor desc;
+
+  auto err = ::vendor::qti::hardware::display::mapper::V4_0::implementation::QtiMapper::Decode(
+      descriptor, &desc);
+  if (err != Error::NONE) {
+    hidl_cb(static_cast<IMapper_4_0_Error>(err), 0, hidl_vec<hidl_handle>());
+    return Void();
+  }
+
+  std::vector<hidl_handle> buffers;
+  buffers.reserve(count);
+  for (uint32_t i = 0; i < count; i++) {
+    buffer_handle_t buffer;
+    ALOGD_IF(DEBUG, "buffer: %p", &buffer);
+    err = buf_mgr_->AllocateBuffer(desc, &buffer);
+    if (err != Error::NONE) {
+      break;
+    }
+    buffers.emplace_back(hidl_handle(buffer));
+  }
+
+  uint32_t stride = 0;
+  hidl_vec<hidl_handle> hidl_buffers;
+  if (err == Error::NONE && buffers.size() > 0) {
+    stride = static_cast<uint32_t>(PRIV_HANDLE_CONST(buffers[0].getNativeHandle())->width);
+    hidl_buffers.setToExternal(buffers.data(), buffers.size());
+  }
+  hidl_cb(static_cast<IMapper_4_0_Error>(err), stride, hidl_buffers);
+
+  for (const auto &b : buffers) {
+    buf_mgr_->ReleaseBuffer(PRIV_HANDLE_CONST(b.getNativeHandle()));
+  }
+
+  return Void();
 }
 
 }  // namespace implementation
-}  // namespace V3_0
+}  // namespace V4_0
 }  // namespace allocator
 }  // namespace display
 }  // namespace hardware
diff --git a/gralloc/QtiAllocator.h b/gralloc/QtiAllocator.h
index 7bf1705..918c6b9 100644
--- a/gralloc/QtiAllocator.h
+++ b/gralloc/QtiAllocator.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -33,8 +33,10 @@
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 #include <vendor/qti/hardware/display/allocator/3.0/IQtiAllocator.h>
+#include <vendor/qti/hardware/display/allocator/4.0/IQtiAllocator.h>
 
 #include "gr_buf_mgr.h"
+#include "gr_utils.h"
 
 namespace vendor {
 namespace qti {
@@ -51,16 +53,16 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::hardware::graphics::allocator::V3_0::IAllocator;
-using ::android::hardware::graphics::mapper::V3_0::Error;
+using android::hardware::graphics::allocator::V3_0::IAllocator;
 using ::android::hidl::base::V1_0::DebugInfo;
 using ::android::hidl::base::V1_0::IBase;
 using gralloc::BufferManager;
-using ::vendor::qti::hardware::display::allocator::V3_0::IQtiAllocator;
+using vendor::qti::hardware::display::allocator::V3_0::IQtiAllocator;
 
 class QtiAllocator : public IQtiAllocator {
  public:
   QtiAllocator();
+
   // Methods from ::android::hardware::graphics::allocator::V2_0::IAllocator follow.
   Return<void> dumpDebugInfo(dumpDebugInfo_cb _hidl_cb) override;
   Return<void> allocate(const hidl_vec<uint32_t> &descriptor, uint32_t count,
@@ -71,8 +73,6 @@
   BufferManager *buf_mgr_ = nullptr;
 };
 
-extern "C" IQtiAllocator *HIDL_FETCH_IQtiAllocator(const char *name);
-
 }  // namespace implementation
 }  // namespace V3_0
 }  // namespace allocator
@@ -81,4 +81,46 @@
 }  // namespace qti
 }  // namespace vendor
 
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace allocator {
+namespace V4_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using android::hardware::graphics::allocator::V4_0::IAllocator;
+using ::android::hidl::base::V1_0::DebugInfo;
+using ::android::hidl::base::V1_0::IBase;
+using gralloc::BufferManager;
+using vendor::qti::hardware::display::allocator::V4_0::IQtiAllocator;
+
+class QtiAllocator : public IQtiAllocator {
+ public:
+  QtiAllocator();
+
+  // Methods from ::android::hardware::graphics::allocator::V4_0::IAllocator follow.
+  Return<void> allocate(const hidl_vec<uint8_t> &descriptor, uint32_t count,
+                        allocate_cb _hidl_cb) override;
+
+  // Methods from ::android::hidl::base::V1_0::IBase follow.
+ private:
+  BufferManager *buf_mgr_ = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V4_0
+}  // namespace allocator
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
+
 #endif  // __QTIALLOCATOR_H__
diff --git a/gralloc/QtiMapper.cpp b/gralloc/QtiMapper.cpp
index 049a442..d8dd675 100644
--- a/gralloc/QtiMapper.cpp
+++ b/gralloc/QtiMapper.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -40,6 +40,7 @@
 namespace hardware {
 namespace display {
 namespace mapper {
+namespace V3_0 {
 namespace implementation {
 
 using gralloc::BufferInfo;
@@ -67,7 +68,7 @@
            static_cast<uint32_t>(descriptor_info.format), descriptor_info.layerCount);
 
   if (ValidDescriptor(descriptor_info)) {
-    auto vec = gralloc::BufferDescriptor::Encode(descriptor_info);
+    auto vec = Encode(descriptor_info);
     *descriptor = vec;
     return Error::NONE;
   } else {
@@ -105,7 +106,8 @@
     return Void();
   }
 
-  auto error = buf_mgr_->RetainBuffer(PRIV_HANDLE_CONST(buffer_handle));
+  auto error =
+      static_cast<IMapper_3_0_Error>(buf_mgr_->RetainBuffer(PRIV_HANDLE_CONST(buffer_handle)));
   if (error != Error::NONE) {
     ALOGE("%s: Unable to retain handle: %p", __FUNCTION__, buffer_handle);
     native_handle_close(buffer_handle);
@@ -124,7 +126,7 @@
   if (!buffer) {
     return Error::BAD_BUFFER;
   }
-  return buf_mgr_->ReleaseBuffer(PRIV_HANDLE_CONST(buffer));
+  return static_cast<IMapper_3_0_Error>(buf_mgr_->ReleaseBuffer(PRIV_HANDLE_CONST(buffer)));
 }
 
 bool QtiMapper::GetFenceFd(const hidl_handle &fence_handle, int *outFenceFd) {
@@ -169,7 +171,7 @@
 
   auto hnd = PRIV_HANDLE_CONST(buffer);
 
-  return buf_mgr_->LockBuffer(hnd, usage);
+  return static_cast<IMapper_3_0_Error>(buf_mgr_->LockBuffer(hnd, usage));
 }
 
 Return<void> QtiMapper::lock(void *buffer, uint64_t cpu_usage,
@@ -183,8 +185,8 @@
 
   auto hnd = PRIV_HANDLE_CONST(buffer);
   auto *out_data = reinterpret_cast<void *>(hnd->base);
-  auto bytes_per_pixel = gralloc::GetBpp(hnd->format);
-  hidl_cb(err, out_data, bytes_per_pixel, hnd->width * bytes_per_pixel);
+  hidl_cb(err, out_data, gralloc::GetBpp(hnd->format),
+          (hnd->width) * (gralloc::GetBpp(hnd->format)));
   return Void();
 }
 
@@ -216,7 +218,7 @@
 Return<void> QtiMapper::unlock(void *buffer, unlock_cb hidl_cb) {
   auto err = Error::BAD_BUFFER;
   if (buffer != nullptr) {
-    err = buf_mgr_->UnlockBuffer(PRIV_HANDLE_CONST(buffer));
+    err = static_cast<IMapper_3_0_Error>(buf_mgr_->UnlockBuffer(PRIV_HANDLE_CONST(buffer)));
   }
   // We don't have a release fence
   hidl_cb(err, hidl_handle(nullptr));
@@ -229,14 +231,14 @@
   auto err = Error::BAD_BUFFER;
   auto hnd = static_cast<private_handle_t *>(buffer);
   if (buffer != nullptr && private_handle_t::validate(hnd) == 0) {
-    if (buf_mgr_->IsBufferImported(hnd) != Error::NONE) {
+    if (static_cast<IMapper_3_0_Error>(buf_mgr_->IsBufferImported(hnd)) != Error::NONE) {
       return Error::BAD_BUFFER;
     }
     auto info = gralloc::BufferInfo(descriptor_info.width, descriptor_info.height,
                                     static_cast<uint32_t>(descriptor_info.format),
                                     static_cast<uint64_t>(descriptor_info.usage));
     info.layer_count = descriptor_info.layerCount;
-    err = buf_mgr_->ValidateBufferSize(hnd, info);
+    err = static_cast<IMapper_3_0_Error>(buf_mgr_->ValidateBufferSize(hnd, info));
   }
   return err;
 }
@@ -246,7 +248,7 @@
   auto hnd = static_cast<private_handle_t *>(buffer);
   uint32_t num_fds = 0, num_ints = 0;
   if (buffer != nullptr && private_handle_t::validate(hnd) == 0) {
-    if (buf_mgr_->IsBufferImported(hnd) != Error::NONE) {
+    if (static_cast<IMapper_3_0_Error>(buf_mgr_->IsBufferImported(hnd)) != Error::NONE) {
       hidl_cb(err, num_fds, num_ints);
       return Void();
     }
@@ -270,14 +272,14 @@
   }
 
   gralloc::BufferDescriptor desc;
-  err = desc.Decode(descriptor);
+  err = static_cast<IMapper_3_0_Error>(Decode(descriptor, &desc));
   if (err != Error::NONE) {
     hidl_cb(err, false);
     return Void();
   }
 
   buffer_handle_t buffer;
-  err = buf_mgr_->AllocateBuffer(desc, &buffer, 0, true);
+  err = static_cast<IMapper_3_0_Error>(buf_mgr_->AllocateBuffer(desc, &buffer, 0, true));
   if (err != Error::NONE) {
     hidl_cb(err, false);
   } else {
@@ -300,18 +302,19 @@
 
 // When we are in passthrough mode, this method is used
 // by hidl to obtain the SP HAL object
-IMapper_3_0 *HIDL_FETCH_IMapper(const char * /* name */) {
+extern "C" IMapper_3_0 *HIDL_FETCH_IMapper(const char * /* name */) {
   ALOGD_IF(DEBUG, "Fetching IMapper from QtiMapper");
   auto mapper = new QtiMapper();
   return static_cast<IMapper_3_0 *>(mapper);
 }
 
-IQtiMapper *HIDL_FETCH_IQtiMapper(const char * /* name */) {
+extern "C" IQtiMapper *HIDL_FETCH_IQtiMapper(const char * /* name */) {
   ALOGD_IF(DEBUG, "Fetching QtiMapper");
   return new QtiMapper();
 }
 
 }  // namespace implementation
+}  // namespace V3_0
 }  // namespace mapper
 }  // namespace display
 }  // namespace hardware
diff --git a/gralloc/QtiMapper.h b/gralloc/QtiMapper.h
index 2500120..0c191f5 100644
--- a/gralloc/QtiMapper.h
+++ b/gralloc/QtiMapper.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -36,11 +36,14 @@
 
 #include "QtiMapperExtensions.h"
 #include "gr_buf_mgr.h"
+#include "gr_utils.h"
+
 namespace vendor {
 namespace qti {
 namespace hardware {
 namespace display {
 namespace mapper {
+namespace V3_0 {
 namespace implementation {
 
 using ::android::sp;
@@ -58,14 +61,15 @@
 using ::android::hidl::base::V1_0::DebugInfo;
 using ::android::hidl::base::V1_0::IBase;
 using gralloc::BufferManager;
-using ::vendor::qti::hardware::display::mapper::V3_0::IQtiMapper;
 using ::vendor::qti::hardware::display::mapperextensions::V1_1::IQtiMapperExtensions;
 using ::vendor::qti::hardware::display::mapperextensions::V1_1::implementation::QtiMapperExtensions;
+using ::vendor::qti::hardware::display::mapper::V3_0::IQtiMapper;
 
 using IMapper_3_0 = android::hardware::graphics::mapper::V3_0::IMapper;
 using BufferDescriptorInfo_3_0 =
     android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo;
 using IMapperBufferDescriptor = android::hardware::graphics::mapper::V3_0::BufferDescriptor;
+using IMapper_3_0_Error = ::android::hardware::graphics::mapper::V3_0::Error;
 
 class QtiMapper : public IQtiMapper {
  public:
@@ -91,6 +95,34 @@
 
   Return<void> getMapperExtensions(getMapperExtensions_cb hidl_cb);
   sp<mapperextensions::V1_1::IQtiMapperExtensions> extensions_ = nullptr;
+  hidl_vec<uint32_t> Encode(const IMapper_3_0::BufferDescriptorInfo &bd_info) {
+    hidl_vec<uint32_t> out;
+    out.resize(gralloc::kBufferDescriptorSize);
+    out[0] = gralloc::kMagicVersion;
+    out[1] = bd_info.width;
+    out[2] = bd_info.height;
+    out[3] = bd_info.layerCount;
+    out[4] = static_cast<uint32_t>(bd_info.format);
+    out[5] = static_cast<uint32_t>(bd_info.usage);
+    out[6] = static_cast<uint32_t>(bd_info.usage >> 32);
+    return out;
+  }
+  static gralloc::Error Decode(const hidl_vec<uint32_t> &in,
+                               gralloc::BufferDescriptor *buf_descriptor) {
+    if (in.size() != gralloc::kBufferDescriptorSize || in[0] != gralloc::kMagicVersion) {
+      return gralloc::Error::BAD_DESCRIPTOR;
+    }
+    int32_t width = static_cast<int32_t>(in[1]);
+    int32_t height = static_cast<int32_t>(in[2]);
+    buf_descriptor->SetDimensions(width, height);
+    uint32_t layer_count = in[3];
+    buf_descriptor->SetLayerCount(layer_count);
+    int32_t format = static_cast<int32_t>(in[4]);
+    buf_descriptor->SetColorFormat(format);
+    uint64_t usage = static_cast<uint64_t>(in[6]) << 32 | in[5];
+    buf_descriptor->SetUsage(usage);
+    return gralloc::Error::NONE;
+  }
 
  private:
   BufferManager *buf_mgr_ = nullptr;
@@ -102,10 +134,8 @@
   Error LockBuffer(void *buffer, uint64_t usage, const hidl_handle &acquire_fence);
 };
 
-extern "C" IMapper_3_0 *HIDL_FETCH_IMapper(const char *name);
-extern "C" IQtiMapper *HIDL_FETCH_IQtiMapper(const char *name);
-
 }  // namespace implementation
+}  // namespace V3_0
 }  // namespace mapper
 }  // namespace display
 }  // namespace hardware
diff --git a/gralloc/QtiMapper4.cpp b/gralloc/QtiMapper4.cpp
new file mode 100644
index 0000000..fe12dd0
--- /dev/null
+++ b/gralloc/QtiMapper4.cpp
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#define DEBUG 0
+#include "QtiMapper4.h"
+
+#include <cutils/trace.h>
+#include <qdMetaData.h>
+#include <sync/sync.h>
+
+#include <vector>
+
+#include "gr_utils.h"
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace mapper {
+namespace V4_0 {
+namespace implementation {
+
+using gralloc::BufferInfo;
+
+using aidl::android::hardware::graphics::common::StandardMetadataType;
+QtiMapper::QtiMapper() {
+  extensions_ = new QtiMapperExtensions();
+  buf_mgr_ = BufferManager::GetInstance();
+  ALOGD_IF(DEBUG, "Created QtiMapper instance");
+}
+
+bool QtiMapper::ValidDescriptor(const BufferDescriptorInfo_4_0 &bd) {
+  if (bd.width == 0 || bd.height == 0 || (static_cast<int32_t>(bd.format) <= 0) ||
+      bd.layerCount <= 0) {
+    return false;
+  }
+
+  return true;
+}
+
+Error QtiMapper::CreateDescriptor(const BufferDescriptorInfo_4_0 &descriptor_info,
+                                  IMapperBufferDescriptor *descriptor) {
+  ALOGD_IF(DEBUG,
+           "BufferDescriptorInfo: name %s wxh: %dx%d usage: 0x%" PRIu64
+           " format: %d layer_count: %d",
+           descriptor_info.name.c_str(), descriptor_info.width, descriptor_info.height,
+           descriptor_info.usage, static_cast<uint32_t>(descriptor_info.format),
+           descriptor_info.layerCount);
+
+  if (ValidDescriptor(descriptor_info)) {
+    auto vec = Encode(descriptor_info);
+    *descriptor = vec;
+    return Error::NONE;
+  } else {
+    return Error::BAD_VALUE;
+  }
+}
+
+// Methods from ::android::hardware::graphics::mapper::V2_0::IMapper follow.
+Return<void> QtiMapper::createDescriptor(const BufferDescriptorInfo_4_0 &descriptor_info,
+                                         createDescriptor_cb hidl_cb) {
+  IMapperBufferDescriptor descriptor;
+  auto info_4_0 = BufferDescriptorInfo_4_0{descriptor_info.name,
+                                           descriptor_info.width,
+                                           descriptor_info.height,
+                                           descriptor_info.layerCount,
+                                           static_cast<PixelFormat>(descriptor_info.format),
+                                           descriptor_info.usage,
+                                           descriptor_info.reservedSize};
+  auto err = CreateDescriptor(info_4_0, &descriptor);
+  hidl_cb(err, descriptor);
+  return Void();
+}
+
+Return<void> QtiMapper::importBuffer(const hidl_handle &raw_handle, importBuffer_cb hidl_cb) {
+  if (!raw_handle.getNativeHandle()) {
+    ALOGE("%s: Unable to import handle", __FUNCTION__);
+    hidl_cb(Error::BAD_BUFFER, nullptr);
+    return Void();
+  }
+
+  native_handle_t *buffer_handle = native_handle_clone(raw_handle.getNativeHandle());
+  if (!buffer_handle) {
+    ALOGE("%s: Unable to clone handle", __FUNCTION__);
+    hidl_cb(Error::NO_RESOURCES, nullptr);
+    return Void();
+  }
+
+  auto error =
+      static_cast<IMapper_4_0_Error>(buf_mgr_->RetainBuffer(PRIV_HANDLE_CONST(buffer_handle)));
+  if (error != Error::NONE) {
+    ALOGE("%s: Unable to retain handle: %p", __FUNCTION__, buffer_handle);
+    native_handle_close(buffer_handle);
+    native_handle_delete(buffer_handle);
+
+    hidl_cb(error, nullptr);
+    return Void();
+  }
+  ALOGD_IF(DEBUG, "Imported handle: %p id: %" PRIu64, buffer_handle,
+           PRIV_HANDLE_CONST(buffer_handle)->id);
+  hidl_cb(Error::NONE, buffer_handle);
+  return Void();
+}
+
+Return<Error> QtiMapper::freeBuffer(void *buffer) {
+  if (!buffer) {
+    return Error::BAD_BUFFER;
+  }
+  return static_cast<IMapper_4_0_Error>(buf_mgr_->ReleaseBuffer(PRIV_HANDLE_CONST(buffer)));
+}
+
+bool QtiMapper::GetFenceFd(const hidl_handle &fence_handle, int *outFenceFd) {
+  auto handle = fence_handle.getNativeHandle();
+  if (handle && handle->numFds > 1) {
+    ALOGE("invalid fence handle with %d fds", handle->numFds);
+    return false;
+  }
+
+  *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+  return true;
+}
+
+void QtiMapper::WaitFenceFd(int fence_fd) {
+  if (fence_fd < 0) {
+    return;
+  }
+
+  const int timeout = 3000;
+  ATRACE_BEGIN("fence wait");
+  const int error = sync_wait(fence_fd, timeout);
+  ATRACE_END();
+  if (error < 0) {
+    ALOGE("QtiMapper: lock fence %d didn't signal in %u ms -  error: %s", fence_fd, timeout,
+          strerror(errno));
+  }
+}
+
+Error QtiMapper::LockBuffer(void *buffer, uint64_t usage, const hidl_handle &acquire_fence,
+                            const IMapper::Rect &access_region) {
+  if (!buffer) {
+    return Error::BAD_BUFFER;
+  }
+
+  int fence_fd;
+  if (!GetFenceFd(acquire_fence, &fence_fd)) {
+    return Error::BAD_VALUE;
+  }
+
+  if (fence_fd > 0) {
+    WaitFenceFd(fence_fd);
+  }
+
+  auto hnd = PRIV_HANDLE_CONST(buffer);
+
+  if (access_region.top < 0 || access_region.left < 0 || access_region.width < 0 ||
+      access_region.height < 0 || access_region.width > hnd->width ||
+      access_region.height > hnd->height) {
+    return Error::BAD_VALUE;
+  }
+  return static_cast<IMapper_4_0_Error>(buf_mgr_->LockBuffer(hnd, usage));
+}
+
+Return<void> QtiMapper::lock(void *buffer, uint64_t cpu_usage, const IMapper::Rect &access_region,
+                             const hidl_handle &acquire_fence, lock_cb hidl_cb) {
+  auto err = LockBuffer(buffer, cpu_usage, acquire_fence, access_region);
+  if (err != Error::NONE) {
+    hidl_cb(err, nullptr);
+    return Void();
+  }
+
+  auto hnd = PRIV_HANDLE_CONST(buffer);
+  auto *out_data = reinterpret_cast<void *>(hnd->base);
+
+  hidl_cb(err, out_data);
+  return Void();
+}
+
+Return<void> QtiMapper::unlock(void *buffer, unlock_cb hidl_cb) {
+  auto err = Error::BAD_BUFFER;
+  if (buffer != nullptr) {
+    err = static_cast<IMapper_4_0_Error>(buf_mgr_->UnlockBuffer(PRIV_HANDLE_CONST(buffer)));
+  }
+  // We don't have a release fence
+  hidl_cb(err, hidl_handle(nullptr));
+  return Void();
+}
+
+Return<Error> QtiMapper::validateBufferSize(void *buffer,
+                                            const BufferDescriptorInfo_4_0 &descriptor_info,
+                                            uint32_t /*stride*/) {
+  auto err = Error::BAD_BUFFER;
+  auto hnd = static_cast<private_handle_t *>(buffer);
+  if (buffer != nullptr && private_handle_t::validate(hnd) == 0) {
+    if (static_cast<IMapper_4_0_Error>(buf_mgr_->IsBufferImported(hnd)) != Error::NONE) {
+      return Error::BAD_BUFFER;
+    }
+    auto info = gralloc::BufferInfo(descriptor_info.width, descriptor_info.height,
+                                    static_cast<uint32_t>(descriptor_info.format),
+                                    static_cast<uint64_t>(descriptor_info.usage));
+    info.layer_count = descriptor_info.layerCount;
+    err = static_cast<IMapper_4_0_Error>(buf_mgr_->ValidateBufferSize(hnd, info));
+  }
+  return err;
+}
+
+Return<void> QtiMapper::getTransportSize(void *buffer, getTransportSize_cb hidl_cb) {
+  auto err = Error::BAD_BUFFER;
+  auto hnd = static_cast<private_handle_t *>(buffer);
+  uint32_t num_fds = 0, num_ints = 0;
+  if (buffer != nullptr && private_handle_t::validate(hnd) == 0) {
+    if (static_cast<IMapper_4_0_Error>(buf_mgr_->IsBufferImported(hnd)) != Error::NONE) {
+      hidl_cb(err, num_fds, num_ints);
+      return Void();
+    }
+    num_fds = 2;
+    // TODO(user): reduce to transported values;
+    num_ints = static_cast<uint32_t>(hnd->numInts);
+    err = Error::NONE;
+  }
+  ALOGD_IF(DEBUG, "GetTransportSize: num fds: %d num ints: %d err:%d", num_fds, num_ints, err);
+  hidl_cb(err, num_fds, num_ints);
+  return Void();
+}
+
+Return<void> QtiMapper::get(void *buffer, const MetadataType &metadataType, get_cb hidl_cb) {
+  auto err = Error::BAD_BUFFER;
+  hidl_vec<uint8_t> metadata;
+  if (buffer != nullptr) {
+    if (metadataType.name != GRALLOC4_STANDARD_METADATA_TYPE &&
+        metadataType.name != qtigralloc::VENDOR_QTI) {
+      hidl_cb(Error::UNSUPPORTED, metadata);
+      return Void();
+    }
+    auto hnd = static_cast<private_handle_t *>(buffer);
+    err = static_cast<IMapper_4_0_Error>(buf_mgr_->GetMetadata(hnd, metadataType.value, &metadata));
+  }
+  hidl_cb(err, metadata);
+  return Void();
+}
+
+Return<Error> QtiMapper::set(void *buffer, const MetadataType &metadataType,
+                             const hidl_vec<uint8_t> &metadata) {
+  auto err = Error::BAD_BUFFER;
+  if (buffer != nullptr) {
+    auto hnd = static_cast<private_handle_t *>(buffer);
+    err = static_cast<IMapper_4_0_Error>(buf_mgr_->SetMetadata(hnd, metadataType.value, metadata));
+  }
+  return err;
+}
+
+Return<void> QtiMapper::getFromBufferDescriptorInfo(const BufferDescriptorInfo &description,
+                                                    const MetadataType &metadataType,
+                                                    getFromBufferDescriptorInfo_cb hidl_cb) {
+  hidl_vec<uint8_t> out;
+  auto err = Error::UNSUPPORTED;
+  switch (metadataType.value) {
+    case static_cast<int64_t>(StandardMetadataType::NAME):
+      err = static_cast<IMapper_4_0_Error>(android::gralloc4::encodeName(description.name, &out));
+      break;
+    case static_cast<int64_t>(StandardMetadataType::WIDTH):
+      err = static_cast<IMapper_4_0_Error>(android::gralloc4::encodeWidth(description.width, &out));
+      break;
+    case static_cast<int64_t>(StandardMetadataType::HEIGHT):
+      err =
+          static_cast<IMapper_4_0_Error>(android::gralloc4::encodeHeight(description.height, &out));
+      break;
+    case static_cast<int64_t>(StandardMetadataType::LAYER_COUNT):
+      err = static_cast<IMapper_4_0_Error>(
+          android::gralloc4::encodeLayerCount(description.layerCount, &out));
+      break;
+    case static_cast<int64_t>(StandardMetadataType::PIXEL_FORMAT_REQUESTED):
+      err = static_cast<IMapper_4_0_Error>(
+          android::gralloc4::encodePixelFormatRequested(description.format, &out));
+      break;
+    case static_cast<int64_t>(StandardMetadataType::USAGE):
+      err = static_cast<IMapper_4_0_Error>(android::gralloc4::encodeUsage(description.usage, &out));
+      break;
+    case static_cast<int64_t>(StandardMetadataType::COMPRESSION): {
+      int format =
+          gralloc::GetImplDefinedFormat(description.usage, static_cast<int>(description.format));
+      if (gralloc::IsUBwcEnabled(format, description.usage)) {
+        err = static_cast<IMapper_4_0_Error>(
+            android::gralloc4::encodeCompression(qtigralloc::Compression_QtiUBWC, &out));
+      } else {
+        err = static_cast<IMapper_4_0_Error>(
+            android::gralloc4::encodeCompression(android::gralloc4::Compression_None, &out));
+      }
+      break;
+    }
+    case static_cast<int64_t>(StandardMetadataType::PROTECTED_CONTENT): {
+      uint64_t protected_content = 0;
+      if (description.usage & GRALLOC_USAGE_PROTECTED &&
+          !(description.usage & GRALLOC_USAGE_SW_READ_MASK) &&
+          !(description.usage & GRALLOC_USAGE_SW_WRITE_MASK)) {
+        protected_content = 1;
+      }
+      err = static_cast<IMapper_4_0_Error>(
+          android::gralloc4::encodeProtectedContent(protected_content, &out));
+      break;
+    }
+    case static_cast<int64_t>(StandardMetadataType::PIXEL_FORMAT_FOURCC):
+    case static_cast<int64_t>(StandardMetadataType::PIXEL_FORMAT_MODIFIER): {
+      int format =
+          gralloc::GetImplDefinedFormat(description.usage, static_cast<int>(description.format));
+      uint32_t drm_format;
+      uint64_t drm_format_modifier;
+      if (gralloc::IsUBwcEnabled(format, description.usage)) {
+        gralloc::GetDRMFormat(format, private_handle_t::PRIV_FLAGS_UBWC_ALIGNED, &drm_format,
+                              &drm_format_modifier);
+      } else {
+        gralloc::GetDRMFormat(format, 0, &drm_format, &drm_format_modifier);
+      }
+      if (metadataType.value == static_cast<int64_t>(StandardMetadataType::PIXEL_FORMAT_FOURCC)) {
+        err = static_cast<IMapper_4_0_Error>(
+            android::gralloc4::encodePixelFormatFourCC(drm_format, &out));
+      } else {
+        err = static_cast<IMapper_4_0_Error>(
+            android::gralloc4::encodePixelFormatModifier(drm_format_modifier, &out));
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  hidl_cb(err, out);
+  return Void();
+}
+Return<void> QtiMapper::flushLockedBuffer(void *buffer, flushLockedBuffer_cb hidl_cb) {
+  auto err = Error::BAD_BUFFER;
+  if (buffer != nullptr) {
+    err = static_cast<IMapper_4_0_Error>(buf_mgr_->FlushBuffer(PRIV_HANDLE_CONST(buffer)));
+  }
+  // We don't have a release fence
+  hidl_cb(err, hidl_handle(nullptr));
+  return Void();
+}
+
+Return<Error> QtiMapper::rereadLockedBuffer(void *buffer) {
+  auto err = Error::BAD_BUFFER;
+  if (buffer != nullptr) {
+    err = static_cast<IMapper_4_0_Error>(buf_mgr_->RereadBuffer(PRIV_HANDLE_CONST(buffer)));
+  }
+  return err;
+}
+
+Return<void> QtiMapper::getReservedRegion(void *buffer, getReservedRegion_cb hidl_cb) {
+  auto hnd = static_cast<private_handle_t *>(buffer);
+  void *reserved_region = nullptr;
+  uint64_t reserved_size = 0;
+  if (static_cast<IMapper_4_0_Error>(buf_mgr_->IsBufferImported(hnd)) != Error::NONE) {
+    hidl_cb(Error::BAD_BUFFER, reserved_region, reserved_size);
+  }
+  auto err = static_cast<IMapper_4_0_Error>(
+      buf_mgr_->GetReservedRegion(hnd, &reserved_region, &reserved_size));
+
+  hidl_cb(err, reserved_region, reserved_size);
+  return Void();
+}
+
+Error QtiMapper::DumpBufferMetadata(const private_handle_t *buffer, BufferDump *outBufferDump) {
+  outBufferDump->metadataDump.resize(metadata_type_descriptions_.size());
+  for (int i = 0; i < static_cast<int>(metadata_type_descriptions_.size()); i++) {
+    auto type = metadata_type_descriptions_[i].metadataType;
+    hidl_vec<uint8_t> metadata;
+    if (static_cast<IMapper_4_0_Error>(buf_mgr_->GetMetadata(
+            const_cast<private_handle_t *>(buffer), type.value, &metadata)) == Error::BAD_BUFFER) {
+      // If buffer is deleted during metadata dump, return BAD_BUFFER
+      return Error::BAD_BUFFER;
+    }
+    MetadataDump metadata_dump = {type, metadata};
+    outBufferDump->metadataDump[i] = metadata_dump;
+  }
+  return Error::NONE;
+}
+Return<void> QtiMapper::dumpBuffer(void *buffer, dumpBuffer_cb hidl_cb) {
+  BufferDump buffer_dump;
+  auto hnd = PRIV_HANDLE_CONST(buffer);
+  if (buffer != nullptr) {
+    if (DumpBufferMetadata(hnd, &buffer_dump) == Error::NONE) {
+      hidl_cb(Error::NONE, buffer_dump);
+      return Void();
+    }
+  }
+  hidl_cb(Error::BAD_BUFFER, buffer_dump);
+  return Void();
+}
+Return<void> QtiMapper::dumpBuffers(dumpBuffers_cb hidl_cb) {
+  hidl_vec<BufferDump> buffers_dump;
+  std::vector<const private_handle_t *> handle_list;
+  if (static_cast<IMapper_4_0_Error>(buf_mgr_->GetAllHandles(&handle_list)) != Error::NONE) {
+    hidl_cb(Error::NO_RESOURCES, buffers_dump);
+  }
+  buffers_dump.resize(handle_list.size());
+  for (int i = 0; i < handle_list.size(); i++) {
+    BufferDump buffer_dump;
+    if (DumpBufferMetadata(handle_list[i], &buffer_dump) != Error::NONE) {
+      continue;
+    }
+    buffers_dump[i] = buffer_dump;
+  }
+  hidl_cb(Error::NONE, buffers_dump);
+  return Void();
+}
+
+Return<void> QtiMapper::listSupportedMetadataTypes(listSupportedMetadataTypes_cb hidl_cb) {
+  hidl_cb(Error::NONE, metadata_type_descriptions_);
+  return Void();
+}
+
+Return<void> QtiMapper::isSupported(const BufferDescriptorInfo_4_0 &descriptor_info,
+                                    isSupported_cb hidl_cb) {
+  IMapperBufferDescriptor descriptor;
+  auto err = CreateDescriptor(descriptor_info, &descriptor);
+  if (err != Error::NONE) {
+    hidl_cb(err, false);
+    return Void();
+  }
+
+  gralloc::BufferDescriptor desc;
+  err = static_cast<Error>(Decode(descriptor, &desc));
+  if (err != Error::NONE) {
+    hidl_cb(err, false);
+    return Void();
+  }
+
+  buffer_handle_t buffer;
+  err = static_cast<IMapper_4_0_Error>(buf_mgr_->AllocateBuffer(desc, &buffer, 0, true));
+  if (err != Error::NONE) {
+    hidl_cb(err, false);
+  } else {
+    hidl_cb(err, true);
+  }
+
+  return Void();
+}
+
+Return<void> QtiMapper::getMapperExtensions(QtiMapper::getMapperExtensions_cb hidl_cb) {
+  if (extensions_ != nullptr) {
+    hidl_cb(Error::NONE, extensions_);
+  } else {
+    hidl_cb(Error::UNSUPPORTED, extensions_);
+  }
+  return Void();
+}
+
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+
+// When we are in passthrough mode, this method is used
+// by hidl to obtain the SP HAL object
+extern "C" IMapper *HIDL_FETCH_IMapper(const char * /* name */) {
+  ALOGD_IF(DEBUG, "Fetching IMapper from QtiMapper");
+  auto mapper = new QtiMapper();
+  return static_cast<IMapper *>(mapper);
+}
+
+extern "C" IQtiMapper *HIDL_FETCH_IQtiMapper(const char * /* name */) {
+  ALOGD_IF(DEBUG, "Fetching QtiMapper");
+  return new QtiMapper();
+}
+
+}  // namespace implementation
+}  // namespace V4_0
+}  // namespace mapper
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
diff --git a/gralloc/QtiMapper4.h b/gralloc/QtiMapper4.h
new file mode 100644
index 0000000..936393d
--- /dev/null
+++ b/gralloc/QtiMapper4.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __QTIMAPPER4_H__
+#define __QTIMAPPER4_H__
+
+#include <QtiGralloc.h>
+#include <gralloctypes/Gralloc4.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <vendor/qti/hardware/display/mapper/4.0/IQtiMapper.h>
+
+#include <algorithm>
+#include <string>
+
+#include "QtiMapperExtensions.h"
+#include "gr_buf_mgr.h"
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace mapper {
+namespace V4_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
+using ::android::hardware::graphics::mapper::V4_0::Error;
+using ::android::hardware::graphics::mapper::V4_0::IMapper;
+using ::android::hidl::base::V1_0::DebugInfo;
+using ::android::hidl::base::V1_0::IBase;
+using gralloc::BufferManager;
+using ::vendor::qti::hardware::display::mapper::V4_0::IQtiMapper;
+using ::vendor::qti::hardware::display::mapperextensions::V1_1::IQtiMapperExtensions;
+using ::vendor::qti::hardware::display::mapperextensions::V1_1::implementation::QtiMapperExtensions;
+
+using android::hardware::graphics::mapper::V4_0::IMapper;
+using BufferDescriptorInfo_4_0 =
+    android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo;
+using IMapperBufferDescriptor = android::hardware::graphics::mapper::V4_0::BufferDescriptor;
+using MetadataType = ::android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
+using MetadataTypeDescription =
+    ::android::hardware::graphics::mapper::V4_0::IMapper::MetadataTypeDescription;
+using IMapper_4_0_Error = ::android::hardware::graphics::mapper::V4_0::Error;
+
+class QtiMapper : public IQtiMapper {
+ public:
+  QtiMapper();
+  // Methods from ::android::hardware::graphics::mapper::V2_0::IMapper follow.
+  Return<void> createDescriptor(const BufferDescriptorInfo_4_0 &descriptor_info,
+                                createDescriptor_cb hidl_cb) override;
+  Return<void> importBuffer(const hidl_handle &raw_handle, importBuffer_cb hidl_cb) override;
+  Return<Error> freeBuffer(void *buffer) override;
+  Return<void> lock(void *buffer, uint64_t cpu_usage, const IMapper::Rect &access_region,
+                    const hidl_handle &acquire_fence, lock_cb hidl_cb) override;
+  Return<void> unlock(void *buffer, unlock_cb hidl_cb) override;
+
+  // Methods from ::android::hardware::graphics::mapper::V2_1::IMapper follow.
+  Return<Error> validateBufferSize(void *buffer, const BufferDescriptorInfo_4_0 &descriptorInfo,
+                                   uint32_t stride) override;
+  Return<void> getTransportSize(void *buffer, getTransportSize_cb hidl_cb) override;
+
+  Return<void> isSupported(const BufferDescriptorInfo_4_0 &descriptor_info,
+                           isSupported_cb hidl_cb) override;
+
+  Return<void> getMapperExtensions(getMapperExtensions_cb hidl_cb);
+  sp<mapperextensions::V1_1::IQtiMapperExtensions> extensions_ = nullptr;
+
+  // Methods from ::android::hardware::graphics::mapper::V4:0::IMapper follow.
+  Return<void> get(void *buffer, const MetadataType &metadataType, get_cb hidl_cb) override;
+  Return<Error> set(void *buffer, const MetadataType &metadataType,
+                    const hidl_vec<uint8_t> &metadata) override;
+  Return<void> getFromBufferDescriptorInfo(const BufferDescriptorInfo &description,
+                                           const MetadataType &metadataType,
+                                           getFromBufferDescriptorInfo_cb hidl_cb) override;
+  Return<void> flushLockedBuffer(void *buffer, flushLockedBuffer_cb hidl_cb);
+  Return<Error> rereadLockedBuffer(void *buffer);
+  Return<void> listSupportedMetadataTypes(listSupportedMetadataTypes_cb hidl_cb);
+  Return<void> getReservedRegion(void *buffer, getReservedRegion_cb _hidl_cb);
+  Return<void> dumpBuffer(void *buffer, dumpBuffer_cb _hidl_cb);
+  Return<void> dumpBuffers(dumpBuffers_cb _hidl_cb);
+
+  hidl_vec<uint8_t> Encode(const BufferDescriptorInfo_4_0 &bd_info) {
+    hidl_vec<uint8_t> out;
+
+    uint64_t name_size = bd_info.name.size();
+
+    /* Name length is variable, need to store string prepended with size
+     * The rest of the packet size is constant
+     */
+    out.resize(gralloc::kBufferDescriptorSizeV4 + sizeof(name_size) +
+               static_cast<size_t>(name_size));
+
+    size_t index = 0;
+    uint32_t magic_version = gralloc::kMagicVersion;
+    std::memcpy(&out[index], &magic_version, sizeof(magic_version));
+    index += sizeof(magic_version);
+
+    std::memcpy(&out[index], &name_size, sizeof(name_size));
+    index += sizeof(name_size);
+
+    std::memcpy(&out[index], bd_info.name.c_str(), bd_info.name.size());
+    index += name_size;
+
+    std::memcpy(&out[index], &bd_info.width, sizeof(bd_info.width));
+    index += sizeof(bd_info.width);
+
+    std::memcpy(&out[index], &bd_info.height, sizeof(bd_info.height));
+    index += sizeof(bd_info.height);
+
+    std::memcpy(&out[index], &bd_info.layerCount, sizeof(bd_info.layerCount));
+    index += sizeof(bd_info.layerCount);
+
+    std::memcpy(&out[index], &bd_info.format, sizeof(bd_info.format));
+    index += sizeof(bd_info.format);
+
+    std::memcpy(&out[index], &bd_info.usage, sizeof(bd_info.usage));
+    index += sizeof(bd_info.usage);
+
+    std::memcpy(&out[index], &bd_info.reservedSize, sizeof(bd_info.reservedSize));
+
+    return out;
+  }
+  static gralloc::Error Decode(const hidl_vec<uint8_t> &in,
+                               gralloc::BufferDescriptor *buf_descriptor) {
+    // First check is to avoid dereferencing if the vector is too short
+    if (in.size() < gralloc::kBufferDescriptorSizeV4) {
+      return gralloc::Error::BAD_DESCRIPTOR;
+    }
+
+    size_t index = 0;
+    uint32_t magic_version;
+    std::memcpy(&magic_version, &in[index], sizeof(magic_version));
+    index += sizeof(magic_version);
+
+    uint64_t name_size;
+    std::memcpy(&name_size, &in[index], sizeof(name_size));
+    index += sizeof(name_size);
+
+    // The second check validates that the size and magic version are correct
+    if (in.size() != (gralloc::kBufferDescriptorSizeV4 + name_size + sizeof(name_size)) ||
+        magic_version != gralloc::kMagicVersion) {
+      return gralloc::Error::BAD_DESCRIPTOR;
+    }
+
+    std::string name;
+
+    name.resize(static_cast<size_t>(name_size));
+    std::memcpy(name.data(), &in[index], name.size());
+    index += name_size;
+    buf_descriptor->SetName(name);
+
+    int32_t width, height;
+    std::memcpy(&width, &in[index], sizeof(width));
+
+    index += sizeof(width);
+    std::memcpy(&height, &in[index], sizeof(height));
+    index += sizeof(height);
+    buf_descriptor->SetDimensions(width, height);
+
+    uint32_t layer_count;
+    std::memcpy(&layer_count, &in[index], sizeof(layer_count));
+    index += sizeof(layer_count);
+    buf_descriptor->SetLayerCount(layer_count);
+
+    int32_t format;
+    std::memcpy(&format, &in[index], sizeof(format));
+    index += sizeof(format);
+    buf_descriptor->SetColorFormat(format);
+
+    uint64_t usage;
+    std::memcpy(&usage, &in[index], sizeof(usage));
+    index += sizeof(usage);
+    buf_descriptor->SetUsage(usage);
+
+    uint64_t reserved_size;
+    std::memcpy(&reserved_size, &in[index], sizeof(reserved_size));
+    index += sizeof(reserved_size);
+
+    buf_descriptor->SetReservedSize(reserved_size);
+    return gralloc::Error::NONE;
+  }
+
+ private:
+  BufferManager *buf_mgr_ = nullptr;
+  Error CreateDescriptor(const BufferDescriptorInfo_4_0 &descriptor_info,
+                         IMapperBufferDescriptor *descriptor);
+  bool ValidDescriptor(const IMapper::BufferDescriptorInfo &bd);
+  bool GetFenceFd(const hidl_handle &fence_handle, int *outFenceFd);
+  void WaitFenceFd(int fence_fd);
+  Error LockBuffer(void *buffer, uint64_t usage, const hidl_handle &acquire_fence,
+                   const IMapper::Rect &access_region);
+
+  Error DumpBufferMetadata(const private_handle_t *buffer, BufferDump *outBufferDump);
+
+  hidl_vec<MetadataTypeDescription> metadata_type_descriptions_ = {
+      // MetadataType, description, gettable, settable
+      {android::gralloc4::MetadataType_BufferId, "", true, false},
+      {android::gralloc4::MetadataType_Name, "", true, false},
+      {android::gralloc4::MetadataType_Width, "", true, false},
+      {android::gralloc4::MetadataType_Height, "", true, false},
+      {android::gralloc4::MetadataType_LayerCount, "", true, false},
+      {android::gralloc4::MetadataType_PixelFormatRequested, "", true, false},
+      {android::gralloc4::MetadataType_PixelFormatFourCC, "", true, false},
+      {android::gralloc4::MetadataType_PixelFormatModifier, "", true, false},
+      {android::gralloc4::MetadataType_Usage, "", true, false},
+      {android::gralloc4::MetadataType_AllocationSize, "", true, false},
+      {android::gralloc4::MetadataType_ProtectedContent, "", true, false},
+      {android::gralloc4::MetadataType_ChromaSiting, "", true, false},
+      {android::gralloc4::MetadataType_Compression, "", true, false},
+      {android::gralloc4::MetadataType_Interlaced, "", true, false},
+      {android::gralloc4::MetadataType_PlaneLayouts, "", true, false},
+      {android::gralloc4::MetadataType_Dataspace, "", true, true},
+      {android::gralloc4::MetadataType_BlendMode, "", true, true},
+      {android::gralloc4::MetadataType_Smpte2086, "", true, true},
+      {android::gralloc4::MetadataType_Cta861_3, "", true, true},
+      {android::gralloc4::MetadataType_Smpte2094_40, "", true, true},
+      {android::gralloc4::MetadataType_Crop, "", true, true},
+      {qtigralloc::MetadataType_VTTimestamp, "VT Timestamp", true, true},
+      {qtigralloc::MetadataType_ColorMetadata, "Color metadata", true, true},
+      {qtigralloc::MetadataType_PPParamInterlaced, "Interlaced", true, true},
+      {qtigralloc::MetadataType_VideoPerfMode, "Video perf mode", true, true},
+      {qtigralloc::MetadataType_GraphicsMetadata, "Graphics metadata", true, true},
+      {qtigralloc::MetadataType_UBWCCRStatsInfo, "UBWC stats", true, true},
+      {qtigralloc::MetadataType_RefreshRate, "Refresh rate", true, true},
+      {qtigralloc::MetadataType_MapSecureBuffer, "Secure buffer mappable", true, true},
+      {qtigralloc::MetadataType_LinearFormat, "Linear format", true, true},
+      {qtigralloc::MetadataType_SingleBufferMode, "Single buffer mode flag", true, true},
+      {qtigralloc::MetadataType_CVPMetadata, "CVP metadata", true, true},
+      {qtigralloc::MetadataType_VideoHistogramStats, "Video histogram stats", true, true},
+      {qtigralloc::MetadataType_FD, "fd from private_handle_t", true, false},
+      {qtigralloc::MetadataType_PrivateFlags, "Flags in private_handle_t", true, false},
+      {qtigralloc::MetadataType_AlignedWidthInPixels, "width in private_handle_t", true, false},
+      {qtigralloc::MetadataType_AlignedHeightInPixels, "height in private_handle_t", true, false},
+#ifdef METADATA_V2
+      {qtigralloc::MetadataType_StandardMetadataStatus, "Is standard metadata set", true, false},
+      {qtigralloc::MetadataType_VendorMetadataStatus, "Is vendor metadata set", true, false},
+#endif
+#ifdef QTI_BUFFER_TYPE
+      {qtigralloc::MetadataType_BufferType, "Buffer type from private_handle_t", true, false},
+#endif
+  };
+};
+
+}  // namespace implementation
+}  // namespace V4_0
+}  // namespace mapper
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
+
+#endif  // __QTIMAPPER4_H__
diff --git a/gralloc/QtiMapperExtensions.h b/gralloc/QtiMapperExtensions.h
index 1e2a4ad..5f1df06 100644
--- a/gralloc/QtiMapperExtensions.h
+++ b/gralloc/QtiMapperExtensions.h
@@ -52,7 +52,6 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::graphics::common::V1_2::PixelFormat;
-using ::android::hardware::graphics::mapper::V3_0::IMapper;
 using ::android::hidl::base::V1_0::DebugInfo;
 using ::android::hidl::base::V1_0::IBase;
 using gralloc::BufferManager;
diff --git a/gralloc/android.hardware.graphics.mapper-impl-qti-display.xml b/gralloc/android.hardware.graphics.mapper-impl-qti-display.xml
new file mode 100644
index 0000000..4e5c3ad
--- /dev/null
+++ b/gralloc/android.hardware.graphics.mapper-impl-qti-display.xml
@@ -0,0 +1,52 @@
+<!--
+Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>vendor.qti.hardware.display.mapper</name>
+        <transport arch="32+64">passthrough</transport>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IQtiMapper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl">
+        <name>android.hardware.graphics.mapper</name>
+        <transport arch="32+64">passthrough</transport>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IMapper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
+
+
diff --git a/gralloc/gr_adreno_info.cpp b/gralloc/gr_adreno_info.cpp
index 9277e84..a52e6fc 100644
--- a/gralloc/gr_adreno_info.cpp
+++ b/gralloc/gr_adreno_info.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved.
 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -77,20 +77,11 @@
   } else {
     ALOGE(" Failed to load libadreno_utils.so");
   }
-
-  // Check if the overriding property debug.gralloc.gfx_ubwc_disable
-  // that disables UBWC allocations for the graphics stack is set
   char property[PROPERTY_VALUE_MAX];
   property_get(DISABLE_UBWC_PROP, property, "0");
   if (!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
       !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
-    gfx_ubwc_disable_ = true;
-  }
-
-  property_get(DISABLE_AHARDWAREBUFFER_PROP, property, "0");
-  if (!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
-      !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
-    gfx_ahardware_buffer_disable_ = true;
+     gfx_ubwc_disable_ = true;
   }
 }
 
@@ -100,6 +91,10 @@
   }
 }
 
+void AdrenoMemInfo::AdrenoSetProperties(gralloc::GrallocProperties props) {
+  gfx_ahardware_buffer_disable_ = props.ahardware_buffer_disable;
+}
+
 void AdrenoMemInfo::AlignUnCompressedRGB(int width, int height, int format, int tile_enabled,
                                          unsigned int *aligned_w, unsigned int *aligned_h) {
   *aligned_w = (unsigned int)ALIGN(width, 32);
diff --git a/gralloc/gr_adreno_info.h b/gralloc/gr_adreno_info.h
index ad16943..357b25a 100644
--- a/gralloc/gr_adreno_info.h
+++ b/gralloc/gr_adreno_info.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved.
 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -113,6 +113,12 @@
   SURFACE_TILE_MODE_ENABLE     = 0x1     // used for tiled surface
 } surface_tile_mode_t;
 
+struct GrallocProperties {
+  bool use_system_heap_for_sensors = true;
+  bool ubwc_disable = false;
+  bool ahardware_buffer_disable = false;
+};
+
 class AdrenoMemInfo {
  public:
   /*
@@ -192,6 +198,8 @@
   */
   bool AdrenoSizeAPIAvaliable();
 
+  void AdrenoSetProperties(gralloc::GrallocProperties props);
+
   static AdrenoMemInfo *GetInstance();
 
  private:
diff --git a/gralloc/gr_allocator.cpp b/gralloc/gr_allocator.cpp
index 1e755e4..23f44d6 100644
--- a/gralloc/gr_allocator.cpp
+++ b/gralloc/gr_allocator.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved.
 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -100,11 +100,6 @@
 
 bool Allocator::Init() {
   ion_allocator_ = new IonAlloc();
-  char property[PROPERTY_VALUE_MAX];
-  property_get(USE_SYSTEM_HEAP_FOR_SENSORS, property, "1");
-  if (!(strncmp(property, "0", PROPERTY_VALUE_MAX))) {
-    use_system_heap_for_sensors_ = false;
-  }
 
   if (!ion_allocator_->Init()) {
     return false;
@@ -119,6 +114,10 @@
   }
 }
 
+void Allocator::SetProperties(gralloc::GrallocProperties props) {
+  use_system_heap_for_sensors_ = props.use_system_heap_for_sensors;
+}
+
 int Allocator::AllocateMem(AllocData *alloc_data, uint64_t usage, int format) {
   int ret;
   alloc_data->uncached = UseUncached(format, usage);
diff --git a/gralloc/gr_allocator.h b/gralloc/gr_allocator.h
index 630151a..e3ebdec 100644
--- a/gralloc/gr_allocator.h
+++ b/gralloc/gr_allocator.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2020, The Linux Foundation. All rights reserved.
 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -34,6 +34,7 @@
 
 #include "gr_buf_descriptor.h"
 #include "gr_ion_alloc.h"
+#include "gr_adreno_info.h"
 #include "gr_utils.h"
 #include "gralloc_priv.h"
 
@@ -44,6 +45,7 @@
   Allocator();
   ~Allocator();
   bool Init();
+  void SetProperties(gralloc::GrallocProperties props);
   int MapBuffer(void **base, unsigned int size, unsigned int offset, int fd);
   int ImportBuffer(int fd);
   int FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd, int handle);
diff --git a/gralloc/gr_buf_descriptor.h b/gralloc/gr_buf_descriptor.h
index 06b6986..2bfaa92 100644
--- a/gralloc/gr_buf_descriptor.h
+++ b/gralloc/gr_buf_descriptor.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,47 +30,22 @@
 #ifndef __GR_BUF_DESCRIPTOR_H__
 #define __GR_BUF_DESCRIPTOR_H__
 
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
 #include <atomic>
+#include <string>
+
+#include "gr_utils.h"
 
 namespace gralloc {
 using android::hardware::hidl_vec;
-using android::hardware::graphics::mapper::V3_0::Error;
-using android::hardware::graphics::mapper::V3_0::IMapper;
 
 const uint32_t kBufferDescriptorSize = 7;
+const uint32_t kBufferDescriptorSizeV4 = 42;
 const uint32_t kMagicVersion = 0x76312E30;  // v1.0
 
 class BufferDescriptor {
  public:
   BufferDescriptor() {}
   explicit BufferDescriptor(uint64_t id) : id_(id) {}
-
-  static hidl_vec<uint32_t> Encode(const IMapper::BufferDescriptorInfo &bd_info) {
-    hidl_vec<uint32_t> out;
-    out.resize(kBufferDescriptorSize);
-    out[0] = kMagicVersion;
-    out[1] = bd_info.width;
-    out[2] = bd_info.height;
-    out[3] = bd_info.layerCount;
-    out[4] = static_cast<uint32_t>(bd_info.format);
-    out[5] = static_cast<uint32_t>(bd_info.usage);
-    out[6] = static_cast<uint32_t>(bd_info.usage >> 32);
-    return out;
-  }
-
-  Error Decode(const hidl_vec<uint32_t> &in) {
-    if (in.size() != kBufferDescriptorSize || in[0] != kMagicVersion) {
-      return Error::BAD_DESCRIPTOR;
-    }
-    width_ = static_cast<int32_t>(in[1]);
-    height_ = static_cast<int32_t>(in[2]);
-    layer_count_ = in[3];
-    format_ = static_cast<int32_t>(in[4]);
-    usage_ = static_cast<uint64_t>(in[6]) << 32 | in[5];
-    return Error::NONE;
-  }
-
   void SetUsage(uint64_t usage) { usage_ |= usage; }
 
   void SetDimensions(int w, int h) {
@@ -82,6 +57,10 @@
 
   void SetLayerCount(uint32_t layer_count) { layer_count_ = layer_count; }
 
+  void SetName(std::string name) { name_ = name; }
+
+  void SetReservedSize(uint64_t reserved_size) { reserved_size_ = reserved_size; }
+
   uint64_t GetUsage() const { return usage_; }
 
   int GetWidth() const { return width_; }
@@ -94,13 +73,19 @@
 
   uint64_t GetId() const { return id_; }
 
+  uint64_t GetReservedSize() const { return reserved_size_; }
+
+  std::string GetName() const { return name_; }
+
  private:
+  std::string name_ = "";
   int width_ = -1;
   int height_ = -1;
   int format_ = -1;
   uint32_t layer_count_ = 1;
   uint64_t usage_ = 0;
   const uint64_t id_ = 0;
+  uint64_t reserved_size_ = 0;
 };
 };      // namespace gralloc
 #endif  // __GR_BUF_DESCRIPTOR_H__
diff --git a/gralloc/gr_buf_mgr.cpp b/gralloc/gr_buf_mgr.cpp
index 86d730e..1674058 100644
--- a/gralloc/gr_buf_mgr.cpp
+++ b/gralloc/gr_buf_mgr.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved.
  * Not a Contribution
  *
  * Copyright (C) 2010 The Android Open Source Project
@@ -19,24 +19,682 @@
 
 #define DEBUG 0
 
+#include "gr_buf_mgr.h"
+
+#include <QtiGralloc.h>
+#include <QtiGrallocPriv.h>
+#include <gralloctypes/Gralloc4.h>
+#include <sys/mman.h>
+
 #include <iomanip>
 #include <sstream>
+#include <string>
 #include <utility>
 #include <vector>
 
+#include "gr_adreno_info.h"
 #include "gr_buf_descriptor.h"
-#include "gr_buf_mgr.h"
 #include "gr_priv_handle.h"
+#include "gr_utils.h"
 #include "qdMetaData.h"
 #include "qd_utils.h"
 
 namespace gralloc {
 
+using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::Cta861_3;
+using aidl::android::hardware::graphics::common::Dataspace;
+using aidl::android::hardware::graphics::common::PlaneLayout;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
+using aidl::android::hardware::graphics::common::Rect;
+using aidl::android::hardware::graphics::common::Smpte2086;
+using aidl::android::hardware::graphics::common::StandardMetadataType;
+using aidl::android::hardware::graphics::common::XyColor;
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
+
 static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) {
   return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(),
                     descriptor.GetUsage());
 }
 
+static uint64_t getMetaDataSize(uint64_t reserved_region_size) {
+// Only include the reserved region size when using Metadata_t V2
+#ifndef METADATA_V2
+  reserved_region_size = 0;
+#endif
+  return static_cast<uint64_t>(ROUND_UP_PAGESIZE(sizeof(MetaData_t) +
+                               static_cast<uint32_t>(reserved_region_size)));
+}
+
+static void unmapAndReset(private_handle_t *handle, uint64_t reserved_region_size = 0) {
+  if (private_handle_t::validate(handle) == 0 && handle->base_metadata) {
+    munmap(reinterpret_cast<void *>(handle->base_metadata),
+           static_cast<uint32_t>(getMetaDataSize(reserved_region_size)));
+    handle->base_metadata = 0;
+  }
+}
+
+static int validateAndMap(private_handle_t *handle, uint64_t reserved_region_size = 0) {
+  if (private_handle_t::validate(handle)) {
+    ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle);
+    return -1;
+  }
+  if (handle->fd_metadata < 0) {
+    // Silently return, metadata cannot be used
+    return -1;
+  }
+
+  if (!handle->base_metadata) {
+    uint64_t size = getMetaDataSize(reserved_region_size);
+    void *base = mmap(NULL, static_cast<uint32_t>(size), PROT_READ | PROT_WRITE,
+                      MAP_SHARED, handle->fd_metadata, 0);
+    if (base == reinterpret_cast<void *>(MAP_FAILED)) {
+      ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", __func__, handle,
+            handle->fd_metadata, strerror(errno));
+      return -1;
+    }
+    handle->base_metadata = (uintptr_t)base;
+#ifdef METADATA_V2
+    // The allocator process gets the reserved region size from the BufferDescriptor.
+    // When importing to another process, the reserved size is unknown until mapping the metadata,
+    // hence the re-mapping below
+    auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+    if (reserved_region_size == 0 && metadata->reservedSize) {
+      size = getMetaDataSize(metadata->reservedSize);
+      unmapAndReset(handle);
+      void *new_base = mmap(NULL, static_cast<uint32_t>(size), PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd_metadata, 0);
+      if (new_base == reinterpret_cast<void *>(MAP_FAILED)) {
+        ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", __func__, handle,
+              handle->fd_metadata, strerror(errno));
+        return -1;
+      }
+      handle->base_metadata = (uintptr_t)new_base;
+    }
+#endif
+  }
+  return 0;
+}
+
+static Error dataspaceToColorMetadata(Dataspace dataspace, ColorMetaData *color_metadata) {
+  ColorMetaData out;
+  uint32_t primaries = (uint32_t)dataspace & (uint32_t)Dataspace::STANDARD_MASK;
+  uint32_t transfer = (uint32_t)dataspace & (uint32_t)Dataspace::TRANSFER_MASK;
+  uint32_t range = (uint32_t)dataspace & (uint32_t)Dataspace::RANGE_MASK;
+
+  switch (primaries) {
+    case (uint32_t)Dataspace::STANDARD_BT709:
+      out.colorPrimaries = ColorPrimaries_BT709_5;
+      break;
+    // TODO(tbalacha): verify this is equivalent
+    case (uint32_t)Dataspace::STANDARD_BT470M:
+      out.colorPrimaries = ColorPrimaries_BT470_6M;
+      break;
+    case (uint32_t)Dataspace::STANDARD_BT601_625:
+    case (uint32_t)Dataspace::STANDARD_BT601_625_UNADJUSTED:
+      out.colorPrimaries = ColorPrimaries_BT601_6_625;
+      break;
+    case (uint32_t)Dataspace::STANDARD_BT601_525:
+    case (uint32_t)Dataspace::STANDARD_BT601_525_UNADJUSTED:
+      out.colorPrimaries = ColorPrimaries_BT601_6_525;
+      break;
+    case (uint32_t)Dataspace::STANDARD_FILM:
+      out.colorPrimaries = ColorPrimaries_GenericFilm;
+      break;
+    case (uint32_t)Dataspace::STANDARD_BT2020:
+      out.colorPrimaries = ColorPrimaries_BT2020;
+      break;
+    case (uint32_t)Dataspace::STANDARD_ADOBE_RGB:
+      out.colorPrimaries = ColorPrimaries_AdobeRGB;
+      break;
+    case (uint32_t)Dataspace::STANDARD_DCI_P3:
+      out.colorPrimaries = ColorPrimaries_DCIP3;
+      break;
+    default:
+      return Error::UNSUPPORTED;
+      /*
+       ColorPrimaries_SMPTE_240M;
+       ColorPrimaries_SMPTE_ST428;
+       ColorPrimaries_EBU3213;
+      */
+  }
+
+  switch (transfer) {
+    case (uint32_t)Dataspace::TRANSFER_SRGB:
+      out.transfer = Transfer_sRGB;
+      break;
+    case (uint32_t)Dataspace::TRANSFER_GAMMA2_2:
+      out.transfer = Transfer_Gamma2_2;
+      break;
+    case (uint32_t)Dataspace::TRANSFER_GAMMA2_8:
+      out.transfer = Transfer_Gamma2_8;
+      break;
+    case (uint32_t)Dataspace::TRANSFER_SMPTE_170M:
+      out.transfer = Transfer_SMPTE_170M;
+      break;
+    case (uint32_t)Dataspace::TRANSFER_LINEAR:
+      out.transfer = Transfer_Linear;
+      break;
+    case (uint32_t)Dataspace::TRANSFER_HLG:
+      out.transfer = Transfer_HLG;
+      break;
+    default:
+      return Error::UNSUPPORTED;
+      /*
+      Transfer_SMPTE_240M
+      Transfer_Log
+      Transfer_Log_Sqrt
+      Transfer_XvYCC
+      Transfer_BT1361
+      Transfer_sYCC
+      Transfer_BT2020_2_1
+      Transfer_BT2020_2_2
+      Transfer_SMPTE_ST2084
+      Transfer_ST_428
+      */
+  }
+
+  switch (range) {
+    case (uint32_t)Dataspace::RANGE_FULL:
+      out.range = Range_Full;
+      break;
+    case (uint32_t)Dataspace::RANGE_LIMITED:
+      out.range = Range_Limited;
+      break;
+    case (uint32_t)Dataspace::RANGE_EXTENDED:
+      out.range = Range_Extended;
+      break;
+    default:
+      return Error::UNSUPPORTED;
+  }
+
+  color_metadata->colorPrimaries = out.colorPrimaries;
+  color_metadata->transfer = out.transfer;
+  color_metadata->range = out.range;
+  return Error::NONE;
+}
+static Error colorMetadataToDataspace(ColorMetaData color_metadata, Dataspace *dataspace) {
+  Dataspace primaries, transfer, range = Dataspace::UNKNOWN;
+
+  switch (color_metadata.colorPrimaries) {
+    case ColorPrimaries_BT709_5:
+      primaries = Dataspace::STANDARD_BT709;
+      break;
+    // TODO(tbalacha): verify this is equivalent
+    case ColorPrimaries_BT470_6M:
+      primaries = Dataspace::STANDARD_BT470M;
+      break;
+    case ColorPrimaries_BT601_6_625:
+      primaries = Dataspace::STANDARD_BT601_625;
+      break;
+    case ColorPrimaries_BT601_6_525:
+      primaries = Dataspace::STANDARD_BT601_525;
+      break;
+    case ColorPrimaries_GenericFilm:
+      primaries = Dataspace::STANDARD_FILM;
+      break;
+    case ColorPrimaries_BT2020:
+      primaries = Dataspace::STANDARD_BT2020;
+      break;
+    case ColorPrimaries_AdobeRGB:
+      primaries = Dataspace::STANDARD_ADOBE_RGB;
+      break;
+    case ColorPrimaries_DCIP3:
+      primaries = Dataspace::STANDARD_DCI_P3;
+      break;
+    default:
+      return Error::UNSUPPORTED;
+      /*
+       ColorPrimaries_SMPTE_240M;
+       ColorPrimaries_SMPTE_ST428;
+       ColorPrimaries_EBU3213;
+      */
+  }
+
+  switch (color_metadata.transfer) {
+    case Transfer_sRGB:
+      transfer = Dataspace::TRANSFER_SRGB;
+      break;
+    case Transfer_Gamma2_2:
+      transfer = Dataspace::TRANSFER_GAMMA2_2;
+      break;
+    case Transfer_Gamma2_8:
+      transfer = Dataspace::TRANSFER_GAMMA2_8;
+      break;
+    case Transfer_SMPTE_170M:
+      transfer = Dataspace::TRANSFER_SMPTE_170M;
+      break;
+    case Transfer_Linear:
+      transfer = Dataspace::TRANSFER_LINEAR;
+      break;
+    case Transfer_HLG:
+      transfer = Dataspace::TRANSFER_HLG;
+      break;
+    default:
+      return Error::UNSUPPORTED;
+      /*
+      Transfer_SMPTE_240M
+      Transfer_Log
+      Transfer_Log_Sqrt
+      Transfer_XvYCC
+      Transfer_BT1361
+      Transfer_sYCC
+      Transfer_BT2020_2_1
+      Transfer_BT2020_2_2
+      Transfer_SMPTE_ST2084
+      Transfer_ST_428
+      */
+  }
+
+  switch (color_metadata.range) {
+    case Range_Full:
+      range = Dataspace::RANGE_FULL;
+      break;
+    case Range_Limited:
+      range = Dataspace::RANGE_LIMITED;
+      break;
+    case Range_Extended:
+      range = Dataspace::RANGE_EXTENDED;
+      break;
+    default:
+      return Error::UNSUPPORTED;
+  }
+
+  *dataspace = (Dataspace)((uint32_t)primaries | (uint32_t)transfer | (uint32_t)range);
+  return Error::NONE;
+}
+
+static Error getComponentSizeAndOffset(int32_t format, PlaneLayoutComponent &comp) {
+  switch (format) {
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGBA_8888):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGBX_8888):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGB_888):
+      comp.sizeInBits = 8;
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.offsetInBits = 8;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.offsetInBits = 16;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value &&
+                 format != HAL_PIXEL_FORMAT_RGB_888) {
+        comp.offsetInBits = 24;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGB_565):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = 5;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.offsetInBits = 5;
+        comp.sizeInBits = 6;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.offsetInBits = 11;
+        comp.sizeInBits = 5;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_BGR_565):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.offsetInBits = 11;
+        comp.sizeInBits = 5;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.offsetInBits = 5;
+        comp.sizeInBits = 6;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = 5;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_BGRA_8888):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_BGRX_8888):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_BGR_888):
+      comp.sizeInBits = 8;
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.offsetInBits = 16;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.offsetInBits = 8;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value &&
+                 format != HAL_PIXEL_FORMAT_BGR_888) {
+        comp.offsetInBits = 24;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGBA_5551):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.sizeInBits = 5;
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.sizeInBits = 5;
+        comp.offsetInBits = 5;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.sizeInBits = 5;
+        comp.offsetInBits = 10;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) {
+        comp.sizeInBits = 1;
+        comp.offsetInBits = 15;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGBA_4444):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.sizeInBits = 4;
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.sizeInBits = 4;
+        comp.offsetInBits = 4;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.sizeInBits = 4;
+        comp.offsetInBits = 8;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) {
+        comp.sizeInBits = 4;
+        comp.offsetInBits = 12;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_R_8):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RG_88):
+      comp.sizeInBits = 8;
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value &&
+                 format != HAL_PIXEL_FORMAT_R_8) {
+        comp.offsetInBits = 8;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGBA_1010102):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGBX_1010102):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 10;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 20;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) {
+        comp.sizeInBits = 2;
+        comp.offsetInBits = 30;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_ARGB_2101010):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_XRGB_2101010):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 2;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 12;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 22;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) {
+        comp.sizeInBits = 2;
+        comp.offsetInBits = 0;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_BGRA_1010102):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_BGRX_1010102):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 20;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 10;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) {
+        comp.sizeInBits = 2;
+        comp.offsetInBits = 30;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_ABGR_2101010):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_XBGR_2101010):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 22;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 12;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.sizeInBits = 10;
+        comp.offsetInBits = 2;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) {
+        comp.sizeInBits = 2;
+        comp.offsetInBits = 0;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RGBA_FP16):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) {
+        comp.sizeInBits = 16;
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) {
+        comp.sizeInBits = 16;
+        comp.offsetInBits = 16;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) {
+        comp.sizeInBits = 16;
+        comp.offsetInBits = 32;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) {
+        comp.sizeInBits = 16;
+        comp.offsetInBits = 48;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YCbCr_420_SP):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YCbCr_422_SP):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_NV12_ENCODEABLE):
+      comp.sizeInBits = 8;
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value ||
+          comp.type.value == android::gralloc4::PlaneLayoutComponentType_CB.value) {
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_CR.value) {
+        comp.offsetInBits = 8;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YCrCb_420_SP):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YCrCb_422_SP):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_NV21_ZSL):
+      comp.sizeInBits = 8;
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value ||
+          comp.type.value == android::gralloc4::PlaneLayoutComponentType_CR.value) {
+        comp.offsetInBits = 0;
+      } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_CB.value) {
+        comp.offsetInBits = 8;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_Y16):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = 16;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YV12):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value ||
+          comp.type.value == android::gralloc4::PlaneLayoutComponentType_CB.value ||
+          comp.type.value == android::gralloc4::PlaneLayoutComponentType_CR.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = 8;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_Y8):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = 8;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_YCbCr_420_P010):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value ||
+          comp.type.value == android::gralloc4::PlaneLayoutComponentType_CB.value ||
+          comp.type.value == android::gralloc4::PlaneLayoutComponentType_CR.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = 10;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RAW16):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_RAW.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = 16;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RAW12):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RAW10):
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_BLOB):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_RAW.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = -1;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    case static_cast<int32_t>(HAL_PIXEL_FORMAT_RAW8):
+      if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_RAW.value) {
+        comp.offsetInBits = 0;
+        comp.sizeInBits = 8;
+      } else {
+        return Error::BAD_VALUE;
+      }
+      break;
+    default:
+      ALOGI_IF(DEBUG, "Offset and size in bits unknown for format %d", format);
+      return Error::UNSUPPORTED;
+  }
+  return Error::NONE;
+}
+
+static void grallocToStandardPlaneLayoutComponentType(uint32_t in,
+                                                      std::vector<PlaneLayoutComponent> *components,
+                                                      int32_t format) {
+  PlaneLayoutComponent comp;
+  comp.offsetInBits = -1;
+  comp.sizeInBits = -1;
+
+  if (in & PLANE_COMPONENT_Y) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_Y;
+    if (getComponentSizeAndOffset(format, comp) == Error::NONE)
+      components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_Cb) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_CB;
+    if (getComponentSizeAndOffset(format, comp) == Error::NONE)
+      components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_Cr) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_CR;
+    if (getComponentSizeAndOffset(format, comp) == Error::NONE)
+      components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_R) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_R;
+    if (getComponentSizeAndOffset(format, comp) == Error::NONE)
+      components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_G) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_G;
+    if (getComponentSizeAndOffset(format, comp) == Error::NONE)
+      components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_B) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_B;
+    if (getComponentSizeAndOffset(format, comp) == Error::NONE)
+      components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_A) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_A;
+    if (getComponentSizeAndOffset(format, comp) == Error::NONE)
+      components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_RAW) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_RAW;
+    if (getComponentSizeAndOffset(format, comp) == Error::NONE)
+      components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_META) {
+    comp.type = qtigralloc::PlaneLayoutComponentType_Meta;
+    components->push_back(comp);
+  }
+}
+
+static Error getFormatLayout(private_handle_t *handle, std::vector<PlaneLayout> *out) {
+  std::vector<PlaneLayout> plane_info;
+  int plane_count = 0;
+  BufferInfo info(handle->unaligned_width, handle->unaligned_height, handle->format, handle->usage);
+
+  gralloc::PlaneLayoutInfo plane_layout[8] = {};
+  if (gralloc::IsYuvFormat(handle->format)) {
+    gralloc::GetYUVPlaneInfo(info, handle->format, handle->width, handle->height, handle->flags,
+                             &plane_count, plane_layout);
+  } else if (gralloc::IsUncompressedRGBFormat(handle->format) ||
+             gralloc::IsCompressedRGBFormat(handle->format)) {
+    gralloc::GetRGBPlaneInfo(info, handle->format, handle->width, handle->height, handle->flags,
+                             &plane_count, plane_layout);
+  } else {
+    return Error::BAD_BUFFER;
+  }
+  plane_info.resize(plane_count);
+  for (int i = 0; i < plane_count; i++) {
+    std::vector<PlaneLayoutComponent> components;
+    grallocToStandardPlaneLayoutComponentType(plane_layout[i].component, &plane_info[i].components,
+                                              handle->format);
+    plane_info[i].horizontalSubsampling = (1ull << plane_layout[i].h_subsampling);
+    plane_info[i].verticalSubsampling = (1ull << plane_layout[i].v_subsampling);
+    plane_info[i].offsetInBytes = static_cast<int64_t>(plane_layout[i].offset);
+    plane_info[i].sampleIncrementInBits = static_cast<int64_t>(plane_layout[i].step * 8);
+    plane_info[i].strideInBytes = static_cast<int64_t>(plane_layout[i].stride_bytes);
+    plane_info[i].totalSizeInBytes = static_cast<int64_t>(plane_layout[i].size);
+    plane_info[i].widthInSamples = handle->unaligned_width >> plane_layout[i].h_subsampling;
+    plane_info[i].heightInSamples = handle->unaligned_height >> plane_layout[i].v_subsampling;
+  }
+  *out = plane_info;
+  return Error::NONE;
+}
+
 BufferManager::BufferManager() : next_id_(0) {
   handles_map_.clear();
   allocator_ = new Allocator();
@@ -54,6 +712,11 @@
   }
 }
 
+void BufferManager::SetGrallocDebugProperties(gralloc::GrallocProperties props) {
+  allocator_->SetProperties(props);
+  AdrenoMemInfo::GetInstance()->AdrenoSetProperties(props);
+}
+
 Error BufferManager::FreeBuffer(std::shared_ptr<Buffer> buf) {
   auto hnd = buf->handle;
   ALOGD_IF(DEBUG, "FreeBuffer handle:%p", hnd);
@@ -63,14 +726,16 @@
     return Error::BAD_BUFFER;
   }
 
+  auto meta_size = getMetaDataSize(buf->reserved_size);
+
   if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset, hnd->fd,
                              buf->ion_handle_main) != 0) {
     return Error::BAD_BUFFER;
   }
 
-  unsigned int meta_size = ALIGN((unsigned int)sizeof(MetaData_t), PAGE_SIZE);
-  if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base_metadata), meta_size,
-                             hnd->offset_metadata, hnd->fd_metadata, buf->ion_handle_meta) != 0) {
+  if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base_metadata),
+                             static_cast<uint32_t>(meta_size), hnd->offset_metadata,
+                             hnd->fd_metadata, buf->ion_handle_meta) != 0) {
     return Error::BAD_BUFFER;
   }
 
@@ -100,6 +765,23 @@
 void BufferManager::RegisterHandleLocked(const private_handle_t *hnd, int ion_handle,
                                          int ion_handle_meta) {
   auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta);
+
+  if (hnd->base_metadata) {
+    auto metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
+#ifdef METADATA_V2
+    buffer->reserved_size = metadata->reservedSize;
+    if (buffer->reserved_size > 0) {
+      buffer->reserved_region_ptr =
+          reinterpret_cast<void *>(hnd->base_metadata + sizeof(MetaData_t));
+    } else {
+      buffer->reserved_region_ptr = nullptr;
+    }
+#else
+    buffer->reserved_region_ptr = reinterpret_cast<void *>(&(metadata->reservedRegion.data));
+    buffer->reserved_size = metadata->reservedRegion.size;
+#endif
+  }
+
   handles_map_.emplace(std::make_pair(hnd, buffer));
 }
 
@@ -127,6 +809,12 @@
   hnd->base = 0;
   hnd->base_metadata = 0;
   hnd->gpuaddr = 0;
+
+  if (validateAndMap(hnd)) {
+    ALOGE("Failed to map metadata: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id);
+    return Error::BAD_BUFFER;
+  }
+
   RegisterHandleLocked(hnd, ion_handle, ion_handle_meta);
   return Error::NONE;
 }
@@ -235,6 +923,42 @@
   return err;
 }
 
+Error BufferManager::FlushBuffer(const private_handle_t *handle) {
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  auto status = Error::NONE;
+
+  private_handle_t *hnd = const_cast<private_handle_t *>(handle);
+  auto buf = GetBufferFromHandleLocked(hnd);
+  if (buf == nullptr) {
+    return Error::BAD_BUFFER;
+  }
+
+  if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
+                              buf->ion_handle_main, CACHE_CLEAN, hnd->fd) != 0) {
+    status = Error::BAD_BUFFER;
+  }
+
+  return status;
+}
+
+Error BufferManager::RereadBuffer(const private_handle_t *handle) {
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  auto status = Error::NONE;
+
+  private_handle_t *hnd = const_cast<private_handle_t *>(handle);
+  auto buf = GetBufferFromHandleLocked(hnd);
+  if (buf == nullptr) {
+    return Error::BAD_BUFFER;
+  }
+
+  if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
+                              buf->ion_handle_main, CACHE_INVALIDATE, hnd->fd) != 0) {
+    status = Error::BAD_BUFFER;
+  }
+
+  return status;
+}
+
 Error BufferManager::UnlockBuffer(const private_handle_t *handle) {
   std::lock_guard<std::mutex> lock(buffer_lock_);
   auto status = Error::NONE;
@@ -309,7 +1033,7 @@
 
   // Allocate memory for MetaData
   AllocData e_data;
-  e_data.size = ALIGN(UINT(sizeof(MetaData_t)), page_size);
+  e_data.size = static_cast<unsigned int>(getMetaDataSize(descriptor.GetReservedSize()));
   e_data.handle = data.handle;
   e_data.align = page_size;
 
@@ -331,16 +1055,42 @@
   hnd->base = 0;
   hnd->base_metadata = 0;
   hnd->layer_count = layer_count;
-  // set default csc as 709, but for video(yuv) its 601L
-  ColorSpace_t colorSpace = (buffer_type == BUFFER_TYPE_VIDEO) ? ITU_R_601 : ITU_R_709;
-  setMetaDataAndUnmap(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
 
   bool use_adreno_for_size = CanUseAdrenoForSize(buffer_type, usage);
   if (use_adreno_for_size) {
     setMetaDataAndUnmap(hnd, SET_GRAPHICS_METADATA, reinterpret_cast<void *>(&graphics_metadata));
   }
 
+#ifdef METADATA_V2
+  auto error = validateAndMap(hnd, descriptor.GetReservedSize());
+#else
+  auto error = validateAndMap(hnd);
+#endif
+
+  if (error != 0) {
+    ALOGE("validateAndMap failed");
+    return Error::BAD_BUFFER;
+  }
+  auto metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
+  auto nameLength = std::min(descriptor.GetName().size(), size_t(MAX_NAME_LEN - 1));
+  nameLength = descriptor.GetName().copy(metadata->name, nameLength);
+  metadata->name[nameLength] = '\0';
+
+#ifdef METADATA_V2
+  metadata->reservedSize = descriptor.GetReservedSize();
+#else
+  metadata->reservedRegion.size =
+     static_cast<uint32_t>(std::min(descriptor.GetReservedSize(), (uint64_t)RESERVED_REGION_SIZE));
+#endif
+  metadata->crop.top = 0;
+  metadata->crop.left = 0;
+  metadata->crop.right = hnd->width;
+  metadata->crop.bottom = hnd->height;
+
+  unmapAndReset(hnd, descriptor.GetReservedSize());
+
   *handle = hnd;
+
   RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle);
   ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id);
   if (DEBUG) {
@@ -373,4 +1123,499 @@
   }
   return Error::NONE;
 }
+
+// Get list of private handles in handles_map_
+Error BufferManager::GetAllHandles(std::vector<const private_handle_t *> *out_handle_list) {
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  if (handles_map_.empty()) {
+    return Error::NO_RESOURCES;
+  }
+  out_handle_list->reserve(handles_map_.size());
+  for (auto handle : handles_map_) {
+    out_handle_list->push_back(handle.first);
+  }
+  return Error::NONE;
+}
+
+Error BufferManager::GetReservedRegion(private_handle_t *handle, void **reserved_region,
+                                       uint64_t *reserved_region_size) {
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  if (!handle)
+    return Error::BAD_BUFFER;
+
+  auto buf = GetBufferFromHandleLocked(handle);
+  if (buf == nullptr)
+    return Error::BAD_BUFFER;
+  if (!handle->base_metadata) {
+    return Error::BAD_BUFFER;
+  }
+
+  *reserved_region = buf->reserved_region_ptr;
+  *reserved_region_size = buf->reserved_size;
+
+  return Error::NONE;
+}
+
+Error BufferManager::GetMetadata(private_handle_t *handle, int64_t metadatatype_value,
+                                 hidl_vec<uint8_t> *out) {
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  if (!handle)
+    return Error::BAD_BUFFER;
+  auto buf = GetBufferFromHandleLocked(handle);
+  if (buf == nullptr)
+    return Error::BAD_BUFFER;
+
+  if (!handle->base_metadata) {
+    return Error::BAD_BUFFER;
+  }
+
+  auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+
+  Error error = Error::NONE;
+  switch (metadatatype_value) {
+    case (int64_t)StandardMetadataType::BUFFER_ID:
+      android::gralloc4::encodeBufferId((uint64_t)handle->id, out);
+      break;
+    case (int64_t)StandardMetadataType::NAME: {
+      std::string name(metadata->name);
+      android::gralloc4::encodeName(name, out);
+      break;
+    }
+    case (int64_t)StandardMetadataType::WIDTH:
+      android::gralloc4::encodeWidth((uint64_t)handle->unaligned_width, out);
+      break;
+    case (int64_t)StandardMetadataType::HEIGHT:
+      android::gralloc4::encodeHeight((uint64_t)handle->unaligned_height, out);
+      break;
+    case (int64_t)StandardMetadataType::LAYER_COUNT:
+      android::gralloc4::encodeLayerCount((uint64_t)handle->layer_count, out);
+      break;
+    case (int64_t)StandardMetadataType::PIXEL_FORMAT_REQUESTED:
+      // TODO(tbalacha): need to return IMPLEMENTATION_DEFINED,
+      // which wouldn't be known from private_handle_t
+      android::gralloc4::encodePixelFormatRequested((PixelFormat)handle->format, out);
+      break;
+    case (int64_t)StandardMetadataType::PIXEL_FORMAT_FOURCC: {
+      uint32_t drm_format = 0;
+      uint64_t drm_format_modifier = 0;
+      GetDRMFormat(handle->format, handle->flags, &drm_format, &drm_format_modifier);
+      android::gralloc4::encodePixelFormatFourCC(drm_format, out);
+      break;
+    }
+    case (int64_t)StandardMetadataType::PIXEL_FORMAT_MODIFIER: {
+      uint32_t drm_format = 0;
+      uint64_t drm_format_modifier = 0;
+      GetDRMFormat(handle->format, handle->flags, &drm_format, &drm_format_modifier);
+      android::gralloc4::encodePixelFormatModifier(drm_format_modifier, out);
+      break;
+    }
+    case (int64_t)StandardMetadataType::USAGE:
+      android::gralloc4::encodeUsage((uint64_t)handle->usage, out);
+      break;
+    case (int64_t)StandardMetadataType::ALLOCATION_SIZE:
+      android::gralloc4::encodeAllocationSize((uint64_t)handle->size, out);
+      break;
+    case (int64_t)StandardMetadataType::PROTECTED_CONTENT: {
+      uint64_t protected_content = (handle->flags & qtigralloc::PRIV_FLAGS_SECURE_BUFFER) ? 1 : 0;
+      android::gralloc4::encodeProtectedContent(protected_content, out);
+      break;
+    }
+    case (int64_t)StandardMetadataType::CHROMA_SITING:
+      android::gralloc4::encodeChromaSiting(android::gralloc4::ChromaSiting_None, out);
+      break;
+    case (int64_t)StandardMetadataType::DATASPACE:
+#ifdef METADATA_V2
+      if (metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)]) {
+#endif
+        Dataspace dataspace;
+        colorMetadataToDataspace(metadata->color, &dataspace);
+        android::gralloc4::encodeDataspace(dataspace, out);
+#ifdef METADATA_V2
+      } else {
+        android::gralloc4::encodeDataspace(Dataspace::UNKNOWN, out);
+      }
+#endif
+      break;
+    case (int64_t)StandardMetadataType::INTERLACED:
+      if (metadata->interlaced > 0) {
+        android::gralloc4::encodeInterlaced(qtigralloc::Interlaced_Qti, out);
+      } else {
+        android::gralloc4::encodeInterlaced(android::gralloc4::Interlaced_None, out);
+      }
+      break;
+    case (int64_t)StandardMetadataType::COMPRESSION:
+      if (handle->flags & qtigralloc::PRIV_FLAGS_UBWC_ALIGNED ||
+          handle->flags & qtigralloc::PRIV_FLAGS_UBWC_ALIGNED_PI) {
+        android::gralloc4::encodeCompression(qtigralloc::Compression_QtiUBWC, out);
+      } else {
+        android::gralloc4::encodeCompression(android::gralloc4::Compression_None, out);
+      }
+      break;
+    case (int64_t)StandardMetadataType::PLANE_LAYOUTS: {
+      std::vector<PlaneLayout> plane_layouts;
+      getFormatLayout(handle, &plane_layouts);
+      android::gralloc4::encodePlaneLayouts(plane_layouts, out);
+      break;
+    }
+    case (int64_t)StandardMetadataType::BLEND_MODE:
+      android::gralloc4::encodeBlendMode((BlendMode)metadata->blendMode, out);
+      break;
+    case (int64_t)StandardMetadataType::SMPTE2086: {
+      if (metadata->color.masteringDisplayInfo.colorVolumeSEIEnabled) {
+        Smpte2086 mastering_display_values;
+        mastering_display_values.primaryRed = {
+            static_cast<float>(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[0][0]) /
+                50000.0f,
+            static_cast<float>(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[0][1]) /
+                50000.0f};
+        mastering_display_values.primaryGreen = {
+            static_cast<float>(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[1][0]) /
+                50000.0f,
+            static_cast<float>(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[1][1]) /
+                50000.0f};
+        mastering_display_values.primaryBlue = {
+            static_cast<float>(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[2][0]) /
+                50000.0f,
+            static_cast<float>(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[2][1]) /
+                50000.0f};
+        mastering_display_values.whitePoint = {
+            static_cast<float>(metadata->color.masteringDisplayInfo.primaries.whitePoint[0]) /
+                50000.0f,
+            static_cast<float>(metadata->color.masteringDisplayInfo.primaries.whitePoint[1]) /
+                50000.0f};
+        mastering_display_values.maxLuminance =
+            static_cast<float>(metadata->color.masteringDisplayInfo.maxDisplayLuminance);
+        mastering_display_values.minLuminance =
+            static_cast<float>(metadata->color.masteringDisplayInfo.minDisplayLuminance) / 10000.0f;
+        android::gralloc4::encodeSmpte2086(mastering_display_values, out);
+      } else {
+        android::gralloc4::encodeSmpte2086(std::nullopt, out);
+      }
+      break;
+    }
+    case (int64_t)StandardMetadataType::CTA861_3: {
+      if (metadata->color.contentLightLevel.lightLevelSEIEnabled) {
+        Cta861_3 content_light_level;
+        content_light_level.maxContentLightLevel =
+            static_cast<float>(metadata->color.contentLightLevel.maxContentLightLevel);
+        content_light_level.maxFrameAverageLightLevel =
+            static_cast<float>(metadata->color.contentLightLevel.minPicAverageLightLevel) /
+            10000.0f;
+        android::gralloc4::encodeCta861_3(content_light_level, out);
+      } else {
+        android::gralloc4::encodeCta861_3(std::nullopt, out);
+      }
+      break;
+    }
+    case (int64_t)StandardMetadataType::SMPTE2094_40: {
+      if (metadata->color.dynamicMetaDataValid &&
+          metadata->color.dynamicMetaDataLen <= HDR_DYNAMIC_META_DATA_SZ) {
+        std::vector<uint8_t> dynamic_metadata_payload;
+        dynamic_metadata_payload.resize(metadata->color.dynamicMetaDataLen);
+        dynamic_metadata_payload.assign(
+            metadata->color.dynamicMetaDataPayload,
+            metadata->color.dynamicMetaDataPayload + metadata->color.dynamicMetaDataLen);
+        android::gralloc4::encodeSmpte2094_40(dynamic_metadata_payload, out);
+      } else {
+        android::gralloc4::encodeSmpte2094_40(std::nullopt, out);
+      }
+      break;
+    }
+    case (int64_t)StandardMetadataType::CROP: {
+      // Crop is the same for all planes
+      std::vector<Rect> out_crop = {{metadata->crop.left, metadata->crop.top, metadata->crop.right,
+                                     metadata->crop.bottom}};
+      android::gralloc4::encodeCrop(out_crop, out);
+      break;
+    }
+    case QTI_VT_TIMESTAMP:
+      android::gralloc4::encodeUint64(qtigralloc::MetadataType_VTTimestamp, metadata->vtTimeStamp,
+                                      out);
+      break;
+    case QTI_COLOR_METADATA:
+      qtigralloc::encodeColorMetadata(metadata->color, out);
+      break;
+    case QTI_PP_PARAM_INTERLACED:
+      android::gralloc4::encodeInt32(qtigralloc::MetadataType_PPParamInterlaced,
+                                     metadata->interlaced, out);
+      break;
+    case QTI_VIDEO_PERF_MODE:
+      android::gralloc4::encodeUint32(qtigralloc::MetadataType_VideoPerfMode,
+                                      metadata->isVideoPerfMode, out);
+      break;
+    case QTI_GRAPHICS_METADATA:
+      qtigralloc::encodeGraphicsMetadata(metadata->graphics_metadata, out);
+      break;
+    case QTI_UBWC_CR_STATS_INFO:
+      qtigralloc::encodeUBWCStats(metadata->ubwcCRStats, out);
+      break;
+    case QTI_REFRESH_RATE:
+      android::gralloc4::encodeFloat(qtigralloc::MetadataType_RefreshRate, metadata->refreshrate,
+                                     out);
+      break;
+    case QTI_MAP_SECURE_BUFFER:
+      android::gralloc4::encodeInt32(qtigralloc::MetadataType_MapSecureBuffer,
+                                     metadata->mapSecureBuffer, out);
+      break;
+    case QTI_LINEAR_FORMAT:
+      android::gralloc4::encodeUint32(qtigralloc::MetadataType_LinearFormat, metadata->linearFormat,
+                                      out);
+      break;
+    case QTI_SINGLE_BUFFER_MODE:
+      android::gralloc4::encodeUint32(qtigralloc::MetadataType_SingleBufferMode,
+                                      metadata->isSingleBufferMode, out);
+      break;
+    case QTI_CVP_METADATA:
+      qtigralloc::encodeCVPMetadata(metadata->cvpMetadata, out);
+      break;
+    case QTI_VIDEO_HISTOGRAM_STATS:
+      qtigralloc::encodeVideoHistogramMetadata(metadata->video_histogram_stats, out);
+      break;
+    case QTI_FD:
+      android::gralloc4::encodeInt32(qtigralloc::MetadataType_FD, handle->fd, out);
+      break;
+    case QTI_PRIVATE_FLAGS:
+      android::gralloc4::encodeInt32(qtigralloc::MetadataType_PrivateFlags, handle->flags, out);
+      break;
+    case QTI_ALIGNED_WIDTH_IN_PIXELS:
+      android::gralloc4::encodeUint32(qtigralloc::MetadataType_AlignedWidthInPixels, handle->width,
+                                      out);
+      break;
+    case QTI_ALIGNED_HEIGHT_IN_PIXELS:
+      android::gralloc4::encodeUint32(qtigralloc::MetadataType_AlignedHeightInPixels,
+                                      handle->height, out);
+      break;
+#ifdef METADATA_V2
+    case QTI_STANDARD_METADATA_STATUS:
+      qtigralloc::encodeMetadataState(metadata->isStandardMetadataSet, out);
+      break;
+    case QTI_VENDOR_METADATA_STATUS:
+      qtigralloc::encodeMetadataState(metadata->isVendorMetadataSet, out);
+      break;
+#endif
+#ifdef QTI_BUFFER_TYPE
+    case QTI_BUFFER_TYPE:
+      android::gralloc4::encodeUint32(qtigralloc::MetadataType_BufferType, handle->buffer_type,
+                                      out);
+      break;
+#endif
+    default:
+      error = Error::UNSUPPORTED;
+  }
+
+  return error;
+}
+
+Error BufferManager::SetMetadata(private_handle_t *handle, int64_t metadatatype_value,
+                                 hidl_vec<uint8_t> in) {
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  if (!handle)
+    return Error::BAD_BUFFER;
+
+  auto buf = GetBufferFromHandleLocked(handle);
+  if (buf == nullptr)
+    return Error::BAD_BUFFER;
+
+  if (!handle->base_metadata) {
+    return Error::BAD_BUFFER;
+  }
+  if (in.size() == 0) {
+    return Error::UNSUPPORTED;
+  }
+
+  auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+
+#ifdef METADATA_V2
+  // By default, set these to true
+  // Reset to false for special cases below
+  if (IS_VENDOR_METADATA_TYPE(metadatatype_value)) {
+    metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(metadatatype_value)] = true;
+  } else if (GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value) < METADATA_SET_SIZE) {
+    metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] = true;
+  }
+#endif
+
+  switch (metadatatype_value) {
+    // These are constant (unchanged after allocation)
+    case (int64_t)StandardMetadataType::BUFFER_ID:
+    case (int64_t)StandardMetadataType::NAME:
+    case (int64_t)StandardMetadataType::WIDTH:
+    case (int64_t)StandardMetadataType::HEIGHT:
+    case (int64_t)StandardMetadataType::LAYER_COUNT:
+    case (int64_t)StandardMetadataType::PIXEL_FORMAT_REQUESTED:
+    case (int64_t)StandardMetadataType::USAGE:
+      return Error::BAD_VALUE;
+    case (int64_t)StandardMetadataType::PIXEL_FORMAT_FOURCC:
+    case (int64_t)StandardMetadataType::PIXEL_FORMAT_MODIFIER:
+    case (int64_t)StandardMetadataType::PROTECTED_CONTENT:
+    case (int64_t)StandardMetadataType::ALLOCATION_SIZE:
+    case (int64_t)StandardMetadataType::PLANE_LAYOUTS:
+    case (int64_t)StandardMetadataType::CHROMA_SITING:
+    case (int64_t)StandardMetadataType::INTERLACED:
+    case (int64_t)StandardMetadataType::COMPRESSION:
+    case QTI_FD:
+    case QTI_PRIVATE_FLAGS:
+    case QTI_ALIGNED_WIDTH_IN_PIXELS:
+    case QTI_ALIGNED_HEIGHT_IN_PIXELS:
+      return Error::UNSUPPORTED;
+    case (int64_t)StandardMetadataType::DATASPACE:
+      Dataspace dataspace;
+      android::gralloc4::decodeDataspace(in, &dataspace);
+      dataspaceToColorMetadata(dataspace, &metadata->color);
+      break;
+    case (int64_t)StandardMetadataType::BLEND_MODE:
+      BlendMode mode;
+      android::gralloc4::decodeBlendMode(in, &mode);
+      metadata->blendMode = (int32_t)mode;
+      break;
+    case (int64_t)StandardMetadataType::SMPTE2086: {
+      std::optional<Smpte2086> mastering_display_values;
+      android::gralloc4::decodeSmpte2086(in, &mastering_display_values);
+      if (mastering_display_values != std::nullopt) {
+        metadata->color.masteringDisplayInfo.colorVolumeSEIEnabled = true;
+
+        metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[0][0] =
+            static_cast<uint32_t>(mastering_display_values->primaryRed.x * 50000.0f);
+        metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[0][1] =
+            static_cast<uint32_t>(mastering_display_values->primaryRed.y * 50000.0f);
+
+        metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[1][0] =
+            static_cast<uint32_t>(mastering_display_values->primaryGreen.x * 50000.0f);
+        metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[1][1] =
+            static_cast<uint32_t>(mastering_display_values->primaryGreen.y * 50000.0f);
+
+        metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[2][0] =
+            static_cast<uint32_t>(mastering_display_values->primaryBlue.x * 50000.0f);
+        metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[2][1] =
+            static_cast<uint32_t>(mastering_display_values->primaryBlue.y * 50000.0f);
+
+        metadata->color.masteringDisplayInfo.primaries.whitePoint[0] =
+            static_cast<uint32_t>(mastering_display_values->whitePoint.x * 50000.0f);
+        metadata->color.masteringDisplayInfo.primaries.whitePoint[1] =
+            static_cast<uint32_t>(mastering_display_values->whitePoint.y * 50000.0f);
+
+        metadata->color.masteringDisplayInfo.maxDisplayLuminance =
+            static_cast<uint32_t>(mastering_display_values->maxLuminance);
+        metadata->color.masteringDisplayInfo.minDisplayLuminance =
+            static_cast<uint32_t>(mastering_display_values->minLuminance * 10000.0f);
+      } else {
+#ifdef METADATA_V2
+        metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] =
+            false;
+#endif
+        metadata->color.masteringDisplayInfo.colorVolumeSEIEnabled = false;
+      }
+      break;
+    }
+    case (int64_t)StandardMetadataType::CTA861_3: {
+      std::optional<Cta861_3> content_light_level;
+      android::gralloc4::decodeCta861_3(in, &content_light_level);
+      if (content_light_level != std::nullopt) {
+        metadata->color.contentLightLevel.lightLevelSEIEnabled = true;
+        metadata->color.contentLightLevel.maxContentLightLevel =
+            static_cast<uint32_t>(content_light_level->maxContentLightLevel);
+        metadata->color.contentLightLevel.minPicAverageLightLevel =
+            static_cast<uint32_t>(content_light_level->maxFrameAverageLightLevel * 10000.0f);
+      } else {
+#ifdef METADATA_V2
+        metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] =
+            false;
+#endif
+        metadata->color.contentLightLevel.lightLevelSEIEnabled = false;
+      }
+      break;
+    }
+    case (int64_t)StandardMetadataType::SMPTE2094_40: {
+      std::optional<std::vector<uint8_t>> dynamic_metadata_payload;
+      android::gralloc4::decodeSmpte2094_40(in, &dynamic_metadata_payload);
+      if (dynamic_metadata_payload != std::nullopt) {
+        if (dynamic_metadata_payload->size() > HDR_DYNAMIC_META_DATA_SZ)
+          return Error::BAD_VALUE;
+
+        metadata->color.dynamicMetaDataLen = static_cast<uint32_t>(dynamic_metadata_payload->size());
+        std::copy(dynamic_metadata_payload->begin(), dynamic_metadata_payload->end(),
+                  metadata->color.dynamicMetaDataPayload);
+        metadata->color.dynamicMetaDataValid = true;
+      } else {
+        // Reset metadata by passing in std::nullopt
+#ifdef METADATA_V2
+        metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] =
+            false;
+#endif
+        metadata->color.dynamicMetaDataValid = false;
+      }
+      break;
+    }
+    case (int64_t)StandardMetadataType::CROP: {
+      std::vector<Rect> in_crop;
+      android::gralloc4::decodeCrop(in, &in_crop);
+      if (in_crop.size() != 1)
+        return Error::UNSUPPORTED;
+
+      metadata->crop.left = in_crop[0].left;
+      metadata->crop.top = in_crop[0].top;
+      metadata->crop.right = in_crop[0].right;
+      metadata->crop.bottom = in_crop[0].bottom;
+      break;
+    }
+    case QTI_VT_TIMESTAMP:
+      android::gralloc4::decodeUint64(qtigralloc::MetadataType_VTTimestamp, in,
+                                      &metadata->vtTimeStamp);
+      break;
+    case QTI_COLOR_METADATA:
+      ColorMetaData color;
+      qtigralloc::decodeColorMetadata(in, &color);
+      metadata->color = color;
+      break;
+    case QTI_PP_PARAM_INTERLACED:
+      android::gralloc4::decodeInt32(qtigralloc::MetadataType_PPParamInterlaced, in,
+                                     &metadata->interlaced);
+      break;
+    case QTI_VIDEO_PERF_MODE:
+      android::gralloc4::decodeUint32(qtigralloc::MetadataType_VideoPerfMode, in,
+                                      &metadata->isVideoPerfMode);
+      break;
+    case QTI_GRAPHICS_METADATA:
+      qtigralloc::decodeGraphicsMetadata(in, &metadata->graphics_metadata);
+      break;
+    case QTI_UBWC_CR_STATS_INFO:
+      qtigralloc::decodeUBWCStats(in, &metadata->ubwcCRStats[0]);
+      break;
+    case QTI_REFRESH_RATE:
+      android::gralloc4::decodeFloat(qtigralloc::MetadataType_RefreshRate, in,
+                                     &metadata->refreshrate);
+      break;
+    case QTI_MAP_SECURE_BUFFER:
+      android::gralloc4::decodeInt32(qtigralloc::MetadataType_MapSecureBuffer, in,
+                                     &metadata->mapSecureBuffer);
+      break;
+    case QTI_LINEAR_FORMAT:
+      android::gralloc4::decodeUint32(qtigralloc::MetadataType_LinearFormat, in,
+                                      &metadata->linearFormat);
+      break;
+    case QTI_SINGLE_BUFFER_MODE:
+      android::gralloc4::decodeUint32(qtigralloc::MetadataType_SingleBufferMode, in,
+                                      &metadata->isSingleBufferMode);
+      break;
+    case QTI_CVP_METADATA:
+      qtigralloc::decodeCVPMetadata(in, &metadata->cvpMetadata);
+      break;
+    case QTI_VIDEO_HISTOGRAM_STATS:
+      qtigralloc::decodeVideoHistogramMetadata(in, &metadata->video_histogram_stats);
+      break;
+    default:
+#ifdef METADATA_V2
+      if (IS_VENDOR_METADATA_TYPE(metadatatype_value)) {
+        metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(metadatatype_value)] = false;
+      } else if (GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value) < METADATA_SET_SIZE) {
+        metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] =
+            false;
+      }
+#endif
+      return Error::BAD_VALUE;
+  }
+
+  return Error::NONE;
+}
+
 }  //  namespace gralloc
diff --git a/gralloc/gr_buf_mgr.h b/gralloc/gr_buf_mgr.h
index 1ff5455..a0037f9 100644
--- a/gralloc/gr_buf_mgr.h
+++ b/gralloc/gr_buf_mgr.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved.
  * Not a Contribution
  *
  * Copyright (C) 2008 The Android Open Source Project
@@ -21,20 +21,21 @@
 #define __GR_BUF_MGR_H__
 
 #include <pthread.h>
+
 #include <mutex>
 #include <unordered_map>
 #include <unordered_set>
 #include <utility>
+#include <vector>
 
 #include "gr_allocator.h"
-#include "gr_utils.h"
 #include "gr_buf_descriptor.h"
+#include "gr_adreno_info.h"
+#include "gr_utils.h"
 #include "gralloc_priv.h"
 
 namespace gralloc {
-
-using android::hardware::graphics::mapper::V3_0::Error;
-
+using gralloc::Error;
 class BufferManager {
  public:
   ~BufferManager();
@@ -49,6 +50,14 @@
   Error ValidateBufferSize(private_handle_t const *hnd, BufferInfo info);
   Error IsBufferImported(const private_handle_t *hnd);
   static BufferManager *GetInstance();
+  Error GetMetadata(private_handle_t *handle, int64_t metadatatype_value, hidl_vec<uint8_t> *out);
+  Error SetMetadata(private_handle_t *handle, int64_t metadatatype_value, hidl_vec<uint8_t> in);
+  Error GetReservedRegion(private_handle_t *handle, void **reserved_region,
+                          uint64_t *reserved_region_size);
+  Error FlushBuffer(const private_handle_t *handle);
+  Error RereadBuffer(const private_handle_t *handle);
+  Error GetAllHandles(std::vector<const private_handle_t *> *out_handle_list);
+  void SetGrallocDebugProperties(gralloc::GrallocProperties props);
 
  private:
   BufferManager();
@@ -79,6 +88,8 @@
         : handle(h), ion_handle_main(ih_main), ion_handle_meta(ih_meta) {}
     void IncRef() { ++ref_count; }
     bool DecRef() { return --ref_count == 0; }
+    uint64_t reserved_size = 0;
+    void *reserved_region_ptr = nullptr;
   };
 
   Error FreeBuffer(std::shared_ptr<Buffer> buf);
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 663c180..86159a6 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -28,6 +28,9 @@
  */
 
 #include <media/msm_media_info.h>
+
+#include <drm/drm_fourcc.h>
+
 #include <algorithm>
 
 #include "gr_adreno_info.h"
@@ -518,15 +521,10 @@
       c_size = (width * height) / 2;
       c_height = height >> 1;
       break;
-    case HAL_PIXEL_FORMAT_RAW16:
     case HAL_PIXEL_FORMAT_Y16:
       c_size = width * height;
       c_height = height;
       break;
-    case HAL_PIXEL_FORMAT_RAW10:
-      c_size = 0;
-      break;
-    case HAL_PIXEL_FORMAT_RAW8:
     case HAL_PIXEL_FORMAT_Y8:
       c_size = 0;
       break;
@@ -631,6 +629,48 @@
   return err;
 }
 
+int GetRawPlaneInfo(int32_t format, int32_t width, int32_t height, PlaneLayoutInfo *plane_info) {
+  int32_t step = 0;
+
+  switch (format) {
+    case HAL_PIXEL_FORMAT_RAW16:
+      step = 2;
+      break;
+    case HAL_PIXEL_FORMAT_RAW8:
+      step = 1;
+      break;
+    case HAL_PIXEL_FORMAT_RAW12:
+    case HAL_PIXEL_FORMAT_RAW10:
+    case HAL_PIXEL_FORMAT_BLOB:
+      step = 0;
+      break;
+    default:
+      ALOGW("RawPlaneInfo is unsupported for format 0x%x", format);
+      return -EINVAL;
+  }
+
+  BufferInfo info(width, height, format);
+  uint32_t alignedWidth, alignedHeight;
+  GetAlignedWidthAndHeight(info, &alignedWidth, &alignedHeight);
+
+  uint32_t size = GetSize(info, alignedWidth, alignedHeight);
+
+  plane_info[0].component = (PlaneComponent)PLANE_COMPONENT_RAW;
+  plane_info[0].h_subsampling = 0;
+  plane_info[0].v_subsampling = 0;
+  plane_info[0].offset = 0;
+  plane_info[0].step = step;
+  plane_info[0].stride = width;
+  plane_info[0].stride_bytes = static_cast<int32_t>(alignedWidth);
+  if (format == HAL_PIXEL_FORMAT_RAW16) {
+    plane_info[0].stride_bytes = static_cast<int32_t>(alignedWidth * GetBpp(format));
+  }
+  plane_info[0].scanlines = height;
+  plane_info[0].size = size;
+
+  return 0;
+}
+
 // Explicitly defined UBWC formats
 bool IsUBwcFormat(int format) {
   switch (format) {
@@ -723,6 +763,9 @@
   switch (format) {
     case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+      *aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+      *aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
+      break;
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
       *aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
       *aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height);
@@ -806,8 +849,20 @@
       size = alignedw * alignedh * bpp;
       size += GetRgbUBwcMetaBufferSize(width, height, bpp);
       break;
+    /*
+     * 1. The CtsMediaV2TestCases#CodecEncoderSurfaceTest is a transcode use case and shares
+     *    same surface between encoder and decoder.
+     * 2. Configures encoder with Opaque color format thus encoder sets ubwc usage bits and
+     *    is configured with NV12_UBWC format.
+     * 3. Configures decoder as 'flexible', thus configuring decoder with NV12 format.
+     * 4. Decoder should produce output to surface that will be fed back to encoder as input.
+     * 5. Though UBWC is enabled, we need to compute the actual buffer size (including aligned
+     *    width and height) based on pixel format that is set.
+     */
     case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+      size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
+      break;
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
       size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
       break;
@@ -984,6 +1039,16 @@
       aligned_w = ALIGN(width, 128);
       break;
     case HAL_PIXEL_FORMAT_YV12:
+      if ((usage & BufferUsage::GPU_TEXTURE) || (usage & BufferUsage::GPU_RENDER_TARGET)) {
+        if (AdrenoMemInfo::GetInstance() == nullptr) {
+          return;
+        }
+        alignment = AdrenoMemInfo::GetInstance()->GetGpuPixelAlignment();
+        aligned_w = ALIGN(width, alignment);
+      } else {
+        aligned_w = ALIGN(width, 16);
+      }
+      break;
     case HAL_PIXEL_FORMAT_YCbCr_422_SP:
     case HAL_PIXEL_FORMAT_YCrCb_422_SP:
     case HAL_PIXEL_FORMAT_YCbCr_422_I:
@@ -1332,10 +1397,7 @@
     case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
     case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
     case HAL_PIXEL_FORMAT_NV21_ZSL:
-    case HAL_PIXEL_FORMAT_RAW16:
     case HAL_PIXEL_FORMAT_Y16:
-    case HAL_PIXEL_FORMAT_RAW10:
-    case HAL_PIXEL_FORMAT_RAW8:
     case HAL_PIXEL_FORMAT_Y8:
       *plane_count = 2;
       GetYuvSPPlaneInfo(info, format, width, height, 1, plane_info);
@@ -1346,6 +1408,16 @@
       plane_info[1].v_subsampling = v_subsampling;
       break;
 
+    case HAL_PIXEL_FORMAT_RAW10:
+    case HAL_PIXEL_FORMAT_RAW8:
+    case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_RAW12:
+    case HAL_PIXEL_FORMAT_BLOB:
+      *plane_count = 1;
+      GetRawPlaneInfo(format, info.width, info.height, plane_info);
+      break;
+
+
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
       GetYuvSubSamplingFactor(format, &h_subsampling, &v_subsampling);
       if (flags & LAYOUT_INTERLACED_FLAG) {
@@ -1554,10 +1626,7 @@
       *h_subsampling = 1;
       *v_subsampling = 0;
       break;
-    case HAL_PIXEL_FORMAT_RAW16:
     case HAL_PIXEL_FORMAT_Y16:
-    case HAL_PIXEL_FORMAT_RAW12:
-    case HAL_PIXEL_FORMAT_RAW10:
     case HAL_PIXEL_FORMAT_Y8:
     case HAL_PIXEL_FORMAT_BLOB:
     case HAL_PIXEL_FORMAT_RAW_OPAQUE:
@@ -1649,4 +1718,124 @@
   plane_info->scanlines = height;
 }
 
+// TODO(tbalacha): tile vs ubwc -- may need to find a diff way to differentiate
+void GetDRMFormat(uint32_t format, uint32_t flags, uint32_t *drm_format,
+                  uint64_t *drm_format_modifier) {
+  bool compressed = (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) ? true : false;
+  switch (format) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+      *drm_format = DRM_FORMAT_ABGR8888;
+      break;
+    case HAL_PIXEL_FORMAT_RGBA_5551:
+      *drm_format = DRM_FORMAT_ABGR1555;
+      break;
+    case HAL_PIXEL_FORMAT_RGBA_4444:
+      *drm_format = DRM_FORMAT_ABGR4444;
+      break;
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+      *drm_format = DRM_FORMAT_ARGB8888;
+      break;
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+      *drm_format = DRM_FORMAT_XBGR8888;
+      if (compressed)
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case HAL_PIXEL_FORMAT_BGRX_8888:
+      *drm_format = DRM_FORMAT_XRGB8888;
+      break;
+    case HAL_PIXEL_FORMAT_RGB_888:
+      *drm_format = DRM_FORMAT_BGR888;
+      break;
+    case HAL_PIXEL_FORMAT_RGB_565:
+      *drm_format = DRM_FORMAT_BGR565;
+      break;
+    case HAL_PIXEL_FORMAT_BGR_565:
+      *drm_format = DRM_FORMAT_BGR565;
+      if (compressed)
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+      *drm_format = DRM_FORMAT_ABGR2101010;
+      if (compressed)
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case HAL_PIXEL_FORMAT_ARGB_2101010:
+      *drm_format = DRM_FORMAT_BGRA1010102;
+      break;
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+      *drm_format = DRM_FORMAT_XBGR2101010;
+      if (compressed)
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case HAL_PIXEL_FORMAT_XRGB_2101010:
+      *drm_format = DRM_FORMAT_BGRX1010102;
+      break;
+    case HAL_PIXEL_FORMAT_BGRA_1010102:
+      *drm_format = DRM_FORMAT_ARGB2101010;
+      break;
+    case HAL_PIXEL_FORMAT_ABGR_2101010:
+      *drm_format = DRM_FORMAT_RGBA1010102;
+      break;
+    case HAL_PIXEL_FORMAT_BGRX_1010102:
+      *drm_format = DRM_FORMAT_XRGB2101010;
+      break;
+    case HAL_PIXEL_FORMAT_XBGR_2101010:
+      *drm_format = DRM_FORMAT_RGBX1010102;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+      *drm_format = DRM_FORMAT_NV12;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+      *drm_format = DRM_FORMAT_NV12;
+      if (compressed) {
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      } else {
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_TILE;
+      }
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+      *drm_format = DRM_FORMAT_NV21;
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+      *drm_format = DRM_FORMAT_NV21;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS:
+      *drm_format = DRM_FORMAT_NV12;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_DX;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      *drm_format = DRM_FORMAT_NV12;
+      if (compressed) {
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED | DRM_FORMAT_MOD_QCOM_DX;
+      } else {
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_TILE | DRM_FORMAT_MOD_QCOM_DX;
+      }
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+      *drm_format = DRM_FORMAT_NV12;
+      if (compressed) {
+        *drm_format_modifier =
+            DRM_FORMAT_MOD_QCOM_COMPRESSED | DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT;
+      } else {
+        *drm_format_modifier =
+            DRM_FORMAT_MOD_QCOM_TILE | DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT;
+      }
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+      *drm_format = DRM_FORMAT_NV16;
+      break;
+      /*
+    TODO: No HAL_PIXEL_FORMAT equivalent?
+    case kFormatYCrCb422H2V1SemiPlanar:
+      *drm_format = DRM_FORMAT_NV61;
+      break;*/
+    case HAL_PIXEL_FORMAT_YV12:
+      *drm_format = DRM_FORMAT_YVU420;
+      break;
+    default:
+      ALOGE("Unsupported format %d", format);
+  }
+}
+
 }  // namespace gralloc
diff --git a/gralloc/gr_utils.h b/gralloc/gr_utils.h
index bdde659..6eb6c79 100644
--- a/gralloc/gr_utils.h
+++ b/gralloc/gr_utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016,2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2016,2018-2020, The Linux Foundation. All rights reserved.
 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -68,6 +68,33 @@
   return (Type1)((x + (Type1)align - 1) & ~((Type1)align - 1));
 }
 
+enum class Error : int32_t {
+  /**
+   * No error.
+   */
+  NONE = 0,
+  /**
+   * Invalid BufferDescriptor.
+   */
+  BAD_DESCRIPTOR = 1,
+  /**
+   * Invalid buffer handle.
+   */
+  BAD_BUFFER = 2,
+  /**
+   * Invalid HardwareBufferDescription.
+   */
+  BAD_VALUE = 3,
+  /**
+   * Resource unavailable.
+   */
+  NO_RESOURCES = 5,
+  /**
+   * Permanent failure.
+   */
+  UNSUPPORTED = 7,
+};
+
 enum PlaneComponent {
   /* luma */
   PLANE_COMPONENT_Y = 1 << 0,
@@ -183,6 +210,9 @@
 int GetBufferType(int inputFormat);
 bool IsGPUFlagSupported(uint64_t usage);
 bool HasAlphaComponent(int32_t format);
+
+void GetDRMFormat(uint32_t format, uint32_t flags, uint32_t *drm_format,
+                  uint64_t *drm_format_modifier);
 }  // namespace gralloc
 
 #endif  // __GR_UTILS_H__
diff --git a/gralloc/service.cpp b/gralloc/service.cpp
index 1ef8fec..c5b14a4 100644
--- a/gralloc/service.cpp
+++ b/gralloc/service.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -27,25 +27,40 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <hidl/LegacySupport.h>
+
 #include "QtiAllocator.h"
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::setMinSchedulerPolicy;
-using vendor::qti::hardware::display::allocator::V3_0::IQtiAllocator;
-using vendor::qti::hardware::display::allocator::V3_0::implementation::QtiAllocator;
+using IQtiAllocator3 = vendor::qti::hardware::display::allocator::V3_0::IQtiAllocator;
+using IQtiAllocator4 = vendor::qti::hardware::display::allocator::V4_0::IQtiAllocator;
 
 int main(int, char **) {
-  android::sp<IQtiAllocator> service = new QtiAllocator();
+  android::sp<IQtiAllocator3> service3 =
+      new vendor::qti::hardware::display::allocator::V3_0::implementation::QtiAllocator();
+
   configureRpcThreadpool(4, true /*callerWillJoin*/);
-  if (!setMinSchedulerPolicy(service, SCHED_NORMAL, -20)) {
+  if (!setMinSchedulerPolicy(service3, SCHED_NORMAL, -20)) {
     ALOGW("Cannot bump allocator priority");
   }
-  if (service->registerAsService() != android::OK) {
-    ALOGE("Cannot register QTI Allocator service");
+  if (service3->registerAsService() != android::OK) {
+    ALOGE("Cannot register QTI Allocator 3 service");
     return -EINVAL;
   }
-  ALOGI("Initialized qti-allocator");
+  ALOGI("Initialized qti-allocator 3");
+
+#ifdef TARGET_USES_GRALLOC4
+  android::sp<IQtiAllocator4> service4 =
+      new vendor::qti::hardware::display::allocator::V4_0::implementation::QtiAllocator();
+  if (service4->registerAsService() != android::OK) {
+    ALOGE("Cannot register QTI Allocator 4 service");
+    return -EINVAL;
+  }
+  ALOGI("Initialized qti-allocator 4");
+#endif
+
   joinRpcThreadpool();
+
   return 0;
 }
diff --git a/gralloc/vendor.qti.hardware.display.allocator-service.xml b/gralloc/vendor.qti.hardware.display.allocator-service.xml
new file mode 100644
index 0000000..506c58b
--- /dev/null
+++ b/gralloc/vendor.qti.hardware.display.allocator-service.xml
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.graphics.allocator</name>
+        <transport>hwbinder</transport>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl">
+        <name>vendor.qti.hardware.display.allocator</name>
+        <transport>hwbinder</transport>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IQtiAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/include/display_properties.h b/include/display_properties.h
index 3270ad6..2ea0562 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2018 - 2019, The Linux Foundation. All rights reserved.
+* Copyright (c) 2018 - 2020, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -125,6 +125,8 @@
 
 #define ZERO_SWAP_INTERVAL                   "vendor.debug.egl.swapinterval"
 #define DEFER_FPS_FRAME_COUNT                DISPLAY_PROP("defer_fps_frame_count")
+#define DISABLE_IDLE_TIME_VIDEO              DISPLAY_PROP("disable_idle_time_video")
+#define DISABLE_IDLE_TIME_HDR                DISPLAY_PROP("disable_idle_time_hdr")
 #define ENABLE_OPTIMIZE_REFRESH              DISPLAY_PROP("enable_optimize_refresh")
 #define ENABLE_ASYNC_POWERMODE               DISPLAY_PROP("enable_async_powermode")
 #define DISABLE_UI_3D_TONEMAP                DISPLAY_PROP("disable_ui_3d_tonemap")
diff --git a/libdrmutils/Android.mk b/libdrmutils/Android.mk
index b8bc659..12a6c5b 100644
--- a/libdrmutils/Android.mk
+++ b/libdrmutils/Android.mk
@@ -8,7 +8,8 @@
 LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := external/libdrm \
-                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/display
 LOCAL_HEADER_LIBRARIES        := display_headers
 LOCAL_SHARED_LIBRARIES        := libdrm libdl libdisplaydebug
 LOCAL_CFLAGS                  := -DLOG_TAG=\"DRMUTILS\" -Wall  -Werror -fno-operator-names
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 264f5e8..6c3d94d 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -40,6 +40,7 @@
 #include "xf86drmMode.h"
 #include <drm/msm_drm.h>
 #include <drm/msm_drm_pp.h>
+#include <drm/sde_drm.h>
 
 namespace sde_drm {
 
diff --git a/libdrmutils/drm_master.cpp b/libdrmutils/drm_master.cpp
old mode 100644
new mode 100755
index f0d14b1..3a8516d
--- a/libdrmutils/drm_master.cpp
+++ b/libdrmutils/drm_master.cpp
@@ -33,6 +33,8 @@
 #include <unistd.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
+#include <drm/sde_drm.h>
+
 // Intentionally included after xf86 headers so that they in-turn include libdrm version of drm.h
 // that doesn't use keyword "virtual" for a variable name. Not doing so leads to the kernel version
 // of drm.h being included causing compilation to fail
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index 5fff1cb..9e8cad7 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2018, 2020, The Linux Foundation. All rights reserved.
 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -84,91 +84,6 @@
     return -1;
 }
 
-static int querySDEInfoDRM(HWQueryType type, int *value) {
-    char property[PROPERTY_VALUE_MAX] = {0};
-
-    // TODO(user): If future targets don't support WB UBWC, add separate
-    // properties in target specific system.prop and have clients like WFD
-    // directly rely on those.
-    switch(type) {
-    case HAS_UBWC:
-    case HAS_WB_UBWC:  // WFD stack still uses this
-        *value = 1;
-        property_get(DISABLE_UBWC_PROP, property, "0");
-        if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
-                !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
-            *value = 0;
-        }
-        break;
-    default:
-        ALOGE("Invalid query type %d", type);
-        return -EINVAL;
-    }
-
-    return 0;
-}
-
-static int querySDEInfoFB(HWQueryType type, int *value) {
-    FILE *fileptr = NULL;
-    const char *featureName;
-    char stringBuffer[MAX_STRING_LENGTH];
-    uint32_t tokenCount = 0;
-    const uint32_t maxCount = 10;
-    char *tokens[maxCount] = { NULL };
-
-    switch(type) {
-    case HAS_UBWC:
-        featureName = "ubwc";
-        break;
-    case HAS_WB_UBWC:
-        featureName = "wb_ubwc";
-        break;
-    default:
-        ALOGE("Invalid query type %d", type);
-        return -EINVAL;
-    }
-
-    fileptr = fopen("/sys/devices/virtual/graphics/fb0/mdp/caps", "rb");
-    if (!fileptr) {
-        ALOGE("File '%s' not found", stringBuffer);
-        return -EINVAL;
-    }
-
-    size_t len = MAX_STRING_LENGTH;
-    ssize_t read;
-    char *line = stringBuffer;
-    while ((read = getline(&line, &len, fileptr)) != -1) {
-        // parse the line and update information accordingly
-        if (parseLine(line, tokens, maxCount, &tokenCount)) {
-            continue;
-        }
-
-        if (strncmp(tokens[0], "features", strlen("features"))) {
-            continue;
-        }
-
-        for (uint32_t i = 0; i < tokenCount; i++) {
-            if (!strncmp(tokens[i], featureName, strlen(featureName))) {
-              *value = 1;
-            }
-        }
-    }
-    fclose(fileptr);
-
-    return 0;
-}
-
-int querySDEInfo(HWQueryType type, int *value) {
-    if (!value) {
-        return -EINVAL;
-    }
-
-    if (getDriverType() ==  DriverType::DRM) {
-        return querySDEInfoDRM(type, value);
-    }
-
-    return querySDEInfoFB(type, value);
-}
 
 bool isDPConnected() {
     char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
diff --git a/libqdutils/qd_utils.h b/libqdutils/qd_utils.h
index d83f273..0b0816a 100644
--- a/libqdutils/qd_utils.h
+++ b/libqdutils/qd_utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2017 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013, 2017, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -58,7 +58,6 @@
     MAX_STRING_LENGTH = 1024,
 };
 
-int querySDEInfo(HWQueryType type, int *value);
 int getEdidRawData(char *buffer);
 int getHDMINode(void);
 bool isDPConnected();
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index fb3cc38..5b42002 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -25,6 +25,10 @@
     LOCAL_CFLAGS              += -DPP_DRM_ENABLE
 endif
 
+ifeq ($(ENABLE_HYP),true)
+    LOCAL_CFLAGS += -DHYPERVISOR
+endif
+
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := core_interface.cpp \
                                  core_impl.cpp \
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index c18c5e3..e621495 100755
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -433,9 +433,22 @@
     safe_mode_in_fast_path_ = false;
   }
 
+  // Reset pending doze if any after the commit
+  error = ResetPendingDoze(layer_stack->retire_fence_fd);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  // Handle pending vsync enable if any after the commit
+  error = HandlePendingVSyncEnable(layer_stack->retire_fence_fd);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+
   DLOGI_IF(kTagDisplay, "Exiting commit for display: %d-%d", display_id_, display_type_);
 
-  return kErrorNone;
+  return error;
 }
 
 DisplayError DisplayBase::Flush(LayerStack *layer_stack) {
@@ -551,6 +564,14 @@
     return kErrorNone;
   }
 
+  // If vsync is enabled, disable vsync before power off/Doze suspend
+  if (vsync_enable_ && (state == kStateOff || state == kStateDozeSuspend)) {
+    error = SetVSyncState(false /* enable */);
+    if (error == kErrorNone) {
+      vsync_enable_pending_ = true;
+    }
+  }
+
   switch (state) {
   case kStateOff:
     hw_layers_.info.hw_layers.clear();
@@ -605,12 +626,10 @@
     comp_manager_->SetDisplayState(display_comp_ctx_, state, release_fence ? *release_fence : -1);
   }
 
-  if (vsync_state_change_pending_ && (state_ != kStateOff || state_ != kStateStandby)) {
-    error = SetVSyncState(requested_vsync_state_);
-    if (error != kErrorNone) {
-      return error;
-    }
-    vsync_state_change_pending_ = false;
+  // Handle vsync pending on resume, Since the power on commit is synchronous we pass -1 as retire
+  // fence otherwise pass valid retire fence
+  if (state_ == kStateOn) {
+    return HandlePendingVSyncEnable(-1 /* retire fence */);
   }
 
   return error;
@@ -1126,14 +1145,29 @@
   return error;
 }
 
+DisplayError DisplayBase::HandlePendingVSyncEnable(int32_t retire_fence) {
+  if (vsync_enable_pending_) {
+    // Retire fence signalling confirms that CRTC enabled, hence wait for retire fence before
+    // we enable vsync
+    buffer_sync_handler_->SyncWait(retire_fence);
+
+    DisplayError error = SetVSyncState(true /* enable */);
+    if (error != kErrorNone) {
+      return error;
+    }
+    vsync_enable_pending_ = false;
+  }
+  return kErrorNone;
+}
+
 DisplayError DisplayBase::SetVSyncState(bool enable) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
-  if (state_ == kStateOff) {
-    DLOGW("Can't %s vsync when power state is off for display %d-%d," \
-          "Defer it when display is active", enable ? "enable":"disable",
-          display_id_, display_type_);
-    vsync_state_change_pending_ = true;
-    requested_vsync_state_ = enable;
+
+  if ((state_ == kStateOff || pending_doze_) && enable) {
+    DLOGW("Can't enable vsync when power state is off or doze pending for display %d-%d," \
+          "Defer it when display is active state %d pending_doze_ %d", display_id_, display_type_,
+          state_, pending_doze_);
+    vsync_enable_pending_ = true;
     return kErrorNone;
   }
   DisplayError error = kErrorNone;
@@ -1148,8 +1182,11 @@
     }
     if (error == kErrorNone) {
       vsync_enable_ = enable;
+    } else {
+      vsync_enable_pending_ = true;
     }
   }
+  vsync_enable_pending_ = !enable ? false : vsync_enable_pending_;
 
   return error;
 }
@@ -1961,4 +1998,15 @@
   return;
 }
 
+DisplayError DisplayBase::ResetPendingDoze(int32_t retire_fence) {
+  if (pending_doze_) {
+    // Retire fence signalling confirms that CRTC enabled, hence wait for retire fence before
+    // we enable vsync
+    buffer_sync_handler_->SyncWait(retire_fence);
+
+    pending_doze_ = false;
+  }
+  return kErrorNone;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 447c4bd..3937160 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -187,6 +187,8 @@
   PrimariesTransfer GetBlendSpaceFromColorMode();
   bool IsHdrMode(const AttrVal &attr);
   void InsertBT2020PqHlgModes();
+  DisplayError HandlePendingVSyncEnable(int32_t retire_fence);
+  DisplayError ResetPendingDoze(int32_t retire_fence);
 
   recursive_mutex recursive_mutex_;
   int32_t display_id_ = -1;
@@ -237,12 +239,12 @@
   bool drop_skewed_vsync_ = false;
   bool custom_mixer_resolution_ = false;
   DisplayState power_state_pending_ = kStateOff;
-  bool vsync_state_change_pending_ = false;
-  bool requested_vsync_state_ = false;
+  bool vsync_enable_pending_ = false;
   bool defer_power_state_ = false;
   QSyncMode qsync_mode_ = kQSyncModeNone;
   bool needs_avr_update_ = false;
   bool safe_mode_in_fast_path_ = false;
+  bool pending_doze_ = false;
 
   static Locker display_power_reset_lock_;
   static bool display_power_reset_pending_;
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 47c2a3a..297ec88 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -350,6 +350,7 @@
 
 void HWDeviceDRM::Registry::MapBufferToFbId(Layer* layer, LayerBuffer* buffer) {
   if (buffer->planes[0].fd < 0) {
+    layer->buffer_map->buffer_map.clear();
     return;
   }
 
@@ -706,6 +707,9 @@
   // Convert the luminance values to cd/m^2 units.
   hw_panel_info_.peak_luminance = FLOAT(connector_info_.panel_hdr_prop.peak_brightness) / 10000.0f;
   hw_panel_info_.blackness_level = FLOAT(connector_info_.panel_hdr_prop.blackness_level) / 10000.0f;
+  hw_panel_info_.average_luminance = FLOAT(connector_info_.panel_hdr_prop.peak_brightness +
+                                           connector_info_.panel_hdr_prop.blackness_level) /
+                                           (2 * 10000.0f);
   hw_panel_info_.primaries.white_point[0] = connector_info_.panel_hdr_prop.display_primaries[0];
   hw_panel_info_.primaries.white_point[1] = connector_info_.panel_hdr_prop.display_primaries[1];
   hw_panel_info_.primaries.red[0] = connector_info_.panel_hdr_prop.display_primaries[2];
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index b40bf7e..ed6e606 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -557,6 +557,7 @@
   DisplayError ret = kErrorNone;
   vsync_handler_count_ = 0;  //  reset vsync handler count. lock not needed
   {
+    DisplayError ret = kErrorNone;
     std::lock_guard<std::mutex> lock(vsync_mutex_);
     vsync_registered_ = false;
     if (vsync_enabled_) {
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 3cbb6de..6cbfba4 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -827,7 +827,7 @@
         hw_info.display_type = kVirtual;
         break;
       default:
-        DLOGE("Unknown display type = %d on connector id %u.", iter.second.type,
+        DLOGW("Unknown display type = %d on connector id %u.", iter.second.type,
               hw_info.display_id);
         break;
     }
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index a2476ab..d9245c5 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -116,6 +116,18 @@
   return kErrorNone;
 }
 
+DisplayError HWPeripheralDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+  DisplayError error = HWDeviceDRM::SetDisplayMode(hw_display_mode);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  // update bit clk rates.
+  hw_panel_info_.bitclk_rates = bitclk_rates_;
+
+  return kErrorNone;
+}
+
 DisplayError HWPeripheralDRM::Validate(HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   SetDestScalarData(hw_layer_info, true);
@@ -142,6 +154,7 @@
 
   // Initialize to default after successful commit
   synchronous_commit_ = false;
+  idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
 
   return error;
 }
@@ -426,15 +439,14 @@
 }
 
 DisplayError HWPeripheralDRM::ControlIdlePowerCollapse(bool enable, bool synchronous) {
-  sde_drm::DRMIdlePCState idle_pc_state =
-    enable ? sde_drm::DRMIdlePCState::ENABLE : sde_drm::DRMIdlePCState::DISABLE;
-  if (idle_pc_state == idle_pc_state_) {
+  if (enable == idle_pc_enabled_) {
     return kErrorNone;
   }
+  idle_pc_state_ = enable ? sde_drm::DRMIdlePCState::ENABLE : sde_drm::DRMIdlePCState::DISABLE;
   // As idle PC is disabled after subsequent commit, Make sure to have synchrounous commit and
   // ensure TA accesses the display_cc registers after idle PC is disabled.
-  idle_pc_state_ = idle_pc_state;
   synchronous_commit_ = !enable ? synchronous : false;
+  idle_pc_enabled_ = enable;
   return kErrorNone;
 }
 
@@ -448,13 +460,16 @@
   if (first_cycle_) {
     return kErrorNone;
   }
-  drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_IDLE_PC_STATE, token_.crtc_id,
-                            sde_drm::DRMIdlePCState::ENABLE);
+  if (!idle_pc_enabled_) {
+    drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_IDLE_PC_STATE, token_.crtc_id,
+                              sde_drm::DRMIdlePCState::ENABLE);
+  }
   DisplayError err = HWDeviceDRM::PowerOn(qos_data, release_fence);
   if (err != kErrorNone) {
     return err;
   }
-  idle_pc_state_ = sde_drm::DRMIdlePCState::ENABLE;
+  idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
+  idle_pc_enabled_ = true;
 
   return kErrorNone;
 }
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index 5f5bdcc..267d440 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -60,6 +60,7 @@
   virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
   virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
   virtual DisplayError TeardownConcurrentWriteback(void);
   virtual DisplayError SetPanelBrightness(int32_t level) override;
   virtual DisplayError GetPanelBrightness(int32_t &level) const override;
@@ -92,6 +93,7 @@
   std::vector<SDEScaler> scalar_data_ = {};
   CWBConfig cwb_config_ = {};
   sde_drm::DRMIdlePCState idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
+  bool idle_pc_enabled_ = true;
   std::vector<DestScalarCache> dest_scalar_cache_ = {};
   drm_msm_ad4_roi_cfg ad4_roi_cfg_ = {};
   bool needs_ds_update_ = false;
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index 1899170..b96627f 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -190,6 +190,10 @@
     return kErrorNone;
   }
 
+#ifdef HYPERVISOR
+  teardown = true;
+#endif
+
   if (teardown) {
     // LP connecter prop N/A for External
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index 70593bd..7b076b1 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -75,6 +75,7 @@
                                  display_null.cpp \
                                  hwc_socket_handler.cpp \
                                  hwc_buffer_allocator.cpp
+#LOCAL_VINTF_FRAGMENTS         := android.hardware.graphics.composer-qti-display.xml
 
 include $(BUILD_SHARED_LIBRARY)
 endif
diff --git a/sdm/libs/hwc2/android.hardware.graphics.composer-qti-display.xml b/sdm/libs/hwc2/android.hardware.graphics.composer-qti-display.xml
new file mode 100644
index 0000000..7e9e905
--- /dev/null
+++ b/sdm/libs/hwc2/android.hardware.graphics.composer-qti-display.xml
@@ -0,0 +1,48 @@
+<!--
+Copyright (c) 2020, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.graphics.composer</name>
+        <transport>hwbinder</transport>
+        <version>2.4</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl">
+        <name>vendor.display.config</name>
+        <transport>hwbinder</transport>
+        <version>1.11</version>
+        <interface>
+            <name>IDisplayConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>