Merge "sdm: Refactor framebuffer refresh condition."
diff --git a/sdm/include/private/rotator_interface.h b/sdm/include/private/rotator_interface.h
index 9901d21..5432ac2 100644
--- a/sdm/include/private/rotator_interface.h
+++ b/sdm/include/private/rotator_interface.h
@@ -40,7 +40,7 @@
   virtual DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(Handle display_ctx, HWLayers *hw_layers) = 0;
   virtual DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers) = 0;
-  virtual DisplayError Purge(Handle display_ctx, HWLayers *hw_layers) = 0;
+  virtual DisplayError Purge(Handle display_ctx) = 0;
 
  protected:
   virtual ~RotatorInterface() { }
diff --git a/sdm/include/utils/rect.h b/sdm/include/utils/rect.h
index 248b11c..04f3bf3 100644
--- a/sdm/include/utils/rect.h
+++ b/sdm/include/utils/rect.h
@@ -42,6 +42,7 @@
   void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
   void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect);
   LayerRect Union(const LayerRect &rect1, const LayerRect &rect2);
+  LayerRect Union(const LayerRectArray &rects);
   LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2);
   LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2);
   LayerRect Reposition(const LayerRect &rect1, const int &x_offset, const int &y_offset);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 4c373a9..30aac4e 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -48,32 +48,12 @@
   hw_panel_info_ = HWPanelInfo();
   hw_intf_->GetHWPanelInfo(&hw_panel_info_);
 
-  error = hw_intf_->GetNumDisplayAttributes(&num_modes_);
-  if (error != kErrorNone) {
-    goto CleanupOnError;
-  }
+  HWDisplayAttributes display_attrib;
+  uint32_t active_index = 0;
+  hw_intf_->GetActiveConfig(&active_index);
+  hw_intf_->GetDisplayAttributes(active_index, &display_attrib);
 
-  display_attributes_ = new HWDisplayAttributes[num_modes_];
-  if (!display_attributes_) {
-    error = kErrorMemory;
-    goto CleanupOnError;
-  }
-
-  for (uint32_t i = 0; i < num_modes_; i++) {
-    error = hw_intf_->GetDisplayAttributes(&display_attributes_[i], i);
-    if (error != kErrorNone) {
-      goto CleanupOnError;
-    }
-  }
-
-  active_mode_index_ = GetBestConfig();
-
-  error = hw_intf_->SetDisplayAttributes(active_mode_index_);
-  if (error != kErrorNone) {
-    goto CleanupOnError;
-  }
-
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[active_mode_index_],
+  error = comp_manager_->RegisterDisplay(display_type_, display_attrib,
                                          hw_panel_info_, &display_comp_ctx_);
   if (error != kErrorNone) {
     goto CleanupOnError;
@@ -98,7 +78,7 @@
   }
 
   color_mgr_ = ColorManagerProxy::CreateColorManagerProxy(display_type_, hw_intf_,
-                               display_attributes_[active_mode_index_], hw_panel_info_);
+                               display_attrib, hw_panel_info_);
   if (!color_mgr_) {
     DLOGW("Unable to create ColorManagerProxy for display = %d", display_type_);
   }
@@ -110,11 +90,6 @@
     comp_manager_->UnregisterDisplay(display_comp_ctx_);
   }
 
-  if (display_attributes_) {
-    delete[] display_attributes_;
-    display_attributes_ = NULL;
-  }
-
   return error;
 }
 
@@ -130,11 +105,6 @@
 
   comp_manager_->UnregisterDisplay(display_comp_ctx_);
 
-  if (display_attributes_) {
-    delete[] display_attributes_;
-    display_attributes_ = NULL;
-  }
-
   return kErrorNone;
 }
 
@@ -177,7 +147,7 @@
       } else {
         // Release all the previous rotator sessions.
         if (rotator_intf_) {
-          error = rotator_intf_->Purge(display_rotator_ctx_, &hw_layers_);
+          error = rotator_intf_->Purge(display_rotator_ctx_);
         }
       }
 
@@ -281,7 +251,17 @@
   hw_layers_.info.count = 0;
   error = hw_intf_->Flush();
   if (error == kErrorNone) {
+    // Release all the rotator sessions.
+    if (rotator_intf_) {
+      error = rotator_intf_->Purge(display_rotator_ctx_);
+      if (error != kErrorNone) {
+        DLOGE("Rotator purge failed for display %d", display_type_);
+        return error;
+      }
+    }
+
     comp_manager_->Purge(display_comp_ctx_);
+
     pending_commit_ = false;
   } else {
     DLOGW("Unable to flush display = %d", display_type_);
@@ -300,41 +280,21 @@
 }
 
 DisplayError DisplayBase::GetNumVariableInfoConfigs(uint32_t *count) {
-  if (!count) {
-    return kErrorParameters;
-  }
-
-  *count = num_modes_;
-
-  return kErrorNone;
-}
-
-DisplayError DisplayBase::GetConfig(DisplayConfigFixedInfo *fixed_info) {
-  if (!fixed_info) {
-    return kErrorParameters;
-  }
-
-  return kErrorNone;
+  return hw_intf_->GetNumDisplayAttributes(count);
 }
 
 DisplayError DisplayBase::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
