Merge "hwc2: Allow commit to go through if flush_ flag is set"
diff --git a/common.mk b/common.mk
index a039e5f..bb0e83e 100644
--- a/common.mk
+++ b/common.mk
@@ -9,6 +9,9 @@
 display_config_version := $(shell \
     if [ -d "$(TOP)/vendor/qcom/opensource/interfaces/display/config/1.3" ];\
     then echo DISPLAY_CONFIG_1_3; fi)
+display_config_version := $(shell \
+    if [ -d "$(TOP)/vendor/qcom/opensource/interfaces/display/config/1.4" ];\
+    then echo DISPLAY_CONFIG_1_4; fi)
 #Common C flags
 common_flags := -Wno-missing-field-initializers
 common_flags += -Wconversion -Wall -Werror -std=c++14
@@ -27,6 +30,10 @@
 ifeq ($(display_config_version), DISPLAY_CONFIG_1_3)
     common_flags += -DDISPLAY_CONFIG_1_1 -DDISPLAY_CONFIG_1_2 -DDISPLAY_CONFIG_1_3
 endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_4)
+    common_flags += -DDISPLAY_CONFIG_1_1 -DDISPLAY_CONFIG_1_2
+    common_flags += -DDISPLAY_CONFIG_1_3 -DDISPLAY_CONFIG_1_4
+endif
 
 ifeq ($(TARGET_USES_COLOR_METADATA), true)
     common_flags += -DUSE_COLOR_METADATA
diff --git a/config/talos.mk b/config/talos.mk
new file mode 100644
index 0000000..74d1f70
--- /dev/null
+++ b/config/talos.mk
@@ -0,0 +1,60 @@
+#Display related packages and configuration
+
+PRODUCT_PACKAGES += \
+    android.hardware.graphics.composer@2.1-impl \
+    android.hardware.graphics.composer@2.1-service \
+    android.hardware.graphics.mapper@2.0-impl-qti-display \
+    vendor.qti.hardware.display.allocator@1.0-service \
+    android.hardware.memtrack@1.0-impl \
+    android.hardware.memtrack@1.0-service \
+    android.hardware.light@2.0-impl \
+    android.hardware.light@2.0-service \
+    gralloc.talos \
+    lights.talos \
+    hwcomposer.talos \
+    memtrack.talos \
+    libqdutils \
+    libqdMetaData \
+    libqdMetaData.system \
+    modetest
+
+#QDCM calibration xml file
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_hx83112a_video_mode_dsi_truly_panel.xml
+
+#Enable Charging Icon
+TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888
+
+TARGET_USES_GRALLOC1 := true
+TARGET_USES_DRM_PP := true
+TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS := true
+MAX_VIRTUAL_DISPLAY_DIMENSION := 4096
+NUM_FRAMEBUFFER_SURFACE_BUFFERS := 3
+TARGET_USES_HWC2 := true
+TARGET_USES_QCOM_DISPLAY_BSP := true
+TARGET_USES_COLOR_METADATA := true
+TARGET_HAS_WIDE_COLOR_DISPLAY := true
+
+PRODUCT_PROPERTY_OVERRIDES += \
+    persist.demo.hdmirotationlock=false \
+    debug.sf.hw=0 \
+    debug.egl.hw=0 \
+    debug.sf.latch_unsignaled=1 \
+    debug.mdpcomp.logs=0 \
+    debug.sf.enable_hwc_vds=1 \
+    ro.vendor.display.cabl=2 \
+    vendor.gralloc.disable_ubwc=0 \
+    vendor.display.disable_scaler=0 \
+    vendor.display.disable_inline_rotator=1 \
+    vendor.display.disable_decimation=1 \
+    vendor.display.enable_null_display=0 \
+    vendor.display.disable_excl_rect=0 \
+    vendor.display.comp_mask=0 \
+    vendor.display.disable_hw_recovery=1 \
+    vendor.display.enable_default_color_mode=1
+
+# This matrix should be in column major order, per SurfaceFlinger requirement
+#  1.16868   -0.16868    0.00000
+# -0.03155    1.03155    0.00000
+# -0.01473   -0.05899    1.07372
+PRODUCT_PROPERTY_OVERRIDES += \
+    vendor.display.dataspace_saturation_matrix=1.16868,-0.03155,-0.01473,-0.16868,1.03155,-0.05899,0.00000,0.00000,1.07372
diff --git a/gralloc/gr_priv_handle.h b/gralloc/gr_priv_handle.h
index 964bed0..39e5e20 100644
--- a/gralloc/gr_priv_handle.h
+++ b/gralloc/gr_priv_handle.h
@@ -33,6 +33,7 @@
 
 #define PRIV_HANDLE_CONST(exp) static_cast<const private_handle_t *>(exp)
 
