Merge "sdm: Add basic makefiles"
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/msmnile.mk b/config/msmnile.mk
index 053cfeb..8d14935 100644
--- a/config/msmnile.mk
+++ b/config/msmnile.mk
@@ -53,7 +53,6 @@
     vendor.display.comp_mask=0 \
     vendor.display.disable_hw_recovery=0 \
     vendor.display.enable_default_color_mode=1
-    vendor.display.disable_hw_recovery=1
 
 # This matrix should be in column major order, per SurfaceFlinger requirement
 #  1.16868   -0.16868    0.00000
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/QtiMapper.cpp b/gralloc/QtiMapper.cpp
index 3848878..14c788e 100644
--- a/gralloc/QtiMapper.cpp
+++ b/gralloc/QtiMapper.cpp
@@ -52,7 +52,7 @@
 
 bool QtiMapper::ValidDescriptor(const BufferDescriptorInfo_2_1 &bd) {
   if (bd.width == 0 || bd.height == 0 || (static_cast<int32_t>(bd.format) <= 0) ||
-      bd.layerCount != 1) {
+      bd.layerCount <= 0) {
     return false;
   }
 
diff --git a/gralloc/gr_buf_mgr.cpp b/gralloc/gr_buf_mgr.cpp
index 3d4bfac..9a25a8e 100644
--- a/gralloc/gr_buf_mgr.cpp
+++ b/gralloc/gr_buf_mgr.cpp
@@ -101,6 +101,10 @@
 }
 
 Error BufferManager::ImportHandleLocked(private_handle_t *hnd) {
+  if (private_handle_t::validate(hnd) != 0) {
+    ALOGE("ImportHandleLocked: Invalid handle: %p", hnd);
+    return Error::BAD_BUFFER;
+  }
   ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id);
   int ion_handle = allocator_->ImportBuffer(hnd->fd);
   if (ion_handle < 0) {
@@ -335,6 +339,7 @@
 }
 
 Error BufferManager::Dump(std::ostringstream *os) {
+  std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
   for (auto it : handles_map_) {
     auto buf = it.second;
     auto hnd = buf->handle;
diff --git a/gralloc/gr_priv_handle.h b/gralloc/gr_priv_handle.h
index 964bed0..ace762e 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';
@@ -131,12 +132,14 @@
   static int validate(const native_handle *h) {
     auto *hnd = static_cast<const private_handle_t *>(h);
     if (!h || h->version != sizeof(native_handle) || h->numInts != NumInts() ||
-        h->numFds != kNumFds || hnd->magic != kMagic) {
-      ALOGE(
-          "Invalid gralloc handle (at %p): ver(%d/%zu) ints(%d/%d) fds(%d/%d) "
-          "magic(%c%c%c%c/%c%c%c%c)",
+        h->numFds != kNumFds) {
+      ALOGE("Invalid gralloc handle (at %p): ver(%d/%zu) ints(%d/%d) fds(%d/%d) ",
           h, h ? h->version : -1, sizeof(native_handle), h ? h->numInts : -1, NumInts(),
-          h ? h->numFds : -1, kNumFds,
+          h ? h->numFds : -1, kNumFds);
+      return -EINVAL;
+    }
+    if (hnd->magic != kMagic) {
+       ALOGE("magic(%c%c%c%c/%c%c%c%c)",
           hnd ? (((hnd->magic >> 24) & 0xFF) ? ((hnd->magic >> 24) & 0xFF) : '-') : '?',
           hnd ? (((hnd->magic >> 16) & 0xFF) ? ((hnd->magic >> 16) & 0xFF) : '-') : '?',
           hnd ? (((hnd->magic >> 8) & 0xFF) ? ((hnd->magic >> 8) & 0xFF) : '-') : '?',
@@ -173,5 +176,6 @@
 
   uint64_t GetBackingstore() const { return id; }
 };
+#pragma pack(pop)
 
 #endif  // __GR_PRIV_HANDLE_H__
diff --git a/include/display_properties.h b/include/display_properties.h
index ddcde64..9af7ddd 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -107,6 +107,7 @@
 #define QDCM_DISABLE_TIMEOUT_PROP            PERSIST_DISPLAY_PROP("qdcm.disable_timeout")
 #define QDCM_MODE_COMBINE_PROP               DISPLAY_PROP("qdcm.mode_combine")
 #define PREFER_MULTIRECT_PROP                DISPLAY_PROP("prefer_multirect")
+#define DROP_SKEWED_VSYNC                    DISPLAY_PROP("drop_skewed_vsync");
 
 #define ZERO_SWAP_INTERVAL                   "vendor.debug.egl.swapinterval"
 
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..0fe0d2c 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -38,6 +38,7 @@
 #include "xf86drm.h"
 #include "xf86drmMode.h"
 #include <drm/msm_drm.h>
+#include <drm/msm_drm_pp.h>
 
 namespace sde_drm {
 
@@ -601,6 +602,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>
@@ -666,6 +668,7 @@
   kFeatureAd4Init,
   kFeatureAd4Cfg,
   kFeatureAd4Input,
+  kFeatureAd4Roi,
   kFeatureAd4Backlight,
   kFeatureAd4Assertiveness,
   kFeatureAd4ManualStrength,
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/IQService.h b/libqservice/IQService.h
index 929f7b6..11cbf22 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -80,6 +80,7 @@
         SET_QSYNC_MODE = 38, // Set qsync mode. 0 - (none)disable qsync, 1 - continuous mode.
         SET_COLOR_MODE_WITH_RENDER_INTENT = 39,
         SET_IDLE_PC = 40, // Enable/disable Idle power collapse
+        SET_DPPS_AD4_ROI_CONFIG = 41, // Set ad4 roi config for debug
         COMMAND_LIST_END = 400,
     };
 
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..7cac5e1 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -163,6 +163,16 @@
   kQsyncModeOneShot,     // This is set by client to enable qsync only for current frame.
 };
 
+/*! @brief This structure defines configuration for display dpps ad4 region of interest. */
+struct DisplayDppsAd4RoiCfg {
+  uint32_t h_start;     //!< start in hotizontal direction
+  uint32_t h_end;       //!< end in hotizontal direction
+  uint32_t v_start;     //!< start in vertical direction
+  uint32_t v_end;       //!< end in vertical direction
+  uint32_t factor_in;   //!< the strength factor of inside ROI region
+  uint32_t factor_out;  //!< the strength factor of outside ROI region
+};
+
 /*! @brief This structure defines configuration for fixed properties of a display device.
 
   @sa DisplayInterface::GetConfig
@@ -175,9 +185,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.
 };
 
@@ -409,13 +419,16 @@
   /*! @brief Method to set current state of the display device.
 
     @param[in] state \link DisplayState \endlink
+    @param[in] flag to force full bridge teardown for pluggable displays, no-op for other displays,
+               if requested state is kStateOff
     @param[in] pointer to release fence
 
     @return \link DisplayError \endlink
 
     @sa SetDisplayState
   */
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence) = 0;
+  virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
+                                       int *release_fence) = 0;
 
   /*! @brief Method to set active configuration for variable properties of the display device.
 
@@ -730,6 +743,15 @@
   */
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event) = 0;
 
+  /*! @brief Method to set dpps ad roi.
+
+    @param[in] roi config parmas
+
+    @return \link DisplayError \endlink
+  */
+
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) = 0;
+
   /*! @brief Method to set the Qsync mode.
 
   @param[in] qsync_mode: \link QSyncMode \endlink
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 699cb8b..b0e042f 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -101,6 +101,7 @@
   kCompositionBlit,         //!< This layer will be composed using Blit Engine.
                             //!< This composition type is used only if BlitTarget layer is provided
                             //!< in a composition cycle.
+  kCompositionNone,         //!< This layer will not be composed by any hardware.
 
   /* === List of composition types set by Client === */
   /* These composition types represent target buffer layers onto which GPU or Blit will draw if SDM
diff --git a/sdm/include/private/color_interface.h b/sdm/include/private/color_interface.h
index 884df5e..feaea30 100644
--- a/sdm/include/private/color_interface.h
+++ b/sdm/include/private/color_interface.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -45,11 +45,12 @@
 
 class ColorInterface;
 
-typedef DisplayError (*CreateColorInterface)(uint16_t version, DisplayType type,
+typedef DisplayError (*CreateColorInterface)(uint16_t version, int32_t display_id,
+                                             DisplayType type,
                                              const PPHWAttributes &attributes,
                                              ColorInterface **interface);
 
-typedef DisplayError (*DestroyColorInterface)(DisplayType type);
+typedef DisplayError (*DestroyColorInterface)(int32_t display_id);
 
 class ColorModeInterface {
  public:
@@ -63,8 +64,8 @@
   virtual ~ColorModeInterface() {}
 };
 
-extern "C" ColorModeInterface* GetColorModeInterface(DisplayType type);
-extern "C" void ReleaseColorModeInterface(DisplayType type);
+extern "C" ColorModeInterface* GetColorModeInterface(int32_t display_id, DisplayType type);
+extern "C" void ReleaseColorModeInterface(int32_t display_id);
 
 class ColorInterface {
  public:
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 32f0505..7c2846f 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -55,6 +55,8 @@
   kDisableFrameCapture = BITMAP(7),
   kConfigureDetailedEnhancer = BITMAP(8),
   kModeSet = BITMAP(10),
+  kMultiDispProc = BITMAP(11),
+  kMultiDispGetId = BITMAP(12),
   kGetDetailedEnhancerData = BITMAP(21),
   kNoAction = BITMAP(31),
 };
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/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 5bb2c4b..14f156b 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -35,6 +35,7 @@
   enum ResourceCmd {
     kCmdResetLUT,
     kCmdGetDefaultClk,
+    kCmdDisableRotatorOneFrame,
     kCmdMax,
   };
 
diff --git a/sdm/include/utils/locker.h b/sdm/include/utils/locker.h
index dabeb11..e0d91cb 100755
--- a/sdm/include/utils/locker.h
+++ b/sdm/include/utils/locker.h
@@ -127,15 +127,15 @@
 
   Locker() : sequence_wait_(0) {
     pthread_mutex_init(&mutex_, 0);
-    pthread_condattr_init(&cond_attr);
-    pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
-    pthread_cond_init(&condition_, &cond_attr);
+    pthread_condattr_init(&cond_attr_);
+    pthread_condattr_setclock(&cond_attr_, CLOCK_MONOTONIC);
+    pthread_cond_init(&condition_, &cond_attr_);
   }
 
   ~Locker() {
     pthread_mutex_destroy(&mutex_);
     pthread_cond_destroy(&condition_);
-    pthread_condattr_destroy(&cond_attr);
+    pthread_condattr_destroy(&cond_attr_);
   }
 
   void Lock() { pthread_mutex_lock(&mutex_); }
@@ -157,7 +157,7 @@
  private:
   pthread_mutex_t mutex_;
   pthread_cond_t condition_;
-  pthread_condattr_t cond_attr;
+  pthread_condattr_t cond_attr_;
   int sequence_wait_;   // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
                         // Some routines will wait for sequence of function calls to finish
                         // so that capturing a transitionary snapshot of context is prevented.
diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp
index 694aada..d895bf7 100644
--- a/sdm/libs/core/color_manager.cpp
+++ b/sdm/libs/core/color_manager.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015 - 2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015 - 2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -99,10 +99,11 @@
   color_lib_.~DynLib();
 }
 
-ColorManagerProxy::ColorManagerProxy(DisplayType type, HWInterface *intf,
+ColorManagerProxy::ColorManagerProxy(int32_t id, DisplayType type, HWInterface *intf,
                                      const HWDisplayAttributes &attr,
                                      const HWPanelInfo &info)
-    : device_type_(type), pp_hw_attributes_(), hw_intf_(intf), color_intf_(NULL), pp_features_() {}
+    : display_id_(id), device_type_(type), pp_hw_attributes_(), hw_intf_(intf),
+      color_intf_(NULL), pp_features_() {}
 
 ColorManagerProxy *ColorManagerProxy::CreateColorManagerProxy(DisplayType type,
                                                               HWInterface *hw_intf,
@@ -110,6 +111,8 @@
                                                               const HWPanelInfo &panel_info) {
   DisplayError error = kErrorNone;
   PPFeatureVersion versions;
+  int32_t display_id = -1;
+  ColorManagerProxy *color_manager_proxy = NULL;
 
   // check if all resources are available before invoking factory method from libsdm-color.so.
   if (!color_lib_ || !create_intf_ || !destroy_intf_) {
@@ -117,8 +120,9 @@
     return NULL;
   }
 
-  ColorManagerProxy *color_manager_proxy =
-      new ColorManagerProxy(type, hw_intf, attribute, panel_info);
+  hw_intf->GetDisplayId(&display_id);
+  color_manager_proxy = new ColorManagerProxy(display_id, type, hw_intf, attribute, panel_info);
+
   if (color_manager_proxy) {
     // 1. need query post-processing feature version from HWInterface.
     error = color_manager_proxy->hw_intf_->GetPPFeaturesVersion(&versions);
@@ -133,7 +137,8 @@
     }
 
     // 2. instantiate concrete ColorInterface from libsdm-color.so, pass all hardware info in.
-    error = create_intf_(COLOR_VERSION_TAG, color_manager_proxy->device_type_, hw_attr,
+    error = create_intf_(COLOR_VERSION_TAG, color_manager_proxy->display_id_,
+                         color_manager_proxy->device_type_, hw_attr,
                          &color_manager_proxy->color_intf_);
     if (error != kErrorNone) {
       DLOGW("Unable to instantiate concrete ColorInterface from %s", COLORMGR_LIBRARY_NAME);
@@ -147,7 +152,7 @@
 
 ColorManagerProxy::~ColorManagerProxy() {
   if (destroy_intf_)
-    destroy_intf_(device_type_);
+    destroy_intf_(display_id_);
   color_intf_ = NULL;
 }
 
diff --git a/sdm/libs/core/color_manager.h b/sdm/libs/core/color_manager.h
index db050af..74270e0 100644
--- a/sdm/libs/core/color_manager.h
+++ b/sdm/libs/core/color_manager.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -77,8 +77,8 @@
 
  protected:
   ColorManagerProxy() {}
-  ColorManagerProxy(DisplayType type, HWInterface *intf, const HWDisplayAttributes &attr,
-                    const HWPanelInfo &info);
+  ColorManagerProxy(int32_t id, DisplayType type, HWInterface *intf,
+                    const HWDisplayAttributes &attr, const HWPanelInfo &info);
 
  private:
   static DynLib color_lib_;
@@ -86,6 +86,7 @@
   static DestroyColorInterface destroy_intf_;
   static HWResourceInfo hw_res_info_;
 
+  int32_t display_id_;
   DisplayType device_type_;
   PPHWAttributes pp_hw_attributes_;
   HWInterface *hw_intf_;
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 838de0c..e07aae1 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;
@@ -249,7 +250,8 @@
   if (!display_comp_ctx->is_primary_panel) {
     bool low_end_hw = ((hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe +
                         hw_res_info_.num_dma_pipe) <= kSafeModeThreshold);
-    constraints->max_layers = max_sde_ext_layers_;
+    constraints->max_layers = display_comp_ctx->display_type == kBuiltIn ?
+                              max_sde_builtin_layers_ : max_sde_ext_layers_;
     constraints->safe_mode = (low_end_hw && !hw_res_info_.separate_rotator) ? true : safe_mode_;
   }
 
@@ -379,8 +381,8 @@
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
   configured_displays_.insert(display_comp_ctx->display_id);
 
-  // Check if all registered displays are in the configured display list.
-  if ((registered_displays_.size() == configured_displays_.size())) {
+  // Check if all poweredon displays are in the configured display list.
+  if ((powered_on_displays_.size() == configured_displays_.size())) {
     safe_mode_ = false;
   }
 
@@ -549,19 +551,31 @@
     configured_displays_.erase(display_comp_ctx->display_id);
     DLOGV_IF(kTagCompManager, "Configured displays = [%s]",
              StringDisplayList(configured_displays_));
+    powered_on_displays_.erase(display_comp_ctx->display_id);
     break;
 
   case kStateOn:
-    if (registered_displays_.size() > 1) {
+  case kStateDoze:
+    // Get active display count.
+    if (powered_on_displays_.size()) {
       safe_mode_ = true;
       DLOGV_IF(kTagCompManager, "safe_mode = %d", safe_mode_);
     }
+    powered_on_displays_.insert(display_comp_ctx->display_id);
+    break;
+
+  case kStateDozeSuspend:
+    configured_displays_.erase(display_comp_ctx->display_id);
+    powered_on_displays_.erase(display_comp_ctx->display_id);
     break;
 
   default:
     break;
   }
 
+  bool inactive = (state == kStateOff) || (state == kStateDozeSuspend);
+  UpdateStrategyConstraints(display_comp_ctx->is_primary_panel, inactive);
+
   return true;
 }
 
@@ -596,4 +610,27 @@
   return kErrorNone;
 }
 
+void CompManager::HandleSecureEvent(Handle display_ctx, SecureEvent secure_event) {
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  // Disable rotator for non secure layers at the end of secure display session, because scm call
+  // has been made to end secure display session during the display commit. Since then access to
+  // non secure memory is unavailable. So this results in smmu page fault when rotator tries to
+  // access the non secure memory.
+  if (secure_event == kSecureDisplayEnd) {
+    resource_intf_->Perform(ResourceInterface::kCmdDisableRotatorOneFrame,
+                            display_comp_ctx->display_resource_ctx);
+  }
+}
+
+void CompManager::UpdateStrategyConstraints(bool is_primary, bool disabled) {
+  if (!is_primary) {
+    return;
+  }
+
+  // Allow builtin display to use all pipes when primary is suspended.
+  // Restore it back to 2 after primary poweron.
+  max_sde_builtin_layers_ = (disabled && (powered_on_displays_.size() <= 1)) ? kMaxSDELayers : 2;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 5814a67..aba0b8b 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -81,12 +81,14 @@
   DisplayError SetColorModesInfo(Handle display_ctx,
                                  const std::vector<PrimariesTransfer> &colormodes_cs);
   DisplayError SetBlendSpace(Handle display_ctx, const PrimariesTransfer &blend_space);
+  void HandleSecureEvent(Handle display_ctx, SecureEvent secure_event);
 
  private:
   static const int kMaxThermalLevel = 3;
   static const int kSafeModeThreshold = 4;
 
   void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
+  void UpdateStrategyConstraints(bool is_primary, bool disabled);
   const char *StringDisplayList(const std::set<int32_t> &displays);
 
   struct DisplayCompositionContext {
@@ -110,6 +112,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
@@ -118,6 +121,7 @@
   ExtensionInterface *extension_intf_ = NULL;
   uint32_t max_layers_ = kMaxSDELayers;
   uint32_t max_sde_ext_layers_ = 0;
+  uint32_t max_sde_builtin_layers_ = 2;
   DppsControlInterface *dpps_ctrl_intf_ = NULL;
 };
 
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 6d54b4e..c646668 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -98,6 +98,7 @@
   int property_value = Debug::GetMaxPipesPerMixer(display_type_);
 
   uint32_t active_index = 0;
+  int drop_vsync = 0;
   hw_intf_->GetActiveConfig(&active_index);
   hw_intf_->GetDisplayAttributes(active_index, &display_attributes_);
   fb_config_ = display_attributes_;
@@ -127,17 +128,15 @@
     }
   }
 
-  if (!color_mgr_exists_) {
+  // ColorManager supported for built-in display.
+  if (kBuiltIn == display_type_) {
     color_mgr_ = ColorManagerProxy::CreateColorManagerProxy(display_type_, hw_intf_,
                                                             display_attributes_, hw_panel_info_);
 
     if (!color_mgr_) {
-      DLOGW("Unable to create ColorManagerProxy for display = %d", display_type_);
-    } else {
-      color_mgr_exists_ = true;
-      if (InitializeColorModes() != kErrorNone) {
-        DLOGW("InitColorModes failed for display = %d", display_type_);
-      }
+      DLOGW("Unable to create ColorManagerProxy for display %d-%d", display_id_, display_type_);
+    } else if (InitializeColorModes() != kErrorNone) {
+      DLOGW("InitColorModes failed for display %d-%d", display_id_, display_type_);
     }
   }
 
@@ -168,6 +167,9 @@
   Debug::GetProperty(DISABLE_HW_RECOVERY_DUMP_PROP, &disable_hw_recovery_dump_);
   DLOGI("disable_hw_recovery_dump_ set to %d", disable_hw_recovery_dump_);
 
+  Debug::Get()->GetProperty("DROP_SKEWED_VSYNC", &drop_vsync);
+  drop_skewed_vsync_ = (drop_vsync == 1);
+
   return kErrorNone;
 
 CleanupOnError:
@@ -390,7 +392,10 @@
     return error;
   }
 
+  // Stop dropping vsync when first commit is received after idle fallback.
+  drop_hw_vsync_ = false;
   DLOGI_IF(kTagDisplay, "Exiting commit for display: %d-%d", display_id_, display_type_);
+
   return kErrorNone;
 }
 
@@ -484,12 +489,14 @@
   return last_power_mode_;
 }
 
-DisplayError DisplayBase::SetDisplayState(DisplayState state, int *release_fence) {
+DisplayError DisplayBase::SetDisplayState(DisplayState state, bool teardown,
+                                          int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
   bool active = false;
 
-  DLOGI("Set state = %d, display %d-%d", state, display_id_, display_type_);
+  DLOGI("Set state = %d, display %d-%d, teardown = %d", state, display_id_,
+        display_type_, teardown);
 
   if (state == state_) {
     DLOGI("Same state transition is requested.");
@@ -501,7 +508,7 @@
     hw_layers_.info.hw_layers.clear();
     error = hw_intf_->Flush();
     if (error == kErrorNone) {
-      error = hw_intf_->PowerOff();
+      error = hw_intf_->PowerOff(teardown);
     }
     break;
 
@@ -1051,6 +1058,10 @@
   if (vsync_enable_ != enable) {
     error = hw_intf_->SetVSyncState(enable);
     if (error == kErrorNotSupported) {
+      if (drop_skewed_vsync_ && (hw_panel_info_.mode == kModeVideo) &&
+        enable && (current_refresh_rate_ == hw_panel_info_.min_fps)) {
+        drop_hw_vsync_ = true;
+      }
       error = hw_events_intf_->SetEventState(HWEvent::VSYNC, enable);
     }
     if (error == kErrorNone) {
@@ -1620,8 +1631,6 @@
                                 mixer_height != display_height);
 }
 
-bool DisplayBase::color_mgr_exists_ = false;
-
 void DisplayBase::ClearColorInfo() {
   color_modes_.clear();
   color_mode_map_.clear();
@@ -1631,7 +1640,6 @@
   if (color_mgr_) {
     delete color_mgr_;
     color_mgr_ = NULL;
-    color_mgr_exists_ = false;
   }
 }
 
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index e4efb92..7f8e32d 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -66,7 +66,8 @@
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
+  virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
+                                       int *release_fence);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
     return kErrorNotSupported;
@@ -124,6 +125,9 @@
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event) {
     return kErrorNotSupported;
   }
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) {
+    return kErrorNotSupported;
+  }
   virtual DisplayError SetQSyncMode(QSyncMode qsync_mode) { return kErrorNotSupported; }
   virtual std::string Dump();
   virtual DisplayError InitializeColorModes();
@@ -185,8 +189,6 @@
   uint32_t max_mixer_stages_ = 0;
   HWInfoInterface *hw_info_intf_ = NULL;
   ColorManagerProxy *color_mgr_ = NULL;  // each display object owns its ColorManagerProxy
-  // TODO(user): ColorManager supported only on a single built-in display.
-  static bool color_mgr_exists_;
   bool partial_update_control_ = true;
   HWEventsInterface *hw_events_intf_ = NULL;
   bool disable_pu_one_frame_ = false;
@@ -211,6 +213,9 @@
   bool hw_recovery_logs_captured_ = false;
   int disable_hw_recovery_dump_ = 0;
   HWQosData default_qos_data_;
+  bool drop_hw_vsync_ = false;
+  uint32_t current_refresh_rate_ = 0;
+  bool drop_skewed_vsync_ = false;
 
   static Locker display_power_reset_lock_;
   static bool display_power_reset_pending_;
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index f93ac18..e617818 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -191,10 +191,11 @@
   return error;
 }
 
-DisplayError DisplayBuiltIn::SetDisplayState(DisplayState state, int *release_fence) {
+DisplayError DisplayBuiltIn::SetDisplayState(DisplayState state, bool teardown,
+                                             int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
-  error = DisplayBase::SetDisplayState(state, release_fence);
+  error = DisplayBase::SetDisplayState(state, teardown, release_fence);
   if (error != kErrorNone) {
     return error;
   }
@@ -311,7 +312,7 @@
 }
 
 DisplayError DisplayBuiltIn::VSync(int64_t timestamp) {
-  if (vsync_enable_) {
+  if (vsync_enable_ && !drop_hw_vsync_) {
     DisplayEventVSync vsync;
     vsync.timestamp = timestamp;
     event_handler_->VSync(vsync);
@@ -322,7 +323,9 @@
 
 void DisplayBuiltIn::IdleTimeout() {
   if (hw_panel_info_.mode == kModeVideo) {
-    event_handler_->HandleEvent(kIdleTimeout);
+    if (event_handler_->HandleEvent(kIdleTimeout) != kErrorNone) {
+      return;
+    }
     handle_idle_timeout_ = true;
     event_handler_->Refresh();
     lock_guard<recursive_mutex> obj(recursive_mutex_);
@@ -425,7 +428,7 @@
   int release_fence = -1;
 
   DLOGI("Powering off built-in/primary %d", display_id_);
-  status = SetDisplayState(kStateOff, &release_fence);
+  status = SetDisplayState(kStateOff, true /* teardown */, &release_fence);
   if (status != kErrorNone) {
     DLOGE("power-off on built-in/primary %d failed with error = %d", display_id_, status);
   }