-  if (!variable_info || index >= num_modes_) {
-    return kErrorParameters;
+  HWDisplayAttributes attrib;
+  if (hw_intf_->GetDisplayAttributes(index, &attrib) == kErrorNone) {
+    *variable_info = attrib;
+    return kErrorNone;
   }
 
-  *variable_info = display_attributes_[index];
-
-  return kErrorNone;
+  return kErrorNotSupported;
 }
 
 DisplayError DisplayBase::GetActiveConfig(uint32_t *index) {
-  if (!index) {
-    return kErrorParameters;
-  }
-
-  *index = active_mode_index_;
-
-  return kErrorNone;
+  return hw_intf_->GetActiveConfig(index);
 }
 
 DisplayError DisplayBase::GetVSyncState(bool *enabled) {
@@ -364,6 +324,15 @@
     hw_layers_.info.count = 0;
     error = hw_intf_->Flush();
     if (error == kErrorNone) {
+      // Release all the rotator sessions.
+      if (rotator_intf_) {
+        error = rotator_intf_->Purge(display_rotator_ctx_);
+        if (error != kErrorNone) {
+          DLOGE("Rotator purge failed for display %d", display_type_);
+          return error;
+        }
+      }
+
       comp_manager_->Purge(display_comp_ctx_);
 
       error = hw_intf_->PowerOff();
@@ -400,9 +369,12 @@
 
 DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
   DisplayError error = kErrorNone;
+  uint32_t active_index = 0;
 
-  if (index >= num_modes_) {
-    return kErrorParameters;
+  hw_intf_->GetActiveConfig(&active_index);
+
+  if (active_index == index) {
+    return kErrorNone;
   }
 
   error = hw_intf_->SetDisplayAttributes(index);
@@ -410,13 +382,17 @@
     return error;
   }
 
-  active_mode_index_ = index;
+  HWDisplayAttributes attrib;
+  error = hw_intf_->GetDisplayAttributes(index, &attrib);
+  if (error != kErrorNone) {
+    return error;
+  }
 
   if (display_comp_ctx_) {
     comp_manager_->UnregisterDisplay(display_comp_ctx_);
   }
 
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index], hw_panel_info_,
+  error = comp_manager_->RegisterDisplay(display_type_, attrib, hw_panel_info_,
                                          &display_comp_ctx_);
 
   return error;
@@ -481,14 +457,21 @@
 }
 
 void DisplayBase::AppendDump(char *buffer, uint32_t length) {
+  HWDisplayAttributes attrib;
+  uint32_t active_index = 0;
+  uint32_t num_modes = 0;
+  hw_intf_->GetNumDisplayAttributes(&num_modes);
+  hw_intf_->GetActiveConfig(&active_index);
+  hw_intf_->GetDisplayAttributes(active_index, &attrib);
+
   DumpImpl::AppendString(buffer, length, "\n-----------------------");
   DumpImpl::AppendString(buffer, length, "\ndevice type: %u", display_type_);
   DumpImpl::AppendString(buffer, length, "\nstate: %u, vsync on: %u, max. mixer stages: %u",
                          state_, INT(vsync_enable_), max_mixer_stages_);
   DumpImpl::AppendString(buffer, length, "\nnum configs: %u, active config index: %u",
-                         num_modes_, active_mode_index_);
+                         num_modes, active_index);
 
-  DisplayConfigVariableInfo &info = display_attributes_[active_mode_index_];
+  DisplayConfigVariableInfo &info = attrib;
   DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%.2f,"
                          "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi,
                          info.y_dpi, info.fps, info.vsync_period_ns);
@@ -595,10 +578,6 @@
   }
 }
 
