Merge "gralloc1: Check linear format"
diff --git a/gpu_tonemapper/Android.mk b/gpu_tonemapper/Android.mk
index 769d0ab..89bad79 100644
--- a/gpu_tonemapper/Android.mk
+++ b/gpu_tonemapper/Android.mk
@@ -4,6 +4,7 @@
 include $(CLEAR_VARS)
 LOCAL_COPY_HEADERS_TO     := $(common_header_export_path)
 LOCAL_COPY_HEADERS        := TonemapFactory.h Tonemapper.h
+LOCAL_VENDOR_MODULE       := true
 include $(BUILD_COPY_HEADERS)
 
 include $(CLEAR_VARS)
diff --git a/include/Android.mk b/include/Android.mk
index 6aacfb8..a72d5c3 100644
--- a/include/Android.mk
+++ b/include/Android.mk
@@ -2,6 +2,7 @@
 include $(LOCAL_PATH)/../common.mk
 include $(CLEAR_VARS)
 
+LOCAL_VENDOR_MODULE           := true
 LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
 LOCAL_COPY_HEADERS            := color_metadata.h
 
@@ -9,7 +10,8 @@
 
 include $(CLEAR_VARS)
 #TODO move all exported headers to this directory
-LOCAL_MODULE := display_headers
+LOCAL_MODULE                  := display_headers
+LOCAL_VENDOR_MODULE           := true
 LOCAL_EXPORT_C_INCLUDE_DIRS   := $(LOCAL_PATH) \
                                  $(display_top)/libcopybit \
                                  $(display_top)/libdrmutils \
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
index a363b85..8396d51 100644
--- a/libcopybit/Android.mk
+++ b/libcopybit/Android.mk
@@ -16,6 +16,7 @@
 include $(LOCAL_PATH)/../common.mk
 include $(CLEAR_VARS)
 
+LOCAL_VENDOR_MODULE           := true
 LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
 LOCAL_COPY_HEADERS            := copybit.h copybit_priv.h c2d2.h
 #Copy the headers regardless of whether copybit is built
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 5dc5e4b..ca2f6ff 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -407,8 +407,7 @@
   uint32_t mmWidth;
   uint32_t mmHeight;
   uint32_t type;
-  uint32_t num_modes;
-  drmModeModeInfo *modes;
+  std::vector<drmModeModeInfo> modes;
   DRMTopology topology;
   std::string panel_name;
   DRMPanelMode panel_mode;
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 0ce2e09..584737d 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -49,13 +49,6 @@
     map_fb_mem_ = true;
   }
 
-  // Enable UBWC for framebuffer
-  if ((property_get("debug.gralloc.enable_fb_ubwc", property, NULL) > 0) &&
-      (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
-       (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
-    ubwc_for_fb_ = true;
-  }
-
   handles_map_.clear();
   allocator_ = new Allocator();
   allocator_->Init();
diff --git a/libgralloc1/gr_buf_mgr.h b/libgralloc1/gr_buf_mgr.h
index 4476eaf..861a7a7 100644
--- a/libgralloc1/gr_buf_mgr.h
+++ b/libgralloc1/gr_buf_mgr.h
@@ -118,7 +118,6 @@
   std::shared_ptr<Buffer> GetBufferFromHandleLocked(const private_handle_t *hnd);
 
   bool map_fb_mem_ = false;
-  bool ubwc_for_fb_ = false;
   Allocator *allocator_ = NULL;
   std::mutex buffer_lock_;
   std::mutex descriptor_lock_;
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index 87604c6..2abdd84 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -78,6 +78,7 @@
 #define GRALLOC_USAGE_PRIVATE_IOMMU_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_IOMMU_HEAP
 #define GRALLOC_USAGE_PRIVATE_WFD GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD
 #define GRALLOC_USAGE_PRIVATE_CAMERA_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP
+#define GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY
 #define GRALLOC_USAGE_PRIVATE_MM_HEAP 0x0
 
 
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index 60efb3a..5dac581 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder libqservice
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_HEADER_LIBRARIES        += libhardware_headers
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdutils\" -Wno-sign-conversion
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 14ec40f..fdab206 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -89,7 +89,7 @@
 static const std::string kSdr = "sdr";
 
 static const std::string kNative = "native";
-static const std::string kDcip3 = "dci_p3";
+static const std::string kDcip3 = "dcip3";
 static const std::string kSrgb = "srgb";
 static const std::string kDisplayP3 = "display_p3";
 
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index cf3543c..bb3b71d 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -60,6 +60,7 @@
 
 SDM_HEADER_PATH := ../../include
 include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE           := true
 LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)/sdm/core
 LOCAL_COPY_HEADERS             = $(SDM_HEADER_PATH)/core/buffer_allocator.h \
                                  $(SDM_HEADER_PATH)/core/buffer_sync_handler.h \
@@ -74,6 +75,7 @@
 include $(BUILD_COPY_HEADERS)
 
 include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE           := true
 LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)/sdm/private
 LOCAL_COPY_HEADERS             = $(SDM_HEADER_PATH)/private/color_interface.h \
                                  $(SDM_HEADER_PATH)/private/color_params.h \
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 965ff3b..391e699 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -55,6 +55,7 @@
   virtual DisplayError Init();
   virtual DisplayError Deinit();
   void GetDRMDisplayToken(sde_drm::DRMDisplayToken *token) const;