@@ -435,7 +438,7 @@
 
   DLOGI("Restoring power mode on built-in/primary %d", display_id_);
   DisplayState mode = GetLastPowerMode();
-  status = SetDisplayState(mode, &release_fence);
+  status = SetDisplayState(mode, false /* teardown */, &release_fence);
   if (status != kErrorNone) {
     DLOGE("Setting power mode = %d on built-in/primary %d failed with error = %d", mode,
           display_id_, status);
@@ -507,6 +510,17 @@
   return error;
 }
 
+DisplayError DisplayBuiltIn::SetDisplayDppsAdROI(void *payload) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError err = kErrorNone;
+
+  err = hw_intf_->SetDisplayDppsAdROI(payload);
+  if (err != kErrorNone)
+    DLOGE("Failed to set ad roi config, err %d", err);
+
+  return err;
+}
+
 void DppsInfo::Init(DppsPropIntf *intf, const std::string &panel_name) {
   int error = 0;
 
@@ -561,7 +575,13 @@
 }
 
 DisplayError DisplayBuiltIn::HandleSecureEvent(SecureEvent secure_event) {
-  return hw_intf_->HandleSecureEvent(secure_event);
+  DisplayError err = hw_intf_->HandleSecureEvent(secure_event);
+  if (err != kErrorNone) {
+    return err;
+  }
+  comp_manager_->HandleSecureEvent(display_comp_ctx_, secure_event);
+
+  return kErrorNone;
 }
 
 DisplayError DisplayBuiltIn::SetQSyncMode(QSyncMode qsync_mode) {
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index d4295fa..267267a 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -62,7 +62,8 @@
   virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
   virtual DisplayError DisablePartialUpdateOneFrame();
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
+  virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
+                                       int *release_fence);
   virtual void SetIdleTimeoutMs(uint32_t active_ms);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