-int DisplayBase::GetBestConfig() {
-  return (num_modes_ == 1) ? 0 : -1;
-}
-
 bool DisplayBase::IsRotationRequired(HWLayers *hw_layers) {
   HWLayersInfo &layer_info = hw_layers->info;
 
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 5a588a1..dae9074 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -54,7 +54,6 @@
   virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
-  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
   virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
@@ -77,7 +76,6 @@
   // DumpImpl method
   void AppendDump(char *buffer, uint32_t length);
 
-  virtual int GetBestConfig();
   bool IsRotationRequired(HWLayers *hw_layers);
   const char *GetName(const LayerComposition &composition);
   const char *GetName(const LayerBufferFormat &format);
@@ -94,9 +92,6 @@
   Handle hw_device_ = 0;
   Handle display_comp_ctx_ = 0;
   Handle display_rotator_ctx_ = 0;
-  HWDisplayAttributes *display_attributes_ = NULL;
-  uint32_t num_modes_ = 0;
-  uint32_t active_mode_index_ = 0;
   HWLayers hw_layers_;
   bool pending_commit_ = false;
   bool vsync_enable_ = false;
@@ -105,6 +100,12 @@
   HWInfoInterface *hw_info_intf_ = NULL;
   ColorManagerProxy *color_mgr_ = NULL;  // each display object owns its ColorManagerProxy
   bool partial_update_control_ = true;
+
+ private:
+  // Unused
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info) {
+    return kErrorNone;
+  }
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index cdf7aca..8add374 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -50,6 +50,13 @@
     return error;
   }
 
+  uint32_t active_mode_index = GetBestConfig();
+
+  error = hw_intf_->SetDisplayAttributes(active_mode_index);
+  if (error != kErrorNone) {
+    HWHDMI::Destroy(hw_intf_);
+  }
+
   error = DisplayBase::Init();
   if (error != kErrorNone) {
     HWHDMI::Destroy(hw_intf_);
@@ -95,11 +102,6 @@
   return DisplayBase::GetNumVariableInfoConfigs(count);
 }
 
-DisplayError DisplayHDMI::GetConfig(DisplayConfigFixedInfo *fixed_info) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::GetConfig(fixed_info);
-}
-
 DisplayError DisplayHDMI::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
   SCOPE_LOCK(locker_);
   return DisplayBase::GetConfig(index, variable_info);
