gralloc: Add support for IMapper/IAllocator 4.0

* Add QtiMapper and QtiAllocator 4.0
* Implement IMapper 4.0 APIs: get, set,
  getFromBufferDescriptorInfo, flushLockedBuffer,
  rereadLockedBuffer, listSupportedMetadataTypes,
  dumpBuffer, dumpBuffers, and getReservedRegion

CRs-Fixed: 2633272
Change-Id: Ica42e485e426b366ffb41f30f1ea2cf395901356
diff --git a/config/display-board.mk b/config/display-board.mk
index 29f540b..dc06a64 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 := false
\ No newline at end of file
diff --git a/config/display-product.mk b/config/display-product.mk
index 365307e..db8f90e 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -1,6 +1,7 @@
 # Display product definitions
 PRODUCT_PACKAGES += \
     android.hardware.graphics.mapper@3.0-impl-qti-display \
+    android.hardware.graphics.mapper@4.0-impl-qti-display \
     vendor.qti.hardware.display.allocator-service \
     vendor.qti.hardware.display.composer-service \
     android.hardware.memtrack@1.0-impl \
@@ -17,6 +18,7 @@
     libdisplayconfig.vendor \
     vendor.qti.hardware.display.mapper@2.0.vendor \
     vendor.qti.hardware.display.mapper@3.0.vendor \
+    vendor.qti.hardware.display.mapper@4.0.vendor \
     modetest
 
 #QDCM calibration xml file for 2k panel
diff --git a/gralloc/Android.mk b/gralloc/Android.mk
index 1434d80..088669a 100644
--- a/gralloc/Android.mk
+++ b/gralloc/Android.mk
@@ -25,8 +25,10 @@
                                  libgralloccore \
                                  android.hardware.graphics.mapper@2.0 \
                                  android.hardware.graphics.mapper@2.1 \
-                                 android.hardware.graphics.mapper@3.0
-LOCAL_CFLAGS                  := $(common_flags) $(qmaa_flags) -DLOG_TAG=\"qdgralloc\" -Wall -Werror
+                                 android.hardware.graphics.mapper@3.0 \
+                                 android.hardware.graphics.mapper@4.0
+LOCAL_CFLAGS                  := $(common_flags) $(qmaa_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
@@ -43,8 +45,10 @@
 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) $(qmaa_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
+                                  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               := gr_utils.cpp gr_adreno_info.cpp gr_camera_info.cpp
 include $(BUILD_SHARED_LIBRARY)
@@ -60,10 +64,13 @@
                                  $(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) $(qmaa_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
+                                  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               := gr_allocator.cpp gr_buf_mgr.cpp gr_ion_alloc.cpp
 include $(BUILD_SHARED_LIBRARY)
@@ -89,12 +96,45 @@
                                   android.hardware.graphics.mapper@2.1 \
                                   vendor.qti.hardware.display.mapperextensions@1.1 \
                                   android.hardware.graphics.mapper@3.0
-LOCAL_CFLAGS                  := $(common_flags) $(qmaa_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
+LOCAL_CFLAGS                  := $(common_flags) $(qmaa_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
+include $(BUILD_SHARED_LIBRARY)
+endif
+
 #allocator
 include $(CLEAR_VARS)
 LOCAL_MODULE                  := vendor.qti.hardware.display.allocator-service
@@ -108,11 +148,22 @@
                                  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) $(qmaa_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
diff --git a/gralloc/QtiAllocator.cpp b/gralloc/QtiAllocator.cpp
index 9b784d0..1a04237 100644
--- a/gralloc/QtiAllocator.cpp
+++ b/gralloc/QtiAllocator.cpp
@@ -32,8 +32,13 @@
 
 #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) {
@@ -66,6 +71,8 @@
 
 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;
@@ -89,9 +96,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();
   }
 
@@ -113,7 +121,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()));
@@ -122,14 +130,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 a1ac903..468a865 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,
@@ -215,7 +217,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));
@@ -228,14 +230,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;
 }
@@ -245,7 +247,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();
     }