+#pragma pack(push, 4)
 struct private_handle_t : public native_handle_t {
   enum {
     PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
@@ -75,15 +76,15 @@
   int format;
   int buffer_type;
   unsigned int layer_count;
-  uint64_t id __attribute__((aligned(8)));
-  uint64_t usage __attribute__((aligned(8)));
+  uint64_t id;
+  uint64_t usage;
 
   unsigned int size;
   unsigned int offset;
   unsigned int offset_metadata;
-  uint64_t base __attribute__((aligned(8)));
-  uint64_t base_metadata __attribute__((aligned(8)));
-  uint64_t gpuaddr __attribute__((aligned(8)));
+  uint64_t base;
+  uint64_t base_metadata;
+  uint64_t gpuaddr;
 
   static const int kNumFds = 2;
   static const int kMagic = 'gmsm';
@@ -173,5 +174,6 @@
 
   uint64_t GetBackingstore() const { return id; }
 };
+#pragma pack(pop)
 
 #endif  // __GR_PRIV_HANDLE_H__
diff --git a/libdisplayconfig/DisplayConfig.h b/libdisplayconfig/DisplayConfig.h
index 17b6421..fbce8b6 100644
--- a/libdisplayconfig/DisplayConfig.h
+++ b/libdisplayconfig/DisplayConfig.h
@@ -83,6 +83,10 @@
     float min_luminance = 0.0f;
 };
 
+struct WriteBackCapabilities {
+    bool isWbUbwcSupported;
+};
+
 //=============================================================================
 // The functions below run in the client pocess and wherever necessary
 // do a binder call to HWC to get/set data.
@@ -104,6 +108,7 @@
 int getHDRCapabilities(int dpy, DisplayHDRCapabilities *caps);
 int setCameraLaunchStatus(uint32_t on);
 bool displayBWTransactionPending();
+int32_t getWriteBackCapabilities( WriteBackCapabilities *caps);
 
 } // namespace display
 
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index c352839..4598ad5 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -601,6 +601,7 @@
   bool qsync_support;
   // Connection status of this connector
   bool is_connected;
+  bool is_wb_ubwc_supported;
 };
 
 // All DRM Connectors as map<Connector_id , connector_info>
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 87ca401..964640f 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-2014, 2016, 2018, 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
@@ -342,9 +342,9 @@
     return err;
 }
 