@@ -70,6 +71,7 @@
   virtual DisplayError SetPanelBrightness(int level);
   virtual DisplayError GetPanelBrightness(int *level);
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event);
+  virtual DisplayError SetDisplayDppsAdROI(void *payload);
   virtual DisplayError SetQSyncMode(QSyncMode qsync_mode);
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
 
@@ -95,7 +97,6 @@
   bool avr_prop_disabled_ = false;
   bool switch_to_cmd_ = false;
   bool handle_idle_timeout_ = false;
-  uint32_t current_refresh_rate_ = 0;
   bool reset_panel_ = false;
   bool commit_event_enabled_ = false;
   DppsInfo dpps_info_ = {};
diff --git a/sdm/libs/core/display_pluggable.cpp b/sdm/libs/core/display_pluggable.cpp
index a0b1aab..2aaa03a 100644
--- a/sdm/libs/core/display_pluggable.cpp
+++ b/sdm/libs/core/display_pluggable.cpp
@@ -65,22 +65,24 @@
     hw_intf_->GetDisplayId(&display_id_);
   }
 
-  uint32_t active_mode_index;
-  char value[64] = "0";
-  Debug::GetProperty(HDMI_S3D_MODE_PROP, value);
-  HWS3DMode mode = (HWS3DMode)atoi(value);
-  if (mode > kS3DModeNone && mode < kS3DModeMax) {
-    active_mode_index = GetBestConfig(mode);
-  } else {
-    active_mode_index = GetBestConfig(kS3DModeNone);
-  }
-
-  error = hw_intf_->SetDisplayAttributes(active_mode_index);
+  uint32_t active_mode_index = 0;
+  error = hw_intf_->GetActiveConfig(&active_mode_index);
   if (error != kErrorNone) {
     HWInterface::Destroy(hw_intf_);
     return error;
   }
 
+  uint32_t override_mode_index = active_mode_index;
+  error = GetOverrideConfig(&override_mode_index);
+  if (error == kErrorNone && override_mode_index != active_mode_index) {
+    DLOGI("Overriding display mode %d with mode %d.", active_mode_index, override_mode_index);
+    error = hw_intf_->SetDisplayAttributes(override_mode_index);
+    if (error != kErrorNone) {
+      DLOGI("Failed overriding display mode %d with mode %d. Continuing with display mode %d.",
+            active_mode_index, override_mode_index, active_mode_index);
+    }
+  }
+
   error = DisplayBase::Init();
   if (error != kErrorNone) {
     HWInterface::Destroy(hw_intf_);
@@ -182,56 +184,29 @@
   return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
 }
 
-uint32_t DisplayPluggable::GetBestConfig(HWS3DMode s3d_mode) {
-  uint32_t best_index = 0, index;
-  uint32_t num_modes = 0;
+DisplayError DisplayPluggable::GetOverrideConfig(uint32_t *mode_index) {
+  DisplayError error = kErrorNone;
 
-  hw_intf_->GetNumDisplayAttributes(&num_modes);
-
-  // Get display attribute for each mode
-  std::vector<HWDisplayAttributes> attrib(num_modes);
-  for (index = 0; index < num_modes; index++) {
-    hw_intf_->GetDisplayAttributes(index, &attrib[index]);
+  if (!mode_index) {
+    DLOGE("Invalid mode index parameter.");
+    return kErrorParameters;
   }
 
-  // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone
-  for (index = 0; index < num_modes; index++) {
-    if (attrib[index].s3d_config[s3d_mode]) {
-      break;
-    }
-  }
+  // TODO(user): Need to add support for S3D modes based on HDMI_S3D_MODE_PROP property.
 
-  index = 0;
-  best_index = UINT32(index);
-  for (size_t index = best_index + 1; index < num_modes; index++) {
-    // TODO(user): Need to add support to S3D modes
-    // From the available configs, select the best
-    // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
-    if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
-      best_index = UINT32(index);
-    } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
-      if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
-        best_index = UINT32(index);
-      } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
-        if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
-          best_index = UINT32(index);
-        }
-      }
-    }
-  }
   char val[kPropertyMax] = {};
-  // Used for changing HDMI Resolution - override the best with user set config
-  bool user_config = (Debug::GetExternalResolution(val));
-
+  // Used for changing HDMI Resolution - Override the preferred mode with user set config.
+  bool user_config = Debug::GetExternalResolution(val);
   if (user_config) {
     uint32_t config_index = 0;
     // For the config, get the corresponding index
-    DisplayError error = hw_intf_->GetConfigIndex(val, &config_index);
-    if (error == kErrorNone)
-      return config_index;
+    error = hw_intf_->GetConfigIndex(val, &config_index);
+    if (error == kErrorNone) {
+      *mode_index = config_index;
+    }
   }
 
-  return best_index;
+  return error;
 }
 
 void DisplayPluggable::GetScanSupport() {
@@ -334,6 +309,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();
@@ -367,17 +343,6 @@
   return kErrorNone;
 }
 
-DisplayError DisplayPluggable::SetDisplayState(DisplayState state, int *release_fence) {
-  lock_guard<recursive_mutex> obj(recursive_mutex_);
-  DisplayError error = kErrorNone;
-  error = DisplayBase::SetDisplayState(state, release_fence);
-  if (error != kErrorNone) {
-    return error;
-  }
-
-  return kErrorNone;
-}
-
 static PrimariesTransfer GetBlendSpaceFromAttributes(const std::string &color_gamut,
                                                      const std::string &transfer) {
   PrimariesTransfer blend_space_ = {};
@@ -427,6 +392,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 +447,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/display_pluggable.h b/sdm/libs/core/display_pluggable.h
index 902ff92..d15129c 100644
--- a/sdm/libs/core/display_pluggable.h
+++ b/sdm/libs/core/display_pluggable.h
@@ -53,7 +53,6 @@
   virtual DisplayError GetColorModeCount(uint32_t *mode_count);
   virtual DisplayError GetColorModes(uint32_t *mode_count, std::vector<std::string> *color_modes);
   virtual DisplayError GetColorModeAttr(const std::string &color_mode, AttrVal *attr);
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
   virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform) {
     return kErrorNone;
   }
