Merge "gralloc: Add support to RGB compressed format and handle error"
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..74fce80
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,6 @@
+# Clean old composer
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.graphics.composer@2.1-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.graphics.composer@2.1-service.rc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/lib64/hw/android.hardware.graphics.composer@2.1-impl.so)
+#Clean display includes
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/include/qcom/display)
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 3b019a3..3ba38c7 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -67,6 +67,7 @@
     case HAL_PIXEL_FORMAT_BLOB:
     case HAL_PIXEL_FORMAT_RAW_OPAQUE:
     case HAL_PIXEL_FORMAT_NV12_HEIF:
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
       return true;
     default:
       return false;
@@ -1003,6 +1004,9 @@
       offset[2] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
       (*num_planes)++;
       break;
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+      *num_planes = 1;
+      break;
     default:
       ALOGW("%s: Unsupported format", __FUNCTION__);
       ret = -EINVAL;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index a68c708..6b5b065 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -491,10 +491,6 @@
   return kErrorNone;
 }
 
-DisplayState DisplayBase::GetLastPowerMode() {
-  return last_power_mode_;
-}
-
 DisplayError DisplayBase::SetDisplayState(DisplayState state, bool teardown,
                                           int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
@@ -532,13 +528,11 @@
     }
 
     active = true;
-    last_power_mode_ = kStateOn;
     break;
 
   case kStateDoze:
     error = hw_intf_->Doze(default_qos_data_, release_fence);
     active = true;
-    last_power_mode_ = kStateDoze;
     break;
 
   case kStateDozeSuspend:
@@ -546,12 +540,10 @@
     if (display_type_ != kBuiltIn) {
       active = true;
     }
-    last_power_mode_ = kStateDozeSuspend;
     break;
 
   case kStateStandby:
     error = hw_intf_->Standby();
-    last_power_mode_ = kStateStandby;
     break;
 
   default:
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 609eeab..35c07a4 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -157,7 +157,6 @@
   DisplayError GetValueOfModeAttribute(const AttrVal &attr, const std::string &type,
                                        std::string *value);
   bool IsSupportColorModeAttribute(const std::string &color_mode);
-  DisplayState GetLastPowerMode();
   void SetPUonDestScaler();
   void ClearColorInfo();
   void GetColorPrimaryTransferFromAttributes(const AttrVal &attr,
@@ -209,7 +208,6 @@
   uint32_t req_mixer_height_ = 0;
   std::string current_color_mode_ = "hal_native";
   int disable_hdr_lut_gen_ = 0;
-  DisplayState last_power_mode_ = kStateOff;
   bool hw_recovery_logs_captured_ = false;
   int disable_hw_recovery_dump_ = 0;
   HWQosData default_qos_data_;
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 7503321..a28c57b 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -128,12 +128,6 @@
   uint32_t display_width = display_attributes_.x_pixels;
   uint32_t display_height = display_attributes_.y_pixels;
 
-  if (reset_panel_) {
-    DLOGW("panel is in bad state, resetting the panel");
-    ResetPanel();
-    reset_panel_ = false;
-  }
-
   if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
     error = ReconfigureMixer(new_mixer_width, new_mixer_height);
     if (error != kErrorNone) {
@@ -354,13 +348,6 @@
 
 void DisplayBuiltIn::PanelDead() {
   event_handler_->HandleEvent(kPanelDeadEvent);
-  event_handler_->Refresh();
-  {
-    lock_guard<recursive_mutex> obj(recursive_mutex_);
-    reset_panel_ = true;
-    // Handle IPC is clearing scalar and sspp luts, call same here.
-    comp_manager_->ProcessIdlePowerCollapse(display_comp_ctx_);
-  }
 }
 
 // HWEventHandler overload, not DisplayBase
@@ -423,39 +410,6 @@
            (!hw_panel_info_.dynamic_fps && hw_panel_info_.min_fps != hw_panel_info_.max_fps)));
 }
 