-extern "C" int refreshScreen() {
+extern "C" int refreshScreen(int dpy) {
     int ret = 0;
-    ret = screenRefresh();
+    ret = screenRefresh(dpy);
     return ret;
 }
 
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 1f5e5e8..8073bb1 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 - 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 2016, 2018, 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
@@ -47,9 +47,13 @@
 
 // Use this enum to specify the dpy parameters where needed
 enum {
+    // DO NOT CHANGE THE LEGACY DEFINES
     DISPLAY_PRIMARY = 0,    // = HWC_DISPLAY_PRIMARY
     DISPLAY_EXTERNAL = 1,   // = HWC_DISPLAY_EXTERNAL
     DISPLAY_VIRTUAL = 2,    // = HWC_DISPLAY_VIRTUAL
+
+    // Additional displays only for vendor client (e.g. pp) reference
+    DISPLAY_BUILTIN_2 = 3,
 };
 
 // External Display states - used in setSecondaryDisplayStatus()
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index 8f25253..61ff037 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2013-14 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-14, 2018, 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
@@ -62,8 +62,8 @@
 // ----------------------------------------------------------------------------
 // Convenience wrappers that clients can call
 // ----------------------------------------------------------------------------
-inline android::status_t screenRefresh() {
-    return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
+inline android::status_t screenRefresh(int dpy) {
+    return sendSingleParam(qService::IQService::SCREEN_REFRESH, dpy);
 }
 
 inline android::status_t toggleScreenUpdate(uint32_t on) {
diff --git a/sdm/include/core/core_interface.h b/sdm/include/core/core_interface.h
index ba01175..2165155 100644
--- a/sdm/include/core/core_interface.h
+++ b/sdm/include/core/core_interface.h
@@ -109,6 +109,7 @@
   bool is_connected = false;                   //!< Connection status of the display.
   bool is_primary = false;                     //!< True only if this is the main display of the
                                                //!< device.
+  bool is_wb_ubwc_supported = true;            //!< check hardware wb ubwc support
 };
 
 /*! @brief Information on all displays as a map with display_id as key.
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 35eb366..758a010 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -175,9 +175,9 @@
   bool hdr_supported = false;          //!< if HDR is enabled
   bool hdr_metadata_type_one = false;  //!< Metadata type one obtained from HDR sink
   uint32_t hdr_eotf = 0;               //!< Electro optical transfer function
-  uint32_t max_luminance = 0;          //!< From Panel's peak luminance
-  uint32_t average_luminance = 0;      //!< From Panel's average luminance
-  uint32_t min_luminance = 0;          //!< From Panel's blackness level
+  float max_luminance = 0.0f;          //!< From Panel's peak luminance
+  float average_luminance = 0.0f;      //!< From Panel's average luminance
+  float min_luminance = 0.0f;          //!< From Panel's blackness level
   bool partial_update = false;         //!< If display supports Partial Update.
 };
 
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 47642b7..39ab20b 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -372,9 +372,9 @@
   bool hdr_enabled = false;           // HDR feature supported
   bool hdr_metadata_type_one = false;     // Static HDR metadata type one
   uint32_t hdr_eotf = 0;              // Electro optical transfer function
-  uint32_t peak_luminance = 0;        // Panel's peak luminance level
-  uint32_t average_luminance = 0;     // Panel's average luminance level
-  uint32_t blackness_level = 0;       // Panel's blackness level
+  float peak_luminance = 0.0f;        // Panel's peak luminance level
+  float average_luminance = 0.0f;     // Panel's average luminance level
+  float blackness_level = 0.0f;       // Panel's blackness level
   HWColorPrimaries primaries = {};    // WRGB color primaries
   HWPanelOrientation panel_orientation = {};  // Panel Orientation
   uint32_t transfer_time_us = 0;      // transfer time in micro seconds to panel's active region
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 9a9e75b..305a8fd 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -171,6 +171,7 @@
 
   registered_displays_.erase(display_comp_ctx->display_id);
   configured_displays_.erase(display_comp_ctx->display_id);
+  powered_on_displays_.erase(display_comp_ctx->display_id);
 
   if (display_comp_ctx->display_type == kPluggable) {
     max_layers_ = kMaxSDELayers;
@@ -543,6 +544,8 @@
   DisplayCompositionContext *display_comp_ctx =
       reinterpret_cast<DisplayCompositionContext *>(display_ctx);
 
+  powered_on_displays_.erase(display_comp_ctx->display_id);
+
   switch (state) {
   case kStateOff:
     Purge(display_ctx);
@@ -552,10 +555,13 @@
     break;
 
   case kStateOn:
-    if (registered_displays_.size() > 1) {
+    // Get active display count.
+    if (powered_on_displays_.size()) {
       safe_mode_ = true;
       DLOGV_IF(kTagCompManager, "safe_mode = %d", safe_mode_);
+      break;
     }
+    powered_on_displays_.insert(display_comp_ctx->display_id);
     break;
 
   default:
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 7a5f77c..876a217 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -111,6 +111,7 @@
   ResourceInterface *resource_intf_ = NULL;
   std::set<int32_t> registered_displays_;  // List of registered displays
   std::set<int32_t> configured_displays_;  // List of sucessfully configured displays
+  std::set<int32_t> powered_on_displays_;  // List of powered on displays.
   bool safe_mode_ = false;              // Flag to notify all displays to be in resource crunch
                                         // mode, where strategy manager chooses the best strategy
                                         // that uses optimal number of pipes for each display
diff --git a/sdm/libs/core/display_pluggable.cpp b/sdm/libs/core/display_pluggable.cpp
index a0b1aab..da161df 100644
--- a/sdm/libs/core/display_pluggable.cpp
+++ b/sdm/libs/core/display_pluggable.cpp
@@ -334,6 +334,7 @@
   var.push_back(std::make_pair(kDynamicRangeAttribute, kSdr));
   var.push_back(std::make_pair(kPictureQualityAttribute, kStandard));
   color_mode_attr_map_.insert(std::make_pair(kSrgb, var));
+  current_color_mode_ = kSrgb;
   pt.primaries = ColorPrimaries_BT2020;
   if (!hw_panel_info_.hdr_enabled) {
     UpdateColorModes();
@@ -427,6 +428,7 @@
   if (error != kErrorNone) {
     DLOGE("Failed Set blend space, error = %d display_type_=%d", error, display_type_);
   }
+  current_color_mode_ = color_mode;
 
   return kErrorNone;
 }
@@ -481,10 +483,10 @@
   for (ColorModeAttrMap::iterator it = color_mode_attr_map_.begin();
        ((i < num_color_modes_) && (it != color_mode_attr_map_.end())); i++, it++) {
     color_modes_[i].id = INT32(i);
-    std::size_t length = (it->first).copy(color_modes_[i].name, sizeof(it->first.c_str()));
+    std::size_t length = (it->first).copy(color_modes_[i].name, sizeof(SDEDisplayMode::name) - 1);
     color_modes_[i].name[length] = '\0';
     color_mode_map_.insert(std::make_pair(color_modes_[i].name, &color_modes_[i]));
-    DLOGI("Color mode = %s", it->first.c_str());
+    DLOGI("Color mode = %s", color_modes_[i].name);
   }
   return;
 }
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 5ac7fff..43d182f 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -664,8 +664,9 @@
   hw_panel_info_.is_primary_panel = connector_info_.is_primary;
   hw_panel_info_.is_pluggable = 0;
   hw_panel_info_.hdr_enabled = connector_info_.panel_hdr_prop.hdr_enabled;
-  hw_panel_info_.peak_luminance = connector_info_.panel_hdr_prop.peak_brightness;
-  hw_panel_info_.blackness_level = connector_info_.panel_hdr_prop.blackness_level;
+  // Convert the luminance values to cd/m^2 units.
+  hw_panel_info_.peak_luminance = FLOAT(connector_info_.panel_hdr_prop.peak_brightness) / 10000.0f;
+  hw_panel_info_.blackness_level = FLOAT(connector_info_.panel_hdr_prop.blackness_level) / 10000.0f;
   hw_panel_info_.primaries.white_point[0] = connector_info_.panel_hdr_prop.display_primaries[0];
   hw_panel_info_.primaries.white_point[1] = connector_info_.panel_hdr_prop.display_primaries[1];
   hw_panel_info_.primaries.red[0] = connector_info_.panel_hdr_prop.display_primaries[2];
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 09903b9..c7ac2f0 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -781,6 +781,7 @@
     }
     hw_info.is_connected = iter.second.is_connected ? 1 : 0;
     hw_info.is_primary = iter.second.is_primary ? 1 : 0;
+    hw_info.is_wb_ubwc_supported = iter.second.is_wb_ubwc_supported;
     if (hw_info.display_id >= 0) {
       (*hw_displays_info)[hw_info.display_id] = hw_info;
     }
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index cd1f4ce..b6f1b08 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -28,6 +28,7 @@
 */
 
 #include "hw_tv_drm.h"
+#include <math.h>
 #include <sys/time.h>
 #include <utils/debug.h>
 #include <utils/sys.h>
@@ -89,6 +90,14 @@
   return hdr_transfer;
 }
 
+static float GetMaxOrAverageLuminance(float luminance) {
+  return (50.0f * powf(2.0f, (luminance / 32.0f)));
+}
+
+static float GetMinLuminance(float luminance, float max_luminance) {
+  return (max_luminance * ((luminance / 255.0f) * (luminance / 255.0f)) / 100.0f);
+}
+
 HWTVDRM::HWTVDRM(int32_t display_id, BufferSyncHandler *buffer_sync_handler,
                  BufferAllocator *buffer_allocator, HWInfoInterface *hw_info_intf)
   : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf) {
@@ -185,10 +194,30 @@
   hw_panel_info_.hdr_enabled = connector_info_.ext_hdr_prop.hdr_supported;
   hw_panel_info_.hdr_metadata_type_one = connector_info_.ext_hdr_prop.hdr_metadata_type_one;
   hw_panel_info_.hdr_eotf = connector_info_.ext_hdr_prop.hdr_eotf;
-  hw_panel_info_.peak_luminance = connector_info_.ext_hdr_prop.hdr_max_luminance;
-  hw_panel_info_.average_luminance = connector_info_.ext_hdr_prop.hdr_avg_luminance;
-  hw_panel_info_.blackness_level = connector_info_.ext_hdr_prop.hdr_min_luminance;
-  DLOGI("TV Panel: %s, type_one = %d, eotf = %d, luminance[max = %d, min = %d, avg = %d]",
+
+  // Convert the raw luminance values from driver to Candela per meter^2 unit.
+  float max_luminance = FLOAT(connector_info_.ext_hdr_prop.hdr_max_luminance);
+  if (max_luminance != 0.0f) {
+    max_luminance = GetMaxOrAverageLuminance(max_luminance);
+  }
+  bool valid_luminance = (max_luminance > kMinPeakLuminance) && (max_luminance < kMaxPeakLuminance);
+  hw_panel_info_.peak_luminance = valid_luminance ? max_luminance : kDefaultMaxLuminance;
+
+  float min_luminance = FLOAT(connector_info_.ext_hdr_prop.hdr_min_luminance);
+  if (min_luminance != 0.0f) {
+    min_luminance = GetMinLuminance(min_luminance, hw_panel_info_.peak_luminance);
+  }
+  hw_panel_info_.blackness_level = (min_luminance < 1.0f) ? min_luminance : kDefaultMinLuminance;
+
+  float average_luminance = FLOAT(connector_info_.ext_hdr_prop.hdr_avg_luminance);
+  if (average_luminance != 0.0f) {
+    average_luminance = GetMaxOrAverageLuminance(average_luminance);
+  } else {
+    average_luminance = (hw_panel_info_.peak_luminance + hw_panel_info_.blackness_level) / 2.0f;
+  }
+  hw_panel_info_.average_luminance = average_luminance;
+
+  DLOGI("TV Panel: %s, type_one = %d, eotf = %d, luminance[max = %f, min = %f, avg = %f]",
         hw_panel_info_.hdr_enabled ? "HDR" : "Non-HDR", hw_panel_info_.hdr_metadata_type_one,
         hw_panel_info_.hdr_eotf, hw_panel_info_.peak_luminance, hw_panel_info_.blackness_level,
         hw_panel_info_.average_luminance);
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index 46f3117..9fed9ca 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -57,6 +57,10 @@
 
   static const int kBitRGB  = 20;
   static const int kBitYUV  = 21;
+  const float kDefaultMinLuminance = 0.02f;
+  const float kDefaultMaxLuminance = 500.0f;
+  const float kMinPeakLuminance = 300.0f;
+  const float kMaxPeakLuminance = 1000.0f;
   drm_msm_ext_hdr_metadata hdr_metadata_ = {};
 };
 
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 2dca3c2..9795328 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -881,11 +881,11 @@
       } else if (!strncmp(tokens[0], "is_hdr_enabled", strlen("is_hdr_enabled"))) {
         panel_info->hdr_enabled = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "peak_brightness", strlen("peak_brightness"))) {
-        panel_info->peak_luminance = UINT32(atoi(tokens[1]));
+        panel_info->peak_luminance = FLOAT(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "average_brightness", strlen("average_brightness"))) {
-        panel_info->average_luminance = UINT32(atoi(tokens[1]));
+        panel_info->average_luminance = FLOAT(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "blackness_level", strlen("blackness_level"))) {
-        panel_info->blackness_level = UINT32(atoi(tokens[1]));
+        panel_info->blackness_level = FLOAT(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "white_chromaticity_x", strlen("white_chromaticity_x"))) {
         panel_info->primaries.white_point[0] = UINT32(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "white_chromaticity_y", strlen("white_chromaticity_y"))) {
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index 6edbf5f..2ac716d 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -38,6 +38,12 @@
 LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
 LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
 endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_4)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+endif
 
 LOCAL_SRC_FILES               := hwc_session.cpp \
                                  hwc_session_services.cpp \
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 26f4c54..f29bb93 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -107,8 +107,7 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCColorMode::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
-  DTRACE_SCOPED();
+HWC2::Error HWCColorMode::ValidateColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
   if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
     DLOGE("Could not find mode: %d", mode);
     return HWC2::Error::BadParameter;
