Merge "sdm: properly close all the fence Fds" into dev-1.0
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 8b512bf..a0d7d8d 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -315,6 +315,7 @@
             (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
             useFbMem = true;
         } else {
+            usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
             if (property_get("debug.gralloc.enable_fb_ubwc", isUBWC, NULL) > 0){
                 if ((!strncmp(isUBWC, "1", PROPERTY_VALUE_MAX)) ||
                     (!strncasecmp(isUBWC, "true", PROPERTY_VALUE_MAX))) {
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 43887e0..e9b30f3 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -280,26 +280,6 @@
     return err;
 }
 
-int minHdcpEncryptionLevelChanged(int dpy) {
-    status_t err = (status_t) FAILED_TRANSACTION;
-    sp<IQService> binder = getBinder();
-    Parcel inParcel, outParcel;
-    inParcel.writeInt32(dpy);
-
-    if(binder != NULL) {
-        err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED,
-                &inParcel, &outParcel);
-    }
-
-    if(err) {
-        ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err);
-    } else {
-        err = outParcel.readInt32();
-    }
-
-    return err;
-}
-
 int setPanelBrightness(int level) {
     status_t err = (status_t) FAILED_TRANSACTION;
     sp<IQService> binder = getBinder();
@@ -338,8 +318,28 @@
 }// namespace
 
 // ----------------------------------------------------------------------------
-// Screen refresh for native daemons linking dynamically to libqdutils
+// Functions for linking dynamically to libqdutils
 // ----------------------------------------------------------------------------
+extern "C" int minHdcpEncryptionLevelChanged(int dpy) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED,
+                &inParcel, &outParcel);
+    }
+
+    if(err) {
+        ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err);
+    } else {
+        err = outParcel.readInt32();
+    }
+
+    return err;
+}
+
 extern "C" int refreshScreen() {
     int ret = 0;
     ret = screenRefresh();
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 101e230..9ba60f2 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -141,11 +141,6 @@
 // Set the primary display mode to command or video mode
 int setDisplayMode(int mode);
 
-// Notify change in minimum encryption level for HDCP
-// Return -1 on error.
-// Only HDMI display is supported as dpy for now
-int minHdcpEncryptionLevelChanged(int dpy);
-
 // Sets the panel brightness of the primary display
 int setPanelBrightness(int level);
 
diff --git a/sdm/include/core/debug_interface.h b/sdm/include/core/debug_interface.h
index bd2b5dd..67a38be 100644
--- a/sdm/include/core/debug_interface.h
+++ b/sdm/include/core/debug_interface.h
@@ -118,6 +118,15 @@
   */
   virtual DisplayError GetProperty(const char *property_name, int *value) = 0;
 
+  /*! @brief Method to get property value corresponding to give string.
+
+   @param[in] property_name name of the property
+   @param[out] string value corresponding to the property name
+
+   @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetProperty(const char *property_name, char *value) = 0;
+
  protected:
   virtual ~DebugHandler() { }
 };
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index c8a3a98..b4a286a 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -72,6 +72,7 @@
   static bool IsRotatorSplitDisabled();
   static bool IsScalarDisabled();
   static bool IsUbwcTiledFrameBuffer();
+  static bool GetProperty(const char *property_name, char *value);
 
  private:
   Debug();
@@ -91,6 +92,9 @@
     virtual DisplayError GetProperty(const char */*property_name*/, int */*value*/) {
       return kErrorNotSupported;
     }
+    virtual DisplayError GetProperty(const char */*property_name*/, char */*value*/) {
+      return kErrorNotSupported;
+    }
   };
 
   DefaultDebugHandler default_debug_handler_;
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index de4b326..9e1b277 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -202,7 +202,11 @@
     constraints->safe_mode = true;
   }
 
-  if (display_comp_ctx->idle_fallback || display_comp_ctx->fallback_) {
+  // Avoid idle fallback, if there is only one app layer.
+  // TODO(user): App layer count will change for hybrid composition
+  uint32_t app_layer_count = hw_layers->info.stack->layer_count - 1;
+  if ((app_layer_count > 1 && display_comp_ctx->idle_fallback) || display_comp_ctx->fallback_) {
+    // Handle the idle timeout by falling back
     constraints->safe_mode = true;
   }
 
@@ -218,13 +222,6 @@
   display_comp_ctx->strategy->Start(&hw_layers->info, &display_comp_ctx->max_strategies,
                                     display_comp_ctx->partial_update_enable);
   display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
-
-  // Avoid idle fallback, if there is only one app layer.
-  // TODO(user): App layer count will change for hybrid composition
-  uint32_t app_layer_count = hw_layers->info.stack->layer_count - 1;
-  if (!display_comp_ctx->idle_fallback && app_layer_count > 1) {
-    display_comp_ctx->handle_idle_timeout = true;
-  }
 }
 
 DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