@@ -174,30 +176,36 @@
 }
 
 int DisplayHDMI::GetBestConfig() {
-  uint32_t best_config_mode = 0;
-  HWDisplayAttributes *best = &display_attributes_[0];
-  if (num_modes_ == 1) {
-    return best_config_mode;
+  uint32_t best_index = 0;
+  uint32_t num_modes = 0;
+  HWDisplayAttributes best_attrib;
+
+  hw_intf_->GetNumDisplayAttributes(&num_modes);
+  if (num_modes == 1) {
+    return best_index;
   }
 
+  hw_intf_->GetDisplayAttributes(0, &best_attrib);
+
   // From the available configs, select the best
   // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
-  for (uint32_t index = 1; index < num_modes_; index++) {
-    HWDisplayAttributes *current = &display_attributes_[index];
+  for (uint32_t index = 1; index < num_modes; index++) {
+    HWDisplayAttributes current_attrib;
+    hw_intf_->GetDisplayAttributes(index, &current_attrib);
     // compare the two modes: in the order of Resolution followed by refreshrate
-    if (current->y_pixels > best->y_pixels) {
-      best_config_mode = index;
-    } else if (current->y_pixels == best->y_pixels) {
-      if (current->x_pixels > best->x_pixels) {
-        best_config_mode = index;
-      } else if (current->x_pixels == best->x_pixels) {
-        if (current->vsync_period_ns < best->vsync_period_ns) {
-          best_config_mode = index;
+    if (current_attrib.y_pixels > best_attrib.y_pixels) {
+      best_index = index;
+    } else if (current_attrib.y_pixels == best_attrib.y_pixels) {
+      if (current_attrib.x_pixels > best_attrib.x_pixels) {
+        best_index = index;
+      } else if (current_attrib.x_pixels == best_attrib.x_pixels) {
+        if (current_attrib.vsync_period_ns < best_attrib.vsync_period_ns) {
+          best_index = index;
         }
       }
     }
-    if (best_config_mode == index) {
-      best = &display_attributes_[index];
+    if (best_index == index) {
+      best_attrib = current_attrib;
     }
   }
 
@@ -211,7 +219,7 @@
       return config_index;
   }
 
-  return best_config_mode;
+  return best_index;
 }
 
 void DisplayHDMI::GetScanSupport() {
@@ -221,7 +229,10 @@
   HWScanInfo scan_info = HWScanInfo();
   hw_intf_->GetHWScanInfo(&scan_info);
 
-  error = hw_intf_->GetVideoFormat(active_mode_index_, &video_format);
+  uint32_t active_mode_index = 0;
+  hw_intf_->GetActiveConfig(&active_mode_index);
+
+  error = hw_intf_->GetVideoFormat(active_mode_index, &video_format);
   if (error != kErrorNone) {
     return;
   }
@@ -235,7 +246,7 @@
   // Preferred Timing if the preferred timing of the display is currently active, and if it is
   // valid. In all other cases, we must read the scan support from CEA scan info if
   // the resolution is a CEA resolution, or from IT scan info for all other resolutions.
-  if (active_mode_index_ == 0 && scan_info.pt_scan_support != kScanNotSupported) {
+  if (active_mode_index == 0 && scan_info.pt_scan_support != kScanNotSupported) {
     scan_support_ = scan_info.pt_scan_support;
   } else if (video_format < max_cea_format) {
     scan_support_ = scan_info.cea_scan_support;
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
index d3ff97b..b6f4116 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -44,7 +44,6 @@
   virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
-  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
   virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index d1ce1ff..8698ab8 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -92,6 +92,7 @@
   DisplayError error = kErrorNone;
   HWPanelInfo panel_info;
   HWDisplayAttributes display_attributes;
+  uint32_t active_index = 0;
 
   error = DisplayBase::Commit(layer_stack);
   if (error != kErrorNone) {
@@ -99,15 +100,12 @@
   }
 
   hw_intf_->GetHWPanelInfo(&panel_info);
+  hw_intf_->GetActiveConfig(&active_index);
+  hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
 
-  hw_intf_->GetDisplayAttributes(&display_attributes, active_mode_index_);
-
-  if (panel_info != hw_panel_info_ ||
-      display_attributes != display_attributes_[active_mode_index_]) {
+  if (panel_info != hw_panel_info_) {
     comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
-
     hw_panel_info_ = panel_info;
-    display_attributes_[active_mode_index_] = display_attributes;
   }
 
   return error;
@@ -128,11 +126,6 @@
   return DisplayBase::GetNumVariableInfoConfigs(count);
 }
 
-DisplayError DisplayPrimary::GetConfig(DisplayConfigFixedInfo *fixed_info) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::GetConfig(fixed_info);
-}
-
 DisplayError DisplayPrimary::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
   SCOPE_LOCK(locker_);
   return DisplayBase::GetConfig(index, variable_info);
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 9f7f5b5..1a61688 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -44,7 +44,6 @@
   virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
-  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
   virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index 56d2f93..ea4e829 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -50,6 +50,8 @@
     return error;
   }
 
+  hw_intf_->GetDisplayAttributes(0 /* active_index */, &display_attributes_);
+
   error = DisplayBase::Init();
   if (error != kErrorNone) {
     HWVirtual::Destroy(hw_intf_);
@@ -89,22 +91,20 @@
 
 DisplayError DisplayVirtual::GetNumVariableInfoConfigs(uint32_t *count) {
   SCOPE_LOCK(locker_);
-  return DisplayBase::GetNumVariableInfoConfigs(count);
-}
-
-DisplayError DisplayVirtual::GetConfig(DisplayConfigFixedInfo *fixed_info) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::GetConfig(fixed_info);
+  *count = 1;
+  return kErrorNone;
 }
 
 DisplayError DisplayVirtual::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
   SCOPE_LOCK(locker_);
-  return DisplayBase::GetConfig(index, variable_info);
+  *variable_info = display_attributes_;
+  return kErrorNone;
 }
 
 DisplayError DisplayVirtual::GetActiveConfig(uint32_t *index) {
   SCOPE_LOCK(locker_);
-  return DisplayBase::GetActiveConfig(index);
+  *index = 0;
+  return kErrorNone;
 }
 
 DisplayError DisplayVirtual::GetVSyncState(bool *enabled) {
@@ -130,11 +130,9 @@
     return kErrorParameters;
   }
 
-  HWDisplayAttributes display_attributes = display_attributes_[active_mode_index_];
-
-  display_attributes.x_pixels = variable_info->x_pixels;
-  display_attributes.y_pixels = variable_info->y_pixels;
-  display_attributes.fps = variable_info->fps;
+  display_attributes_.x_pixels = variable_info->x_pixels;
+  display_attributes_.y_pixels = variable_info->y_pixels;
+  display_attributes_.fps = variable_info->fps;
 
   // if display is already connected, unregister display from composition manager and register
   // the display with new configuration.
@@ -142,20 +140,18 @@
     comp_manager_->UnregisterDisplay(display_comp_ctx_);
   }
 
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info_,
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
                                          &display_comp_ctx_);
   if (error != kErrorNone) {
     return error;
   }
 
-  display_attributes_[active_mode_index_] = display_attributes;
-
   return error;
 }
 
 DisplayError DisplayVirtual::SetActiveConfig(uint32_t index) {
   SCOPE_LOCK(locker_);
-  return DisplayBase::SetActiveConfig(index);
+  return kErrorNotSupported;
 }
 
 DisplayError DisplayVirtual::SetVSyncState(bool enable) {
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index 45198bc..10978a7 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -25,6 +25,7 @@
 #ifndef __DISPLAY_VIRTUAL_H__
 #define __DISPLAY_VIRTUAL_H__
 
+#include <private/hw_info_types.h>
 #include "display_base.h"
 #include "dump_impl.h"
 
@@ -44,7 +45,6 @@
   virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
-  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
   virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
@@ -64,6 +64,7 @@
 
  private:
   Locker locker_;
+  HWDisplayAttributes display_attributes_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 7d11407..97aa5c9 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -94,13 +94,18 @@
   return kErrorNone;
 }
 
+DisplayError HWDevice::GetActiveConfig(uint32_t *active_config) {
+  *active_config = 0;
+  return kErrorNone;
+}
+
 DisplayError HWDevice::GetNumDisplayAttributes(uint32_t *count) {
   *count = 1;
   return kErrorNone;
 }
 
-DisplayError HWDevice::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
-                                                 uint32_t index) {
+DisplayError HWDevice::GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes) {
   return kErrorNone;
 }
 
@@ -117,7 +122,6 @@
   return kErrorNone;
 }
 