@@ -120,6 +119,42 @@
     return HWC2::Error::Unsupported;
   }
 
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
+  DTRACE_SCOPED();
+  HWC2::Error hwc_error = ValidateColorModeWithRenderIntent(mode, intent);
+  if (hwc_error != HWC2::Error::None) {
+    return hwc_error;
+  }
+
+  if (current_color_mode_ == mode && current_render_intent_ == intent) {
+    return HWC2::Error::None;
+  }
+
+  auto mode_string = color_mode_map_[mode][intent];
+  DisplayError error = display_intf_->SetColorMode(mode_string);
+  if (error != kErrorNone) {
+    DLOGE("failed for mode = %d intent = %d name = %s", mode, intent, mode_string.c_str());
+    return HWC2::Error::Unsupported;
+  }
+  // The mode does not have the PCC configured, restore the transform
+  RestoreColorTransform();
+
+  current_color_mode_ = mode;
+  current_render_intent_ = intent;
+  DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d name = %s", mode, intent,
+           mode_string.c_str());
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::CacheColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
+  HWC2::Error error = ValidateColorModeWithRenderIntent(mode, intent);
+  if (error != HWC2::Error::None) {
+    return error;
+  }
+
   if (current_color_mode_ == mode && current_render_intent_ == intent) {
     return HWC2::Error::None;
   }