@@ -72,7 +71,7 @@
   void UpdateColorModes();
 
  private:
-  uint32_t GetBestConfig(HWS3DMode s3d_mode);
+  DisplayError GetOverrideConfig(uint32_t *mode_index);
   void GetScanSupport();
   void SetS3DMode(LayerStack *layer_stack);
 
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index cff7519..21a7890 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -165,5 +165,14 @@
   return DisplayBase::Prepare(layer_stack);
 }
 
+DisplayError DisplayVirtual::GetColorModeCount(uint32_t *mode_count) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  // Color Manager isn't supported for virtual displays.
+  *mode_count = 1;
+
+  return kErrorNone;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index a651447..e3daec6 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -69,6 +69,7 @@
   virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform) {
     return kErrorNone;
   }
+  virtual DisplayError GetColorModeCount(uint32_t *mode_count);
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 23d174c..cd08e38 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -522,6 +522,8 @@
   // Update current mode with preferred mode
   for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
       if (connector_info_.modes[mode_index].mode.type & DRM_MODE_TYPE_PREFERRED) {
+        DLOGI("Updating current display mode %d to preferred mode %d.", current_mode_index_,
+              mode_index);
         current_mode_index_ = mode_index;
         break;
       }
@@ -664,8 +666,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];
@@ -819,7 +822,6 @@
   current_mode_index_ = index;
   PopulateHWPanelInfo();
   UpdateMixerAttributes();
-  update_mode_ = true;
 
   DLOGI("Display attributes[%d]: WxH: %dx%d, DPI: %fx%f, FPS: %d, LM_SPLIT: %d, V_BACK_PORCH: %d," \
         " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, CLK: %dKHZ, TOPOLOGY: %d",
@@ -861,7 +863,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDeviceDRM::PowerOff() {
+DisplayError HWDeviceDRM::PowerOff(bool teardown) {
   DTRACE_SCOPED();
   if (!drm_atomic_intf_) {
     DLOGE("DRM Atomic Interface is null!");
@@ -1760,6 +1762,7 @@
                                      ? hw_panel_info_.split_info.left_split
                                      : mixer_attributes_.width;
   DLOGI("Mixer WxH %dx%d for %s", mixer_attributes_.width, mixer_attributes_.height, device_name_);
+  update_mode_ = true;
 }
 
 void HWDeviceDRM::SetSecureConfig(const LayerBuffer &input_buffer, DRMSecureMode *fb_secure_mode,
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 6cfd51c..9bc02b6 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -80,7 +80,7 @@
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
-  virtual DisplayError PowerOff();
+  virtual DisplayError PowerOff(bool teardown);
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError Standby();
@@ -116,6 +116,7 @@
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
     return kErrorNotSupported;
   }
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) { return kErrorNotSupported; }
 
   enum {
     kHWEventVSync,
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_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index 29a4660..46e7b5a 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -109,8 +109,7 @@
     return;
   }
 
-  uint32_t count = 0;
-  for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+  for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count && validate; i++) {
     DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
 
     if (it == hw_layer_info.dest_scale_info_map.end()) {
@@ -118,10 +117,10 @@
     }
 
     HWDestScaleInfo *dest_scale_info = it->second;
-    SDEScaler *scale = &scalar_data_[count];
+    SDEScaler *scale = &scalar_data_[i];
     hw_scale_->SetScaler(dest_scale_info->scale_data, scale);
 
-    sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[count];
+    sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[i];
     dest_scalar_data->flags = 0;
     if (scale->scaler_v2.enable) {
       dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENABLE;
@@ -135,24 +134,31 @@
     if (hw_panel_info_.partial_update) {
       dest_scalar_data->flags |= SDE_DRM_DESTSCALER_PU_ENABLE;
     }
-
-    if (!std::memcmp(&dest_scalar_cache_[count].scalar_data, scale, sizeof(SDEScaler)) &&
-        dest_scalar_cache_[count].flags == dest_scalar_data->flags) {
-      continue;
-    }
-
     dest_scalar_data->index = i;
     dest_scalar_data->lm_width = dest_scale_info->mixer_width;
     dest_scalar_data->lm_height = dest_scale_info->mixer_height;
     dest_scalar_data->scaler_cfg = reinterpret_cast<uint64_t>(&scale->scaler_v2);
-    if (!validate) {
-      dest_scalar_cache_[count].flags = dest_scalar_data->flags;
-      dest_scalar_cache_[count].scalar_data = *scale;
+
+    if (std::memcmp(&dest_scalar_cache_[i].scalar_data, scale, sizeof(SDEScaler)) ||
+        dest_scalar_cache_[i].flags != dest_scalar_data->flags) {
+      needs_ds_update_ = true;
     }
-    count++;
   }
-  if (count) {
-    sde_dest_scalar_data_.num_dest_scaler = count;
+
+  if (needs_ds_update_) {
+    if (!validate) {
+      // Cache the destination scalar data during commit
+      for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+        DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
+        if (it == hw_layer_info.dest_scale_info_map.end()) {
+          continue;
+        }
+        dest_scalar_cache_[i].flags = sde_dest_scalar_data_.ds_cfg[i].flags;
+        dest_scalar_cache_[i].scalar_data = scalar_data_[i];
+      }
+      needs_ds_update_ = false;
+    }
+    sde_dest_scalar_data_.num_dest_scaler = UINT32(hw_layer_info.dest_scale_info_map.size());
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DEST_SCALER_CONFIG, token_.crtc_id,
                               reinterpret_cast<uint64_t>(&sde_dest_scalar_data_));
   }
@@ -181,6 +187,27 @@
   object_type = feature_payload->object_type;
   feature_id = feature_payload->feature_id;
   value = feature_payload->value;
+
+  if (feature_id == sde_drm::kFeatureAd4Roi) {
+    if (feature_payload->value) {
+      DisplayDppsAd4RoiCfg *params = reinterpret_cast<DisplayDppsAd4RoiCfg *>
+                                                      (feature_payload->value);
+      if (!params) {
+        DLOGE("invalid playload value %d", feature_payload->value);
+        return kErrorNotSupported;
+      }
+
+      ad4_roi_cfg_.h_x = params->h_start;
+      ad4_roi_cfg_.h_y = params->h_end;
+      ad4_roi_cfg_.v_x = params->v_start;
+      ad4_roi_cfg_.v_y = params->v_end;
+      ad4_roi_cfg_.factor_in = params->factor_in;
+      ad4_roi_cfg_.factor_out = params->factor_out;
+
+      value = (uint64_t)&ad4_roi_cfg_;
+    }
+  }
+
   if (object_type == DRM_MODE_OBJECT_CRTC) {
     obj_id = token_.crtc_id;
   } else if (object_type == DRM_MODE_OBJECT_CONNECTOR) {
@@ -225,6 +252,7 @@
         }
       }
       secure_display_active_ = false;
+      synchronous_commit_ = true;
     }
     break;
 
@@ -335,6 +363,7 @@
   if (!enabled) {
     drm_mgr_intf_->UnregisterDisplay(cwb_config_.token);
     cwb_config_.enabled = false;
+    registry_.Clear();
   }
 }
 
@@ -372,4 +401,26 @@
   return kErrorNone;
 }
 
+DisplayError HWPeripheralDRM::SetDisplayDppsAdROI(void *payload) {
+  DisplayError err = kErrorNone;
+  struct sde_drm::DppsFeaturePayload feature_payload = {};
+
+  if (!payload) {
+    DLOGE("Invalid payload parameter");
+    return kErrorParameters;
+  }
+
+  feature_payload.object_type = DRM_MODE_OBJECT_CRTC;
+  feature_payload.feature_id = sde_drm::kFeatureAd4Roi;
+  feature_payload.value = (uint64_t)(payload);
+
+  err = SetDppsFeature(&feature_payload, sizeof(feature_payload));
+  if (err != kErrorNone) {
+    DLOGE("Faid to SetDppsFeature feature_id = %d, err = %d",
+           sde_drm::kFeatureAd4Roi, err);
+  }
+
+  return err;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index e693163..96889de 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -56,6 +56,7 @@
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event);
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
+  virtual DisplayError SetDisplayDppsAdROI(void *payload);
 
  private:
   void SetDestScalarData(HWLayersInfo hw_layer_info, bool validate);
@@ -79,6 +80,8 @@
   CWBConfig cwb_config_ = {};
   sde_drm::DRMIdlePCState idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
   std::vector<DestScalarCache> dest_scalar_cache_ = {};
+  drm_msm_ad4_roi_cfg ad4_roi_cfg_ = {};
+  bool needs_ds_update_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index cd1f4ce..6272fa7 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) {
@@ -154,9 +163,17 @@
   return kErrorNone;
 }
 
-DisplayError HWTVDRM::PowerOff() {
+DisplayError HWTVDRM::PowerOff(bool teardown) {
   DTRACE_SCOPED();
+  if (!drm_atomic_intf_) {
+    DLOGE("DRM Atomic Interface is null!");
+    return kErrorUndefined;
+  }
 
+  if (teardown) {
+    // LP connecter prop N/A for External
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
+  }
   int ret = drm_atomic_intf_->Commit(true /* synchronous */, false /* retain_planes*/);
   if (ret) {
     DLOGE("%s failed with error %d", __FUNCTION__, ret);
@@ -185,10 +202,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..96d0746 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -42,7 +42,7 @@
  protected:
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
-  virtual DisplayError PowerOff();
+  virtual DisplayError PowerOff(bool teardown);
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError Standby();
@@ -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..9e3f2b9 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -182,7 +182,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDevice::PowerOff() {
+DisplayError HWDevice::PowerOff(bool teardown) {
   return kErrorNone;
 }
 
@@ -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/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index 7504721..6adb93b 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -72,7 +72,7 @@
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
-  virtual DisplayError PowerOff();
+  virtual DisplayError PowerOff(bool teardown);
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError Standby();
@@ -106,6 +106,7 @@
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
     return kErrorNotSupported;
   }
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) { return kErrorNotSupported; }
 
   enum {
     kHWEventVSync,
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index efbd4fb..b8b196d 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -126,6 +126,7 @@
 
   return mdp_pixel_encoding;
 }
+
 static int32_t GetBitsPerComponent(const LayerBuffer &layer_buffer) {
   bool is_yuv = layer_buffer.flags.video;
   bool is_10_bit = Is10BitFormat(layer_buffer.format);
@@ -227,6 +228,12 @@
 
   GetPanelS3DMode();
 
+  error = SetDisplayAttributes(active_config_index_);
+  if (error != kErrorNone) {
+    Deinit();
+    return error;
+  }
+
   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
                              (kS3DModeNone, HDMI_S3D_NONE));
   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index b58c5b5..d130d87 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -333,7 +333,7 @@
   return HWDevice::GetConfigIndex(mode, index);
 }
 
-DisplayError HWPrimary::PowerOff() {
+DisplayError HWPrimary::PowerOff(bool teardown) {
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
     IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
     return kErrorHardware;
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index e2515d1..6d611a5 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -45,7 +45,7 @@
                                             HWDisplayAttributes *display_attributes);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
-  virtual DisplayError PowerOff();
+  virtual DisplayError PowerOff(bool teardown);
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError Validate(HWLayers *hw_layers);
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 06d166e..7980fdd 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -88,7 +88,7 @@
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes) = 0;
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index) = 0;
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence) = 0;
-  virtual DisplayError PowerOff() = 0;
+  virtual DisplayError PowerOff(bool teardown) = 0;
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence) = 0;
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence) = 0;
   virtual DisplayError Standby() = 0;