@@ -269,14 +271,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 {
@@ -299,18 +301,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 cf17d9e..2747115 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;
@@ -66,6 +69,7 @@
 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;
+    }
+    uint32_t width = static_cast<int32_t>(in[1]);
+    uint32_t height = static_cast<int32_t>(in[2]);
+    buf_descriptor->SetDimensions(width, height);
+    uint32_t layer_count = in[3];
+    buf_descriptor->SetLayerCount(layer_count);
+    uint32_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..83591b0
--- /dev/null
+++ b/gralloc/QtiMapper4.cpp
@@ -0,0 +1,494 @@
+/*
+ * 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..c94bdef
--- /dev/null
+++ b/gralloc/QtiMapper4.h
@@ -0,0 +1,276 @@
+/*
+ * 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) + name_size);
+
+    int index = 0;
+    uint32_t magic_version = gralloc::kMagicVersion;
+    std::memcpy(&out[index], &magic_version, sizeof(magic_version));
+    index += sizeof(magic_version);
+
+    out[index] = 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);
+
+    // Cap the reserved region size at one page (4096 bytes)
+    uint64_t reserved_size = std::min(bd_info.reservedSize, (uint64_t)4096);
+    std::memcpy(&out[index], &reserved_size, sizeof(reserved_size));
+
+    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;
+    }
+
+    int index = 0;
+    uint32_t magic_version;
+    std::memcpy(&magic_version, &in[index], sizeof(magic_version));
+    index += sizeof(magic_version);
+
+    uint64_t name_size = in[index];
+    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(name_size);
+    std::memcpy(name.data(), &in[index], name.size());
+    index += name_size;
+    buf_descriptor->SetName(name);
+
+    uint32_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);
+
+    uint32_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},
+      {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},
+  };
+};
+
+}  // 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
index 2eee216..b0a080e 100644
--- a/gralloc/android.hardware.graphics.mapper-impl-qti-display.xml
+++ b/gralloc/android.hardware.graphics.mapper-impl-qti-display.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (c) 2019, The Linux Foundation. All rights reserved.
+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
@@ -31,6 +31,7 @@
         <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>
@@ -40,6 +41,7 @@
         <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>
diff --git a/gralloc/gr_buf_descriptor.h b/gralloc/gr_buf_descriptor.h
index 06b6986..32a208a 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,21 @@
 #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 +56,9 @@
 
   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 +71,18 @@
 
   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 b936539..2b670aa 100644
--- a/gralloc/gr_buf_mgr.cpp
+++ b/gralloc/gr_buf_mgr.cpp
@@ -19,25 +19,356 @@
 
 #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());
 }
 
+// duplicate from qdmetadata
+static uint64_t getMetaDataSize() {
+  return static_cast<uint64_t>(ROUND_UP_PAGESIZE(sizeof(MetaData_t)));
+}
+static int validateAndMap(private_handle_t *handle) {
+  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) {
+    auto size = getMetaDataSize();
+    void *base = mmap(NULL, 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;
+  }
+  return 0;
+}
+
+static void unmapAndReset(private_handle_t *handle) {
+  if (private_handle_t::validate(handle) == 0 && handle->base_metadata) {
+    munmap(reinterpret_cast<void *>(handle->base_metadata), getMetaDataSize());
+    handle->base_metadata = 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 void grallocToStandardPlaneLayoutComponentType(
+    uint32_t in, std::vector<PlaneLayoutComponent> *components) {
+  PlaneLayoutComponent comp;
+  comp.offsetInBits = 0;
+  comp.sizeInBits = 8;
+  if (in & PLANE_COMPONENT_Y) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_Y;
+    components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_Cb) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_CB;
+    components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_Cr) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_CR;
+    components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_R) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_R;
+    components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_G) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_G;
+    components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_B) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_B;
+    components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_A) {
+    comp.type = android::gralloc4::PlaneLayoutComponentType_A;
+    components->push_back(comp);
+  }
+
+  if (in & PLANE_COMPONENT_RAW) {
+    comp.type = qtigralloc::PlaneLayoutComponentType_Raw;
+    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, Rect crop_rect,
+                             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);
+    plane_info[i].horizontalSubsampling =
+        static_cast<int64_t>(pow(2, plane_layout[i].h_subsampling));
+    plane_info[i].verticalSubsampling = static_cast<int64_t>(pow(2, 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 * 8 / plane_info[i].sampleIncrementInBits;
+    plane_info[i].heightInSamples =
+        handle->unaligned_height * 8 / plane_info[i].sampleIncrementInBits;
+    // TODO(tbalacha): This will be removed when standard metadata type CROP_RECTANGLE is added
+    plane_info[i].crop = crop_rect;
+  }
+  *out = plane_info;
+  return Error::NONE;
+}
+
 BufferManager::BufferManager() : next_id_(0) {
   handles_map_.clear();
   allocator_ = new Allocator();
@@ -74,7 +405,7 @@
     return Error::BAD_BUFFER;
   }
 
-  unsigned int meta_size = ALIGN((unsigned int)sizeof(MetaData_t), PAGE_SIZE);
+  unsigned int meta_size = getMetaDataSize();
   if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base_metadata), meta_size,
                              hnd->offset_metadata, hnd->fd_metadata, buf->ion_handle_meta) != 0) {
     return Error::BAD_BUFFER;
@@ -240,6 +571,41 @@
 
   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_);
@@ -315,7 +681,7 @@
 
   // Allocate memory for MetaData
   AllocData e_data;
-  e_data.size = ALIGN(UINT(sizeof(MetaData_t)), page_size);
+  e_data.size = getMetaDataSize();
   e_data.handle = data.handle;
   e_data.align = page_size;
 
@@ -337,7 +703,9 @@
   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));
 
@@ -346,7 +714,20 @@
     setMetaDataAndUnmap(hnd, SET_GRAPHICS_METADATA, reinterpret_cast<void *>(&graphics_metadata));
   }
 
+  auto error = validateAndMap(hnd);
+  if (error != 0) {
+    ALOGE("validateAndMap failed");
+    return Error::BAD_BUFFER;
+  }
+  auto metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
+  descriptor.GetName().copy(metadata->name, descriptor.GetName().size() + 1);
+  metadata->name[descriptor.GetName().size()] = '\0';
+
+  metadata->reservedRegion.size = descriptor.GetReservedSize();
+  unmapAndReset(hnd);
+
   *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) {
@@ -379,4 +760,388 @@
   }
   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;
+
+  auto err = validateAndMap(handle);
+  if (err != 0)
+    return Error::BAD_BUFFER;
+  auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+
+  *reserved_region = reinterpret_cast<void *>(&(metadata->reservedRegion.data));
+  *reserved_region_size = metadata->reservedRegion.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;
+
+  auto err = validateAndMap(handle);
+  if (err != 0)
+    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_Unknown, out);
+      break;
+    case (int64_t)StandardMetadataType::DATASPACE:
+      Dataspace dataspace;
+      colorMetadataToDataspace(metadata->color, &dataspace);
+      android::gralloc4::encodeDataspace(dataspace, out);
+      break;
+    case (int64_t)StandardMetadataType::INTERLACED:
+      android::gralloc4::encodeInterlaced(qtigralloc::Interlaced_Qti, 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;
+      Rect crop = {0, 0, 0, 0};
+      crop = {metadata->crop.left, metadata->crop.top, metadata->crop.right, metadata->crop.bottom};
+      getFormatLayout(handle, crop, &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: {
+      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);
+      break;
+    }
+    case (int64_t)StandardMetadataType::CTA861_3: {
+      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);
+      break;
+    }
+    case (int64_t)StandardMetadataType::SMPTE2094_40: {
+      std::vector<uint8_t> dynamic_metadata_payload;
+      if (metadata->color.dynamicMetaDataValid) {
+        dynamic_metadata_payload.resize(metadata->color.dynamicMetaDataLen);
+        memcpy(&dynamic_metadata_payload, &metadata->color.dynamicMetaDataPayload,
+               metadata->color.dynamicMetaDataLen);
+        android::gralloc4::encodeSmpte2094_40(dynamic_metadata_payload, out);
+      } else {
+        android::gralloc4::encodeSmpte2094_40(std::nullopt, 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;
+    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;
+
+  int err = validateAndMap(handle);
+  if (err != 0)
+    return Error::BAD_BUFFER;
+
+  auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+
+  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:
+      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.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);
+      }
+      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.maxContentLightLevel =
+            static_cast<uint32_t>(content_light_level->maxContentLightLevel);
+        metadata->color.contentLightLevel.minPicAverageLightLevel =
+            static_cast<uint32_t>(content_light_level->maxFrameAverageLightLevel * 10000.0f);
+      }
+      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) {
+        metadata->color.dynamicMetaDataLen = dynamic_metadata_payload->size();
+        memcpy(&metadata->color.dynamicMetaDataPayload, &dynamic_metadata_payload,
+               metadata->color.dynamicMetaDataLen);
+      }
+      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:
+      return Error::BAD_VALUE;
+  }
+  return Error::NONE;
+}
+
 }  //  namespace gralloc
diff --git a/gralloc/gr_buf_mgr.h b/gralloc/gr_buf_mgr.h
index 2d86d6b..998982f 100644
--- a/gralloc/gr_buf_mgr.h
+++ b/gralloc/gr_buf_mgr.h
@@ -21,20 +21,20 @@
 #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_utils.h"
 #include "gralloc_priv.h"
 
 namespace gralloc {
-
-using android::hardware::graphics::mapper::V3_0::Error;
-
+using gralloc::Error;
 class BufferManager {
  public:
   ~BufferManager();
@@ -50,6 +50,13 @@
   Error IsBufferImported(const private_handle_t *hnd);
   static BufferManager *GetInstance();
   void SetGrallocDebugProperties(gralloc::GrallocProperties props);
+  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);
 
  private:
   BufferManager();
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 2de8d5b..79e5d3a 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -31,6 +31,8 @@
 #include <media/msm_media_info.h>
 #endif
 
+#include <drm/drm_fourcc.h>
+
 #include <algorithm>
 
 #include "gr_adreno_info.h"
@@ -1697,4 +1699,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 8e6986b..40a4260 100644
--- a/gralloc/gr_utils.h
+++ b/gralloc/gr_utils.h
@@ -74,6 +74,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,
@@ -190,6 +217,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 7ea1e3a..2b890ff 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,21 +27,36 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <hidl/LegacySupport.h>
+
 #include "QtiAllocator.h"
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
-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 (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
index eb33572..f00bda6 100644
--- a/gralloc/vendor.qti.hardware.display.allocator-service.xml
+++ b/gralloc/vendor.qti.hardware.display.allocator-service.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (c) 2019, The Linux Foundation. All rights reserved.
+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
@@ -31,6 +31,7 @@
         <name>android.hardware.graphics.allocator</name>
         <transport>hwbinder</transport>
         <version>3.0</version>
+        <!-- <version>4.0</version> -->
         <interface>
             <name>IAllocator</name>
             <instance>default</instance>
@@ -40,6 +41,7 @@
         <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>