@@ -619,14 +654,10 @@
   sdm_client_target->flags.updating = IsLayerUpdating(client_target_);
   layer_stack_.layers.push_back(sdm_client_target);
 
-  // Apply current Color Mode and Render Intent.
-  HWC2::Error error = color_mode_->ApplyCurrentColorModeWithRenderIntent();
-
   // fall back frame composition to GPU when client target is 10bit
   // TODO(user): clarify the behaviour from Client(SF) and SDM Extn -
   // when handling 10bit FBT, as it would affect blending
-  // Fallback to GPU Composition, if Color Mode can't be applied.
-  if ((error != HWC2::Error::None) || Is10BitFormat(sdm_client_target->input_buffer.format)) {
+  if (Is10BitFormat(sdm_client_target->input_buffer.format)) {
     // Must fall back to client composition
     MarkLayersForClientComposition();
   }
@@ -1283,11 +1314,9 @@
     // HDR10 and HLG are supported
     out_types[0] = HAL_HDR_HDR10;
     out_types[1] = HAL_HDR_HLG;
-    static const float kLuminanceFactor = 10000.0;
-    // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
-    *out_max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
-    *out_max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
-    *out_min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
+    *out_max_luminance = fixed_info.max_luminance;
+    *out_max_average_luminance = fixed_info.average_luminance;
+    *out_min_luminance = fixed_info.min_luminance;
   }
 
   return HWC2::Error::None;
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index cf3d690..27bed47 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -82,6 +82,7 @@
   HWC2::Error RestoreColorTransform();
   ColorMode GetCurrentColorMode() { return current_color_mode_; }
   HWC2::Error ApplyCurrentColorModeWithRenderIntent();