@@ -119,6 +119,7 @@
   virtual DisplayError GetDppsFeatureInfo(void *payload, size_t size) = 0;
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event) = 0;
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) = 0;
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 1281545..5098b01 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -150,6 +150,11 @@
   Layer layer = *gpu_target_layer;
   hw_layers_info_->index.push_back(hw_layers_info_->gpu_target_index);
   hw_layers_info_->roi_index.push_back(0);
+  layer.transform.flip_horizontal ^= hw_panel_info_.panel_orientation.flip_horizontal;
+  layer.transform.flip_vertical ^= hw_panel_info_.panel_orientation.flip_vertical;
+  // Flip rect to match transform.
+  TransformHV(src_domain, layer.dst_rect, layer.transform, &layer.dst_rect);
+  // Scale to mixer resolution.
   MapRect(src_domain, dst_domain, layer.dst_rect, &layer.dst_rect);
   hw_layers_info_->hw_layers.push_back(layer);
 
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/display_null.cpp b/sdm/libs/hwc2/display_null.cpp
index 99cd017..9076779 100644
--- a/sdm/libs/hwc2/display_null.cpp
+++ b/sdm/libs/hwc2/display_null.cpp
@@ -146,7 +146,8 @@
   return kErrorNone;
 }
 
-DisplayError DisplayNullExternal::SetDisplayState(DisplayState state, int *release_fence) {
+DisplayError DisplayNullExternal::SetDisplayState(DisplayState state, bool teardown,
+                                                  int *release_fence) {
   state_ = state;
   return kErrorNone;
 }
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index 82b7ed4..65096e1 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -59,7 +59,7 @@
 
   MAKE_NO_OP(Commit(LayerStack *))
   MAKE_NO_OP(GetDisplayState(DisplayState *))
-  MAKE_NO_OP(SetDisplayState(DisplayState, int*))
+  MAKE_NO_OP(SetDisplayState(DisplayState, bool, int*))
   MAKE_NO_OP(SetFrameBufferConfig(const DisplayConfigVariableInfo &))
   MAKE_NO_OP(Flush())
   MAKE_NO_OP(GetVSyncState(bool *))
@@ -97,6 +97,7 @@
   MAKE_NO_OP(HandleSecureEvent(SecureEvent))
   MAKE_NO_OP(SetQSyncMode(QSyncMode))
   MAKE_NO_OP(ControlIdlePowerCollapse(bool, bool))
+  MAKE_NO_OP(SetDisplayDppsAdROI(void *))
 
   DisplayConfigVariableInfo default_variable_config_ = {};
   DisplayConfigFixedInfo default_fixed_config_ = {};
@@ -106,7 +107,8 @@
  public:
   virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError GetDisplayState(DisplayState *state);
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
+  virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
+                                       int *release_fence);
   virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
   virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
   void SetActive(bool active) { active_ = active; }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 40daa5c..7c14b70 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,16 @@
     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;
   }
@@ -140,6 +149,45 @@
   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;