@@ -351,16 +348,7 @@
     return;
   }
 
-  // 1. handle_idle_timeout flag is set to true on start of every draw call, if the current
-  //    composition is not due to idle fallback.
-  // 2. idle_fallback flag will be set only if handle_idle_timeout flag is true and there is no
-  //    update to the screen for specified amount of time.
-  // 3. handle_idle_timeout flag helps us handle the very first idle timeout event and
-  //    ignore the next idle timeout event on consecutive two idle timeout events.
-  if (display_comp_ctx->handle_idle_timeout) {
-    display_comp_ctx->idle_fallback = true;
-    display_comp_ctx->handle_idle_timeout = false;
-  }
+  display_comp_ctx->idle_fallback = true;
 }
 
 void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) {
@@ -448,5 +436,20 @@
   return supported;
 }
 
+bool CompManager::CanSetIdleTimeout(Handle display_ctx) {
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (!display_comp_ctx) {
+    return false;
+  }
+
+  if (!display_comp_ctx->idle_fallback) {
+    return true;
+  }
+
+  return false;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 8db045a..a6b1432 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -59,6 +59,7 @@
   DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
   DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
   bool SupportLayerAsCursor(Handle display_ctx, HWLayers *hw_layers);
+  bool CanSetIdleTimeout(Handle display_ctx);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
@@ -69,21 +70,15 @@
   void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
 
   struct DisplayCompositionContext {
-    Strategy *strategy;
+    Strategy *strategy = NULL;
     StrategyConstraints constraints;
-    Handle display_resource_ctx;
-    DisplayType display_type;
-    uint32_t max_strategies;
-    uint32_t remaining_strategies;
-    bool idle_fallback;
-    bool handle_idle_timeout;
-    bool fallback_;
-    uint32_t partial_update_enable;
-
-    DisplayCompositionContext()
-      : display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
-        remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true),
-        fallback_(false), partial_update_enable(true) { }
+    Handle display_resource_ctx = NULL;
+    DisplayType display_type = kPrimary;
+    uint32_t max_strategies = 0;
+    uint32_t remaining_strategies = 0;
+    bool idle_fallback = false;
+    bool fallback_ = false;
+    uint32_t partial_update_enable = true;
   };
 
   Locker locker_;
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
old mode 100755
new mode 100644
index 06bbccb..63fe6b2
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -57,10 +57,7 @@
     return error;
   }
 
-  // Idle fallback feature is supported only for video mode panel.
-  if (hw_panel_info_.mode == kModeVideo) {
-    hw_intf_->SetIdleTimeoutMs(Debug::GetIdleTimeoutMs());
-  }
+  idle_timeout_ms_ = Debug::GetIdleTimeoutMs();
 
   if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) {
     error = hw_intf_->SetDisplayMode(kModeVideo);
@@ -94,6 +91,8 @@
   HWDisplayAttributes display_attributes;
   uint32_t active_index = 0;
 
+  bool set_idle_timeout = comp_manager_->CanSetIdleTimeout(display_comp_ctx_);
+
   error = DisplayBase::Commit(layer_stack);
   if (error != kErrorNone) {
     return error;
@@ -108,6 +107,10 @@
     hw_panel_info_ = panel_info;
   }
 
+  if (set_idle_timeout && hw_panel_info_.mode != kModeCommand) {
+    hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
+  }
+
   return error;
 }
 
@@ -187,10 +190,12 @@
 
 void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
   SCOPE_LOCK(locker_);
+
   // Idle fallback feature is supported only for video mode panel.
   if (hw_panel_info_.mode == kModeVideo) {
     hw_intf_->SetIdleTimeoutMs(timeout_ms);
   }
+  idle_timeout_ms_ = timeout_ms;
 }
 
 DisplayError DisplayPrimary::SetMaxMixerStages(uint32_t max_mixer_stages) {
@@ -241,7 +246,7 @@
   }
 
   if (hw_display_mode == kModeVideo) {
-    hw_intf_->SetIdleTimeoutMs(Debug::GetIdleTimeoutMs());
+    hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
   } else if (hw_display_mode == kModeCommand) {
     hw_intf_->SetIdleTimeoutMs(0);
   }