+  HWC2::Error CacheColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
 
  private:
   static const uint32_t kColorTransformMatrixCount = 16;
@@ -94,6 +95,7 @@
     }
   }
   HWC2::Error ApplyDefaultColorMode();
+  HWC2::Error ValidateColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
 
   DisplayInterface *display_intf_ = NULL;
   bool apply_mode_ = false;
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index 568bdfe..a11d13e 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -195,6 +195,12 @@
   // Checks and replaces layer stack for solid fill
   SolidFillPrepare();
 
+  // Apply current Color Mode and Render Intent.
+  if (color_mode_->ApplyCurrentColorModeWithRenderIntent() != HWC2::Error::None) {
+    // Fallback to GPU Composition, if Color Mode can't be applied.
+    MarkLayersForClientComposition();
+  }
+
   bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
 
   if (readback_buffer_queued_ || pending_output_dump) {
@@ -281,7 +287,7 @@
 }
 
 HWC2::Error HWCDisplayBuiltIn::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
-  auto status = color_mode_->SetColorModeWithRenderIntent(mode, intent);
+  auto status = color_mode_->CacheColorModeWithRenderIntent(mode, intent);
   if (status != HWC2::Error::None) {
     DLOGE("failed for mode = %d intent = %d", mode, intent);
     return status;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 77f0e5e..fbe57b0 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -290,6 +290,9 @@
     case qdutils::DISPLAY_VIRTUAL:
       map_info = map_info_virtual_.size() ? &map_info_virtual_[0] : nullptr;
       break;
+    case qdutils::DISPLAY_BUILTIN_2:
+      map_info = map_info_builtin_.size() ? &map_info_builtin_[0] : nullptr;
+      break;
   }
 
   if (!map_info) {
@@ -1158,7 +1161,11 @@
       break;
 
     case qService::IQService::SCREEN_REFRESH:
-      status = refreshScreen();
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = RefreshScreen(input_parcel);
       break;
 
     case qService::IQService::SET_IDLE_TIMEOUT:
@@ -1626,7 +1633,7 @@
   return 0;
 }
 android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