-void DisplayBuiltIn::ResetPanel() {
-  DisplayError status = kErrorNone;
-  int release_fence = -1;
-
-  DLOGI("Powering off built-in/primary %d", display_id_);
-  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);
-  }
-  CloseFd(&release_fence);
-
-  DLOGI("Restoring power mode on built-in/primary %d", display_id_);
-  DisplayState mode = GetLastPowerMode();
-  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);
-  }
-  CloseFd(&release_fence);
-
-  DLOGI("Enabling HWVsync");
-  status = SetVSyncState(true);
-  if (status != kErrorNone) {
-    DLOGE("enabling vsync failed for built-in/primary %d with error = %d", display_id_, status);
-  }
-
-  DLOGI("Set Color Mode %s", current_color_mode_.c_str());
-  status = SetColorMode(current_color_mode_);
-  if (status != kErrorNone) {
-    DLOGE("set color mode failed for display id %d with error = %d", display_id_, status);
-  }
-}
-
 DisplayError DisplayBuiltIn::DppsProcessOps(enum DppsOps op, void *payload, size_t size) {
   DisplayError error = kErrorNone;
   uint32_t pending;
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 8ae7426..76aedae 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -91,13 +91,11 @@
 
  private:
   bool NeedsAVREnable();
-  void ResetPanel();
 
   std::vector<HWEvent> event_list_;
   bool avr_prop_disabled_ = false;
   bool switch_to_cmd_ = false;
   bool handle_idle_timeout_ = false;
-  bool reset_panel_ = false;
   bool commit_event_enabled_ = false;
   DppsInfo dpps_info_ = {};
   QSyncMode qsync_mode_ = kQSyncModeNone;
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 7592f36..fb949cc 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1171,6 +1171,11 @@
   }
 }
 
+void HWDeviceDRM::ClearSolidfillStages() {
+  solid_fills_.clear();
+  SetSolidfillStages();
+}
+
 DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) {
   DTRACE_SCOPED();
 
@@ -1310,6 +1315,7 @@
 }
 
 DisplayError HWDeviceDRM::Flush(HWLayers *hw_layers) {
+  ClearSolidfillStages();
   int ret = NullCommit(secure_display_active_ /* synchronous */, false /* retain_planes*/);
   if (ret) {
     DLOGE("failed with error %d", ret);
@@ -1512,6 +1518,9 @@
         (refresh_rate == connector_info_.modes[mode_index].mode.vrefresh)) {
       vrefresh_ = refresh_rate;
       DLOGV_IF(kTagDriverConfig, "Set refresh rate to %d", refresh_rate);
+      SetDisplayAttributes(mode_index);
+      UpdateMixerAttributes();
+
       return kErrorNone;
     }
   }
@@ -1612,10 +1621,6 @@
 }
 
 DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
-  if (IsResolutionSwitchEnabled()) {
-    return kErrorNotSupported;
-  }
-
   if (!hw_resource_.hw_dest_scalar_info.count) {
     return kErrorNotSupported;
   }
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 054ff31..ecc92b5 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -141,6 +141,7 @@
   void UpdateMixerAttributes();
   void SetSolidfillStages();
   void AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha);
+  void ClearSolidfillStages();
   void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
   void SetSrcConfig(const LayerBuffer &input_buffer, const HWRotatorMode &mode, uint32_t *config);
   void SelectCscType(const LayerBuffer &input_buffer, sde_drm::DRMCscType *type);
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 59cae00..5147f3e 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -435,7 +435,7 @@
   DisplayConfigFixedInfo fixed_info = {};
   display_intf_->GetConfig(&fixed_info);
   is_cmd_mode_ = fixed_info.is_cmdmode;
-  partial_update_enabled_ = fixed_info.partial_update;
+  partial_update_enabled_ = fixed_info.partial_update || (!fixed_info.is_cmdmode);
   client_target_->SetPartialUpdate(partial_update_enabled_);
 
   DLOGI("Display created with id: %d", id_);
@@ -763,19 +763,15 @@
       if (tone_mapper_) {
         tone_mapper_->Terminate();
       }
-      last_power_mode_ = HWC2::PowerMode::Off;
       break;
     case HWC2::PowerMode::On:
       state = kStateOn;
-      last_power_mode_ = HWC2::PowerMode::On;
       break;
     case HWC2::PowerMode::Doze:
       state = kStateDoze;
-      last_power_mode_ = HWC2::PowerMode::Doze;
       break;
     case HWC2::PowerMode::DozeSuspend:
       state = kStateDozeSuspend;
-      last_power_mode_ = HWC2::PowerMode::DozeSuspend;
       break;
     default:
       return HWC2::Error::BadParameter;
@@ -811,6 +807,7 @@
     }
     ::close(release_fence);
   }
+  current_power_mode_ = mode;
   return HWC2::Error::None;
 }
 