-
 DisplayError HWDevice::PowerOn() {
   DTRACE_SCOPED();
 
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index bc2d0f0..da43441 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -44,9 +44,10 @@
   virtual ~HWDevice() {}
 
   // From HWInterface
+  virtual DisplayError GetActiveConfig(uint32_t *active_config);
   virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
-  virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
-                                            uint32_t index);
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes);
   virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index ac68967..8dc0e35 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -98,7 +98,7 @@
 }
 
 HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler,  HWInfoInterface *hw_info_intf)
-  : HWDevice(buffer_sync_handler), hw_scan_info_() {
+  : HWDevice(buffer_sync_handler), hw_scan_info_(), active_config_index_(0) {
   HWDevice::device_type_ = kDeviceHDMI;
   HWDevice::device_name_ = "HDMI Display Device";
   HWDevice::hw_info_intf_ = hw_info_intf;
@@ -159,6 +159,11 @@
   return kErrorNone;
 }
 
+DisplayError HWHDMI::GetActiveConfig(uint32_t *active_config_index) {
+  *active_config_index = active_config_index_;
+  return kErrorNone;
+}
+
 DisplayError HWHDMI::ReadEDIDInfo() {
   ssize_t length = -1;
   char edid_str[kPageSize] = {'\0'};
@@ -197,8 +202,8 @@
   return kErrorNone;
 }
 
-DisplayError HWHDMI::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
-                                                     uint32_t index) {
+DisplayError HWHDMI::GetDisplayAttributes(uint32_t index,
+                                          HWDisplayAttributes *display_attributes) {
   DTRACE_SCOPED();
 
   if (index > hdmi_mode_count_) {
@@ -290,6 +295,8 @@
     return kErrorHardware;
   }
 
+  active_config_index_ = index;
+
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index 5352249..3f18b28 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -41,8 +41,10 @@
   virtual DisplayError Init(HWEventHandler *eventhandler);
   virtual DisplayError Deinit();
   virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
-  virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
-                                            uint32_t index);
+  // Requirement to call this only after the first config has been explicitly set by client
+  virtual DisplayError GetActiveConfig(uint32_t *active_config);
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes);
   virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info);
   virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format);
   virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
@@ -66,6 +68,7 @@
   // Holds the hdmi timing information. Ex: resolution, fps etc.,
   msm_hdmi_mode_timing_info *supported_video_modes_;
   HWScanInfo hw_scan_info_;
+  uint32_t active_config_index_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 475ed07..d5c913d 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -38,6 +38,9 @@
 #include <sys/resource.h>
 #include <utils/debug.h>
 #include <utils/sys.h>
+#include <core/display_interface.h>
+
+#include <string>
 
 #include "hw_primary.h"
 #include "hw_color_manager.h"
@@ -46,6 +49,8 @@
 
 namespace sdm {
 
+using std::string;
+
 DisplayError HWPrimary::Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
                                BufferSyncHandler *buffer_sync_handler,
                                HWEventHandler *eventhandler) {
@@ -72,8 +77,7 @@
 }
 
 HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