+  }
+
+  current_color_mode_ = mode;
+  current_render_intent_ = intent;
+  apply_mode_ = true;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::ApplyCurrentColorModeWithRenderIntent() {
+  if (!apply_mode_) {
+    return HWC2::Error::None;
+  }
+
+  apply_mode_ = false;
+  auto mode_string = color_mode_map_[current_color_mode_][current_render_intent_];
+  DisplayError error = display_intf_->SetColorMode(mode_string);
+  if (error != kErrorNone) {
+    DLOGE("Failed for mode = %d intent = %d name = %s", current_color_mode_,
+          current_render_intent_, mode_string.c_str());
+    return HWC2::Error::Unsupported;
+  }
+
+  // The mode does not have the PCC configured, restore the transform
+  RestoreColorTransform();
+  DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d name = %s",
+           current_color_mode_, current_render_intent_, mode_string.c_str());
+
+  return HWC2::Error::None;
+}
+
 HWC2::Error HWCColorMode::SetColorModeById(int32_t color_mode_id) {
   DLOGI("Applying mode: %d", color_mode_id);
   DisplayError error = display_intf_->SetColorModeById(color_mode_id);
@@ -440,7 +488,7 @@
 HWCLayer *HWCDisplay::GetHWCLayer(hwc2_layer_t layer_id) {
   const auto map_layer = layer_map_.find(layer_id);
   if (map_layer == layer_map_.end()) {
-    DLOGE("[%" PRIu64 "] GetLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
+    DLOGW("[%" PRIu64 "] GetLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
     return nullptr;
   } else {
     return map_layer->second;
@@ -450,7 +498,7 @@
 HWC2::Error HWCDisplay::DestroyLayer(hwc2_layer_t layer_id) {
   const auto map_layer = layer_map_.find(layer_id);
   if (map_layer == layer_map_.end()) {
-    DLOGE("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
+    DLOGW("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
     return HWC2::Error::BadLayer;
   }
   const auto layer = map_layer->second;
@@ -506,6 +554,7 @@
       }
     }
 
+    bool is_secure = false;
     const private_handle_t *handle =
         reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
     if (handle) {
@@ -513,17 +562,16 @@
         layer_stack_.flags.video_present = true;
       }
       // TZ Protected Buffer - L1
-      if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
-        layer_stack_.flags.secure_present = true;
-      }
       // Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
-      if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) {
+      if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER ||
+          handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
         layer_stack_.flags.secure_present = true;
+        is_secure = true;
       }
     }
 
-    if (layer->flags.skip) {
-      layer_stack_.flags.skip_present = true;
+    if (layer->input_buffer.flags.secure_display) {
+      is_secure = true;
     }
 
     if (hwc_layer->IsSingleBuffered() &&
@@ -553,6 +601,15 @@
       layer_stack_.flags.hdr_present = true;
     }
 
+    if (hwc_layer->IsNonIntegralSourceCrop() && !is_secure && !hdr_layer &&
+        !layer->flags.single_buffer && !layer->flags.solid_fill) {
+      layer->flags.skip = true;
+    }
+
+    if (layer->flags.skip) {
+      layer_stack_.flags.skip_present = true;
+    }
+
     // TODO(user): Move to a getter if this is needed at other places
     hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
                                        INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
@@ -576,11 +633,10 @@
       layer->src_rect.bottom = layer_buffer->height;
     }
 
-    if (layer->frame_rate > metadata_refresh_rate_) {
+    if (hwc_layer->HasMetaDataRefreshRate() && layer->frame_rate > metadata_refresh_rate_) {
       metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
-    } else {
-      layer->frame_rate = current_refresh_rate_;
     }
+
     display_rect_ = Union(display_rect_, layer->dst_rect);
     geometry_changes_ |= hwc_layer->GetGeometryChanges();
 
@@ -598,6 +654,7 @@
   Layer *sdm_client_target = client_target_->GetSDMLayer();
   sdm_client_target->flags.updating = IsLayerUpdating(client_target_);
   layer_stack_.layers.push_back(sdm_client_target);
+
   // 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
@@ -682,7 +739,7 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
+HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode, bool teardown) {
   DLOGV("display = %d, mode = %s", id_, to_string(mode).c_str());
   DisplayState state = kStateOff;
   bool flush_on_error = flush_on_error_;
@@ -725,7 +782,7 @@
   int release_fence = -1;
 
   ATRACE_INT("SetPowerMode ", state);
-  DisplayError error = display_intf_->SetDisplayState(state, &release_fence);
+  DisplayError error = display_intf_->SetDisplayState(state, teardown, &release_fence);
   validated_ = false;
 
   if (error == kErrorNone) {
@@ -886,7 +943,7 @@
   } else {
     *out_size = std::min((UINT32(name.size()) + 1), *out_size);
     if (*out_size > 0) {
-      std::strncpy(out_name, name.c_str(), *out_size);
+      strlcpy(out_name, name.c_str(), *out_size);
       out_name[*out_size - 1] = '\0';
     } else {
       DLOGW("Invalid size requested");
@@ -1031,7 +1088,17 @@
 
 DisplayError HWCDisplay::HandleEvent(DisplayEvent event) {
   switch (event) {
-    case kIdleTimeout:
+    case kIdleTimeout: {
+      SCOPE_LOCK(HWCSession::locker_[type_]);
+      if (pending_commit_) {
+        // If idle timeout event comes in between prepare
+        // and commit, drop it since device is not really
+        // idle.
+        return kErrorNotSupported;
+      }
+      validated_ = false;
+      break;
+    }
     case kThermalEvent:
     case kIdlePowerCollapse:
     case kPanelDeadEvent: {
@@ -1069,6 +1136,7 @@
     return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
   }
 
+  UpdateRefreshRate();
   DisplayError error = display_intf_->Prepare(&layer_stack_);
   if (error != kErrorNone) {
     if (error == kErrorShutDown) {
@@ -1247,11 +1315,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;
@@ -1259,6 +1325,10 @@
 
 
 HWC2::Error HWCDisplay::CommitLayerStack(void) {
+  if (flush_) {
+    return HWC2::Error::None;
+  }
+
   if (!validated_) {
     DLOGV_IF(kTagClient, "Display %d is not validated", id_);
     return HWC2::Error::NotValidated;
@@ -1270,37 +1340,35 @@
 
   DumpInputBuffers();
 
-  if (!flush_) {
-    DisplayError error = kErrorUndefined;
-    int status = 0;
-    if (tone_mapper_) {
-      if (NeedsToneMap(layer_stack_)) {
-        status = tone_mapper_->HandleToneMap(&layer_stack_);
-        if (status != 0) {
-          DLOGE("Error handling HDR in ToneMapper");
-        }
-      } else {
-        tone_mapper_->Terminate();
+  DisplayError error = kErrorUndefined;
+  int status = 0;
+  if (tone_mapper_) {
+    if (NeedsToneMap(layer_stack_)) {
+      status = tone_mapper_->HandleToneMap(&layer_stack_);
+      if (status != 0) {
+        DLOGE("Error handling HDR in ToneMapper");
       }
-    }
-    error = display_intf_->Commit(&layer_stack_);
-
-    if (error == kErrorNone) {
-      // A commit is successfully submitted, start flushing on failure now onwards.
-      flush_on_error_ = true;
     } else {
-      if (error == kErrorShutDown) {
-        shutdown_pending_ = true;
-        return HWC2::Error::Unsupported;
-      } else if (error == kErrorNotValidated) {
-        validated_ = false;
-        return HWC2::Error::NotValidated;
-      } else if (error != kErrorPermission) {
-        DLOGE("Commit failed. Error = %d", error);
-        // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
-        // so that previous buffer and fences are released, and override the error.
-        flush_ = true;
-      }
+      tone_mapper_->Terminate();
+    }
+  }
+  error = display_intf_->Commit(&layer_stack_);
+
+  if (error == kErrorNone) {
+    // A commit is successfully submitted, start flushing on failure now onwards.
+    flush_on_error_ = true;
+  } else {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return HWC2::Error::Unsupported;
+    } else if (error == kErrorNotValidated) {
+      validated_ = false;
+      return HWC2::Error::NotValidated;
+    } else if (error != kErrorPermission) {
+      DLOGE("Commit failed. Error = %d", error);
+      // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+      // so that previous buffer and fences are released, and override the error.
+      flush_ = true;
     }
   }
 
@@ -1631,12 +1699,12 @@
     case kDisplayStatusResume:
       display_paused_ = false;
     case kDisplayStatusOnline:
-      status = INT32(SetPowerMode(HWC2::PowerMode::On));
+      status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
       break;
     case kDisplayStatusPause:
       display_paused_ = true;
     case kDisplayStatusOffline:
-      status = INT32(SetPowerMode(HWC2::PowerMode::Off));
+      status = INT32(SetPowerMode(HWC2::PowerMode::Off, false /* teardown */));
       break;
     default:
       DLOGW("Invalid display status %d", display_status);
@@ -1656,6 +1724,11 @@
     return HWC2::Error::None;
   }
 
+  if (!layer_stack_.flags.cursor_present) {
+    DLOGW("Cursor layer not present");
+    return HWC2::Error::BadLayer;
+  }
+
   HWCLayer *hwc_layer = GetHWCLayer(layer);
   if (hwc_layer == nullptr) {
     return HWC2::Error::BadLayer;
@@ -1847,7 +1920,7 @@
 
   if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
     if (secure_sessions[kSecureDisplay]) {
-      HWC2::Error error = SetPowerMode(HWC2::PowerMode::Off);
+      HWC2::Error error = SetPowerMode(HWC2::PowerMode::Off, true /* teardown */);
       if (error != HWC2::Error::None) {
         DLOGE("SetPowerMode failed. Error = %d", error);
       }
@@ -2026,6 +2099,7 @@
   }
 
   for (auto hwc_layer : layer_set_) {
+    Layer *layer = hwc_layer->GetSDMLayer();
     if (hwc_layer->NeedsValidation()) {
       DLOGV_IF(kTagClient, "hwc_layer[%d] needs validation. Returning false.",
                hwc_layer->GetId());
@@ -2033,9 +2107,9 @@
     }
 
     // Do not allow Skip Validate, if any layer needs GPU Composition.
-    if (hwc_layer->GetDeviceSelectedCompositionType() == HWC2::Composition::Client) {
-      DLOGV_IF(kTagClient, "hwc_layer[%d] is GPU composed. Returning false.",
-               hwc_layer->GetId());
+    if (layer->composition == kCompositionGPU || layer->composition == kCompositionNone) {
+      DLOGV_IF(kTagClient, "hwc_layer[%d] is %s. Returning false.", hwc_layer->GetId(),
+               (layer->composition == kCompositionGPU) ? "GPU composed": "Dropped");
       return false;
     }
   }
@@ -2090,4 +2164,14 @@
   return skip_prepare;
 }
 
+void HWCDisplay::UpdateRefreshRate() {
+  for (auto hwc_layer : layer_set_) {
+    if (hwc_layer->HasMetaDataRefreshRate()) {
+      continue;
+    }
+    auto layer = hwc_layer->GetSDMLayer();
+    layer->frame_rate = current_refresh_rate_;
+  }
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 6072397..f14c79f 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -81,6 +81,8 @@
   HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
   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;
@@ -93,9 +95,10 @@
     }
   }
   HWC2::Error ApplyDefaultColorMode();
+  HWC2::Error ValidateColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
 
   DisplayInterface *display_intf_ = NULL;
-
+  bool apply_mode_ = false;
   ColorMode current_color_mode_ = ColorMode::NATIVE;
   RenderIntent current_render_intent_ = RenderIntent::COLORIMETRIC;
   typedef std::map<RenderIntent, std::string> RenderIntentMap;
@@ -172,6 +175,12 @@
     return HWC2::Error::Unsupported;
   }
 
+  virtual HWC2::Error SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end,
+                                          uint32_t v_start, uint32_t v_end,
+                                          uint32_t factor_in, uint32_t factor_out) {
+    return HWC2::Error::Unsupported;
+  }
+
   // Display Configurations
   virtual int SetActiveDisplayConfig(uint32_t config);
   virtual int GetActiveDisplayConfig(uint32_t *config);
@@ -248,7 +257,7 @@
   virtual HWC2::Error GetDisplayType(int32_t *out_type);
   virtual HWC2::Error SetCursorPosition(hwc2_layer_t layer, int x, int y);
   virtual HWC2::Error SetVsyncEnabled(HWC2::Vsync enabled);
-  virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode);
+  virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode, bool teardown);
   virtual HWC2::Error CreateLayer(hwc2_layer_t *out_layer_id);
   virtual HWC2::Error DestroyLayer(hwc2_layer_t layer_id);
   virtual HWC2::Error SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z);
@@ -358,11 +367,12 @@
   int disable_hdr_handling_ = 0;  // disables HDR handling.
   uint32_t display_config_ = 0;
   bool config_pending_ = false;
+  bool pending_commit_ = false;
 
  private:
   void DumpInputBuffers(void);
   bool CanSkipSdmPrepare(uint32_t *num_types, uint32_t *num_requests);
-
+  void UpdateRefreshRate();
   qService::QService *qservice_ = NULL;
   DisplayClass display_class_;
   uint32_t geometry_changes_ = GeometryChanges::kNone;
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index cc02ad6..106b147 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -125,14 +125,8 @@
 }
 
 void HWCDisplayBuiltIn::ProcessBootAnimCompleted() {
-  uint32_t numBootUpLayers = 0;
-  // TODO(user): Remove this hack
+  bool bootanim_exit = false;
 
-  numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
-
-  if (numBootUpLayers == 0) {
-    numBootUpLayers = 2;
-  }
   /* All other checks namely "init.svc.bootanim" or
   * HWC_GEOMETRY_CHANGED fail in correctly identifying the
   * exact bootup transition to homescreen
@@ -152,9 +146,14 @@
     }
   }
 
+  property_get("service.bootanim.exit", property, "0");
+  if (!strcmp(property, "1")) {
+    bootanim_exit = true;
+  }
+
   if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
-      (layer_set_.size() > numBootUpLayers)) {
-    DLOGI("Applying default mode");
+      bootanim_exit) {
+    DLOGI("Applying default mode for display %d", sdm_id_);
     boot_animation_completed_ = true;
     // Applying default mode after bootanimation is finished And
     // If Data is Encrypted, it is ready for access.
@@ -195,6 +194,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) {
@@ -230,6 +235,7 @@
   }
 
   status = PrepareLayerStack(out_num_types, out_num_requests);
+  pending_commit_ = true;
   return status;
 }
 
@@ -251,6 +257,7 @@
   }
 
   CloseFd(&output_buffer_.acquire_fence_fd);
+  pending_commit_ = false;
   return status;
 }
 
@@ -279,7 +286,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;
@@ -352,6 +359,7 @@
   output_buffer_.planes[0].stride = UINT32(handle->width);
   output_buffer_.acquire_fence_fd = dup(acquire_fence);
   output_buffer_.release_fence_fd = -1;
+  output_buffer_.handle_id = handle->id;
 
   post_processed_output_ = post_processed_output;
   readback_buffer_queued_ = true;
@@ -380,6 +388,46 @@
   return status;
 }
 
+HWC2::Error HWCDisplayBuiltIn::SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end,
+                                                   uint32_t v_start, uint32_t v_end,
+                                                   uint32_t factor_in, uint32_t factor_out) {
+  DisplayError error = kErrorNone;
+  DisplayDppsAd4RoiCfg dpps_ad4_roi_cfg = {};
+  uint32_t panel_width = 0, panel_height = 0;
+  constexpr uint16_t kMaxFactorVal = 0xffff;
+
+  if (h_start >= h_end || v_start >= v_end || factor_in > kMaxFactorVal ||
+      factor_out > kMaxFactorVal) {
+    DLOGE("Invalid roi region = [%u, %u, %u, %u, %u, %u]",
+           h_start, h_end, v_start, v_end, factor_in, factor_out);
+    return HWC2::Error::BadParameter;
+  }
+
+  GetPanelResolution(&panel_width, &panel_height);
+
+  if (h_start >= panel_width || h_end > panel_width ||
+      v_start >= panel_height || v_end > panel_height) {
+    DLOGE("Invalid roi region = [%u, %u, %u, %u], panel resolution = [%u, %u]",
+           h_start, h_end, v_start, v_end, panel_width, panel_height);
+    return HWC2::Error::BadParameter;
+  }
+
+  dpps_ad4_roi_cfg.h_start = h_start;
+  dpps_ad4_roi_cfg.h_end = h_end;
+  dpps_ad4_roi_cfg.v_start = v_start;
+  dpps_ad4_roi_cfg.v_end = v_end;
+  dpps_ad4_roi_cfg.factor_in = factor_in;
+  dpps_ad4_roi_cfg.factor_out = factor_out;
+
+  error = display_intf_->SetDisplayDppsAdROI(&dpps_ad4_roi_cfg);
+  if (error)
+    return HWC2::Error::BadConfig;
+
+  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+  return HWC2::Error::None;
+}
+
 int HWCDisplayBuiltIn::Perform(uint32_t operation, ...) {
   va_list args;
   va_start(args, operation);
@@ -575,13 +623,11 @@
   dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
   DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
 
-  if (!count || !dump_output_to_file_) {
+  if (!count || !dump_output_to_file_ || (output_buffer_info_.alloc_buffer_info.fd >= 0)) {
     return HWC2::Error::None;
   }
 
   // Allocate and map output buffer
-  output_buffer_info_ = {};
-
   if (post_processed) {
     // To dump post-processed (DSPP) output, use Panel resolution.
     GetPanelResolution(&output_buffer_info_.buffer_config.width,
diff --git a/sdm/libs/hwc2/hwc_display_builtin.h b/sdm/libs/hwc2/hwc_display_builtin.h
index 1f01723..6616255 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -80,6 +80,8 @@
   virtual HWC2::Error GetReadbackBufferFence(int32_t *release_fence);
   virtual HWC2::Error SetQSyncMode(QSyncMode qsync_mode);
   virtual HWC2::Error ControlIdlePowerCollapse(bool enable, bool synchronous);
+  virtual HWC2::Error SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end, uint32_t v_start,
+                                          uint32_t v_end, uint32_t factor_in, uint32_t factor_out);
 
  private:
   HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
diff --git a/sdm/libs/hwc2/hwc_display_pluggable.cpp b/sdm/libs/hwc2/hwc_display_pluggable.cpp
index 7d22642..9ac22be 100644
--- a/sdm/libs/hwc2/hwc_display_pluggable.cpp
+++ b/sdm/libs/hwc2/hwc_display_pluggable.cpp
@@ -137,6 +137,7 @@
 
   if (layer_set_.empty()) {
     flush_ = true;
+    validated_ = true;
     return status;
   }
 
@@ -235,7 +236,7 @@
       }
       int release_fence = -1;
       display_null_.GetDisplayState(&state);
-      display_intf_->SetDisplayState(state, &release_fence);
+      display_intf_->SetDisplayState(state, false /* teardown */, &release_fence);
       if (release_fence >= 0) {
         ::close(release_fence);
       }
@@ -254,7 +255,7 @@
       // Preserve required attributes of HDMI display that surfaceflinger sees.
       // Restore HDMI attributes when display is reconnected.
       display_intf_->GetDisplayState(&state);
-      display_null_.SetDisplayState(state, &release_fence);
+      display_null_.SetDisplayState(state, false /* teardown */, &release_fence);
       if (release_fence >= 0) {
         ::close(release_fence);
       }
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 8454536..a05173f 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -63,7 +63,7 @@
     return status;
   }
 
-  status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
+  status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
   if (status) {
     DLOGW("Failed to set power mode on virtual display");
     Destroy(hwc_display_virtual);
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 13c3f8d..9ba14a9 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -455,6 +455,13 @@
 HWC2::Error HWCLayer::SetLayerSourceCrop(hwc_frect_t crop) {
   LayerRect src_rect = {};
   SetRect(crop, &src_rect);
+  non_integral_source_crop_ = ((crop.left != roundf(crop.left)) ||
+                              (crop.top != roundf(crop.top)) ||
+                              (crop.right != roundf(crop.right)) ||
+                              (crop.bottom != roundf(crop.bottom)));
+  if (non_integral_source_crop_) {
+    DLOGV_IF(kTagClient, "Crop: LTRB %f %f %f %f", crop.left, crop.top, crop.right, crop.bottom);
+  }
   if (layer_->src_rect != src_rect) {
     geometry_changes_ |= kSourceCrop;
     layer_->src_rect = src_rect;
@@ -770,6 +777,7 @@
   // in layer_buffer or copy directly to Vector
   if (cr_stats->bDataValid) {
     switch (cr_stats->version) {
+      case UBWC_3_0:
       case UBWC_2_0:
         cr_vec->push_back(std::make_pair(32, cr_stats->ubwc_stats.nCRStatsTile32));
         cr_vec->push_back(std::make_pair(64, cr_stats->ubwc_stats.nCRStatsTile64));
@@ -801,13 +809,13 @@
   uint32_t frame_rate = layer->frame_rate;
   if (getMetaData(handle, GET_REFRESH_RATE, &fps) == 0) {
     frame_rate = (fps != 0) ? RoundToStandardFPS(fps) : layer->frame_rate;
+    has_metadata_refresh_rate_ = true;
   }
 
   int32_t interlaced = 0;
-  bool interlace = layer_buffer->flags.interlace;
-  if (getMetaData(handle, GET_PP_PARAM_INTERLACED, &interlaced) == 0) {
-    interlace = interlaced ? true : false;
-  }
+  getMetaData(handle, GET_PP_PARAM_INTERLACED, &interlaced);
+  bool interlace = interlaced ? true : false;
+
   if (interlace != layer_buffer->flags.interlace) {
     DLOGI("Layer buffer interlaced metadata has changed. old=%d, new=%d",
           layer_buffer->flags.interlace, interlace);
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index 46e83cb..b5d5eaa 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -109,6 +109,8 @@
   static LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
   bool IsSurfaceUpdated() { return surface_updated_; }
   void SetPartialUpdate(bool enabled) { partial_update_enabled_ = enabled; }
+  bool IsNonIntegralSourceCrop() { return non_integral_source_crop_; }
+  bool HasMetaDataRefreshRate() { return has_metadata_refresh_rate_; }
 
  private:
   Layer *layer_ = nullptr;
@@ -127,6 +129,8 @@
   bool dataspace_supported_ = false;
   bool partial_update_enabled_ = false;
   bool surface_updated_ = true;
+  bool non_integral_source_crop_ = false;
+  bool has_metadata_refresh_rate_ = false;
 
   // Composition requested by client(SF)
   HWC2::Composition client_requested_ = HWC2::Composition::Device;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 77f0e5e..ed72532 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) {
@@ -603,23 +606,6 @@
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
 }
 
-static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
-  if (!device || !out_support) {
-    return HWC2_ERROR_BAD_PARAMETER;
-  }
-
-  if (display >= HWCSession::kNumDisplays) {
-    return HWC2_ERROR_BAD_DISPLAY;
-  }
-
-  if (display == HWC_DISPLAY_PRIMARY) {
-    *out_support = 1;
-  } else {
-    *out_support = 0;
-  }
-
-  return HWC2_ERROR_NONE;
-}
 
 static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display,
                                   uint32_t* out_num_types, int32_t* out_types,
@@ -683,7 +669,7 @@
   if (!hwc_session->primary_ready_ && (display == HWC_DISPLAY_PRIMARY)) {
     hwc_session->primary_ready_ = true;
     hwc_session->CreateBuiltInDisplays();
-    hwc_session->CreatePluggableDisplays(false);
+    hwc_session->HandlePluggableDisplays(false);
   }
 
   return INT32(status);
@@ -888,12 +874,13 @@
 
   //  all displays support on/off. Check for doze modes
   int support = 0;
-  GetDozeSupport(device, display, &support);
+  hwc_session->GetDozeSupport(device, display, &support);
   if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) {
     return HWC2_ERROR_UNSUPPORTED;
   }
 
-  auto error = CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
+  auto error = CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode,
+                                   false /* teardown */);
   if (error != HWC2_ERROR_NONE) {
     return error;
   }
@@ -922,6 +909,25 @@
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
 }
 
+int32_t HWCSession::GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
+                                   int32_t *out_support) {
+  if (!device || !out_support) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
+  if (display >= HWCSession::kNumDisplays) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  *out_support = 0;
+  if (display == HWC_DISPLAY_PRIMARY || display == hwc_session->GetNextBuiltinIndex()) {
+    *out_support = 1;
+  }
+
+  return HWC2_ERROR_NONE;
+}
+
 int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
                                     uint32_t *out_num_types, uint32_t *out_num_requests) {
   //  out_num_types and out_num_requests will be non-NULL
@@ -1142,6 +1148,16 @@
   return HWC2::Error::None;
 }
 
+hwc2_display_t HWCSession::GetNextBuiltinIndex() {
+  for (auto &map_info : map_info_builtin_) {
+    if (hwc_display_[map_info.client_id]) {
+        return map_info.client_id;
+    }
+  }
+
+  return 0;
+}
+
 // Qclient methods
 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                              android::Parcel *output_parcel) {
@@ -1158,7 +1174,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:
@@ -1412,6 +1432,14 @@
       status = SetIdlePC(input_parcel);
       break;
 
+    case qService::IQService::SET_DPPS_AD4_ROI_CONFIG:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = SetAd4RoiConfig(input_parcel);
+      break;
+
     default:
       DLOGW("QService command = %d is not supported.", command);
       break;
@@ -1611,6 +1639,29 @@
   return 0;
 }
 
+android::status_t HWCSession::SetAd4RoiConfig(const android::Parcel *input_parcel) {
+  auto display_id = static_cast<uint32_t>(input_parcel->readInt32());
+  auto h_s = static_cast<uint32_t>(input_parcel->readInt32());
+  auto h_e = static_cast<uint32_t>(input_parcel->readInt32());
+  auto v_s = static_cast<uint32_t>(input_parcel->readInt32());
+  auto v_e = static_cast<uint32_t>(input_parcel->readInt32());
+  auto f_in = static_cast<uint32_t>(input_parcel->readInt32());
+  auto f_out = static_cast<uint32_t>(input_parcel->readInt32());
+
+#ifdef DISPLAY_CONFIG_1_5
+  return static_cast<android::status_t>(SetDisplayDppsAdROI(display_id, h_s, h_e, v_s,
+                                                            v_e, f_in, f_out));
+#else
+  auto err = CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+                                 &HWCDisplay::SetDisplayDppsAdROI, h_s, h_e, v_s, v_e,
+                                 f_in, f_out);
+  if (err != HWC2_ERROR_NONE)
+    return -EINVAL;
+
+  return 0;
+#endif
+}
+
 android::status_t HWCSession::SetColorModeWithRenderIntentOverride(
     const android::Parcel *input_parcel) {
   auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
@@ -1626,7 +1677,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 +1695,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);
@@ -1695,6 +1760,41 @@
   }
 }
 
+android::status_t HWCSession::QdcmCMDDispatch(uint32_t display_id,
+                                              const PPDisplayAPIPayload &req_payload,
+                                              PPDisplayAPIPayload *resp_payload,
+                                              PPPendingParams *pending_action) {
+  int ret = 0;
+  bool is_physical_display = false;
+
+  if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
+      DLOGW("Invalid display id or display = %d is not connected.", display_id);
+      return -ENODEV;
+  }
+
+  if (display_id == map_info_primary_.client_id) {
+    is_physical_display = true;
+  } else {
+    for (auto &map_info : map_info_builtin_) {
+      if (map_info.client_id == display_id) {
+        is_physical_display = true;
+        break;
+     }
+    }
+  }
+
+  if (!is_physical_display) {
+    DLOGW("Skipping QDCM command dispatch on display = %d", display_id);
+    return ret;
+  }
+
+  ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload,
+                                                       resp_payload,
+                                                       pending_action);
+
+  return ret;
+}
+
 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
                                              android::Parcel *output_parcel) {
   int ret = 0;
@@ -1702,6 +1802,7 @@
   uint32_t display_id(0);
   PPPendingParams pending_action;
   PPDisplayAPIPayload resp_payload, req_payload;
+  uint8_t *disp_id = NULL;
 
   if (!color_mgr_) {
     DLOGW("color_mgr_ not initialized.");
@@ -1714,21 +1815,7 @@
   // Read display_id, payload_size and payload from in_parcel.
   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
   if (!ret) {
-    if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
-      DLOGW("Invalid display id or display = %d is not connected.", display_id);
-      ret = -ENODEV;
-    }
-  }
-
-  if (!ret) {
-    if ((HWC_DISPLAY_PRIMARY == display_id) || (HWC_DISPLAY_EXTERNAL == display_id)) {
-      ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload, &resp_payload,
-                                                           &pending_action);
-    } else {
-      // Virtual, Tertiary etc. not supported.
-      DLOGW("Operation not supported on display = %d.", display_id);
-      ret = -EINVAL;
-    }
+    ret = QdcmCMDDispatch(display_id, req_payload, &resp_payload, &pending_action);
   }
 
   if (ret) {
@@ -1739,12 +1826,6 @@
   }
 
   if (kNoAction != pending_action.action) {
-    // Restrict pending actions to primary display.
-    if (HWC_DISPLAY_PRIMARY != display_id) {
-      DLOGW("Skipping pending action %d on display = %d.", pending_action.action, display_id);
-      pending_action.action = kNoAction;
-    }
-
     int32_t action = pending_action.action;
     int count = -1;
     while (action > 0) {
@@ -1755,33 +1836,33 @@
       if (!bit)
         continue;
 
-      DLOGV_IF(kTagQDCM, "pending action = %d", BITMAP(count));
+      DLOGV_IF(kTagQDCM, "pending action = %d, display_id = %d", BITMAP(count), display_id);
       switch (BITMAP(count)) {
         case kInvalidating:
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           break;
         case kEnterQDCMMode:
-          ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+          ret = color_mgr_->EnableQDCMMode(true, hwc_display_[display_id]);
           break;
         case kExitQDCMMode:
-          ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+          ret = color_mgr_->EnableQDCMMode(false, hwc_display_[display_id]);
           break;
         case kApplySolidFill:
           {
-            SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+            SCOPE_LOCK(locker_[display_id]);
             ret = color_mgr_->SetSolidFill(pending_action.params,
-                                            true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                           true, hwc_display_[display_id]);
           }
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           usleep(kSolidFillDelay);
           break;
         case kDisableSolidFill:
           {
-            SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+            SCOPE_LOCK(locker_[display_id]);
             ret = color_mgr_->SetSolidFill(pending_action.params,
-                                            false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                           false, hwc_display_[display_id]);
           }
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           usleep(kSolidFillDelay);
           break;
         case kSetPanelBrightness:
@@ -1790,30 +1871,65 @@
             DLOGE("Brightness value is Null");
             ret = -EINVAL;
           } else {
-            ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
+            ret = hwc_display_[display_id]->SetPanelBrightness(*brightness_value);
           }
           break;
         case kEnableFrameCapture:
           ret = color_mgr_->SetFrameCapture(pending_action.params, true,
-                                        hwc_display_[HWC_DISPLAY_PRIMARY]);
-          Refresh(HWC_DISPLAY_PRIMARY);
+                                            hwc_display_[display_id]);
+          Refresh(display_id);
           break;
         case kDisableFrameCapture:
           ret = color_mgr_->SetFrameCapture(pending_action.params, false,
-                                        hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                            hwc_display_[display_id]);
           break;
         case kConfigureDetailedEnhancer:
           ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
-                                            hwc_display_[HWC_DISPLAY_PRIMARY]);
-          Refresh(HWC_DISPLAY_PRIMARY);
+                                                hwc_display_[display_id]);
+          Refresh(display_id);
           break;
         case kModeSet:
           ret = static_cast<int>