@@ -1045,8 +1042,8 @@
   return HWC2::Error::None;
 }
 
-HWC2::PowerMode HWCDisplay::GetLastPowerMode() {
-  return last_power_mode_;
+HWC2::PowerMode HWCDisplay::GetCurrentPowerMode() {
+  return current_power_mode_;
 }
 
 HWC2::Vsync HWCDisplay::GetLastVsyncMode() {
@@ -1086,18 +1083,18 @@
       break;
     }
     case kThermalEvent:
-    case kIdlePowerCollapse:
-    case kPanelDeadEvent: {
+    case kIdlePowerCollapse: {
       SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[type_]);
       validated_ = false;
     } break;
+    case kPanelDeadEvent:
     case kDisplayPowerResetEvent: {
       validated_ = false;
       if (event_handler_) {
         event_handler_->DisplayPowerReset();
       } else {
-        DLOGI("Cannot process kDisplayPowerEventReset (display = %d), event_handler_ is nullptr",
-              type_);
+        DLOGW("Cannot execute DisplayPowerReset (client_id = %d), event_handler_ is nullptr",
+              id_);
       }
     } break;
     default:
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index f931987..4fff369 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -138,7 +138,7 @@
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
     return kErrorNotSupported;
   }
-  virtual HWC2::PowerMode GetLastPowerMode();
+  virtual HWC2::PowerMode GetCurrentPowerMode();
   virtual HWC2::Vsync GetLastVsyncMode();
   virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
   virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
@@ -281,8 +281,8 @@
   virtual HWC2::Error SetQSyncMode(QSyncMode qsync_mode) {
     return HWC2::Error::Unsupported;
   }
-  virtual HWC2::Error ControlIdlePowerCollapse(bool enable, bool synchronous) {
-    return HWC2::Error::Unsupported;
+  virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
+    return kErrorNone;
   }
 
  protected:
@@ -341,7 +341,7 @@
   uint32_t dump_frame_count_ = 0;
   uint32_t dump_frame_index_ = 0;
   bool dump_input_layers_ = false;
-  HWC2::PowerMode last_power_mode_ = HWC2::PowerMode::Off;
+  HWC2::PowerMode current_power_mode_ = HWC2::PowerMode::Off;
   HWC2::Vsync last_vsync_mode_ = HWC2::Vsync::Invalid;
   bool swap_interval_zero_ = false;
   bool display_paused_ = false;
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index e242128..b368ca7 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -755,15 +755,14 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplayBuiltIn::ControlIdlePowerCollapse(bool enable, bool synchronous) {
+DisplayError HWCDisplayBuiltIn::ControlIdlePowerCollapse(bool enable, bool synchronous) {
   DisplayError error = kErrorNone;
 
   if (display_intf_) {
     error = display_intf_->ControlIdlePowerCollapse(enable, synchronous);
     validated_ = false;
   }
-
-  return (error != kErrorNone) ?  HWC2::Error::Unsupported : HWC2::Error::None;
+  return error;
 }
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_builtin.h b/sdm/libs/hwc2/hwc_display_builtin.h
index 6616255..d9eca1a 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -79,7 +79,7 @@
                                         bool post_processed_output);
   virtual HWC2::Error GetReadbackBufferFence(int32_t *release_fence);
   virtual HWC2::Error SetQSyncMode(QSyncMode qsync_mode);
-  virtual HWC2::Error ControlIdlePowerCollapse(bool enable, bool synchronous);
+  virtual DisplayError 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);
 
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index c552137..7c48b24 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -73,6 +73,7 @@
 bool HWCSession::power_on_pending_[kNumDisplays];
 
 static const int kSolidFillDelay = 100 * 1000;
+int HWCSession::null_display_mode_ = 0;
 
 // Map the known color modes to dataspace.
 static int32_t GetDataspace(ColorMode mode) {
@@ -475,6 +476,14 @@
   }
 }
 
+uint32_t HWCSession::GetMaxVirtualDisplayCount(hwc2_device_t *device) {
+  if (device == nullptr) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
+  return null_display_mode_ ? 0 : 1;
+}
+
 static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
                                hwc2_config_t *out_config) {
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, out_config);
@@ -632,13 +641,6 @@
                                          out_max_average_luminance, out_min_luminance);
 }
 
-static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) {
-  if (device == nullptr) {
-    return HWC2_ERROR_BAD_PARAMETER;
-  }
-
-  return 1;
-}
 
 static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
                                 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