-  : HWDevice(buffer_sync_handler), event_thread_name_("SDM_EventThread"), fake_vsync_(false),
-    exit_threads_(false), config_changed_(true) {
+  : HWDevice(buffer_sync_handler) {
   HWDevice::device_type_ = kDevicePrimary;
   HWDevice::device_name_ = "Primary Display Device";
   HWDevice::hw_info_intf_ = hw_info_intf;
@@ -81,10 +85,10 @@
 
 DisplayError HWPrimary::Init(HWEventHandler *eventhandler) {
   DisplayError error = kErrorNone;
-  char node_path[kMaxStringLength] = {0};
-  char data[kMaxStringLength] = {0};
-  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify",
-                                              "msm_fb_thermal_level"};
+  char node_path[kMaxStringLength] = { 0 };
+  char data[kMaxStringLength] = { 0 };
+  const char *event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify",
+                                               "msm_fb_thermal_level"};
 
   error = HWDevice::Init(eventhandler);
   if (error != kErrorNone) {
@@ -131,6 +135,7 @@
   // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
   // This helps for framework reboot or adb shell stop/start
   EnableHotPlugDetection(0);
+  InitializeConfigs();
 
   return kErrorNone;
 
@@ -146,6 +151,73 @@
   return error;
 }
 
+void HWPrimary::InitializeConfigs() {
+  size_t curr_x_pixels = 0;
+  size_t curr_y_pixels = 0;
+  string mode_path = string(fb_path_) + string("0/mode");
+  string modes_path = string(fb_path_) + string("0/modes");
+  size_t len = kPageSize;
+  char *buffer = static_cast<char *>(calloc(len, sizeof(char)));
+
+  if (buffer == NULL) {
+    DLOGW("Failed to allocate memory");
+    return;
+  }
+
+  FILE *fd = Sys::fopen_(mode_path.c_str(), "r");
+  if (fd) {
+    if (Sys::getline_(&buffer, &len, fd) > 0) {
+      // String is of form "U:1600x2560p-0". Documentation/fb/modedb.txt in
+      // kernel has more info on the format.
+      size_t xpos = string(buffer).find(':');
+      size_t ypos = string(buffer).find('x');
+
+      if (xpos == string::npos || ypos == string::npos) {
+        DLOGI("Resolution switch not supported");
+        free(buffer);
+        Sys::fclose_(fd);
+        return;
+      }
+
+      curr_x_pixels = atoi(buffer + xpos + 1);
+      curr_y_pixels = atoi(buffer + ypos + 1);
+      DLOGI("Current Config: %u x %u", curr_x_pixels, curr_y_pixels);
+    }
+
+    Sys::fclose_(fd);
+  }
+
+  fd = Sys::fopen_(modes_path.c_str(), "r");
+  if (fd) {
+    while (Sys::getline_(&buffer, &len, fd) > 0) {
+      DisplayConfigVariableInfo config;
+      size_t xpos = string(buffer).find(':');
+      size_t ypos = string(buffer).find('x');
+
+      if (xpos == string::npos || ypos == string::npos) {
+        continue;
+      }
+
+      config.x_pixels = atoi(buffer + xpos + 1);
+      config.y_pixels = atoi(buffer + ypos + 1);
+      DLOGI("Found mode %d x %d", config.x_pixels, config.y_pixels);
+      display_configs_.push_back(config);
+      display_config_strings_.push_back(string(buffer));
+
+      if (curr_x_pixels == config.x_pixels && curr_y_pixels == config.y_pixels) {
+        active_config_index_ = display_configs_.size() - 1;
+        DLOGI("Active config index %u", active_config_index_);
+      }
+    }
+
+    Sys::fclose_(fd);
+  } else {
+    DLOGI("Unable to process modes");
+  }
+
+  free(buffer);
+}
+
 DisplayError HWPrimary::Deinit() {
   exit_threads_ = true;
   pthread_join(event_thread_, NULL);
@@ -158,25 +230,40 @@
 }
 
 DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
-  return HWDevice::GetNumDisplayAttributes(count);
+  *count = isResolutionSwitchEnabled() ? display_configs_.size() : 1;
+  return kErrorNone;
 }
 