-                 (hwc_display_[HWC_DISPLAY_PRIMARY]->RestoreColorTransform());
-          Refresh(HWC_DISPLAY_PRIMARY);
+                  (hwc_display_[display_id]->RestoreColorTransform());
+          Refresh(display_id);
           break;
         case kNoAction:
           break;
+        case kMultiDispProc:
+          for (auto &map_info : map_info_builtin_) {
+            uint32_t id = UINT32(map_info.client_id);
+            if (id < kNumDisplays && hwc_display_[id]) {
+              int result = 0;
+              resp_payload.DestroyPayload();
+              result = hwc_display_[id]->ColorSVCRequestRoute(req_payload,
+                                                              &resp_payload,
+                                                              &pending_action);
+              if (result) {
+                DLOGW("Failed to dispatch action to disp %d ret %d", id, result);
+                ret = result;
+              }
+            }
+          }
+          break;
+        case kMultiDispGetId:
+          ret = resp_payload.CreatePayloadBytes(HWC_NUM_DISPLAY_TYPES, &disp_id);
+          if (ret) {
+            DLOGW("Unable to create response payload!");
+          } else {
+            for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+              disp_id[i] = HWC_NUM_DISPLAY_TYPES;
+            }
+            if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+              disp_id[HWC_DISPLAY_PRIMARY] = HWC_DISPLAY_PRIMARY;
+            }
+            for (auto &map_info : map_info_builtin_) {
+              uint64_t id = map_info.client_id;
+              if (id < kNumDisplays && hwc_display_[id]) {
+                disp_id[id] = (uint8_t)id;
+              }
+            }
+          }
+          break;
         default:
           DLOGW("Invalid pending action = %d!", pending_action.action);
           break;