@@ -686,7 +688,7 @@
   // Handle pending builtin/pluggable display connections
   if (!hwc_session->primary_ready_ && (display == HWC_DISPLAY_PRIMARY)) {
     hwc_session->primary_ready_ = true;
-    hwc_session->CreateBuiltInDisplays();
+    hwc_session->HandleBuiltInDisplays();
     hwc_session->HandlePluggableDisplays(false);
   }
 
@@ -1023,7 +1025,7 @@
     case HWC2::FunctionDescriptor::GetDozeSupport:
       return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport);
     case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
-      return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(GetMaxVirtualDisplayCount);
+      return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(HWCSession::GetMaxVirtualDisplayCount);
     case HWC2::FunctionDescriptor::GetReleaseFences:
       return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences);
     case HWC2::FunctionDescriptor::PresentDisplay:
@@ -1101,6 +1103,12 @@
 
 HWC2::Error HWCSession::CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
                                                 hwc2_display_t *out_display_id) {
+  if (null_display_mode_) {
+    DLOGW("Virtual display creation attempted. Not supported in null-display mode."
+          " display_id is not set, and no real display object was created");
+    return HWC2::Error::None;
+  }
+
   if (!client_connected_) {
     DLOGE("Client is not ready yet.");
     return HWC2::Error::BadDisplay;
@@ -1191,7 +1199,7 @@
   }
   auto &hwc_display = hwc_display_[builtin_id];
   if (hwc_display) {
-    return hwc_display->GetLastPowerMode() != HWC2::PowerMode::Off;
+    return hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off;
   }
   return false;
 }
@@ -2154,10 +2162,20 @@
   int status = -EINVAL;
   HWDisplaysInfo hw_displays_info = {};
 