-DisplayError HWPrimary::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
-                                             uint32_t index) {
+DisplayError HWPrimary::GetActiveConfig(uint32_t *active_config_index) {
+  *active_config_index = active_config_index_;
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetDisplayAttributes(uint32_t index,
+                                             HWDisplayAttributes *display_attributes) {
   if (!display_attributes) {
     return kErrorParameters;
   }
 
+  if (isResolutionSwitchEnabled() && index >= display_configs_.size()) {
+    return kErrorParameters;
+  }
+
   if (config_changed_) {
     DisplayError error = PopulateDisplayAttributes();
     if (error != kErrorNone) {
       return error;
     }
-
     config_changed_ = false;
   }
 
   *display_attributes = display_attributes_;
+  if (isResolutionSwitchEnabled()) {
+    // Overwrite only the parent portion of object
+    display_attributes->x_pixels = display_configs_.at(index).x_pixels;
+    display_attributes->y_pixels = display_configs_.at(index).y_pixels;
+    display_attributes->fps = display_configs_.at(index).fps;
+  }
 
   return kErrorNone;
 }
@@ -231,7 +318,38 @@
 }
 
 DisplayError HWPrimary::SetDisplayAttributes(uint32_t index) {
-  return HWDevice::SetDisplayAttributes(index);
+  DisplayError ret = kErrorNone;
+
+  if (!isResolutionSwitchEnabled()) {
+    return kErrorNotSupported;
+  }
+
+  if (index >= display_configs_.size()) {
+    return kErrorParameters;
+  }
+
+  string mode_path = string(fb_path_) + string("0/mode");
+  int fd = Sys::open_(mode_path.c_str(), O_WRONLY);
+
+  if (fd < 0) {
+    DLOGE("Opening mode failed");
+    return kErrorNotSupported;
+  }
+
+  ssize_t written = Sys::pwrite_(fd, display_config_strings_.at(index).c_str(),
+                                 display_config_strings_.at(index).length(), 0);
+  if (written > 0) {
+    DLOGI("Successfully set config %u", index);
+    PopulateDisplayAttributes();
+    active_config_index_ = index;
+  } else {
+    DLOGE("Writing config index %u failed with error: %s", index, strerror(errno));
+    ret = kErrorParameters;
+  }
+
+  Sys::close_(fd);
+
+  return ret;
 }
 
 DisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) {
@@ -360,22 +478,18 @@
 
   while (!exit_threads_) {
     int error = Sys::poll_(poll_fds_, kNumDisplayEvents, -1);
-    if (error < 0) {
+    if (error <= 0) {
       DLOGW("poll failed. error = %s", strerror(errno));
       continue;
     }
+
     for (int event = 0; event < kNumDisplayEvents; event++) {
       pollfd &poll_fd = poll_fds_[event];
 
       if (poll_fd.revents & POLLPRI) {
-        ssize_t length = Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0);
-        if (length < 0) {
-          // If the read was interrupted - it is not a fatal error, just continue.
-          DLOGW("pread failed. event = %d, error = %s", event, strerror(errno));
-          continue;
+        if (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0) {
+          (this->*event_handler[event])(data);
         }
-
-        (this->*event_handler[event])(data);
       }
     }
   }
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 6006f35..2f052fc 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -26,11 +26,14 @@
 #define __HW_PRIMARY_H__
 
 #include <sys/poll.h>
+#include <vector>
+#include <string>
 
 #include "hw_device.h"
 
 namespace sdm {
 #define MAX_SYSFS_COMMAND_LENGTH 12
+struct DisplayConfigVariableInfo;
 
 class HWPrimary : public HWDevice {
  public:
@@ -43,8 +46,9 @@
   virtual DisplayError Init(HWEventHandler *eventhandler);
   virtual DisplayError Deinit();
   virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
-  virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
-                                            uint32_t index);
+  virtual DisplayError GetActiveConfig(uint32_t *active_config);
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
   virtual DisplayError PowerOff();
@@ -75,14 +79,19 @@
   void HandleIdleTimeout(char *data);
   void HandleThermal(char *data);
   DisplayError PopulateDisplayAttributes();
+  void InitializeConfigs();
+  bool isResolutionSwitchEnabled() { return !display_configs_.empty(); }
 
   pollfd poll_fds_[kNumDisplayEvents];
   pthread_t event_thread_;
-  const char *event_thread_name_;
-  bool fake_vsync_;
-  bool exit_threads_;
+  const char *event_thread_name_ = "SDM_EventThread";
+  bool fake_vsync_ = false;
+  bool exit_threads_ = false;
   HWDisplayAttributes display_attributes_;
-  bool config_changed_;
+  bool config_changed_ = true;
+  std::vector<DisplayConfigVariableInfo> display_configs_;
+  std::vector<std::string> display_config_strings_;
+  uint32_t active_config_index_ = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index e940d2b..c6e3e50 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -62,9 +62,10 @@
 
 class HWInterface {
  public:
+  virtual DisplayError GetActiveConfig(uint32_t *active_config) = 0;
   virtual DisplayError GetNumDisplayAttributes(uint32_t *count) = 0;
-  virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
-                                            uint32_t index) = 0;
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes) = 0;
   virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info) = 0;
   virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
   virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index) = 0;
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 0e81ed0..602c416 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -439,9 +439,11 @@
       int usage = GRALLOC_USAGE_HW_FB;
       int format = HAL_PIXEL_FORMAT_RGBA_8888;
       int ubwc_enabled = 0;
+      int flags = 0;
       HWCDebugHandler::Get()->GetProperty("debug.gralloc.enable_fb_ubwc", &ubwc_enabled);
       if (ubwc_enabled == 1) {
         usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+        flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
       }
 
       GetFrameBufferResolution(&x_pixels, &y_pixels);
@@ -450,6 +452,7 @@
                                                             usage, aligned_width, aligned_height);
       layer_buffer->width = aligned_width;
       layer_buffer->height = aligned_height;
+      layer_buffer->format = GetSDMFormat(format, flags);
       layer->frame_rate = fps;
     }
   }
@@ -1329,5 +1332,21 @@
   return;
 }
 