@@ -1882,8 +1998,9 @@
 
     hpd_bpp_ = GetEventValue(uevent_data, length, "bpp=");
     hpd_pattern_ = GetEventValue(uevent_data, length, "pattern=");
-    DLOGI("Uevent = %s, bpp = %d, pattern = %d", uevent_data, hpd_bpp_, hpd_pattern_);
-    if (CreatePluggableDisplays(true)) {
+    DLOGI("Uevent = %s, status = %s, MST_HOTPLUG = %s, bpp = %d, pattern = %d", uevent_data,
+          str_status ? str_status : "NULL", str_mst ? str_mst : "NULL", hpd_bpp_, hpd_pattern_);
+    if (HandlePluggableDisplays(true)) {
       DLOGE("Could not handle hotplug. Event dropped.");
     }
 
@@ -1899,14 +2016,15 @@
   HWC2::Error status = HWC2::Error::None;
 
   DLOGI("Powering off primary");
-  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC2::PowerMode::Off);
+  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC2::PowerMode::Off,
+                                                           false /* teardown */);
   if (status != HWC2::Error::None) {
     DLOGE("power-off on primary failed with error = %d", status);
   }
 
   DLOGI("Restoring power mode on primary");
   HWC2::PowerMode mode = hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode();
-  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
+  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode, false /* teardown */);
   if (status != HWC2::Error::None) {
     DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
   }
@@ -2089,7 +2207,7 @@
   return status;
 }
 
-int HWCSession::CreatePluggableDisplays(bool delay_hotplug) {
+int HWCSession::HandlePluggableDisplays(bool delay_hotplug) {
   if (!primary_ready_) {
     DLOGI("Primary display is not ready. Connect displays later if any.");
     return 0;
@@ -2346,7 +2464,8 @@
   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < HWC_NUM_DISPLAY_TYPES; display++) {
     if (hwc_display_[display] != NULL) {
       DLOGI("Powering off display = %d", display);
-      status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::Off);
+      status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::Off,
+                                                   true /* teardown */);
       if (status != HWC2::Error::None) {
         DLOGE("Power off for display = %d failed with error = %d", display, status);
       }
@@ -2355,7 +2474,7 @@
   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < HWC_NUM_DISPLAY_TYPES; display++) {
     if (hwc_display_[display] != NULL) {
       DLOGI("Powering on display = %d", display);
-      status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::On);
+      status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::On, false /* teardown */);
       if (status != HWC2::Error::None) {
         DLOGE("Power on for display = %d failed with error = %d", display, status);
       }
@@ -2422,7 +2541,8 @@
 
   if (power_on_pending_[HWC_DISPLAY_EXTERNAL]) {
     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-      HWC2::Error status = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetPowerMode(HWC2::PowerMode::On);
+      HWC2::Error status = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetPowerMode(HWC2::PowerMode::On,
+                                                                            false /* teardown */);
       if (status == HWC2::Error::None) {
         power_on_pending_[HWC_DISPLAY_EXTERNAL] = false;
       }
@@ -2431,7 +2551,8 @@
 
   if (power_on_pending_[HWC_DISPLAY_VIRTUAL]) {
     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-      HWC2::Error status = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(HWC2::PowerMode::On);
+      HWC2::Error status = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(HWC2::PowerMode::On,
+                                                                           false /* teardown */);
       if (status == HWC2::Error::None) {
         power_on_pending_[HWC_DISPLAY_VIRTUAL] = false;
       }
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 6387cd6..b2a4100 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -20,7 +20,11 @@
 #ifndef __HWC_SESSION_H__
 #define __HWC_SESSION_H__
 
-#ifdef DISPLAY_CONFIG_1_3
+#ifdef DISPLAY_CONFIG_1_5
+#include <vendor/display/config/1.5/IDisplayConfig.h>
+#elif 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 +53,11 @@
 
 namespace sdm {
 
-#ifdef DISPLAY_CONFIG_1_3
+#ifdef DISPLAY_CONFIG_1_5
+using vendor::display::config::V1_5::IDisplayConfig;
+#elif 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;
@@ -202,6 +210,8 @@
 
   static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display,
                                  int32_t int_enabled);
+  static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
+                                int32_t *out_support);
 
   static Locker locker_[kNumDisplays];
 
@@ -236,7 +246,7 @@
   int GetDisplayIndex(int dpy);
   int CreatePrimaryDisplay();
   int CreateBuiltInDisplays();
-  int CreatePluggableDisplays(bool delay_hotplug);
+  int HandlePluggableDisplays(bool delay_hotplug);
   int HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug);
   int HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info);
   void DestroyDisplay(DisplayMapInfo *map_info);
@@ -249,6 +259,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 +301,14 @@
 #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
+#ifdef DISPLAY_CONFIG_1_5
+  Return<int32_t> SetDisplayDppsAdROI(uint32_t dispaly_id, uint32_t h_start, uint32_t h_end,
+                                      uint32_t v_start, uint32_t v_end, uint32_t factor_in,
+                                      uint32_t factor_out) override;
+#endif
 
   // QClient methods
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -301,6 +320,10 @@
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
   android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
                                    android::Parcel *output_parcel);
+  android::status_t QdcmCMDDispatch(uint32_t display_id,
+                                    const PPDisplayAPIPayload &req_payload,
+                                    PPDisplayAPIPayload *resp_payload,
+                                    PPPendingParams *pending_action);
   android::status_t GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
                                                   android::Parcel *output_parcel);
   android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
@@ -313,6 +336,8 @@
   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);
+  android::status_t SetAd4RoiConfig(const android::Parcel *input_parcel);
 
   void Refresh(hwc2_display_t display);
   void HotPlug(hwc2_display_t display, HWC2::Connection state);
@@ -323,6 +348,7 @@
   void HandlePowerOnPending(hwc2_display_t display, int retire_fence);
   void HandleHotplugPending(hwc2_display_t disp_id, int retire_fence);
   void UpdateVsyncSource(hwc2_display_t display);
+  hwc2_display_t GetNextBuiltinIndex();
 
   CoreInterface *core_intf_ = nullptr;
   HWCDisplay *hwc_display_[kNumDisplays] = {nullptr};
@@ -348,7 +374,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..ff71e82 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -602,8 +602,8 @@
       if (!idle_pc_ref_cnt_) {
         HWC2::Error err =
             hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
-        if (err != HWC2::Error::None) {
-          return -EINVAL;
+        if (err == HWC2::Error::Unsupported) {
+          return 0;
         }
         Refresh(HWC_DISPLAY_PRIMARY);
         int32_t error = locker_[HWC_DISPLAY_PRIMARY].WaitFinite(kCommitDoneTimeoutMs);
@@ -618,8 +618,8 @@
       if (!(idle_pc_ref_cnt_ - 1)) {
         HWC2::Error err =
             hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
-        if (err != HWC2::Error::None) {
-          return -EINVAL;
+        if (err == HWC2::Error::Unsupported) {
+          return 0;
         }
         DLOGI("Idle PC enabled!!");
       }
@@ -633,4 +633,44 @@
 }
 #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
+
+#ifdef DISPLAY_CONFIG_1_5
+Return<int32_t> HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
+                                                uint32_t h_end, uint32_t v_start, uint32_t v_end,
+                                                uint32_t factor_in, uint32_t factor_out) {
+  return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+                             &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
+                             factor_in, factor_out);
+}
+#endif  // DISPLAY_CONFIG_1_5
+
 }  // namespace sdm