-  int display = static_cast<int >(input_parcel->readInt32());
+  int display = input_parcel->readInt32();
   auto mode = input_parcel->readInt32();
   auto device = static_cast<hwc2_device_t *>(this);
 
@@ -1644,6 +1651,20 @@
   return 0;
 }
 
+android::status_t HWCSession::RefreshScreen(const android::Parcel *input_parcel) {
+  int display = input_parcel->readInt32();
+
+  int disp_idx = GetDisplayIndex(display);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", display);
+    return -EINVAL;
+  }
+
+  Refresh(static_cast<hwc2_display_t>(disp_idx));
+
+  return 0;
+}
+
 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
   int type = input_parcel->readInt32();
   bool enable = (input_parcel->readInt32() > 0);
@@ -2561,9 +2582,13 @@
 
   // If primary display is powered off, change vsync source to next builtin display.
   // If primary display is powerd on, change vsync source back to primary display.
+  // First check for active builtins. If not found switch to pluggable displays.
+  std::vector<DisplayMapInfo> map_info = map_info_builtin_;
+  std::copy(map_info_pluggable_.begin(), map_info_pluggable_.end(), std::back_inserter(map_info));
+
   if (power_mode == HWC2::PowerMode::Off) {
     hwc2_display_t next_vsync_source = HWC_DISPLAY_PRIMARY;
-    for (auto &info : map_info_builtin_) {
+    for (auto &info : map_info) {
       auto &hwc_display = hwc_display_[info.client_id];
       if (!hwc_display) {
         continue;
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 6387cd6..f581f60 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -20,7 +20,9 @@
 #ifndef __HWC_SESSION_H__
 #define __HWC_SESSION_H__
 
-#ifdef DISPLAY_CONFIG_1_3
+#ifdef DISPLAY_CONFIG_1_4
+#include <vendor/display/config/1.4/IDisplayConfig.h>
+#elif DISPLAY_CONFIG_1_3
 #include <vendor/display/config/1.3/IDisplayConfig.h>
 #elif DISPLAY_CONFIG_1_2
 #include <vendor/display/config/1.2/IDisplayConfig.h>
@@ -49,7 +51,9 @@
 
 namespace sdm {
 
-#ifdef DISPLAY_CONFIG_1_3
+#ifdef DISPLAY_CONFIG_1_4
+using vendor::display::config::V1_4::IDisplayConfig;
+#elif  DISPLAY_CONFIG_1_3
 using vendor::display::config::V1_3::IDisplayConfig;
 #elif DISPLAY_CONFIG_1_2
 using vendor::display::config::V1_2::IDisplayConfig;
@@ -249,6 +253,7 @@
   int32_t SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status);
   int32_t GetPanelBrightness(int *level);
   int32_t MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level);
+  int32_t IsWbUbwcSupported(int *value);
 
   // service methods
   void StartServices();
@@ -290,6 +295,9 @@
 #ifdef DISPLAY_CONFIG_1_3
   Return<int32_t> controlIdlePowerCollapse(bool enable, bool synchronous) override;
 #endif
+#ifdef DISPLAY_CONFIG_1_4
+  Return<void> getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb) override;
+#endif
 
   // QClient methods
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -313,6 +321,7 @@
   android::status_t getComposerStatus();
   android::status_t SetQSyncMode(const android::Parcel *input_parcel);
   android::status_t SetIdlePC(const android::Parcel *input_parcel);
+  android::status_t RefreshScreen(const android::Parcel *input_parcel);
 
   void Refresh(hwc2_display_t display);
   void HotPlug(hwc2_display_t display, HWC2::Connection state);
@@ -348,7 +357,7 @@
   int hpd_bpp_ = 0;
   int hpd_pattern_ = 0;
   int null_display_mode_ = 0;
-  bool power_on_pending_[HWC_NUM_DISPLAY_TYPES] = {false};
+  bool power_on_pending_[kNumDisplays] = {false};
   HotPlugEvent hotplug_pending_event_ = kHotPlugNone;
   bool destroy_virtual_disp_pending_ = false;
   uint32_t idle_pc_ref_cnt_ = 0;
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 467da12..a34d0de 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -633,4 +633,34 @@
 }
 #endif  // DISPLAY_CONFIG_1_3
 
+
+int32_t HWCSession::IsWbUbwcSupported(int *value) {
+  HWDisplaysInfo hw_displays_info = {};
+  DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
+
+  for (auto &iter : hw_displays_info) {
+    auto &info = iter.second;
+    if (info.display_type == kVirtual && info.is_wb_ubwc_supported) {
+      *value = 1;
+    }
+  }
+
+  return error;
+}
+
+#ifdef DISPLAY_CONFIG_1_4
+Return<void> HWCSession::getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb) {
+  int value = 0;
+  IDisplayConfig::WriteBackCapabilities wb_caps = {};
+  int32_t error = IsWbUbwcSupported(&value);
+  wb_caps.isWbUbwcSupported = value;
+  _hidl_cb(error, wb_caps);
+
+  return Void();
+}
+#endif  // DISPLAY_CONFIG_1_4
+
 }  // namespace sdm