@@ -278,12 +283,15 @@
 DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
   SCOPE_LOCK(locker_);
 
-  if (!hw_panel_info_.dynamic_fps || refresh_rate < hw_panel_info_.min_fps ||
-       refresh_rate > hw_panel_info_.max_fps) {
-    DLOGW("Invalid Request");
+  if (state_ != kStateOn || !hw_panel_info_.dynamic_fps) {
     return kErrorNotSupported;
   }
 
+  if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) {
+    DLOGE("Invalid Fps = %d request", refresh_rate);
+    return kErrorParameters;
+  }
+
   DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
   if (error != kErrorNone) {
     return error;
@@ -332,9 +340,9 @@
 }
 
 void DisplayPrimary::IdleTimeout() {
-  if (event_handler_->Refresh() == kErrorNone) {
-    comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
-  }
+  event_handler_->Refresh();
+  comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+  hw_intf_->SetIdleTimeoutMs(0);
 }
 
 void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 900939d..b0f2934 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -71,6 +71,7 @@
 
  private:
   Locker locker_;
+  uint32_t idle_timeout_ms_ = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 50e686a..590c23c 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -852,7 +852,6 @@
 }
 
 bool HWDevice::EnableHotPlugDetection(int enable) {
-  bool ret_value = true;
   char hpdpath[kMaxStringLength];
   int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
   if (hdmi_node_index < 0) {
@@ -860,22 +859,14 @@
   }
 
   snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, hdmi_node_index);
-  int hpdfd = Sys::open_(hpdpath, O_RDWR, 0);
-  if (hpdfd < 0) {
-    DLOGW("Open failed = %s", hpdpath);
+
+  char value = enable ? '1' : '0';
+  ssize_t length = SysFsWrite(hpdpath, &value, sizeof(value));
+  if (length <= 0) {
     return false;
   }
 
-  char value = enable ? '1' : '0';
-  ssize_t length = Sys::pwrite_(hpdfd, &value, 1, 0);
-  if (length <= 0) {
-    DLOGE("Write failed 'hpd' = %d", enable);
-    ret_value = false;
-  }
-
-  Sys::close_(hpdfd);
-
-  return ret_value;
+  return true;
 }
 
 void HWDevice::ResetDisplayParams() {
@@ -1012,5 +1003,20 @@
   return kErrorNotSupported;
 }
 