+  bool IsPrimaryDisplay() const { return hw_panel_info_.is_primary_panel; }
 
  protected:
   // From HWInterface
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index 7487c8a..33f4d3d 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -62,6 +62,11 @@
 
     switch (event_data.event_type) {
       case HWEvent::VSYNC: {
+        if (!is_primary_) {
+          // TODO(user): Once secondary support is added, use a different fd by calling drmOpen
+          break;
+        }
+
         poll_fds_[i].events = POLLIN | POLLPRI | POLLERR;
         DRMMaster *master = nullptr;
         int ret = DRMMaster::GetInstance(&master);
@@ -146,6 +151,8 @@
     return kErrorParameters;
 
   static_cast<const HWDeviceDRM *>(hw_intf)->GetDRMDisplayToken(&token_);
+  is_primary_ = static_cast<const HWDeviceDRM *>(hw_intf)->IsPrimaryDisplay();
+  vsync_enabled_ = is_primary_;
 
   DLOGI("Setup event handler for display %d, CRTC %d, Connector %d",
         display_type, token_.crtc_id, token_.conn_id);
@@ -177,6 +184,9 @@
 DisplayError HWEventsDRM::SetEventState(HWEvent event, bool enable, void *arg) {
   switch (event) {
     case HWEvent::VSYNC:
+      if (!is_primary_) {
+        break;
+      }
       vsync_enabled_ = enable;
       if (enable) {
         WakeUpEventThread();
@@ -208,6 +218,7 @@
   for (uint32_t i = 0; i < event_data_list_.size(); i++) {
     switch (event_data_list_[i].event_type) {
       case HWEvent::VSYNC:
+        // TODO(user): close for secondary
         poll_fds_[i].fd = -1;
         break;
       case HWEvent::EXIT:
@@ -287,6 +298,7 @@
 }
 
 DisplayError HWEventsDRM::RegisterVSync() {
+  // TODO(user): For secondary use DRM_VBLANK_HIGH_CRTC_MASK and DRM_VBLANK_HIGH_CRTC_SHIFT
   drmVBlank vblank{};
   vblank.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT);
   vblank.request.sequence = 1;
diff --git a/sdm/libs/core/drm/hw_events_drm.h b/sdm/libs/core/drm/hw_events_drm.h
index 206751b..1d04153 100644
--- a/sdm/libs/core/drm/hw_events_drm.h
+++ b/sdm/libs/core/drm/hw_events_drm.h
@@ -89,8 +89,9 @@
   std::string event_thread_name_ = "SDM_EventThread";
   bool exit_threads_ = false;
   uint32_t vsync_index_ = 0;
-  bool vsync_enabled_ = true;
+  bool vsync_enabled_ = false;
   sde_drm::DRMDisplayToken token_ = {};
+  bool is_primary_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index 0262915..67485f1 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -104,7 +104,7 @@
 }
 
 DisplayError HWTVDRM::GetNumDisplayAttributes(uint32_t *count) {
-  *count = connector_info_.num_modes;
+  *count = UINT32(connector_info_.modes.size());
   if (*count <= 0) {
     return kErrorHardware;
   }
@@ -118,7 +118,7 @@
 }
 
 DisplayError HWTVDRM::SetDisplayAttributes(uint32_t index) {
-  if (index >= connector_info_.num_modes) {
+  if (index >= connector_info_.modes.size()) {
     return kErrorNotSupported;
   }
 
@@ -162,7 +162,7 @@
     format = UINT32(stoi(str4.substr(str4.find(':') + 1)));
   }
 
-  for (size_t idex = 0; idex < connector_info_.num_modes; idex ++) {
+  for (size_t idex = 0; idex < connector_info_.modes.size(); idex ++) {
     if ((height == connector_info_.modes[idex].vdisplay) &&
         (width == connector_info_.modes[idex].hdisplay) &&
         (fps == connector_info_.modes[idex].vrefresh)) {
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index 8513e82..5ea76b0 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -121,7 +121,7 @@
 }
 
 void HWVirtualDRM::DumpConfigs() {
-  for (uint32_t i = 0; i < (uint32_t)connector_info_.num_modes; i++) {
+  for (uint32_t i = 0; i < (uint32_t)connector_info_.modes.size(); i++) {
   DLOGI(
     "Name: %s\tvref: %d\thdisp: %d\t hsync_s: %d\thsync_e:%d\thtotal: %d\t"
     "vdisp: %d\tvsync_s: %d\tvsync_e: %d\tvtotal: %d\n",
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 4931e1b..eb0d17b 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -46,6 +46,7 @@
 #include <vector>
 #include <algorithm>
 #include <string>
+#include <sstream>
 
 #include "hw_device.h"
 #include "hw_primary.h"
@@ -1363,7 +1364,14 @@
   DLOGW("Pingpong timeout occurred in the driver.");
 #ifdef USER_DEBUG
   // Save the xlogs on ping pong time out
-  std::ofstream  dst("/data/vendor/display/mdp_xlog");
+  const char* xlog_path = "/data/vendor/display/mdp_xlog";
+  DLOGD("Dumping debugfs data to %s", xlog_path);
+  std::ostringstream  dst;
+  auto file = open(xlog_path, O_CREAT | O_TRUNC | O_DSYNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP);
+  if (file < 0) {
+    DLOGE("Couldn't open file: err:%d (%s)", errno, strerror(errno));
+    return kErrorResources;
+  }
   dst << "+++ MDP:XLOG +++" << std::endl;
   std::ifstream  src("/sys/kernel/debug/mdp/xlog/dump");
   dst << src.rdbuf() << std::endl;
@@ -1383,6 +1391,14 @@
   src.open("/sys/kernel/debug/mdp/xlog/vbif_dbgbus_xlog");
   dst << src.rdbuf() << std::endl;
   src.close();
+  auto ret = write(file, dst.str().c_str(), dst.str().size());
+  if (ret < 0) {
+    DLOGE("Failed to write xlog data err: %d (%s)", errno, strerror(errno));
+  } else {
+    fsync(file);
+  }
+  close(file);
+  DLOGD("Finished dumping xlogs");;
 #endif
   return kErrorNone;
 }
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index 4865e08..eb932e3 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -153,6 +153,9 @@
   if (alloc_type & GRALLOC_USAGE_HW_FB) {
     consumer_usage = GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
   }
+  if (alloc_type & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
+    producer_usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+  }
 
   Perform_(gralloc_device_, GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES, width, height, format,
            producer_usage, consumer_usage, aligned_width, aligned_height, &tile_enabled);
diff --git a/sdm/libs/hwc2/hwc_callbacks.cpp b/sdm/libs/hwc2/hwc_callbacks.cpp
index 48ae398..48593f1 100644
--- a/sdm/libs/hwc2/hwc_callbacks.cpp
+++ b/sdm/libs/hwc2/hwc_callbacks.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -34,22 +34,29 @@
 
 namespace sdm {
 
-void HWCCallbacks::Hotplug(hwc2_display_t display, HWC2::Connection state) {
-  if (hotplug_) {
-    hotplug_(hotplug_data_, display, INT32(state));
+HWC2::Error HWCCallbacks::Hotplug(hwc2_display_t display, HWC2::Connection state) {
+  if (!hotplug_) {
+    return HWC2::Error::NoResources;
   }
+  hotplug_(hotplug_data_, display, INT32(state));
+  return HWC2::Error::None;
 }
 
-void HWCCallbacks::Refresh(hwc2_display_t display) {
-  if (refresh_) {
-    refresh_(refresh_data_, display);
+HWC2::Error HWCCallbacks::Refresh(hwc2_display_t display) {
+  if (!refresh_) {
+    return HWC2::Error::NoResources;
   }
+  refresh_(refresh_data_, display);
+  return HWC2::Error::None;
 }
 
-void HWCCallbacks::Vsync(hwc2_display_t display, int64_t timestamp) {
-  if (vsync_) {
-    vsync_(vsync_data_, display, timestamp);
+HWC2::Error HWCCallbacks::Vsync(hwc2_display_t display, int64_t timestamp) {
+  if (!vsync_) {
+    return HWC2::Error::NoResources;
   }
+  DTRACE_SCOPED();
+  vsync_(vsync_data_, display, timestamp);
+  return HWC2::Error::None;
 }
 
 HWC2::Error HWCCallbacks::Register(HWC2::Callback descriptor, hwc2_callback_data_t callback_data,
diff --git a/sdm/libs/hwc2/hwc_callbacks.h b/sdm/libs/hwc2/hwc_callbacks.h
index 015bf5d..d3f4e52 100644
--- a/sdm/libs/hwc2/hwc_callbacks.h
+++ b/sdm/libs/hwc2/hwc_callbacks.h
@@ -40,9 +40,9 @@
 
 class HWCCallbacks {
  public:
-  void Hotplug(hwc2_display_t display, HWC2::Connection state);
-  void Refresh(hwc2_display_t display);
-  void Vsync(hwc2_display_t display, int64_t timestamp);
+  HWC2::Error Hotplug(hwc2_display_t display, HWC2::Connection state);
+  HWC2::Error Refresh(hwc2_display_t display);
+  HWC2::Error Vsync(hwc2_display_t display, int64_t timestamp);
   HWC2::Error Register(HWC2::Callback, hwc2_callback_data_t callback_data,
                        hwc2_function_pointer_t pointer);
 
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index 6f33a6d..d753fdc 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -404,8 +404,8 @@
   };
 
   if (socket_fd_ < 0) {
-    DLOGW("No socket connection available!");
-    return -EFAULT;
+    DLOGW("No socket connection available - assuming dpps is not enabled");
+    return 0;
   }
 
   if (!enable) {  // if client requesting to disable it.
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index f7a9dec..05840d3 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -102,11 +102,16 @@
 }
 
 HWC2::Error HWCColorMode::SetColorMode(android_color_mode_t mode) {
+  DTRACE_SCOPED();
   // first mode in 2D matrix is the mode (identity)
-  if (color_mode_transform_map_.find(mode) == color_mode_transform_map_.end()) {
+  if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_P3) {
     DLOGE("Could not find mode: %d", mode);
     return HWC2::Error::BadParameter;
   }
+  if (color_mode_transform_map_.find(mode) == color_mode_transform_map_.end()) {
+    return HWC2::Error::Unsupported;
+  }
+
   auto status = HandleColorModeTransform(mode, current_color_transform_, color_matrix_);
   if (status != HWC2::Error::None) {
     DLOGE("failed for mode = %d", mode);
@@ -125,10 +130,12 @@
 }
 
 HWC2::Error HWCColorMode::SetColorTransform(const float *matrix, android_color_transform_t hint) {
-  if (!matrix) {
+  if (!matrix || (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
+      hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)) {
     return HWC2::Error::BadParameter;
   }
 
+  DTRACE_SCOPED();
   double color_matrix[kColorTransformMatrixCount] = {0};
   CopyColorTransformMatrix(matrix, color_matrix);
 
@@ -208,8 +215,8 @@
     DLOGV_IF(kTagQDCM, "Color Mode[%d] = %s", i, mode_string.c_str());
     AttrVal attr;
     error = display_intf_->GetColorModeAttr(mode_string, &attr);
+    std::string color_gamut, dynamic_range, pic_quality;
     if (!attr.empty()) {
-      std::string color_gamut, dynamic_range, pic_quality;
       for (auto &it : attr) {
         if (it.first.find(kColorGamutAttribute) != std::string::npos) {
           color_gamut = it.second;
@@ -230,12 +237,15 @@
         PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, color_transform);
       } else if ((color_gamut == kDcip3) &&
                  (pic_quality.empty() || pic_quality == kStandard)) {
-        PopulateTransform(HAL_COLOR_MODE_DCI_P3, mode_string, color_transform);
+        PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, color_transform);
       } else if ((color_gamut == kDisplayP3) &&
                  (pic_quality.empty() || pic_quality == kStandard)) {
         PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, color_transform);
       }
-    } else {
+    }
+
+    // Look at the mode name, if no color gamut is found
+    if (color_gamut.empty()) {
       if (mode_string.find("hal_native") != std::string::npos) {
         PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, mode_string);
       } else if (mode_string.find("hal_srgb") != std::string::npos) {
@@ -622,6 +632,7 @@
 
 HWC2::Error HWCDisplay::SetVsyncEnabled(HWC2::Vsync enabled) {
   DLOGV("Display ID: %d enabled: %s", id_, to_string(enabled).c_str());
+  ATRACE_INT("SetVsyncState ", enabled == HWC2::Vsync::Enable ? 1 : 0);
   DisplayError error = kErrorNone;
 
   if (shutdown_pending_ || !callbacks_->VsyncCallbackRegistered()) {
@@ -685,6 +696,7 @@
       return HWC2::Error::BadParameter;
   }
 
+  ATRACE_INT("SetPowerMode ", state);
   DisplayError error = display_intf_->SetDisplayState(state);
   if (error == kErrorNone) {
     flush_on_error_ = flush_on_error;
@@ -740,9 +752,18 @@
 HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
                                             int32_t *out_value) {
   DisplayConfigVariableInfo variable_config;
-  if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
-    DLOGE("Get variable config failed");
-    return HWC2::Error::BadDisplay;
+  // Get display attributes from config index only if resolution switch is supported.
+  // Otherwise always send mixer attributes. This is to support destination scaler.
+  if (num_configs_ > 1) {
+    if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
+      DLOGE("Get variable config failed");
+      return HWC2::Error::BadDisplay;
+    }
+  } else {
+    if (display_intf_->GetFrameBufferConfig(&variable_config) != kErrorNone) {
+      DLOGV("Get variable config failed");
+      return HWC2::Error::BadDisplay;
+    }
   }
 
   switch (attribute) {
@@ -981,6 +1002,7 @@
     DLOGW("Display is not validated");
     return HWC2::Error::NotValidated;
   }
+
   *out_num_elements = UINT32(layer_changes_.size());
   if (out_layers != nullptr && out_types != nullptr) {
     int i = 0;
@@ -1010,18 +1032,19 @@
 HWC2::Error HWCDisplay::GetDisplayRequests(int32_t *out_display_requests,
                                            uint32_t *out_num_elements, hwc2_layer_t *out_layers,
                                            int32_t *out_layer_requests) {
-  // No display requests for now
-  // Use for sharing blit buffers and
-  // writing wfd buffer directly to output if there is full GPU composition
-  // and no color conversion needed
   if (layer_set_.empty()) {
     return HWC2::Error::None;
   }
 
+  // No display requests for now
+  // Use for sharing blit buffers and
+  // writing wfd buffer directly to output if there is full GPU composition
+  // and no color conversion needed
   if (!validated_) {
     DLOGW("Display is not validated");
     return HWC2::Error::NotValidated;
   }
+
   *out_display_requests = 0;
   *out_num_elements = UINT32(layer_requests_.size());
   if (out_layers != nullptr && out_layer_requests != nullptr) {
@@ -1480,10 +1503,13 @@
   int aligned_height;
   uint32_t usage = GRALLOC_USAGE_HW_FB;
   int format = HAL_PIXEL_FORMAT_RGBA_8888;
-  int ubwc_enabled = 0;
+  int ubwc_disabled = 0;
   int flags = 0;
-  HWCDebugHandler::Get()->GetProperty("debug.gralloc.enable_fb_ubwc", &ubwc_enabled);
-  if (ubwc_enabled == 1) {
+
+  // By default UBWC is enabled and below property is global enable/disable for all
+  // buffers allocated through gralloc , including framebuffer targets.
+  HWCDebugHandler::Get()->GetProperty("debug.gralloc.gfx_ubwc_disable", &ubwc_disabled);
+  if (!ubwc_disabled) {
     usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
     flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
   }
@@ -1564,9 +1590,18 @@
     return HWC2::Error::None;
   }
 
-  if (GetHWCLayer(layer) == nullptr) {
+  HWCLayer *hwc_layer = GetHWCLayer(layer);
+  if (hwc_layer == nullptr) {
     return HWC2::Error::BadLayer;
   }
+  if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
+    return HWC2::Error::None;
+  }
+  if (validated_ == true) {
+    // the device is currently in the middle of the validate/present sequence,
+    // cannot set the Position(as per HWC2 spec)
+    return HWC2::Error::NotValidated;
+  }
 
   DisplayState state;
   if (display_intf_->GetDisplayState(&state) == kErrorNone) {
@@ -1575,9 +1610,9 @@
     }
   }
 
-  if (!validated_) {
-    return HWC2::Error::NotValidated;
-  }
+  // TODO(user): HWC1.5 was not letting SetCursorPosition before validateDisplay,
+  // but HWC2.0 doesn't let setting cursor position after validate before present.
+  // Need to revisit.
 
   auto error = display_intf_->SetCursorPosition(x, y);
   if (error != kErrorNone) {
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 6b5d470..dba00b4 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -198,6 +198,9 @@
 }
 
 HWC2::Error HWCLayer::SetLayerColor(hwc_color_t color) {
+  if (client_requested_ != HWC2::Composition::SolidColor) {
+    return HWC2::Error::None;
+  }
   layer_->solid_fill_color = GetUint32Color(color);
   layer_->input_buffer.format = kFormatARGB8888;
   DLOGV_IF(kTagCompManager, "[%" PRIu64 "][%" PRIu64 "] Layer color set to %x", display_id_, id_,
@@ -582,7 +585,7 @@
     }
   }
 
-  uint32_t fps = 0;
+  float fps = 0;
   if (getMetaData(handle, GET_REFRESH_RATE  , &fps) == 0) {
     layer->frame_rate = RoundToStandardFPS(fps);
   }
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index 30fc362..25ec4dc 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -119,7 +119,7 @@
 };
 
 struct SortLayersByZ {
-  bool operator()(const HWCLayer *lhs, const HWCLayer *rhs) {
+  bool operator()(const HWCLayer *lhs, const HWCLayer *rhs) const {
     return lhs->GetZ() < rhs->GetZ();
   }
 };
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 293ffce..3fce394 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -344,7 +344,7 @@
 
 int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
   SCOPE_LOCK(locker_);
-  if (!device) {
+  if (!device || display != HWC_DISPLAY_VIRTUAL) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
@@ -502,16 +502,16 @@
   if (!device) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
+  SCOPE_LOCK(hwc_session->callbacks_lock_);
   auto desc = static_cast<HWC2::Callback>(descriptor);
   auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
   DLOGD("Registering callback: %s", to_string(desc).c_str());
   if (descriptor == HWC2_CALLBACK_HOTPLUG) {
-    // If primary display (HDMI) is not created yet, wait for it to be hotplugged.
-    if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY] && !hwc_session->hdmi_is_primary_) {
       hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
     }
   }
-
+  hwc_session->callbacks_lock_.Broadcast();
   return INT32(error);
 }
 
@@ -633,8 +633,12 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
+  if (display != HWC_DISPLAY_VIRTUAL) {
+    return HWC2_ERROR_UNSUPPORTED;
+  }
+
   auto *hwc_session = static_cast<HWCSession *>(device);
-  if (display == HWC_DISPLAY_VIRTUAL && hwc_session->hwc_display_[display]) {
+  if (hwc_session->hwc_display_[display]) {
     auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
     auto status = vds->SetOutputBuffer(buffer, releaseFence);
     return INT32(status);
@@ -675,7 +679,7 @@
       }
 
       if (hwc_session->need_invalidate_) {
-        hwc_session->callbacks_.Refresh(display);
+        hwc_session->Refresh(display);
       }
 
       if (hwc_session->color_mgr_) {
@@ -1161,6 +1165,11 @@
   auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
   auto mode = input_parcel->readInt32();
   auto device = static_cast<hwc2_device_t *>(this);
+
+  if (display > HWC_DISPLAY_VIRTUAL) {
+    return -EINVAL;
+  }
+
   auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorModeById, mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
@@ -1248,7 +1257,7 @@
 
   switch (pending_action.action) {
     case kInvalidating:
-      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      Refresh(HWC_DISPLAY_PRIMARY);
       break;
     case kEnterQDCMMode:
       ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
@@ -1259,12 +1268,12 @@
     case kApplySolidFill:
       ret =
           color_mgr_->SetSolidFill(pending_action.params, true, hwc_display_[HWC_DISPLAY_PRIMARY]);
-      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      Refresh(HWC_DISPLAY_PRIMARY);
       break;
     case kDisableSolidFill:
       ret =
           color_mgr_->SetSolidFill(pending_action.params, false, hwc_display_[HWC_DISPLAY_PRIMARY]);
-      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      Refresh(HWC_DISPLAY_PRIMARY);
       break;
     case kSetPanelBrightness:
       brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
@@ -1278,7 +1287,7 @@
     case kEnableFrameCapture:
       ret = color_mgr_->SetFrameCapture(pending_action.params, true,
                                         hwc_display_[HWC_DISPLAY_PRIMARY]);
-      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      Refresh(HWC_DISPLAY_PRIMARY);
       break;
     case kDisableFrameCapture:
       ret = color_mgr_->SetFrameCapture(pending_action.params, false,
@@ -1287,7 +1296,7 @@
     case kConfigureDetailedEnhancer:
       ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
                                             hwc_display_[HWC_DISPLAY_PRIMARY]);
-      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      Refresh(HWC_DISPLAY_PRIMARY);
       break;
     case kNoAction:
       break;
@@ -1319,7 +1328,7 @@
     DLOGI("Uevent FB0 = %s", uevent_data);
     int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
     if (panel_reset == 0) {
-      callbacks_.Refresh(0);
+      Refresh(0);
       reset_panel_ = true;
     }
   } else if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
@@ -1445,7 +1454,7 @@
   } while (0);
 
   if (connected) {
-    callbacks_.Refresh(0);
+    Refresh(0);
 
     if (!hdmi_is_primary_) {
       // wait for sufficient time to ensure sufficient resources are available to process new
@@ -1457,8 +1466,8 @@
 
   // notify client
   if (notify_hotplug) {
-    callbacks_.Hotplug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
-                       connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
+    HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
+            connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
   }
 
   qservice_->onHdmiHotplug(INT(connected));
@@ -1507,4 +1516,22 @@
   return android::NO_ERROR;
 }
 
+void HWCSession::Refresh(hwc2_display_t display) {
+  SCOPE_LOCK(callbacks_lock_);
+  HWC2::Error err = callbacks_.Refresh(display);
+  while (err != HWC2::Error::None) {
+    callbacks_lock_.Wait();
+    err = callbacks_.Refresh(display);
+  }
+}
+
+void HWCSession::HotPlug(hwc2_display_t display, HWC2::Connection state) {
+  SCOPE_LOCK(callbacks_lock_);
+  HWC2::Error err = callbacks_.Hotplug(display, state);
+  while (err != HWC2::Error::None) {
+    callbacks_lock_.Wait();
+    err = callbacks_.Hotplug(display, state);
+  }
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 7d2a30c..288bbba 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -211,6 +211,9 @@
 
   android::status_t SetColorModeById(const android::Parcel *input_parcel);
 
+  void Refresh(hwc2_display_t display);
+  void HotPlug(hwc2_display_t display, HWC2::Connection state);
+
   static Locker locker_;
   CoreInterface *core_intf_ = nullptr;
   HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
@@ -227,6 +230,7 @@
   qService::QService *qservice_ = nullptr;
   HWCSocketHandler socket_handler_;
   bool hdmi_is_primary_ = false;
+  Locker callbacks_lock_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 5cb9cf7..383ec3b 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -208,7 +208,7 @@
   if (hwc_display_[disp_id]) {
     error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
     if (!error) {
-      callbacks_.Refresh(0);
+      Refresh(0);
     }
   }
 
@@ -312,7 +312,7 @@
 Return<int32_t> HWCSession::refreshScreen() {
   SCOPE_LOCK(locker_);
 
-  callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+  Refresh(HWC_DISPLAY_PRIMARY);
 
   return 0;
 }
@@ -349,7 +349,7 @@
   }
 
   // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
-  callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+  Refresh(HWC_DISPLAY_PRIMARY);
 
   // Wait until partial update control is complete
   int32_t error = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
@@ -443,7 +443,7 @@
   HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
 
   // trigger invalidate to apply new bw caps.
-  callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+  Refresh(HWC_DISPLAY_PRIMARY);
 
   if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
     return -EINVAL;
diff --git a/sdm/libs/utils/Android.mk b/sdm/libs/utils/Android.mk
index 09e1414..481ea39 100644
--- a/sdm/libs/utils/Android.mk
+++ b/sdm/libs/utils/Android.mk
@@ -18,6 +18,7 @@
 
 SDM_HEADER_PATH := ../../include
 include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE           := true
 LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)/sdm/utils
 LOCAL_COPY_HEADERS             = $(SDM_HEADER_PATH)/utils/constants.h \
                                  $(SDM_HEADER_PATH)/utils/debug.h \