-  DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
-  if (error != kErrorNone) {
-    DLOGE("Failed to get connected display list. Error = %d", error);
-    return status;
+  if (null_display_mode_) {
+    HWDisplayInfo hw_info = {};
+    hw_info.display_type = kBuiltIn;
+    hw_info.is_connected = 1;
+    hw_info.is_primary = 1;
+    hw_info.is_wb_ubwc_supported = 0;
+    hw_info.display_id = 1;
+    hw_displays_info[hw_info.display_id] = hw_info;
+  } else {
+    DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+    if (error != kErrorNone) {
+      DLOGE("Failed to get connected display list. Error = %d", error);
+      return status;
+    }
   }
 
   for (auto &iter : hw_displays_info) {
@@ -2211,9 +2229,13 @@
   return status;
 }
 
-int HWCSession::CreateBuiltInDisplays() {
-  HWDisplaysInfo hw_displays_info = {};
+int HWCSession::HandleBuiltInDisplays() {
+  if (null_display_mode_) {
+    DLOGW("Skipped BuiltIn display handling in null-display mode");
+    return 0;
+  }
 
+  HWDisplaysInfo hw_displays_info = {};
   DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
   if (error != kErrorNone) {
     DLOGE("Failed to get connected display list. Error = %d", error);
@@ -2263,13 +2285,17 @@
 }
 
 int HWCSession::HandlePluggableDisplays(bool delay_hotplug) {
+  if (null_display_mode_) {
+    DLOGW("Skipped pluggable display handling in null-display mode");
+    return 0;
+  }
+
   if (!primary_ready_) {
     DLOGI("Primary display is not ready. Connect displays later if any.");
     return 0;
   }
 
   HWDisplaysInfo hw_displays_info = {};
-
   DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
   if (error != kErrorNone) {
     DLOGE("Failed to get connected display list. Error = %d", error);
@@ -2432,47 +2458,67 @@
 }
 
 void HWCSession::DestroyDisplay(DisplayMapInfo *map_info) {
-  hwc2_display_t client_id = map_info->client_id;
-  int notify_hotplug = false;
+  switch (map_info->disp_type) {
+    case kPluggable:
+      DestroyPluggableDisplay(map_info);
+      break;
+    default:
+      DestroyNonPluggableDisplay(map_info);
+      break;
+    }
+}
 
-  // Lock confined to this scope. Do not notify hotplug while holding a lock.
+void HWCSession::DestroyPluggableDisplay(DisplayMapInfo *map_info) {
+  hwc2_display_t client_id = map_info->client_id;
+
+  DLOGI("Notify hotplug display disconnected: client id = %d", client_id);
+  callbacks_.Hotplug(client_id, HWC2::Connection::Disconnected);
+  // wait for sufficient time to ensure sufficient resources are available to process
+  // connection.
+  usleep(UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)) * 2 / 1000);
+
   {
     SCOPE_LOCK(locker_[client_id]);
-
     auto &hwc_display = hwc_display_[client_id];
     if (!hwc_display) {
       return;
     }
-
     DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
-          client_id);
-    switch (map_info->disp_type) {
-      case kBuiltIn:
-        HWCDisplayBuiltIn::Destroy(hwc_display);
-        break;
+         client_id);
 
-      case kPluggable:
-        if (!map_info->test_pattern) {
-          HWCDisplayPluggable::Destroy(hwc_display);
-        } else {
-          HWCDisplayPluggableTest::Destroy(hwc_display);
-        }
-        notify_hotplug = true;
-        break;
-
-      default:
-        HWCDisplayVirtual::Destroy(hwc_display);
-        break;
+    if (!map_info->test_pattern) {
+      HWCDisplayPluggable::Destroy(hwc_display);
+    } else {
+      HWCDisplayPluggableTest::Destroy(hwc_display);
     }
+
     hwc_display = nullptr;
     map_info->Reset();
     UpdateVsyncSource();
   }
+}
 
-  if (notify_hotplug) {
-    DLOGI("Notify hotplug display disconnected: client id = %d", client_id);
-    callbacks_.Hotplug(client_id, HWC2::Connection::Disconnected);
+void HWCSession::DestroyNonPluggableDisplay(DisplayMapInfo *map_info) {
+  hwc2_display_t client_id = map_info->client_id;
+
+  SCOPE_LOCK(locker_[client_id]);
+  auto &hwc_display = hwc_display_[client_id];
+  if (!hwc_display) {
+    return;
   }
+  DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
+        client_id);
+  switch (map_info->disp_type) {
+    case kBuiltIn:
+      HWCDisplayBuiltIn::Destroy(hwc_display);
+      break;
+    default:
+      HWCDisplayVirtual::Destroy(hwc_display);
+      break;
+    }
+
+    hwc_display = nullptr;
+    map_info->Reset();
 }
 
 HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
@@ -2515,38 +2561,49 @@
 }
 
 void HWCSession::DisplayPowerReset() {
-  Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
-  Locker::ScopeLock lock_b2(locker_[HWC_DISPLAY_BUILTIN_2]);
-  Locker::ScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
-  Locker::ScopeLock lock_e2(locker_[HWC_DISPLAY_EXTERNAL_2]);
-  Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
+  {
+    Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
+    Locker::ScopeLock lock_b2(locker_[HWC_DISPLAY_BUILTIN_2]);
+    Locker::ScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
+    Locker::ScopeLock lock_e2(locker_[HWC_DISPLAY_EXTERNAL_2]);
+    Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
 
-  HWC2::Error status = HWC2::Error::None;
+    HWC2::Error status = HWC2::Error::None;
+    HWC2::PowerMode last_power_mode[HWC_NUM_DISPLAY_TYPES] = {};
 
-  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,
-                                                   true /* teardown */);
-      if (status != HWC2::Error::None) {
-        DLOGE("Power off for display = %d failed with error = %d", display, status);
+    for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < HWC_NUM_DISPLAY_TYPES; display++) {
+      if (hwc_display_[display] != NULL) {
+        last_power_mode[display] = hwc_display_[display]->GetCurrentPowerMode();
+        DLOGI("Powering off display = %d", display);
+        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);
+        }
       }
     }
-  }
-  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, false /* teardown */);
-      if (status != HWC2::Error::None) {
-        DLOGE("Power on for display = %d failed with error = %d", display, status);
+    for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < HWC_NUM_DISPLAY_TYPES; display++) {
+      if (hwc_display_[display] != NULL) {
+        HWC2::PowerMode mode = last_power_mode[display];
+        DLOGI("Setting display %d to mode = %d", display, mode);
+        status = hwc_display_[display]->SetPowerMode(mode, false /* teardown */);
+        if (status != HWC2::Error::None) {
+          DLOGE("%d mode for display = %d failed with error = %d", mode, display, status);
+        }
+        ColorMode color_mode = hwc_display_[display]->GetCurrentColorMode();
+        status = hwc_display_[display]->SetColorMode(color_mode);
+        if (status != HWC2::Error::None) {
+          DLOGE("SetColorMode failed for display = %d error = %d", display, status);
+        }
       }
     }