+ssize_t HWDevice::SysFsWrite(char* file_node, char* value, ssize_t length) {
+  int fd = Sys::open_(file_node, O_RDWR, 0);
+  if (fd < 0) {
+    DLOGW("Open failed = %s", file_node);
+    return -1;
+  }
+  ssize_t len = Sys::pwrite_(fd, value, length, 0);
+  if (length <= 0) {
+    DLOGE("Write failed for path %s with value %s", file_node, value);
+  }
+  Sys::close_(fd);
+
+  return len;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index cde3efa..138dbda 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -111,6 +111,7 @@
   void SetColorSpace(LayerColorSpace source, mdp_color_space *color_space);
 
   bool EnableHotPlugDetection(int enable);
+  ssize_t SysFsWrite(char* file_node, char* value, ssize_t length);
 
   // Store the Device EventHandler - used for callback
   HWEventHandler *event_handler_;
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index c47a0bd..a5fff54 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -107,6 +107,9 @@
 DisplayError HWHDMI::Init(HWEventHandler *eventhandler) {
   DisplayError error = kErrorNone;
 
+  SetSourceProductInformation("vendor_name", "ro.product.manufacturer");
+  SetSourceProductInformation("product_description", "ro.product.name");
+
   error = HWDevice::Init(eventhandler);
   if (error != kErrorNone) {
     return error;
@@ -530,5 +533,26 @@
   return is_file_present;
 }
 
+void HWHDMI::SetSourceProductInformation(const char *node, const char *name) {
+  char property_value[kMaxStringLength];
+  char sys_fs_path[kMaxStringLength];
+  int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
+  if (hdmi_node_index < 0) {
+    return;
+  }
+
+  ssize_t length = 0;
+  bool prop_read_success = Debug::GetProperty(name, property_value);
+  if (!prop_read_success) {
+    return;
+  }
+
+  snprintf(sys_fs_path , sizeof(sys_fs_path), "%s%d/%s", fb_path_, hdmi_node_index, node);
+  length = HWDevice::SysFsWrite(sys_fs_path, property_value, strlen(property_value));
+  if (length <= 0) {
+    DLOGW("Failed to write %s = %s", node, property_value);
+  }
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index 3f18b28..c216b8f 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -62,6 +62,7 @@
   DisplayError ReadTimingInfo();
   bool ReadResolutionFile(char *config_buffer);
   bool IsResolutionFilePresent();
+  void SetSourceProductInformation(const char *node, const char *name);
 
   uint32_t hdmi_mode_count_;
   uint32_t hdmi_modes_[256];
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index c548a26..884f87c 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -382,6 +382,7 @@
 
   char refresh_rate_string[kMaxStringLength];
   snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
+  DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
   ssize_t len = Sys::pwrite_(fd, refresh_rate_string, strlen(refresh_rate_string), 0);
   if (len < 0) {
     DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
@@ -546,7 +547,7 @@
 void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
   char node_path[kMaxStringLength] = {0};
 
-  DLOGI("Setting idle timeout to = %d ms", timeout_ms);
+  DLOGI_IF(kTagDriverConfig, "Setting idle timeout to = %d ms", timeout_ms);
 
   snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_, fb_node_index_);
 
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 7fe8984..099a507 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -381,9 +381,10 @@
 
   if (pvt_handle) {
     layer_buffer->format = GetSDMFormat(pvt_handle->format, pvt_handle->flags);
+    layer_buffer->width = pvt_handle->width;
+    layer_buffer->height = pvt_handle->height;
 
-    const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
-    if (meta_data && (SetMetaData(*meta_data, layer) != kErrorNone)) {
+    if (SetMetaData(pvt_handle, layer) != kErrorNone) {
       return -EINVAL;
     }
 
@@ -391,8 +392,6 @@
       return -EINVAL;
     }
 
-    layer_buffer->width = pvt_handle->width;
-    layer_buffer->height = pvt_handle->height;
     if (pvt_handle->bufferType == BUFFER_TYPE_VIDEO) {
       layer_stack_.flags.video_present = true;
       layer_buffer->flags.video = true;
@@ -463,7 +462,7 @@
   layer_buffer->acquire_fence_fd = hwc_layer->acquireFenceFd;
 }
 
-int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
+int HWCDisplay::PrePrepareLayerStack(hwc_display_contents_1_t *content_list) {
   if (shutdown_pending_) {
     return 0;
   }
@@ -591,6 +590,15 @@
   // Configure layer stack
   layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
 
+  return 0;
+}
+
+int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
+  if (shutdown_pending_) {
+    return 0;
+  }
+  size_t num_hw_layers = content_list->numHwLayers;
+
   if (!skip_prepare_) {
     DisplayError error = display_intf_->Prepare(&layer_stack_);
     if (error != kErrorNone) {
@@ -871,9 +879,7 @@
 }
 
 void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
-  if (display_intf_) {
-    display_intf_->SetIdleTimeoutMs(timeout_ms);
-  }
+  return;
 }
 
 DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
@@ -1260,25 +1266,40 @@
   return kErrorNone;
 }
 
-DisplayError HWCDisplay::SetMetaData(const MetaData_t &meta_data, Layer *layer) {
-  if (meta_data.operation & UPDATE_REFRESH_RATE) {
-    layer->frame_rate = RoundToStandardFPS(meta_data.refreshrate);
+DisplayError HWCDisplay::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
+  const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
+  LayerBuffer *layer_buffer = layer->input_buffer;
+
+  if (!meta_data) {
+    return kErrorNone;
   }
 
-  if ((meta_data.operation & PP_PARAM_INTERLACED) && meta_data.interlaced) {
-    layer->input_buffer->flags.interlace = true;
-  }
-
-  if (meta_data.operation & LINEAR_FORMAT) {
-    layer->input_buffer->format = GetSDMFormat(meta_data.linearFormat, 0);
-  }
-
-  if (meta_data.operation & UPDATE_COLOR_SPACE) {
-    if (SetColorSpace(meta_data.colorSpace, &layer->color_space) != kErrorNone) {
+  if (meta_data->operation & UPDATE_COLOR_SPACE) {
+    if (SetColorSpace(meta_data->colorSpace, &layer->color_space) != kErrorNone) {
       return kErrorNotSupported;
     }
   }
 
+  if (meta_data->operation & UPDATE_REFRESH_RATE) {
+    layer->frame_rate = RoundToStandardFPS(meta_data->refreshrate);
+  }
+
+  if ((meta_data->operation & PP_PARAM_INTERLACED) && meta_data->interlaced) {
+    layer_buffer->flags.interlace = true;
+  }
+
+  if (meta_data->operation & LINEAR_FORMAT) {
+    layer_buffer->format = GetSDMFormat(meta_data->linearFormat, 0);
+  }
+
+  if (meta_data->operation & UPDATE_BUFFER_GEOMETRY) {
+    int actual_width = pvt_handle->width;
+    int actual_height = pvt_handle->height;
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(pvt_handle, actual_width, actual_height);
+    layer_buffer->width = actual_width;
+    layer_buffer->height = actual_height;
+  }
+
   return kErrorNone;
 }
 
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index ce624a3..9154225 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -126,6 +126,7 @@
   virtual DisplayError Refresh();
 
   virtual int AllocateLayerStack(hwc_display_contents_1_t *content_list);
+  virtual int PrePrepareLayerStack(hwc_display_contents_1_t *content_list);
   virtual int PrepareLayerStack(hwc_display_contents_1_t *content_list);
   virtual int CommitLayerStack(hwc_display_contents_1_t *content_list);
   virtual int PostCommitLayerStack(hwc_display_contents_1_t *content_list);
@@ -144,7 +145,7 @@
   uint32_t RoundToStandardFPS(uint32_t fps);
   virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
   DisplayError SetColorSpace(const ColorSpace_t source, LayerColorSpace *target);
-  DisplayError SetMetaData(const MetaData_t &meta_data, Layer *layer);
+  DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
   bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
   void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
   bool IsLayerUpdating(const hwc_layer_1_t &hwc_layer, const LayerCache &layer_cache);
@@ -181,7 +182,6 @@
   uint32_t force_refresh_rate_ = 0;
   bool boot_animation_completed_ = false;
   bool shutdown_pending_ = false;
-  bool handle_refresh_ = true;
   bool use_blit_comp_ = false;
   bool secure_display_active_ = false;
   bool skip_prepare_ = false;
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index a02be81..99c903c 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -98,6 +98,11 @@
     return 0;
   }
 
+  status = PrePrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
   status = PrepareLayerStack(content_list);
   if (status) {
     return status;
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index 9842b61..416e390 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -133,31 +133,28 @@
     return 0;
   }
 
-  status = PrepareLayerStack(content_list);
+  status = PrePrepareLayerStack(content_list);
   if (status) {
     return status;
   }
 
-  // Drop invalidate trigger to SurfaceFlinger
-  // if all layers in previous draw cycle were composed using GPU
-  // OR
-  // if all layers were composed using GPU sometime in past and the cached content
-  // is being used currently.
-  handle_refresh_ = false;
-  int app_layer_count = content_list->numHwLayers - 1;
-  if (app_layer_count > 1) {
-    int fb_layer_count = 0;
-    for (int i = 0; i < app_layer_count; i++) {
-      if (content_list->hwLayers[i].compositionType == HWC_FRAMEBUFFER) {
-        fb_layer_count++;
-      }
-    }
+  bool one_updating_layer = SingleLayerUpdating(content_list->numHwLayers - 1);
+  ToggleCPUHint(one_updating_layer);
 
-    if ((fb_layer_count == 0) && !layer_stack_cache_.in_use) {
-      handle_refresh_ = true;
-    } else if (fb_layer_count > 0 && fb_layer_count < app_layer_count) {
-      handle_refresh_ = true;
-    }
+  uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
+  DisplayError error = display_intf_->SetRefreshRate(refresh_rate);
+  if (error == kErrorNone) {
+    // On success, set current refresh rate to new refresh rate
+    current_refresh_rate_ = refresh_rate;
+  }
+
+  if (handle_idle_timeout_) {
+    handle_idle_timeout_ = false;
+  }
+
+  status = PrepareLayerStack(content_list);
+  if (status) {
+    return status;
   }
 
   return 0;
@@ -192,24 +189,9 @@
     return status;
   }
 
-  bool one_updating_layer = SingleLayerUpdating(content_list->numHwLayers - 1);
-
-  SetMetadataRefreshRate(one_updating_layer);
-  ToggleCPUHint(one_updating_layer);
-
   return 0;
 }
 
-int HWCDisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
-  DisplayError error = kErrorNone;
-
-  if (display_intf_) {
-    error = display_intf_->SetRefreshRate(refresh_rate);
-  }
-
-  return (error ? -1 : 0);
-}
-
 int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
   va_list args;
   va_start(args, operation);
@@ -287,52 +269,33 @@
   return;
 }
 
-void HWCDisplayPrimary::SetMetadataRefreshRate(bool one_updating_layer) {
-  // return if force_refresh_rate_ is set or metadata_refresh_rate is not enabled
-  if (force_refresh_rate_) {
-    return;
-  }
-
-  uint32_t refresh_rate = max_refresh_rate_;
-  if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
-    refresh_rate = metadata_refresh_rate_;
-  }
-
-  int status = SetRefreshRate(refresh_rate);
-  if (status == 0) {
-    // Set current refresh rate to metadata refresh rate
-    current_refresh_rate_ = refresh_rate;
-  } else {
-    // Failed - Restore to max refresh rate
-    current_refresh_rate_ = max_refresh_rate_;
-  }
-}
-
 void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
-  if (refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) {
-    // Cannot honor force refresh rate, as its beyond the range
+  if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+       force_refresh_rate_ == refresh_rate) {
+    // Cannot honor force refresh rate, as its beyond the range or new request is same
     return;
   }
 
-  uint32_t rate = refresh_rate;
+  const hwc_procs_t *hwc_procs = *hwc_procs_;
   force_refresh_rate_ = refresh_rate;
-  if (refresh_rate == 0) {
-    // refresh rate request of 0 means the client is resetting the forced request rate
-    rate = max_refresh_rate_;
-  }
 
-  int status = SetRefreshRate(rate);
-  if (status) {
-    // failed Reset force_refresh_rate to 0, and restore max refresh rate
-    force_refresh_rate_ = 0;
-    rate = max_refresh_rate_;
-    DLOGE("Setting Refresh Rate = %d Failed", refresh_rate);
-  }
-  current_refresh_rate_ = rate;
+  hwc_procs->invalidate(hwc_procs);
 
   return;
 }
 
+uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
+  if (force_refresh_rate_) {
+    return force_refresh_rate_;
+  } else if (handle_idle_timeout_) {
+    return min_refresh_rate_;
+  } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
+    return metadata_refresh_rate_;
+  }
+
+  return max_refresh_rate_;
+}
+
 DisplayError HWCDisplayPrimary::Refresh() {
   const hwc_procs_t *hwc_procs = *hwc_procs_;
   DisplayError error = kErrorNone;
@@ -341,25 +304,15 @@
     return kErrorParameters;
   }
 
-  if (!handle_refresh_) {
-    error = kErrorNotSupported;
-  }
-
-  if (error == kErrorNone) {
-    hwc_procs->invalidate(hwc_procs);
-  }
-
-  uint32_t refresh_rate = force_refresh_rate_ ? force_refresh_rate_ : min_refresh_rate_;
-
-  int status = SetRefreshRate(refresh_rate);
-  if (status) {
-    DLOGE("Setting Refresh Rate = %d Failed", refresh_rate);
-  } else {
-    current_refresh_rate_ = refresh_rate;
-  }
+  hwc_procs->invalidate(hwc_procs);
+  handle_idle_timeout_ = true;
 
   return error;
 }
 
+void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  display_intf_->SetIdleTimeoutMs(timeout_ms);
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
index 230d2d5..e30d200 100644
--- a/sdm/libs/hwc/hwc_display_primary.h
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -46,10 +46,10 @@
   virtual int Init();
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
-  virtual int SetRefreshRate(uint32_t refresh_rate);
   virtual int Perform(uint32_t operation, ...);
   virtual void SetSecureDisplay(bool secure_display_active);
   virtual DisplayError Refresh();
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
 
  private:
   HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
@@ -58,10 +58,11 @@
   void ProcessBootAnimCompleted();
   void SetQDCMSolidFillInfo(bool enable, uint32_t color);
   void ToggleCPUHint(bool set);
-  void SetMetadataRefreshRate(bool one_updating_layer);
   void ForceRefreshRate(uint32_t refresh_rate);
+  uint32_t GetOptimalRefreshRate(bool one_updating_layer);
 
   CPUHint *cpu_hint_;
+  bool handle_idle_timeout_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp
index 219a81b..f292656 100644
--- a/sdm/libs/hwc/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -147,6 +147,11 @@
     return status;
   }
 
+  status = PrePrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
   status = PrepareLayerStack(content_list);
   if (status) {
     return status;
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index 33f94b9..003be5a 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -133,5 +133,13 @@
   return (ubwc_framebuffer == 1);
 }
 
+bool Debug::GetProperty(const char* property_name, char* value) {
+  if (debug_.debug_handler_->GetProperty(property_name, value) != kErrorNone) {
+    return false;
+  }
+
+  return true;
+}
+
 }  // namespace sdm