+int HWCDisplay::SetActiveDisplayConfig(int config) {
+  return display_intf_->SetActiveConfig(config) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
+  return display_intf_->GetActiveConfig(config) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayConfigCount(uint32_t *count) {
+  return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes) {
+  return display_intf_->GetConfig(config, attributes) == kErrorNone ? 0 : -1;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index b3d7055..edb7a81 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -42,10 +42,13 @@
   virtual int Commit(hwc_display_contents_1_t *content_list) = 0;
   virtual int EventControl(int event, int enable);
   virtual int SetPowerMode(int mode);
+
+  // Framebuffer configurations
   virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
   virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
   virtual int GetActiveConfig();
   virtual int SetActiveConfig(int index);
+
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
@@ -61,6 +64,12 @@
   virtual ~HWCDisplay() { }
   virtual void SetSecureDisplay(bool secure_display_active);
 
+  // Display Configurations
+  virtual int SetActiveDisplayConfig(int config);
+  virtual int GetActiveDisplayConfig(uint32_t *config);
+  virtual int GetDisplayConfigCount(uint32_t *count);
+  virtual int GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes);
+
   int SetPanelBrightness(int level);
   int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
                            PPDisplayAPIPayload *out_payload,
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index 5bcfb98..d1a0e0a 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -50,12 +50,6 @@
     return status;
   }
 
-  status = hwc_display_primary->SetPowerMode(HWC_POWER_MODE_NORMAL);
-  if (status) {
-    Destroy(hwc_display_primary);
-    return status;
-  }
-
   hwc_display_primary->GetPanelResolution(&primary_width, &primary_height);
   int width = 0, height = 0;
   HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 7a4361b..8fccf64 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -586,6 +586,22 @@
     status = ControlPartialUpdate(input_parcel, output_parcel);
     break;
 
+  case qService::IQService::SET_ACTIVE_CONFIG:
+    status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_ACTIVE_CONFIG:
+    status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_CONFIG_COUNT:
+    status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
+    status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
@@ -682,6 +698,93 @@
   return ret;
 }
 
+android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                     android::Parcel *output_parcel) {
+  int config = input_parcel->readInt32();
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
+    if (error == 0) {
+      hwc_procs_->invalidate(hwc_procs_);
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                           android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    uint32_t config = 0;
+    error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
+    if (error == 0) {
+      output_parcel->writeInt32(config);
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
+                                                          android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  uint32_t count = 0;
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
+    if (error == 0) {
+      output_parcel->writeInt32(count);
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
+                                                                  *input_parcel,
+                                                                  android::Parcel *output_parcel) {
+  int config = input_parcel->readInt32();
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+  DisplayConfigVariableInfo attributes;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &attributes);
+    if (error == 0) {
+      output_parcel->writeInt32(attributes.vsync_period_ns);
+      output_parcel->writeInt32(attributes.x_pixels);
+      output_parcel->writeInt32(attributes.y_pixels);
+      output_parcel->writeFloat(attributes.x_dpi);
+      output_parcel->writeFloat(attributes.y_dpi);
+      output_parcel->writeInt32(0);  // Panel type, unsupported.
+    }
+  }
+
+  return error;
+}
+
 android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel) {
   uint32_t display_id = UINT32(input_parcel->readInt32());
   uint32_t display_status = UINT32(input_parcel->readInt32());
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index cd54b15..e61e22d 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -65,6 +65,7 @@
   static int Query(hwc_composer_device_1 *device, int param, int *value);
   static void RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs);
   static void Dump(hwc_composer_device_1 *device, char *buffer, int length);
+  // These config functions always return FB params, the actual display params may differ.
   static int GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
                                size_t *numConfigs);
   static int GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
@@ -97,6 +98,15 @@
   android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out);
   android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
                                    android::Parcel *output_parcel);
+  // These functions return the actual display config info as opposed to FB
+  android::status_t HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel);
+  android::status_t HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel);
+  android::status_t HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
+                                                android::Parcel *output_parcel);
+  android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
+                                                        android::Parcel *output_parcel);
 
   static Locker locker_;
   CoreInterface *core_intf_ = NULL;
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
index 8350340..64183ae 100644
--- a/sdm/libs/utils/rect.cpp
+++ b/sdm/libs/utils/rect.cpp
@@ -138,6 +138,16 @@
   return res;
 }
 
+LayerRect Union(const LayerRectArray &rects) {
+  LayerRect res;
+
+  for (uint32_t i = 0; i < rects.count; i++) {
+    res = Union(rects.rect[i], res);
+  }
+
+  return res;
+}
+
 void SplitLeftRight(const LayerRect &in_rect, uint32_t split_count, uint32_t align_x,
                    LayerRect *out_rects) {
   LayerRect rect_temp = in_rect;