-  }
 
-  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetVsyncEnabled(HWC2::Vsync::Enable);
-  if (status != HWC2::Error::None) {
-    DLOGE("Enabling vsync failed for primary with error = %d", status);
+    status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetVsyncEnabled(HWC2::Vsync::Enable);
+    if (status != HWC2::Error::None) {
+      DLOGE("Enabling vsync failed for primary with error = %d", status);
+    }
   }
+  Refresh(HWC_DISPLAY_PRIMARY);
 }
 
 void HWCSession::HandleSecureSession(hwc2_display_t disp_id) {
@@ -2740,7 +2797,7 @@
   }
 
   callbacks_.SetSwapVsync(next_vsync_source, HWC_DISPLAY_PRIMARY);
-  HWC2::PowerMode power_mode = hwc_display_[next_vsync_source]->GetLastPowerMode();
+  HWC2::PowerMode power_mode = hwc_display_[next_vsync_source]->GetCurrentPowerMode();
 
   // Skip enabling vsync if display is Off, happens only for default source ie; primary.
   if (power_mode == HWC2::PowerMode::Off) {
@@ -2768,7 +2825,7 @@
       continue;
     }
 
-    if (hwc_display->GetLastPowerMode() != HWC2::PowerMode::Off) {
+    if (hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
       return info.client_id;
     }
   }
@@ -2791,8 +2848,8 @@
       return -EINVAL;
     }
     auto error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
-    if (error != HWC2::Error::None) {
-      return -EINVAL;
+    if (error != kErrorNone) {
+      return (error == kErrorNotSupported) ? 0 : -EINVAL;
     }
     if (!enable) {
       Refresh(HWC_DISPLAY_PRIMARY);
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 20c537b..b71bf3f 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -203,6 +203,7 @@
                                    const native_handle_t *buffer, int32_t acquire_fence);
   static int32_t GetReadbackBufferFence(hwc2_device_t *device, hwc2_display_t display,
                                         int32_t *release_fence);
+  static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device);
 
   // HWCDisplayEventHandler
   virtual void DisplayPowerReset();
@@ -244,11 +245,13 @@
   void InitDisplaySlots();
   int GetDisplayIndex(int dpy);
   int CreatePrimaryDisplay();
-  int CreateBuiltInDisplays();
+  int HandleBuiltInDisplays();
   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);
+  void DestroyPluggableDisplay(DisplayMapInfo *map_info);
+  void DestroyNonPluggableDisplay(DisplayMapInfo *map_info);
   int GetVsyncPeriod(int disp);
   int32_t GetConfigCount(int disp_id, uint32_t *count);
   int32_t GetActiveConfigIndex(int disp_id, uint32_t *config);
@@ -377,8 +380,8 @@
   Locker callbacks_lock_;
   int hpd_bpp_ = 0;
   int hpd_pattern_ = 0;
-  int null_display_mode_ = 0;
   static bool power_on_pending_[kNumDisplays];
+  static int null_display_mode_;
   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 c00fc58..6fb1ec2 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -600,10 +600,9 @@
   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
     if (!enable) {
       if (!idle_pc_ref_cnt_) {
-        HWC2::Error err =
-            hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
-        if (err != HWC2::Error::None) {
-          return (err == HWC2::Error::Unsupported) ? 0 : -EINVAL;
+        auto err = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
+        if (err != kErrorNone) {
+          return (err == kErrorNotSupported) ? 0 : -EINVAL;
         }
         Refresh(HWC_DISPLAY_PRIMARY);
         int32_t error = locker_[HWC_DISPLAY_PRIMARY].WaitFinite(kCommitDoneTimeoutMs);
@@ -616,10 +615,9 @@
       idle_pc_ref_cnt_++;
     } else if (idle_pc_ref_cnt_ > 0) {
       if (!(idle_pc_ref_cnt_ - 1)) {
-        HWC2::Error err =
-            hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
-        if (err != HWC2::Error::None) {
-          return (err == HWC2::Error::Unsupported) ? 0 : -EINVAL;
+        auto err = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
+        if (err != kErrorNone) {
+          return (err == kErrorNotSupported) ? 0 : -EINVAL;
         }
         DLOGI("Idle PC enabled!!");
       }