hwc2: Add support for multiple displays

- Add support for an additional display which can be either a builtin
  display or pluggable display.
- Restructure HWCDisplayPrimary as HWCBuiltIn and HWCDisplayExternal
  as HWCDisplayPluggable.
- Refactor hotplug handling. Iterate through all pluggable displays,
  and check present connection status. Connect/disconnect a given
  display if connection status has changed.

CRs-Fixed: 2200594
Change-Id: Ibd2f93ddfbe72af58220691ad481469c8fdcbf86
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index d9ffa0b..a8f259b 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -30,12 +30,16 @@
 ifeq ($(display_config_version), DISPLAY_CONFIG_1_1)
 LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
 endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_2)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2 vendor.display.config@1.1
+endif
 
 LOCAL_SRC_FILES               := hwc_session.cpp \
                                  hwc_session_services.cpp \
                                  hwc_display.cpp \
-                                 hwc_display_primary.cpp \
-                                 hwc_display_external.cpp \
+                                 hwc_display_builtin.cpp \
+                                 hwc_display_pluggable.cpp \
+                                 hwc_display_pluggable_test.cpp \
                                  hwc_display_virtual.cpp \
                                  hwc_debugger.cpp \
                                  hwc_buffer_sync_handler.cpp \
@@ -46,8 +50,7 @@
                                  hwc_tonemapper.cpp \
                                  display_null.cpp \
                                  hwc_socket_handler.cpp \
-                                 hwc_buffer_allocator.cpp \
-                                 hwc_display_external_test.cpp
+                                 hwc_buffer_allocator.cpp
 
 include $(BUILD_SHARED_LIBRARY)
 endif
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index 1b4e15a..31c876f 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -199,14 +199,14 @@
       FLOAT(solid_fill_params_.rect.y) + FLOAT(solid_fill_params_.rect.height),
     };
 
-    hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, &solid_fill_color);
-    hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect);
+    hwc_display->Perform(HWCDisplayBuiltIn::SET_QDCM_SOLID_FILL_INFO, &solid_fill_color);
+    hwc_display->Perform(HWCDisplayBuiltIn::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect);
   } else {
     solid_fill_color.red = 0;
     solid_fill_color.blue = 0;
     solid_fill_color.green = 0;
     solid_fill_color.alpha = 0;
-    hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, &solid_fill_color);
+    hwc_display->Perform(HWCDisplayBuiltIn::UNSET_QDCM_SOLID_FILL_INFO, &solid_fill_color);
   }
 
   return 0;
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index ef65057..002d7f9 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -315,15 +315,16 @@
   *os << std::endl;
 }
 
-HWCDisplay::HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks,
-                       HWCDisplayEventHandler* event_handler, DisplayType type, hwc2_display_t id,
-                       bool needs_blit, qService::QService *qservice, DisplayClass display_class,
-                       BufferAllocator *buffer_allocator)
+HWCDisplay::HWCDisplay(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+                       HWCCallbacks *callbacks, HWCDisplayEventHandler* event_handler,
+                       qService::QService *qservice, DisplayType type, hwc2_display_t id,
+                       int32_t sdm_id, bool needs_blit, DisplayClass display_class)
     : core_intf_(core_intf),
       callbacks_(callbacks),
       event_handler_(event_handler),
       type_(type),
       id_(id),
+      sdm_id_(sdm_id),
       needs_blit_(needs_blit),
       qservice_(qservice),
       display_class_(display_class) {
@@ -342,10 +343,10 @@
     display_intf_ = disp_null;
     DLOGI("Enabling null display mode for display type %d", type_);
   } else {
-    error = core_intf_->CreateDisplay(type_, this, &display_intf_);
+    error = core_intf_->CreateDisplay(sdm_id_, this, &display_intf_);
     if (error != kErrorNone) {
-      DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
-            error, type_, this, &display_intf_);
+      DLOGE("Display create failed. Error = %d display_id = %d event_handler = %p disp_intf = %p",
+            error, sdm_id_, this, &display_intf_);
       return -EINVAL;
     }
   }
@@ -855,14 +856,14 @@
   }
 
   std::string name;
-  switch (id_) {
-    case HWC_DISPLAY_PRIMARY:
-      name = "Primary Display";
+  switch (type_) {
+    case kBuiltIn:
+      name = "Built-in Display";
       break;
-    case HWC_DISPLAY_EXTERNAL:
-      name = "External Display";
+    case kPluggable:
+      name = "Pluggable Display";
       break;
-    case HWC_DISPLAY_VIRTUAL:
+    case kVirtual:
       name = "Virtual Display";
       break;
     default:
@@ -886,16 +887,13 @@
 }
 
 HWC2::Error HWCDisplay::GetDisplayType(int32_t *out_type) {
-  if (out_type != nullptr) {
-    if (id_ == HWC_DISPLAY_VIRTUAL) {
-      *out_type = HWC2_DISPLAY_TYPE_VIRTUAL;
-    } else {
-      *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
-    }
-    return HWC2::Error::None;
-  } else {
+  if (out_type == nullptr) {
     return HWC2::Error::BadParameter;
   }
+
+  *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
+
+  return HWC2::Error::None;
 }
 
 HWC2::Error HWCDisplay::GetPerFrameMetadataKeys(uint32_t *out_num_keys,
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index b4bb554..9c09ab0 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -53,8 +53,8 @@
 // Subclasses set this to their type. This has to be different from DisplayType.
 // This is to avoid RTTI and dynamic_cast
 enum DisplayClass {
-  DISPLAY_CLASS_PRIMARY,
-  DISPLAY_CLASS_EXTERNAL,
+  DISPLAY_CLASS_BUILTIN,
+  DISPLAY_CLASS_PLUGGABLE,
   DISPLAY_CLASS_VIRTUAL,
   DISPLAY_CLASS_NULL
 };
@@ -272,10 +272,9 @@
   // Maximum number of layers supported by display manager.
   static const uint32_t kMaxLayerCount = 32;
 
-  HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks,
-             HWCDisplayEventHandler *event_handler, DisplayType type, hwc2_display_t id,
-             bool needs_blit, qService::QService *qservice, DisplayClass display_class,
-             BufferAllocator *buffer_allocator);
+  HWCDisplay(CoreInterface *core_intf, BufferAllocator *buffer_allocator, HWCCallbacks *callbacks,
+             HWCDisplayEventHandler *event_handler, qService::QService *qservice, DisplayType type,
+             hwc2_display_t id, int32_t sdm_id, bool needs_blit, DisplayClass display_class);
 
   // DisplayEventHandler methods
   virtual DisplayError VSync(const DisplayEventVSync &vsync);
@@ -307,11 +306,12 @@
   bool validated_ = false;
   bool layer_stack_invalid_ = true;
   CoreInterface *core_intf_ = nullptr;
+  HWCBufferAllocator *buffer_allocator_ = NULL;
   HWCCallbacks *callbacks_  = nullptr;
   HWCDisplayEventHandler *event_handler_ = nullptr;
-  HWCBufferAllocator *buffer_allocator_ = NULL;
-  DisplayType type_;
-  hwc2_display_t id_;
+  DisplayType type_ = kDisplayTypeMax;
+  hwc2_display_t id_ = UINT64_MAX;
+  int32_t sdm_id_ = -1;
   bool needs_blit_ = false;
   DisplayInterface *display_intf_ = NULL;
   LayerStack layer_stack_;
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
similarity index 84%
rename from sdm/libs/hwc2/hwc_display_primary.cpp
rename to sdm/libs/hwc2/hwc_display_builtin.cpp
index e285c04..f841dbc 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -39,62 +39,66 @@
 #include <string>
 #include <vector>
 
-#include "hwc_display_primary.h"
+#include "hwc_display_builtin.h"
 #include "hwc_debugger.h"
 
-#define __CLASS__ "HWCDisplayPrimary"
+#define __CLASS__ "HWCDisplayBuiltIn"
 
 namespace sdm {
 
-int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+int HWCDisplayBuiltIn::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
                               HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                              qService::QService *qservice, HWCDisplay **hwc_display) {
+                              qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
+                              HWCDisplay **hwc_display) {
   int status = 0;
-  uint32_t primary_width = 0;
-  uint32_t primary_height = 0;
+  uint32_t builtin_width = 0;
+  uint32_t builtin_height = 0;
 
-  HWCDisplay *hwc_display_primary =
-      new HWCDisplayPrimary(core_intf, buffer_allocator, callbacks, event_handler, qservice);
-  status = hwc_display_primary->Init();
+  HWCDisplay *hwc_display_builtin =
+      new HWCDisplayBuiltIn(core_intf, buffer_allocator, callbacks, event_handler, qservice, id,
+                            sdm_id);
+  status = hwc_display_builtin->Init();
   if (status) {
-    delete hwc_display_primary;
+    delete hwc_display_builtin;
     return status;
   }
 
-  hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
+  hwc_display_builtin->GetMixerResolution(&builtin_width, &builtin_height);
   int width = 0, height = 0;
   HWCDebugHandler::Get()->GetProperty(FB_WIDTH_PROP, &width);
   HWCDebugHandler::Get()->GetProperty(FB_HEIGHT_PROP, &height);
   if (width > 0 && height > 0) {
-    primary_width = UINT32(width);
-    primary_height = UINT32(height);
+    builtin_width = UINT32(width);
+    builtin_height = UINT32(height);
   }
 
-  status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
+  status = hwc_display_builtin->SetFrameBufferResolution(builtin_width, builtin_height);
   if (status) {
-    Destroy(hwc_display_primary);
+    Destroy(hwc_display_builtin);
     return status;
   }
 
-  *hwc_display = hwc_display_primary;
+  *hwc_display = hwc_display_builtin;
 
   return status;
 }
 
-void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
+void HWCDisplayBuiltIn::Destroy(HWCDisplay *hwc_display) {
   hwc_display->Deinit();
   delete hwc_display;
 }
 
-HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+HWCDisplayBuiltIn::HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
                                      HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                                     qService::QService *qservice)
-  : HWCDisplay(core_intf, callbacks, event_handler, kPrimary, HWC_DISPLAY_PRIMARY, true,
-               qservice, DISPLAY_CLASS_PRIMARY, buffer_allocator),
-               buffer_allocator_(buffer_allocator), cpu_hint_(NULL) {
+                                     qService::QService *qservice, hwc2_display_t id,
+                                     int32_t sdm_id)
+    : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kBuiltIn, id,
+                 sdm_id, true, DISPLAY_CLASS_BUILTIN),
+      buffer_allocator_(buffer_allocator),
+      cpu_hint_(NULL) {
 }
 
-int HWCDisplayPrimary::Init() {
+int HWCDisplayBuiltIn::Init() {
   cpu_hint_ = new CPUHint();
   if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
     delete cpu_hint_;
@@ -120,7 +124,7 @@
   return status;
 }
 
-void HWCDisplayPrimary::ProcessBootAnimCompleted() {
+void HWCDisplayBuiltIn::ProcessBootAnimCompleted() {
   uint32_t numBootUpLayers = 0;
   // TODO(user): Remove this hack
 
@@ -161,7 +165,7 @@
   }
 }
 
-HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+HWC2::Error HWCDisplayBuiltIn::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
   auto status = HWC2::Error::None;
   DisplayError error = kErrorNone;
 
@@ -229,7 +233,7 @@
   return status;
 }
 
-HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
+HWC2::Error HWCDisplayBuiltIn::Present(int32_t *out_retire_fence) {
   auto status = HWC2::Error::None;
   if (display_paused_) {
     DisplayError error = display_intf_->Flush();
@@ -250,7 +254,7 @@
   return status;
 }
 
-HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
+HWC2::Error HWCDisplayBuiltIn::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
   if (out_modes == nullptr) {
     *out_num_modes = color_mode_->GetColorModeCount();
   } else {
@@ -260,7 +264,7 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplayPrimary::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+HWC2::Error HWCDisplayBuiltIn::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
                                                 RenderIntent *out_intents) {
   if (out_intents == nullptr) {
     *out_num_intents = color_mode_->GetRenderIntentCount(mode);
@@ -270,11 +274,11 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplayPrimary::SetColorMode(ColorMode mode) {
+HWC2::Error HWCDisplayBuiltIn::SetColorMode(ColorMode mode) {
   return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
 }
 
-HWC2::Error HWCDisplayPrimary::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
+HWC2::Error HWCDisplayBuiltIn::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
   auto status = color_mode_->SetColorModeWithRenderIntent(mode, intent);
   if (status != HWC2::Error::None) {
     DLOGE("failed for mode = %d intent = %d", mode, intent);
@@ -285,7 +289,7 @@
   return status;
 }
 
-HWC2::Error HWCDisplayPrimary::SetColorModeById(int32_t color_mode_id) {
+HWC2::Error HWCDisplayBuiltIn::SetColorModeById(int32_t color_mode_id) {
   auto status = color_mode_->SetColorModeById(color_mode_id);
   if (status != HWC2::Error::None) {
     DLOGE("failed for mode = %d", color_mode_id);
@@ -298,7 +302,7 @@
   return status;
 }
 
-HWC2::Error HWCDisplayPrimary::RestoreColorTransform() {
+HWC2::Error HWCDisplayBuiltIn::RestoreColorTransform() {
   auto status = color_mode_->RestoreColorTransform();
   if (status != HWC2::Error::None) {
     DLOGE("failed to RestoreColorTransform");
@@ -310,7 +314,7 @@
   return status;
 }
 
-HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
+HWC2::Error HWCDisplayBuiltIn::SetColorTransform(const float *matrix,
                                                  android_color_transform_t hint) {
   if (!matrix) {
     return HWC2::Error::BadParameter;
@@ -330,7 +334,7 @@
   return status;
 }
 
-HWC2::Error HWCDisplayPrimary::SetReadbackBuffer(const native_handle_t *buffer,
+HWC2::Error HWCDisplayBuiltIn::SetReadbackBuffer(const native_handle_t *buffer,
                                                  int32_t acquire_fence,
                                                  bool post_processed_output) {
   const private_handle_t *handle = reinterpret_cast<const private_handle_t *>(buffer);
@@ -358,7 +362,7 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplayPrimary::GetReadbackBufferFence(int32_t *release_fence) {
+HWC2::Error HWCDisplayBuiltIn::GetReadbackBufferFence(int32_t *release_fence) {
   auto status = HWC2::Error::None;
 
   if (readback_configured_ && (output_buffer_.release_fence_fd >= 0)) {
@@ -376,7 +380,7 @@
   return status;
 }
 
-int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
+int HWCDisplayBuiltIn::Perform(uint32_t operation, ...) {
   va_list args;
   va_start(args, operation);
   int val = 0;
@@ -419,7 +423,7 @@
   return 0;
 }
 
-DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+DisplayError HWCDisplayBuiltIn::SetDisplayMode(uint32_t mode) {
   DisplayError error = kErrorNone;
 
   if (display_intf_) {
@@ -429,7 +433,7 @@
   return error;
 }
 
-void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+void HWCDisplayBuiltIn::SetMetaDataRefreshRateFlag(bool enable) {
   int disable_metadata_dynfps = 0;
 
   HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
@@ -439,12 +443,12 @@
   use_metadata_refresh_rate_ = enable;
 }
 
-void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, const LayerSolidFill &color) {
+void HWCDisplayBuiltIn::SetQDCMSolidFillInfo(bool enable, const LayerSolidFill &color) {
   solid_fill_enable_ = enable;
   solid_fill_color_ = color;
 }
 
-void HWCDisplayPrimary::ToggleCPUHint(bool set) {
+void HWCDisplayBuiltIn::ToggleCPUHint(bool set) {
   if (!cpu_hint_) {
     return;
   }
@@ -456,7 +460,7 @@
   }
 }
 
-int HWCDisplayPrimary::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
+int HWCDisplayBuiltIn::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
                                            bool *power_on_pending) {
   if (!power_on_pending) {
     return -EINVAL;
@@ -480,7 +484,7 @@
   return 0;
 }
 
-void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
+void HWCDisplayBuiltIn::ForceRefreshRate(uint32_t refresh_rate) {
   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
@@ -494,7 +498,7 @@
   return;
 }
 
-uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
+uint32_t HWCDisplayBuiltIn::GetOptimalRefreshRate(bool one_updating_layer) {
   if (force_refresh_rate_) {
     return force_refresh_rate_;
   } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
@@ -504,7 +508,7 @@
   return max_refresh_rate_;
 }
 
-DisplayError HWCDisplayPrimary::Refresh() {
+DisplayError HWCDisplayBuiltIn::Refresh() {
   DisplayError error = kErrorNone;
 
   callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
@@ -512,12 +516,12 @@
   return error;
 }
 
-void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+void HWCDisplayBuiltIn::SetIdleTimeoutMs(uint32_t timeout_ms) {
   display_intf_->SetIdleTimeoutMs(timeout_ms);
   validated_ = false;
 }
 
-void HWCDisplayPrimary::HandleFrameOutput() {
+void HWCDisplayBuiltIn::HandleFrameOutput() {
   if (readback_buffer_queued_) {
     validated_ = false;
   }
@@ -527,7 +531,7 @@
   }
 }
 
-void HWCDisplayPrimary::HandleFrameDump() {
+void HWCDisplayBuiltIn::HandleFrameDump() {
   if (!readback_configured_) {
     dump_frame_count_ = 0;
   }
@@ -565,7 +569,7 @@
   }
 }
 
-HWC2::Error HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+HWC2::Error HWCDisplayBuiltIn::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
   HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
   dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
   DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
@@ -604,7 +608,7 @@
   return HWC2::Error::None;
 }
 
-int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
+int HWCDisplayBuiltIn::FrameCaptureAsync(const BufferInfo &output_buffer_info,
                                          bool post_processed_output) {
   // Note: This function is called in context of a binder thread and a lock is already held
   if (output_buffer_info.alloc_buffer_info.fd < 0) {
@@ -636,11 +640,11 @@
   return 0;
 }
 
-bool HWCDisplayPrimary::GetFrameCaptureFence(int32_t *release_fence) {
+bool HWCDisplayBuiltIn::GetFrameCaptureFence(int32_t *release_fence) {
   return (GetReadbackBufferFence(release_fence) == HWC2::Error::None);
 }
 
-DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
+DisplayError HWCDisplayBuiltIn::SetDetailEnhancerConfig
                                    (const DisplayDetailEnhancerData &de_data) {
   DisplayError error = kErrorNotSupported;
 
@@ -651,7 +655,7 @@
   return error;
 }
 
-DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+DisplayError HWCDisplayBuiltIn::ControlPartialUpdate(bool enable, uint32_t *pending) {
   DisplayError error = kErrorNone;
 
   if (display_intf_) {
@@ -662,7 +666,7 @@
   return error;
 }
 
-DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
+DisplayError HWCDisplayBuiltIn::DisablePartialUpdateOneFrame() {
   DisplayError error = kErrorNone;
 
   if (display_intf_) {
@@ -674,17 +678,17 @@
 }
 
 
-DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
+DisplayError HWCDisplayBuiltIn::SetMixerResolution(uint32_t width, uint32_t height) {
   DisplayError error = display_intf_->SetMixerResolution(width, height);
   validated_ = false;
   return error;
 }
 
-DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
+DisplayError HWCDisplayBuiltIn::GetMixerResolution(uint32_t *width, uint32_t *height) {
   return display_intf_->GetMixerResolution(width, height);
 }
 
-HWC2::Error HWCDisplayPrimary::SetQSyncMode(QSyncMode qsync_mode) {
+HWC2::Error HWCDisplayBuiltIn::SetQSyncMode(QSyncMode qsync_mode) {
   auto err = display_intf_->SetQSyncMode(qsync_mode);
   if (err != kErrorNone) {
     return HWC2::Error::Unsupported;
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_builtin.h
similarity index 89%
rename from sdm/libs/hwc2/hwc_display_primary.h
rename to sdm/libs/hwc2/hwc_display_builtin.h
index 8957855..7cda451 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -27,8 +27,8 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef __HWC_DISPLAY_PRIMARY_H__
-#define __HWC_DISPLAY_PRIMARY_H__
+#ifndef __HWC_DISPLAY_BUILTIN_H__
+#define __HWC_DISPLAY_BUILTIN_H__
 
 #include <string>
 
@@ -37,7 +37,7 @@
 
 namespace sdm {
 
-class HWCDisplayPrimary : public HWCDisplay {
+class HWCDisplayBuiltIn : public HWCDisplay {
  public:
   enum {
     SET_METADATA_DYN_REFRESH_RATE,
@@ -49,8 +49,9 @@
   };
 
   static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
-                    HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                    qService::QService *qservice, HWCDisplay **hwc_display);
+                    HWCCallbacks *callbacks,  HWCDisplayEventHandler *event_handler,
+                    qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
+                    HWCDisplay **hwc_display);
   static void Destroy(HWCDisplay *hwc_display);
   virtual int Init();
   virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
@@ -79,9 +80,9 @@
   virtual HWC2::Error SetQSyncMode(QSyncMode qsync_mode);
 
  private:
-  HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+  HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
                     HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                    qService::QService *qservice);
+                    qService::QService *qservice, hwc2_display_t id, int32_t sdm_id);
   void SetMetaDataRefreshRateFlag(bool enable);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError DisablePartialUpdateOneFrame();
@@ -98,7 +99,7 @@
   BufferAllocator *buffer_allocator_ = nullptr;
   CPUHint *cpu_hint_ = nullptr;
 
-  // Primary readback buffer configuration
+  // Builtin readback buffer configuration
   LayerBuffer output_buffer_ = {};
   bool post_processed_output_ = false;
   bool readback_buffer_queued_ = false;
@@ -113,4 +114,4 @@
 
 }  // namespace sdm
 
-#endif  // __HWC_DISPLAY_PRIMARY_H__
+#endif  // __HWC_DISPLAY_BUILTIN_H__
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_pluggable.cpp
similarity index 74%
rename from sdm/libs/hwc2/hwc_display_external.cpp
rename to sdm/libs/hwc2/hwc_display_pluggable.cpp
index ad18868..7d22642 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_pluggable.cpp
@@ -32,70 +32,63 @@
 #include <utils/debug.h>
 #include <algorithm>
 
-#include "hwc_display_external.h"
+#include "hwc_display_pluggable.h"
 #include "hwc_debugger.h"
 
-#define __CLASS__ "HWCDisplayExternal"
+#define __CLASS__ "HWCDisplayPluggable"
 
 namespace sdm {
 
-int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+int HWCDisplayPluggable::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
                                HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                               qService::QService *qservice, HWCDisplay **hwc_display) {
-  return Create(core_intf, buffer_allocator, callbacks, event_handler, 0, 0, qservice, false,
-                hwc_display);
-}
-
-int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
-                               HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+                               qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
                                uint32_t primary_width, uint32_t primary_height,
-                               qService::QService *qservice, bool use_primary_res,
-                               HWCDisplay **hwc_display) {
-  uint32_t external_width = 0;
-  uint32_t external_height = 0;
+                               bool use_primary_res, HWCDisplay **hwc_display) {
+  uint32_t pluggable_width = 0;
+  uint32_t pluggable_height = 0;
   DisplayError error = kErrorNone;
 
-  HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, buffer_allocator, callbacks,
-                                                            event_handler, qservice);
-  int status = hwc_display_external->Init();
+  HWCDisplay *hwc_display_pluggable = new HWCDisplayPluggable(core_intf, buffer_allocator,
+                                                  callbacks, event_handler, qservice, id, sdm_id);
+  int status = hwc_display_pluggable->Init();
   if (status) {
-    delete hwc_display_external;
+    delete hwc_display_pluggable;
     return status;
   }
 
-  error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
+  error = hwc_display_pluggable->GetMixerResolution(&pluggable_width, &pluggable_height);
   if (error != kErrorNone) {
-    Destroy(hwc_display_external);
+    Destroy(hwc_display_pluggable);
     return -EINVAL;
   }
 
   if (primary_width && primary_height) {
-    // use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
+    // use_primary_res means HWCDisplayPluggable should directly set framebuffer resolution to the
     // provided primary_width and primary_height
     if (use_primary_res) {
-      external_width = primary_width;
-      external_height = primary_height;
+      pluggable_width = primary_width;
+      pluggable_height = primary_height;
     } else {
       int downscale_enabled = 0;
       HWCDebugHandler::Get()->GetProperty(ENABLE_EXTERNAL_DOWNSCALE_PROP, &downscale_enabled);
       if (downscale_enabled) {
-        GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
+        GetDownscaleResolution(primary_width, primary_height, &pluggable_width, &pluggable_height);
       }
     }
   }
 
-  status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
+  status = hwc_display_pluggable->SetFrameBufferResolution(pluggable_width, pluggable_height);
   if (status) {
-    Destroy(hwc_display_external);
+    Destroy(hwc_display_pluggable);
     return status;
   }
 
-  *hwc_display = hwc_display_external;
+  *hwc_display = hwc_display_pluggable;
 
   return status;
 }
 
-int HWCDisplayExternal::Init() {
+int HWCDisplayPluggable::Init() {
   int status = HWCDisplay::Init();
   if (status) {
     return status;
@@ -106,21 +99,25 @@
   return status;
 }
 
-void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
+void HWCDisplayPluggable::Destroy(HWCDisplay *hwc_display) {
+  // Flush the display to have outstanding fences signaled.
+  hwc_display->Flush();
   hwc_display->Deinit();
   delete hwc_display;
 }
 
-HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf,
-                                       HWCBufferAllocator *buffer_allocator,
-                                       HWCCallbacks *callbacks,
-                                       HWCDisplayEventHandler *event_handler,
-                                       qService::QService *qservice)
-    : HWCDisplay(core_intf, callbacks, event_handler, kHDMI, HWC_DISPLAY_EXTERNAL, false,
-                 qservice, DISPLAY_CLASS_EXTERNAL, buffer_allocator) {
+HWCDisplayPluggable::HWCDisplayPluggable(CoreInterface *core_intf,
+                                         HWCBufferAllocator *buffer_allocator,
+                                         HWCCallbacks *callbacks,
+                                         HWCDisplayEventHandler *event_handler,
+                                         qService::QService *qservice,
+                                         hwc2_display_t id,
+                                         int32_t sdm_id)
+    : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kPluggable, id,
+                 sdm_id, false, DISPLAY_CLASS_PLUGGABLE) {
 }
 
-HWC2::Error HWCDisplayExternal::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+HWC2::Error HWCDisplayPluggable::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
   auto status = HWC2::Error::None;
 
   if (active_secure_sessions_[kSecureDisplay]) {
@@ -149,7 +146,7 @@
   return status;
 }
 
-HWC2::Error HWCDisplayExternal::Present(int32_t *out_retire_fence) {
+HWC2::Error HWCDisplayPluggable::Present(int32_t *out_retire_fence) {
   auto status = HWC2::Error::None;
 
   if (!active_secure_sessions_[kSecureDisplay]) {
@@ -161,7 +158,7 @@
   return status;
 }
 
-void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+void HWCDisplayPluggable::ApplyScanAdjustment(hwc_rect_t *display_frame) {
   if ((underscan_width_ <= 0) || (underscan_height_ <= 0)) {
     return;
   }
@@ -200,7 +197,7 @@
   *src_width = dst_width;
 }
 
-void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+void HWCDisplayPluggable::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
                                                 uint32_t *non_primary_width,
                                                 uint32_t *non_primary_height) {
   uint32_t primary_area = primary_width * primary_height;
@@ -214,7 +211,7 @@
   }
 }
 
-int HWCDisplayExternal::SetState(bool connected) {
+int HWCDisplayPluggable::SetState(bool connected) {
   DisplayError error = kErrorNone;
   DisplayState state = kStateOff;
   DisplayConfigVariableInfo fb_config = {};
@@ -283,7 +280,7 @@
   return 0;
 }
 
-void HWCDisplayExternal::GetUnderScanConfig() {
+void HWCDisplayPluggable::GetUnderScanConfig() {
   if (!display_intf_->IsUnderscanSupported()) {
     // Read user defined underscan width and height
     HWCDebugHandler::Get()->GetProperty(EXTERNAL_ACTION_SAFE_WIDTH_PROP, &underscan_width_);
@@ -291,11 +288,11 @@
   }
 }
 
-DisplayError HWCDisplayExternal::Flush() {
+DisplayError HWCDisplayPluggable::Flush() {
   return display_intf_->Flush();
 }
 
-HWC2::Error HWCDisplayExternal::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
+HWC2::Error HWCDisplayPluggable::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
   if (out_modes == nullptr) {
     *out_num_modes = color_mode_->GetColorModeCount();
   } else {
@@ -304,7 +301,7 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplayExternal::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+HWC2::Error HWCDisplayPluggable::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
                                                  RenderIntent *out_intents) {
   if (out_intents == nullptr) {
     *out_num_intents = color_mode_->GetRenderIntentCount(mode);
@@ -314,11 +311,11 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplayExternal::SetColorMode(ColorMode mode) {
+HWC2::Error HWCDisplayPluggable::SetColorMode(ColorMode mode) {
   return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
 }
 
-HWC2::Error HWCDisplayExternal::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
+HWC2::Error HWCDisplayPluggable::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
   auto status = color_mode_->SetColorModeWithRenderIntent(mode, intent);
   if (status != HWC2::Error::None) {
     DLOGE("failed for mode = %d intent = %d", mode, intent);
diff --git a/sdm/libs/hwc2/hwc_display_external.h b/sdm/libs/hwc2/hwc_display_pluggable.h
similarity index 80%
rename from sdm/libs/hwc2/hwc_display_external.h
rename to sdm/libs/hwc2/hwc_display_pluggable.h
index 89ac87e..1b35b98 100644
--- a/sdm/libs/hwc2/hwc_display_external.h
+++ b/sdm/libs/hwc2/hwc_display_pluggable.h
@@ -27,8 +27,8 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef __HWC_DISPLAY_EXTERNAL_H__
-#define __HWC_DISPLAY_EXTERNAL_H__
+#ifndef __HWC_DISPLAY_PLUGGABLE_H__
+#define __HWC_DISPLAY_PLUGGABLE_H__
 
 #include "hwc_display.h"
 #include "display_null.h"
@@ -36,15 +36,13 @@
 
 namespace sdm {
 
-class HWCDisplayExternal : public HWCDisplay {
+class HWCDisplayPluggable : public HWCDisplay {
  public:
   static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
                     HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                    uint32_t primary_width, uint32_t primary_height, qService::QService *qservice,
+                    qService::QService *qservice, hwc2_display_t id,
+                    int32_t sdm_id, uint32_t primary_width, uint32_t primary_height,
                     bool use_primary_res, HWCDisplay **hwc_display);
-  static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
-                    HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                    qService::QService *qservice, HWCDisplay **hwc_display);
   static void Destroy(HWCDisplay *hwc_display);
   virtual int Init();
   virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
@@ -58,9 +56,9 @@
   virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
 
  private:
-  HWCDisplayExternal(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
-                     HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                     qService::QService *qservice);
+  HWCDisplayPluggable(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                      HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+                      qService::QService *qservice, hwc2_display_t id, int32_t sdm_id);
   void ApplyScanAdjustment(hwc_rect_t *display_frame);
   void GetUnderScanConfig();
   static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
@@ -73,4 +71,4 @@
 
 }  // namespace sdm
 
-#endif  // __HWC_DISPLAY_EXTERNAL_H__
+#endif  // __HWC_DISPLAY_PLUGGABLE_H__
diff --git a/sdm/libs/hwc2/hwc_display_external_test.cpp b/sdm/libs/hwc2/hwc_display_pluggable_test.cpp
similarity index 85%
rename from sdm/libs/hwc2/hwc_display_external_test.cpp
rename to sdm/libs/hwc2/hwc_display_pluggable_test.cpp
index aaeb891..4aa7f9d 100644
--- a/sdm/libs/hwc2/hwc_display_external_test.cpp
+++ b/sdm/libs/hwc2/hwc_display_pluggable_test.cpp
@@ -40,61 +40,64 @@
 #include <string>
 #include <fstream>
 
-#include "hwc_display_external_test.h"
+#include "hwc_display_pluggable_test.h"
 #include "hwc_debugger.h"
 
-#define __CLASS__ "HWCDisplayExternalTest"
+#define __CLASS__ "HWCDisplayPluggableTest"
 
 namespace sdm {
 
 using std::array;
 
-int HWCDisplayExternalTest::Create(CoreInterface *core_intf,
-                                   HWCBufferAllocator *buffer_allocator,
-                                   HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                                   qService::QService *qservice, uint32_t panel_bpp,
-                                   uint32_t pattern_type, HWCDisplay **hwc_display) {
-  HWCDisplay *hwc_external_test = new HWCDisplayExternalTest(core_intf, buffer_allocator,
-                                                             callbacks, event_handler, qservice,
-                                                             panel_bpp, pattern_type);
+int HWCDisplayPluggableTest::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                                    HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+                                    qService::QService *qservice, hwc2_display_t id,
+                                    int32_t sdm_id, uint32_t panel_bpp, uint32_t pattern_type,
+                                    HWCDisplay **hwc_display) {
+  HWCDisplay *hwc_pluggable_test = new HWCDisplayPluggableTest(core_intf, buffer_allocator,
+                                                               callbacks, event_handler, qservice,
+                                                               id, sdm_id, panel_bpp, pattern_type);
 
-  int status = static_cast<HWCDisplayExternalTest *>(hwc_external_test)->Init();
+  int status = hwc_pluggable_test->Init();
   if (status) {
-    delete hwc_external_test;
+    delete hwc_pluggable_test;
     return status;
   }
 
-  *hwc_display = hwc_external_test;
+  *hwc_display = hwc_pluggable_test;
 
-  DLOGE("EXTERNAL panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
+  DLOGD("Pluggable panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
 
   return status;
 }
 
-void HWCDisplayExternalTest::Destroy(HWCDisplay *hwc_display) {
-  static_cast<HWCDisplayExternalTest *>(hwc_display)->Deinit();
+void HWCDisplayPluggableTest::Destroy(HWCDisplay *hwc_display) {
+  // Flush the display to have outstanding fences signaled.
+  hwc_display->Flush();
+  hwc_display->Deinit();
 
   delete hwc_display;
 }
 
-HWCDisplayExternalTest::HWCDisplayExternalTest(CoreInterface *core_intf,
-                                               HWCBufferAllocator *buffer_allocator,
-                                               HWCCallbacks *callbacks,
-                                               HWCDisplayEventHandler *event_handler,
-                                               qService::QService *qservice, uint32_t panel_bpp,
-                                               uint32_t pattern_type)
-  : HWCDisplay(core_intf, callbacks, event_handler, kHDMI, HWC_DISPLAY_EXTERNAL, false,
-               qservice, DISPLAY_CLASS_EXTERNAL, buffer_allocator), panel_bpp_(panel_bpp),
-               pattern_type_(pattern_type) {
+HWCDisplayPluggableTest::HWCDisplayPluggableTest(CoreInterface *core_intf,
+                                                 HWCBufferAllocator *buffer_allocator,
+                                                 HWCCallbacks *callbacks,
+                                                 HWCDisplayEventHandler *event_handler,
+                                                 qService::QService *qservice, hwc2_display_t id,
+                                                 int32_t sdm_id, uint32_t panel_bpp,
+                                                 uint32_t pattern_type)
+  : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kPluggable, id,
+               sdm_id, false, DISPLAY_CLASS_PLUGGABLE),
+    panel_bpp_(panel_bpp), pattern_type_(pattern_type) {
 }
 
-int HWCDisplayExternalTest::Init() {
-  uint32_t external_width = 0;
-  uint32_t external_height = 0;
+int HWCDisplayPluggableTest::Init() {
+  uint32_t pluggable_width = 0;
+  uint32_t pluggable_height = 0;
 
   int status = HWCDisplay::Init();
   if (status) {
-      DLOGE("HWCDisplayExternalTest::Init  status = %d ", status);
+      DLOGE("HWCDisplayPluggableTest::Init  status = %d ", status);
     return status;
   }
 
@@ -104,29 +107,29 @@
     return status;
   }
 
-  DisplayError error = HWCDisplay::GetMixerResolution(&external_width, &external_height);
+  DisplayError error = HWCDisplay::GetMixerResolution(&pluggable_width, &pluggable_height);
   if (error != kErrorNone) {
     Deinit();
     return -EINVAL;
   }
 
-  status = HWCDisplay::SetFrameBufferResolution(external_width, external_height);
+  status = HWCDisplay::SetFrameBufferResolution(pluggable_width, pluggable_height);
   if (status) {
     Deinit();
-    DLOGE("HWCDisplayExternalTest:: set fb resolution status = %d ", status);
+    DLOGE("HWCDisplayPluggableTest:: set fb resolution status = %d ", status);
     return status;
   }
 
   return status;
 }
 
-int HWCDisplayExternalTest::Deinit() {
+int HWCDisplayPluggableTest::Deinit() {
   DestroyLayerStack();
   return HWCDisplay::Deinit();
 }
 
 
-HWC2::Error HWCDisplayExternalTest::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+HWC2::Error HWCDisplayPluggableTest::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
   auto status = HWC2::Error::None;
   if (active_secure_sessions_[kSecureDisplay] || display_paused_) {
     MarkLayersForGPUBypass();
@@ -158,7 +161,7 @@
   return  status;
 }
 
-HWC2::Error HWCDisplayExternalTest::Present(int32_t *out_retire_fence) {
+HWC2::Error HWCDisplayPluggableTest::Present(int32_t *out_retire_fence) {
   auto status = HWC2::Error::None;
 
   if (active_secure_sessions_[kSecureDisplay]) {
@@ -201,11 +204,11 @@
   return status;
 }
 
-int HWCDisplayExternalTest::Perform(uint32_t operation, ...) {
+int HWCDisplayPluggableTest::Perform(uint32_t operation, ...) {
   return 0;
 }
 
-void HWCDisplayExternalTest::DumpInputBuffer() {
+void HWCDisplayPluggableTest::DumpInputBuffer() {
   if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
     return;
   }
@@ -263,7 +266,7 @@
   }
 }
 
-void HWCDisplayExternalTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
+void HWCDisplayPluggableTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
   std::bitset<16> color = {};
   std::bitset<16> temp_crc = {};
 
@@ -319,7 +322,7 @@
   (*crc_data) = temp_crc;
 }
 
-int HWCDisplayExternalTest::FillBuffer() {
+int HWCDisplayPluggableTest::FillBuffer() {
   uint8_t *buffer = reinterpret_cast<uint8_t *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
                                                 PROT_READ|PROT_WRITE, MAP_SHARED,
                                                 buffer_info_.alloc_buffer_info.fd, 0));
@@ -351,7 +354,7 @@
   return 0;
 }
 
-int HWCDisplayExternalTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
+int HWCDisplayPluggableTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
   switch (format) {
   case kFormatRGBA8888:
   case kFormatRGBA1010102:
@@ -368,7 +371,7 @@
   return 0;
 }
 
-void HWCDisplayExternalTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
+void HWCDisplayPluggableTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
                                        uint8_t **buffer) {
   LayerBufferFormat format = buffer_info_.buffer_config.format;
 
@@ -403,7 +406,7 @@
   }
 }
 
-void HWCDisplayExternalTest::GenerateColorRamp(uint8_t *buffer) {
+void HWCDisplayPluggableTest::GenerateColorRamp(uint8_t *buffer) {
   uint32_t width = buffer_info_.buffer_config.width;
   uint32_t height = buffer_info_.buffer_config.height;
   LayerBufferFormat format = buffer_info_.buffer_config.format;
@@ -497,7 +500,7 @@
   DLOGI("CRC blue %x", crc_blue.to_ulong());
 }
 
-void HWCDisplayExternalTest::GenerateBWVertical(uint8_t *buffer) {
+void HWCDisplayPluggableTest::GenerateBWVertical(uint8_t *buffer) {
   uint32_t width = buffer_info_.buffer_config.width;
   uint32_t height = buffer_info_.buffer_config.height;
   LayerBufferFormat format = buffer_info_.buffer_config.format;
@@ -543,7 +546,7 @@
   DLOGI("CRC blue %x", crc_blue.to_ulong());
 }
 
-void HWCDisplayExternalTest::GenerateColorSquare(uint8_t *buffer) {
+void HWCDisplayPluggableTest::GenerateColorSquare(uint8_t *buffer) {
   uint32_t width = buffer_info_.buffer_config.width;
   uint32_t height = buffer_info_.buffer_config.height;
   LayerBufferFormat format = buffer_info_.buffer_config.format;
@@ -611,7 +614,7 @@
   DLOGI("CRC blue %x", crc_blue.to_ulong());
 }
 
-int HWCDisplayExternalTest::InitLayer(Layer *layer) {
+int HWCDisplayPluggableTest::InitLayer(Layer *layer) {
   uint32_t active_config = 0;
   DisplayConfigVariableInfo var_info = {};
 
@@ -674,7 +677,7 @@
   return 0;
 }
 
-int HWCDisplayExternalTest::DeinitLayer(Layer *layer) {
+int HWCDisplayPluggableTest::DeinitLayer(Layer *layer) {
   if (layer->composition != kCompositionGPUTarget) {
     int ret = buffer_allocator_->FreeBuffer(&buffer_info_);
     if (ret != 0) {
@@ -686,14 +689,14 @@
   return 0;
 }
 
-int HWCDisplayExternalTest::CreateLayerStack() {
+int HWCDisplayPluggableTest::CreateLayerStack() {
   for (uint32_t i = 0; i < (kTestLayerCnt + 1 /* one dummy gpu_target layer */); i++) {
     Layer *layer = new Layer();
 
     if (i == kTestLayerCnt) {
       layer->composition = kCompositionGPUTarget;
     }
-    DLOGE("External :: CreateLayerStack %d", i);
+    DLOGD("External :: CreateLayerStack %d", i);
     int ret = InitLayer(layer);
     if (ret != 0) {
       delete layer;
@@ -705,7 +708,7 @@
   return 0;
 }
 
-int HWCDisplayExternalTest::DestroyLayerStack() {
+int HWCDisplayPluggableTest::DestroyLayerStack() {
   for (uint32_t i = 0; i < UINT32(layer_stack_.layers.size()); i++) {
     Layer *layer = layer_stack_.layers.at(i);
     int ret = DeinitLayer(layer);
@@ -719,7 +722,7 @@
   return 0;
 }
 
-HWC2::Error HWCDisplayExternalTest::PostCommit(int32_t *out_retire_fence) {
+HWC2::Error HWCDisplayPluggableTest::PostCommit(int32_t *out_retire_fence) {
   auto status = HWC2::Error::None;
   // Do no call flush on errors, if a successful buffer is never submitted.
   if (flush_ && flush_on_error_) {
diff --git a/sdm/libs/hwc2/hwc_display_external_test.h b/sdm/libs/hwc2/hwc_display_pluggable_test.h
similarity index 82%
rename from sdm/libs/hwc2/hwc_display_external_test.h
rename to sdm/libs/hwc2/hwc_display_pluggable_test.h
index 2526e5c..920003e 100644
--- a/sdm/libs/hwc2/hwc_display_external_test.h
+++ b/sdm/libs/hwc2/hwc_display_pluggable_test.h
@@ -27,8 +27,8 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifndef __HWC_DISPLAY_EXTERNAL_TEST_H__
-#define __HWC_DISPLAY_EXTERNAL_TEST_H__
+#ifndef __HWC_DISPLAY_PLUGGABLE_TEST_H__
+#define __HWC_DISPLAY_PLUGGABLE_TEST_H__
 
 #include <bitset>
 
@@ -37,12 +37,12 @@
 
 namespace sdm {
 
-class HWCDisplayExternalTest : public HWCDisplay {
+class HWCDisplayPluggableTest : public HWCDisplay {
  public:
   static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
                     HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                    qService::QService *qservice, uint32_t panel_bpp, uint32_t pattern_type,
-                    HWCDisplay **hwc_display);
+                    qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
+                    uint32_t panel_bpp, uint32_t pattern_type, HWCDisplay **hwc_display);
   static void Destroy(HWCDisplay *hwc_display);
   virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
   virtual HWC2::Error Present(int32_t *out_retire_fence);
@@ -79,9 +79,10 @@
   };
 
  private:
-  HWCDisplayExternalTest(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
-                         HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
-                         qService::QService *qservice, uint32_t panel_bpp, uint32_t pattern_type);
+  HWCDisplayPluggableTest(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                          HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
+                          qService::QService *qservice, hwc2_display_t id,
+                          int32_t sdm_id, uint32_t panel_bpp, uint32_t pattern_type);
   int Init();
   int Deinit();
   void DumpInputBuffer();
@@ -103,5 +104,5 @@
 
 }  // namespace sdm
 
-#endif  // __HWC_DISPLAY_EXTERNAL_TEST_H__
+#endif  // __HWC_DISPLAY_PLUGGABLE_TEST_H__
 
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index f98e433..97d74ef 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -40,11 +40,12 @@
 namespace sdm {
 
 int HWCDisplayVirtual::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
-                              HWCCallbacks *callbacks, uint32_t width, uint32_t height,
-                              int32_t *format, HWCDisplay **hwc_display) {
+                              HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id,
+                              uint32_t width, uint32_t height, int32_t *format,
+                              HWCDisplay **hwc_display) {
   int status = 0;
   HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, buffer_allocator,
-                                                                 callbacks);
+                                                                 callbacks, id, sdm_id);
 
   // TODO(user): Populate format correctly
   DLOGI("Creating virtual display: w: %d h:%d format:0x%x", width, height, *format);
@@ -89,9 +90,9 @@
 }
 
 HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
-                                     HWCCallbacks *callbacks) :
-      HWCDisplay(core_intf, callbacks, nullptr, kVirtual, HWC_DISPLAY_VIRTUAL, false, nullptr,
-                 DISPLAY_CLASS_VIRTUAL, buffer_allocator) {
+                                     HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id) :
+      HWCDisplay(core_intf, buffer_allocator, callbacks, nullptr, nullptr, kVirtual, id, sdm_id,
+                 false, DISPLAY_CLASS_VIRTUAL) {
 }
 
 int HWCDisplayVirtual::Init() {
@@ -293,4 +294,14 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCDisplayVirtual::GetDisplayType(int32_t *out_type) {
+  if (out_type == nullptr) {
+    return HWC2::Error::BadParameter;
+  }
+
+  *out_type = HWC2_DISPLAY_TYPE_VIRTUAL;
+
+  return HWC2::Error::None;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_virtual.h b/sdm/libs/hwc2/hwc_display_virtual.h
index ba7dd04..509e398 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.h
+++ b/sdm/libs/hwc2/hwc_display_virtual.h
@@ -40,19 +40,20 @@
 class HWCDisplayVirtual : public HWCDisplay {
  public:
   static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
-                    HWCCallbacks *callbacks, uint32_t width, uint32_t height, int32_t *format,
-                    HWCDisplay **hwc_display);
+                    HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id, uint32_t width,
+                    uint32_t height, int32_t *format, HWCDisplay **hwc_display);
   static void Destroy(HWCDisplay *hwc_display);
   virtual int Init();
   virtual int Deinit();
   virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
   virtual HWC2::Error Present(int32_t *out_retire_fence);
   virtual HWC2::Error SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  virtual HWC2::Error GetDisplayType(int32_t *out_type);
   HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
 
  private:
   HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
-                    HWCCallbacks *callbacks);
+                    HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id);
   int SetConfig(uint32_t width, uint32_t height);
 
   bool dump_output_layer_ = false;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 10482ae..d0a8ff5 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -31,6 +31,7 @@
 #include <utils/String16.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <QService.h>
 #include <utils/utils.h>
 #include <algorithm>
 #include <bitset>
@@ -43,9 +44,6 @@
 #include "hwc_buffer_sync_handler.h"
 #include "hwc_session.h"
 #include "hwc_debugger.h"
-#include "hwc_display_primary.h"
-#include "hwc_display_virtual.h"
-#include "hwc_display_external_test.h"
 
 #define __CLASS__ "HWCSession"
 
@@ -72,7 +70,7 @@
 namespace sdm {
 
 static HWCUEvent g_hwc_uevent_;
-Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
+Locker HWCSession::locker_[kNumDisplays];
 static const int kSolidFillDelay = 100 * 1000;
 
 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
@@ -99,7 +97,7 @@
   while (1) {
     char uevent_data[PAGE_SIZE] = {};
 
-    // keep last 2 zeroes to ensure double 0 termination
+    // keep last 2 zeros to ensure double 0 termination
     int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
 
     // scope of lock to this block only, so that caller is free to set event handler to nullptr;
@@ -147,6 +145,8 @@
     return status;
   }
 
+  InitDisplaySlots();
+
   // Start QService and connect to it.
   qService::QService::init();
   android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
@@ -171,7 +171,6 @@
     hw_disp_info.is_connected = true;
   } else {
     g_hwc_uevent_.Register(this);
-
     error = CoreInterface::CreateCore(&buffer_allocator_, &buffer_sync_handler_, &socket_handler_,
                                       &core_intf_);
 
@@ -185,58 +184,34 @@
     }
   }
 
-  // If HDMI display is primary display, defer display creation until hotplug event is received.
-  if (hw_disp_info.type == kHDMI) {
-    status = 0;
-    hdmi_is_primary_ = true;
-    // Create display if it is connected, else wait for hotplug connect event.
-    if (hw_disp_info.is_connected) {
-      status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false);
-    }
-  } else {
-    // Create and power on primary display
-    status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &callbacks_, this, qservice_,
-                                       &hwc_display_[HWC_DISPLAY_PRIMARY]);
-    color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
-    if (!color_mgr_) {
-      DLOGW("Failed to load HWCColorManager.");
-    }
-  }
-
+  // Create primary display here. Remaining builtin displays will be created after client has set
+  // display indexes which may happen sometime before callback is registered.
+  status = CreatePrimaryDisplay();
   if (status) {
-    g_hwc_uevent_.Register(nullptr);
-    CoreInterface::DestroyCore();
+    Deinit();
     return status;
   }
 
   is_composer_up_ = true;
-  struct rlimit fd_limit = {};
-  getrlimit(RLIMIT_NOFILE, &fd_limit);
-  fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
-  if (fd_limit.rlim_cur < fd_limit.rlim_max) {
-    auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);
-    if (err) {
-      DLOGW("Unable to increase fd limit -  err:%d, %s", errno, strerror(errno));
-    }
-  }
 
   return 0;
 }
 
 int HWCSession::Deinit() {
-  Locker::SequenceCancelScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
-  Locker::SequenceCancelScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
-  Locker::SequenceCancelScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
+  // Destroy all connected displays
+  DestroyDisplay(&map_info_primary_);
 
-  HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
-  if (primary_display) {
-    if (hdmi_is_primary_) {
-      HWCDisplayExternal::Destroy(primary_display);
-    } else {
-      HWCDisplayPrimary::Destroy(primary_display);
-    }
+  for (auto &map_info : map_info_builtin_) {
+    DestroyDisplay(&map_info);
   }
-  hwc_display_[HWC_DISPLAY_PRIMARY] = nullptr;
+
+  for (auto &map_info : map_info_pluggable_) {
+    DestroyDisplay(&map_info);
+  }
+
+  for (auto &map_info : map_info_virtual_) {
+    DestroyDisplay(&map_info);
+  }
 
   if (color_mgr_) {
     color_mgr_->DestroyColorManager();
@@ -254,6 +229,57 @@
   return 0;
 }
 
+void HWCSession::InitDisplaySlots() {
+  // Default slots:
+  //    Primary = 0, External = 1, Virtual = 2 (legacy IDs)
+  //    Additional builtin displays 3, 4 ... x
+  //    Additional external displays x+1, x+2 ... y
+  //    Additional virtual displays y+1, y+2 ... z
+  // If client does not support additional displays, hotplug for such displays
+  //    will be disregarded by the client.
+  // If client supports different range of ids for additional displays, those
+  //    will be set and overridden by an explicit call to set display indexes.
+  hwc2_display_t additional_base_id = qdutils::DISPLAY_VIRTUAL + 1;
+
+  map_info_primary_.client_id = qdutils::DISPLAY_PRIMARY;
+
+  map_info_builtin_.resize(kNumBuiltIn);
+  for (size_t i = 0; i < kNumBuiltIn; i++) {
+    map_info_builtin_[i].client_id = additional_base_id++;
+  }
+
+  map_info_pluggable_.resize(kNumPluggable);
+  for (size_t i = 0; i < kNumPluggable; i++) {
+    map_info_pluggable_[i].client_id = i ? additional_base_id++ : qdutils::DISPLAY_EXTERNAL;
+  }
+
+  map_info_virtual_.resize(kNumVirtual);
+  for (size_t i = 0; i < kNumVirtual; i++) {
+    map_info_virtual_[i].client_id = i ? additional_base_id++ : qdutils::DISPLAY_VIRTUAL;
+  }
+}
+
+int HWCSession::GetDisplayIndex(int dpy) {
+  DisplayMapInfo *map_info = nullptr;
+  switch (dpy) {
+    case qdutils::DISPLAY_PRIMARY:
+      map_info = &map_info_primary_;
+      break;
+    case qdutils::DISPLAY_EXTERNAL:
+      map_info = map_info_pluggable_.size() ? &map_info_pluggable_[0] : nullptr;
+      break;
+    case qdutils::DISPLAY_VIRTUAL:
+      map_info = map_info_virtual_.size() ? &map_info_virtual_[0] : nullptr;
+      break;
+  }
+
+  if (!map_info) {
+    return -1;
+  }
+
+  return INT(map_info->client_id);
+}
+
 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
   if (!module || !name || !device) {
     DLOGE("Invalid parameters.");
@@ -349,12 +375,9 @@
   }
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  auto status = hwc_session->CreateVirtualDisplayObject(width, height, format);
-
+  auto status = hwc_session->CreateVirtualDisplayObj(width, height, format, out_display_id);
   if (status == HWC2::Error::None) {
-    *out_display_id = HWC_DISPLAY_VIRTUAL;
-    DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d",
-          *out_display_id, width, height);
+    DLOGI("Created virtual display id:% " PRIu64 ", res: %dx%d", *out_display_id, width, height);
   } else {
     DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
   }
@@ -367,7 +390,7 @@
 }
 
 int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
-  if (!device || display != HWC_DISPLAY_VIRTUAL) {
+  if (!device || display >= kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
@@ -386,13 +409,15 @@
     }
   }
 
-  if (hwc_session->hwc_display_[display]) {
-    HWCDisplayVirtual::Destroy(hwc_session->hwc_display_[display]);
-    hwc_session->hwc_display_[display] = nullptr;
-    return HWC2_ERROR_NONE;
-  } else {
-    return HWC2_ERROR_BAD_DISPLAY;
+  for (auto &map_info : hwc_session->map_info_virtual_) {
+    if (map_info.client_id == display) {
+      DLOGI("Destroying virtual display id:%" PRIu64, display);
+      hwc_session->DestroyDisplay(&map_info);
+      break;
+    }
   }
+
+  return HWC2_ERROR_NONE;
 }
 
 void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
@@ -407,7 +432,7 @@
     *out_size = max_dump_size;
   } else {
     std::string s {};
-    for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) {
+    for (int id = 0; id < kNumDisplays; id++) {
       SCOPE_LOCK(locker_[id]);
       if (hwc_session->hwc_display_[id]) {
         s += hwc_session->hwc_display_[id]->Dump();
@@ -565,7 +590,7 @@
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
-  if (display >= HWC_NUM_DISPLAY_TYPES) {
+  if (display >= HWCSession::kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
@@ -608,7 +633,7 @@
   auto status = HWC2::Error::BadDisplay;
   DTRACE_SCOPED();
 
-  if (display >= HWC_NUM_DISPLAY_TYPES) {
+  if (display >= kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
@@ -636,6 +661,13 @@
   hwc_session->HandlePowerOnPending(display, *out_retire_fence);
   hwc_session->HandleHotplugPending(display, *out_retire_fence);
 
+  // Handle pending builtin/pluggable display connections
+  if (!hwc_session->primary_ready_ && (display == HWC_DISPLAY_PRIMARY)) {
+    hwc_session->CreateBuiltInDisplays();
+    hwc_session->CreatePluggableDisplays(false);
+    hwc_session->primary_ready_ = true;
+  }
+
   return INT32(status);
 }
 
@@ -649,15 +681,21 @@
   SCOPE_LOCK(hwc_session->callbacks_lock_);
   auto desc = static_cast<HWC2::Callback>(descriptor);
   auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
+  if (error != HWC2::Error::None) {
+    return INT32(error);
+  }
+
   DLOGD("%s callback: %s", pointer ? "Registering" : "Deregistering", to_string(desc).c_str());
   if (descriptor == HWC2_CALLBACK_HOTPLUG) {
     if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
       hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
     }
+    hwc_session->client_connected_ = true;
   }
   hwc_session->need_invalidate_ = false;
   hwc_session->callbacks_lock_.Broadcast();
-  return INT32(error);
+
+  return 0;
 }
 
 static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
@@ -797,12 +835,12 @@
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
-  if (display != HWC_DISPLAY_VIRTUAL) {
+  auto *hwc_session = static_cast<HWCSession *>(device);
+  if (INT32(display) != hwc_session->GetDisplayIndex(qdutils::DISPLAY_VIRTUAL)) {
     return HWC2_ERROR_UNSUPPORTED;
   }
 
   SCOPE_LOCK(locker_[display]);
-  auto *hwc_session = static_cast<HWCSession *>(device);
   if (hwc_session->hwc_display_[display]) {
     auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
     auto status = vds->SetOutputBuffer(buffer, releaseFence);
@@ -813,7 +851,7 @@
 }
 
 int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
-  if (display >= HWC_NUM_DISPLAY_TYPES) {
+  if (display >= kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
@@ -857,14 +895,13 @@
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
-  if (display >= HWC_NUM_DISPLAY_TYPES) {
+  if (display >= kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
   DTRACE_SCOPED();
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   // TODO(user): Handle secure session, handle QDCM solid fill
-  // Handle external_pending_connect_ in CreateVirtualDisplay
   auto status = HWC2::Error::BadDisplay;
   hwc_session->HandleSecureSession(display);
   {
@@ -998,8 +1035,8 @@
   return nullptr;
 }
 
-HWC2::Error HWCSession::CreateVirtualDisplayObject(uint32_t width, uint32_t height,
-                                                   int32_t *format) {
+HWC2::Error HWCSession::CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
+                                                hwc2_display_t *out_display_id) {
   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
     SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
     std :: bitset < kSecureMax > secure_sessions = 0;
@@ -1010,18 +1047,58 @@
     }
   }
 
+  if (!client_connected_) {
+    DLOGE("Client is not ready yet.");
+    return HWC2::Error::BadDisplay;
+  }
+
+  // Use first virtual display only for now.
+  if (!map_info_virtual_.size()) {
+    DLOGE("Virtual display is not supported");
+    return HWC2::Error::NoResources;
+  }
+
+  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 HWC2::Error::BadDisplay;
+  }
+
+  auto &map_info = map_info_virtual_[0];
+  hwc2_display_t client_id = map_info.client_id;
+
+  // Lock confined to this scope
+  int status = -EINVAL;
   {
-    SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
-    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+    SCOPE_LOCK(locker_[client_id]);
+    auto &hwc_display = hwc_display_[client_id];
+    if (hwc_display) {
+      DLOGE("Virtual display is already created.");
       return HWC2::Error::NoResources;
     }
 
-    auto status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_,
-                                            width, height, format,
-                                            &hwc_display_[HWC_DISPLAY_VIRTUAL]);
-    // TODO(user): validate width and height support
+    for (auto &iter : hw_displays_info) {
+      auto &info = iter.second;
+      if (info.display_type != kVirtual) {
+        continue;
+      }
+
+      status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, client_id,
+                                         info.display_id, width, height, format, &hwc_display);
+      // TODO(user): validate width and height support
+      if (!status) {
+        DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", client_id, width, height);
+
+        *out_display_id = client_id;
+        map_info.disp_type = info.display_type;
+        map_info.sdm_id = info.display_id;
+      }
+      break;
+    }
+
     if (status) {
-      return HWC2::Error::Unsupported;
+      return HWC2::Error::BadDisplay;
     }
   }
 
@@ -1031,46 +1108,6 @@
   return HWC2::Error::None;
 }
 
-int32_t HWCSession::ConnectDisplay(int disp) {
-  DLOGI("Display = %d", disp);
-
-  int status = 0;
-  uint32_t primary_width = 0;
-  uint32_t primary_height = 0;
-
-  hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
-
-  if (disp == HWC_DISPLAY_EXTERNAL) {
-    status = CreateExternalDisplay(disp, primary_width, primary_height, false);
-  } else {
-    DLOGE("Invalid display type");
-    return -1;
-  }
-
-  return status;
-}
-
-int HWCSession::DisconnectDisplay(int disp) {
-  DLOGI("Display = %d", disp);
-
-  if (disp == HWC_DISPLAY_EXTERNAL) {
-    DisplayError error = hwc_display_[disp]->Flush();
-    if (error != kErrorNone) {
-        DLOGW("Flush failed. Error = %d", error);
-    }
-    HWCDisplayExternal::Destroy(hwc_display_[disp]);
-  } else if (disp == HWC_DISPLAY_VIRTUAL) {
-    HWCDisplayVirtual::Destroy(hwc_display_[disp]);
-  } else {
-    DLOGE("Invalid display type");
-    return -1;
-  }
-
-  hwc_display_[disp] = NULL;
-
-  return 0;
-}
-
 // Qclient methods
 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                              android::Parcel *output_parcel) {
@@ -1230,7 +1267,7 @@
         DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
         break;
       }
-      status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
+      status = GetDisplayAttributesForConfig(input_parcel, output_parcel);
       break;
 
     case qService::IQService::GET_PANEL_BRIGHTNESS: {
@@ -1345,21 +1382,22 @@
   return is_composer_up_;
 }
 
-android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
-                                                                  *input_parcel,
-                                                                  android::Parcel *output_parcel) {
+android::status_t HWCSession::GetDisplayAttributesForConfig(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 display_attributes;
 
-  if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) {
+  int disp_idx = GetDisplayIndex(dpy);
+  if (disp_idx == -1 || config < 0) {
+    DLOGE("Invalid display = %d, or config = %d", dpy, config);
     return android::BAD_VALUE;
   }
 
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
-  if (hwc_display_[dpy]) {
-    error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+  if (hwc_display_[disp_idx]) {
+    error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(config, &display_attributes);
     if (error == 0) {
       output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
       output_parcel->writeInt32(INT(display_attributes.x_pixels));
@@ -1386,14 +1424,14 @@
 
   switch (operation) {
     case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
-      return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+      return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
 
     case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
-      return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+      return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
 
     case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
       uint32_t refresh_rate = UINT32(input_parcel->readInt32());
-      return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
+      return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
     }
 
     default:
@@ -1413,7 +1451,7 @@
   }
 
   uint32_t mode = UINT32(input_parcel->readInt32());
-  return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
+  return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayBuiltIn::SET_DISPLAY_MODE, mode);
 }
 
 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
@@ -1422,20 +1460,22 @@
   uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
   android::status_t status = 0;
 
-  for (uint32_t disp_id = HWC_DISPLAY_PRIMARY; disp_id < HWC_NUM_DISPLAY_TYPES; disp_id++) {
-    if (bit_mask_display_type[disp_id]) {
-      SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
-      if (hwc_display_[disp_id]) {
-        error = hwc_display_[disp_id]->SetMaxMixerStages(max_mixer_stages);
-        if (error != kErrorNone) {
-          status = -EINVAL;
-          continue;
-        }
-      } else {
-        DLOGW("Display = %d is not connected.", disp_id);
-        status = (status)? status : -ENODEV;  // Return higher priority error.
-        continue;
-      }
+  for (uint32_t i = 0; i < 32 && bit_mask_display_type[i]; i++) {
+    int disp_idx = GetDisplayIndex(INT(i));
+    if (disp_idx == -1) {
+      continue;
+    }
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+    auto &hwc_display = hwc_display_[disp_idx];
+    if (!hwc_display) {
+      DLOGW("Display = %d is not connected.", disp_idx);
+      status = (status)? status : -ENODEV;  // Return higher priority error.
+      continue;
+    }
+
+    error = hwc_display->SetMaxMixerStages(max_mixer_stages);
+    if (error != kErrorNone) {
+      status = -EINVAL;
     }
   }
 
@@ -1448,24 +1488,22 @@
   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
   android::status_t status = 0;
 
-  for (uint32_t disp_id = HWC_DISPLAY_PRIMARY; disp_id < HWC_NUM_DISPLAY_TYPES; disp_id++) {
-    if (bit_mask_display_type[disp_id]) {
-      SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
-      if (hwc_display_[disp_id]) {
-        HWC2::Error error;
-        error = hwc_display_[disp_id]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
-        if (HWC2::Error::None != error) {
-          if (HWC2::Error::NoResources == error)
-            status = -ENOMEM;
-          else
-            status = -EINVAL;
-          continue;
-        }
-      } else {
-        DLOGW("Display = %d is not connected.", disp_id);
-        status = (status)? status : -ENODEV;  // Return higher priority error.
-        continue;
-      }
+  for (uint32_t i = 0; i < 32 && bit_mask_display_type[i]; i++) {
+    int disp_idx = GetDisplayIndex(INT(i));
+    if (disp_idx == -1) {
+      continue;
+    }
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+    auto &hwc_display = hwc_display_[disp_idx];
+    if (!hwc_display) {
+      DLOGW("Display = %d is not connected.", disp_idx);
+      status = (status)? status : -ENODEV;  // Return higher priority error.
+      continue;
+    }
+
+    HWC2::Error error = hwc_display->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    if (error != HWC2::Error::None) {
+      status = (HWC2::Error::NoResources == error) ? -ENOMEM : -EINVAL;
     }
   }
 
@@ -1499,11 +1537,18 @@
 }
 
 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
-  auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
+  int display = static_cast<int>(input_parcel->readInt32());
   auto mode = static_cast<ColorMode>(input_parcel->readInt32());
   auto device = static_cast<hwc2_device_t *>(this);
 
-  auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
+  int disp_idx = GetDisplayIndex(display);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", display);
+    return -EINVAL;
+  }
+
+  auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
+                                 &HWCDisplay::SetColorMode, mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
 
@@ -1525,11 +1570,18 @@
   return 0;
 }
 android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
-  auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
+  int display = static_cast<int >(input_parcel->readInt32());
   auto mode = input_parcel->readInt32();
   auto device = static_cast<hwc2_device_t *>(this);
 
-  auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorModeById, mode);
+  int disp_idx = GetDisplayIndex(display);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", display);
+    return -EINVAL;
+  }
+
+  auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
+                                 &HWCDisplay::SetColorModeById, mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
 
@@ -1606,7 +1658,7 @@
   // Read display_id, payload_size and payload from in_parcel.
   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
   if (!ret) {
-    if ((display_id >= HWC_NUM_DISPLAY_TYPES) || !hwc_display_[display_id]) {
+    if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
       DLOGW("Invalid display id or display = %d is not connected.", display_id);
       ret = -ENODEV;
     }
@@ -1722,26 +1774,17 @@
   return ret;
 }
 
-void HWCSession::UEventHandler(const char *uevent_data, int length) {
-  if (strcasestr(uevent_data, HWC_UEVENT_SWITCH_HDMI)) {
-    DLOGI("Uevent HDMI = %s", uevent_data);
-    int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
-    if (connected >= 0) {
-      DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
-      if (HotPlugHandler(connected) == -1) {
-        DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
-      }
+int GetEventValue(const char *uevent_data, int length, const char *event_info) {
+  const char *iterator_str = uevent_data;
+  while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+    const char *pstr = strstr(iterator_str, event_info);
+    if (pstr != NULL) {
+      return (atoi(iterator_str + strlen(event_info)));
     }
-  } else if (strcasestr(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
-    DLOGI("Uevent FB0 = %s", uevent_data);
-    int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
-    if (panel_reset == 0) {
-      Refresh(0);
-      reset_panel_ = true;
-    }
-  } else if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
-    HandleExtHPD(uevent_data, length);
+    iterator_str += strlen(iterator_str) + 1;
   }
+
+  return -1;
 }
 
 const char *GetTokenValue(const char *uevent_data, int length, const char *token) {
@@ -1761,46 +1804,41 @@
   return pstr;
 }
 
-void HWCSession::HandleExtHPD(const char *uevent_data, int length) {
-  const char *pstr = GetTokenValue(uevent_data, length, "name=");
-  if (!pstr || (strncmp(pstr, "DP-1", strlen("DP-1")) != 0)) {
+void HWCSession::UEventHandler(const char *uevent_data, int length) {
+  if (strcasestr(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
+    DLOGI("Uevent FB0 = %s", uevent_data);
+    int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
+    if (panel_reset == 0) {
+      Refresh(0);
+      reset_panel_ = true;
+    }
     return;
   }
 
-  pstr = GetTokenValue(uevent_data, length, "status=");
-  if (pstr) {
-    bool connected = false;
-    hpd_bpp_ = 0;
-    hpd_pattern_ = 0;
-    if (strncmp(pstr, "connected", strlen("connected")) == 0) {
-      connected = true;
-    }
-    int bpp = GetEventValue(uevent_data, length, "bpp=");
-    int pattern = GetEventValue(uevent_data, length, "pattern=");
-    if (bpp >=0 && pattern >= 0) {
-      hpd_bpp_ = bpp;
-      hpd_pattern_ = pattern;
+  if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
+    // MST hotplug will not carry connection status/test pattern etc.
+    // Pluggable display handler will check all connection status' and take action accordingly.
+    const char *str_status = GetTokenValue(uevent_data, length, "status=");
+    const char *str_mst = GetTokenValue(uevent_data, length, "MST_HOTPLUG=");
+    if (!str_status && !str_mst) {
+      return;
     }
 
-    DLOGI("Recived Ext HPD, connected:%d  status=%s  bpp = %d pattern =%d ",
-          connected, pstr, hpd_bpp_, hpd_pattern_);
-    HotPlugHandler(connected);
+    hpd_bpp_ = GetEventValue(uevent_data, length, "bpp=");
+    hpd_pattern_ = GetEventValue(uevent_data, length, "pattern=");
+    DLOGI("Uevent = %s, bpp = %d, pattern = %d", uevent_data, hpd_bpp_, hpd_pattern_);
+    if (CreatePluggableDisplays(true)) {
+      DLOGE("Could not handle hotplug. Event dropped.");
+    }
+
+    if (str_status) {
+      bool connected = (strncmp(str_status, "connected", strlen("connected")) == 0);
+      DLOGI("Connected = %d", connected);
+      qservice_->onHdmiHotplug(INT(connected));
+    }
   }
 }
 
-int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
-  const char *iterator_str = uevent_data;
-  while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
-    const char *pstr = strstr(iterator_str, event_info);
-    if (pstr != NULL) {
-      return (atoi(iterator_str + strlen(event_info)));
-    }
-    iterator_str += strlen(iterator_str) + 1;
-  }
-
-  return -1;
-}
-
 void HWCSession::ResetPanel() {
   HWC2::Error status = HWC2::Error::None;
 
@@ -1825,116 +1863,6 @@
   reset_panel_ = false;
 }
 
-int HWCSession::HotPlugHandler(bool connected) {
-  int status = 0;
-  bool notify_hotplug = false;
-  std :: bitset < kSecureMax > secure_sessions = 0;
-
-  // To prevent sending events to client while a lock is held, acquire scope locks only within
-  // below scope so that those get automatically unlocked after the scope ends.
-  do {
-    // If HDMI is primary but not created yet (first time), create it and notify surfaceflinger.
-    //    if it is already created, but got disconnected/connected again,
-    //    just toggle display status and do not notify surfaceflinger.
-    // If HDMI is not primary, create/destroy external display normally.
-    if (hdmi_is_primary_) {
-      SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
-      if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
-        status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected);
-      } else {
-        status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false);
-        notify_hotplug = true;
-      }
-      break;
-    }
-
-    {
-      SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
-      // Primary display must be connected for HDMI as secondary cases.
-      if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
-        DLOGE("Primary display is not connected.");
-        return -1;
-      }
-      hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
-      hwc_display_[HWC_DISPLAY_PRIMARY]->GetActiveSecureSession(&secure_sessions);
-      hotplug_pending_event_ = kHotPlugNone;
-      if (secure_sessions[kSecureDisplay]) {
-        hotplug_pending_event_ = connected ? kHotPlugConnect : kHotPlugDisconnect;
-        notify_hotplug = connected ? false : true;
-        break;
-      }
-    }
-
-    if (connected) {
-      SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
-      Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
-      // Connect external display if virtual display is not connected.
-      // Else, defer external display connection and process it when virtual display
-      // tears down; Do not notify SurfaceFlinger since connection is deferred now.
-      if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-        status = ConnectDisplay(HWC_DISPLAY_EXTERNAL);
-        if (status) {
-          return status;
-        }
-        notify_hotplug = true;
-      } else {
-        DLOGI("Virtual display is connected, pending connection");
-        hotplug_pending_event_ = kHotPlugConnect;
-      }
-    } else {
-      SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
-      if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-        notify_hotplug = true;
-      }
-    }
-  } while (0);
-
-  if (connected) {
-    // In connect case, we send hotplug after we create display
-    Refresh(0);
-
-    if (!hdmi_is_primary_) {
-      // wait for sufficient time to ensure sufficient resources are available to process new
-      // new display connection.
-      uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
-      usleep(vsync_period * 2 / 1000);
-    }
-    if (notify_hotplug) {
-      HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
-              HWC2::Connection::Connected);
-    }
-  } else {
-    // In disconnect case, we notify hotplug first to let the listener state update happen first
-    // Then we can destroy the underlying display object
-    if (notify_hotplug) {
-      HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
-              HWC2::Connection::Disconnected);
-    }
-    Refresh(0);
-    if (!hdmi_is_primary_) {
-      uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
-      usleep(vsync_period * 2 / 1000);
-    }
-    // Now disconnect the display
-    {
-      SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
-      // Do not return error if external display is not in connected status.
-      // Due to virtual display concurrency, external display connection might be still pending
-      // but hdmi got disconnected before pending connection could be processed.
-      // if secure display session is in progress, defer disconnection of external display
-      if (hwc_display_[HWC_DISPLAY_EXTERNAL] && !secure_sessions[kSecureDisplay]) {
-        status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
-      }
-    }
-  }
-
-  // notify client
-
-  qservice_->onHdmiHotplug(INT(connected));
-
-  return 0;
-}
-
 int HWCSession::GetVsyncPeriod(int disp) {
   SCOPE_LOCK(locker_[disp]);
   // default value
@@ -1950,18 +1878,19 @@
 
 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
                                                     android::Parcel *output_parcel) {
-  int dpy = input_parcel->readInt32();
-  if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) {
+  int disp_idx = GetDisplayIndex(input_parcel->readInt32());
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", disp_idx);
     return android::BAD_VALUE;
   }
 
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
-  if (!hwc_display_[dpy]) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+  if (!hwc_display_[disp_idx]) {
     return android::NO_INIT;
   }
 
   hwc_rect_t visible_rect = {0, 0, 0, 0};
-  int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
+  int error = hwc_display_[disp_idx]->GetVisibleDisplayRect(&visible_rect);
   if (error < 0) {
     return error;
   }
@@ -1992,36 +1921,295 @@
   }
 }
 
-int HWCSession::CreateExternalDisplay(int disp_id, uint32_t primary_width,
-                                      uint32_t primary_height, bool use_primary_res) {
-  uint32_t panel_bpp = 0;
-  uint32_t pattern_type = 0;
+int HWCSession::CreatePrimaryDisplay() {
+  int status = -EINVAL;
+  HWDisplaysInfo hw_displays_info = {};
 
-  if (GetDriverType() == DriverType::FB) {
-    qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
-  } else {
-    panel_bpp = static_cast<uint32_t>(hpd_bpp_);
-    pattern_type = static_cast<uint32_t>(hpd_pattern_);
+  DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+  if (error != kErrorNone) {
+    DLOGE("Failed to get connected display list. Error = %d", error);
+    return status;
   }
 
-  if (panel_bpp && pattern_type) {
-    return HWCDisplayExternalTest::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
-                                          qservice_, panel_bpp, pattern_type,
-                                          &hwc_display_[disp_id]);
+  for (auto &iter : hw_displays_info) {
+    auto &info = iter.second;
+    if (!info.is_primary) {
+      continue;
+    }
+
+    // todo (user): If primary display is not connected (e.g. hdmi as primary), a NULL display
+    // need to be created. SF expects primary display hotplug during callback registration unlike
+    // previous implementation where first hotplug could be notified anytime.
+    if (!info.is_connected) {
+      DLOGE("Primary display is not connected. Not supported at present.");
+      break;
+    }
+
+    auto hwc_display = &hwc_display_[HWC_DISPLAY_PRIMARY];
+    hwc2_display_t client_id = map_info_primary_.client_id;
+
+    DLOGI("Create primary display type = %d, sdm id = %d, client id = %d", info.display_type,
+                                                                    info.display_id, client_id);
+    if (info.display_type == kBuiltIn) {
+      status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
+                                         qservice_, client_id, info.display_id, hwc_display);
+    } else if (info.display_type == kPluggable) {
+      status = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
+                                           qservice_, client_id, info.display_id, 0, 0, false,
+                                           hwc_display);
+    } else {
+      DLOGE("Spurious primary display type = %d", info.display_type);
+      break;
+    }
+
+    if (!status) {
+      DLOGI("Primary display created.");
+      map_info_primary_.disp_type = info.display_type;
+      map_info_primary_.sdm_id = info.display_id;
+
+      color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
+      if (!color_mgr_) {
+        DLOGW("Failed to load HWCColorManager.");
+      }
+    } else {
+      DLOGE("Primary display creation failed.");
+    }
+
+    // Primary display is found, no need to parse more.
+    break;
   }
 
-  return  HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
-                                     primary_width, primary_height, qservice_, use_primary_res,
-                                     &hwc_display_[disp_id]);
+  return status;
 }
 
-#ifdef DISPLAY_CONFIG_1_1
-// Methods from ::vendor::hardware::display::config::V1_1::IDisplayConfig follow.
-Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
-  return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
-                             &HWCDisplay::SetDisplayAnimating, animating);
+int HWCSession::CreateBuiltInDisplays() {
+  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 -EINVAL;
+  }
+
+  int status = 0;
+  size_t next_builtin_index = 0;
+  for (auto &iter : hw_displays_info) {
+    auto &info = iter.second;
+
+    // Do not recreate primary display.
+    if (info.is_primary || info.display_type != kBuiltIn) {
+      continue;
+    }
+
+    if (next_builtin_index >= map_info_builtin_.size()) {
+      DLOGW("Insufficient builtin display slots. All displays could not be created.");
+      return 0;
+    }
+
+    DisplayMapInfo &map_info = map_info_builtin_[next_builtin_index];
+    hwc2_display_t client_id = map_info.client_id;
+
+    // Lock confined to this scope
+    {
+      SCOPE_LOCK(locker_[client_id]);
+
+      DLOGI("Create builtin display, sdm id = %d, client id = %d", info.display_id, client_id);
+      status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
+                                         qservice_, client_id, info.display_id,
+                                         &hwc_display_[client_id]);
+      if (!status) {
+        DLOGI("Builtin display created.");
+        map_info.disp_type = info.display_type;
+        map_info.sdm_id = info.display_id;
+      } else {
+        DLOGE("Builtin display creation failed.");
+        break;
+      }
+    }
+
+    callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
+  }
+
+  return status;
 }
-#endif
+
+int HWCSession::CreatePluggableDisplays(bool delay_hotplug) {
+  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);
+    return -EINVAL;
+  }
+
+  int status = HandleDisconnectedDisplays(&hw_displays_info);
+  if (status) {
+    DLOGE("All displays could not be disconnected.");
+    return status;
+  }
+
+  status = HandleConnectedDisplays(&hw_displays_info, delay_hotplug);
+  if (status) {
+    DLOGE("All displays could not be connected.");
+    return status;
+  }
+
+  return 0;
+}
+
+int HWCSession::HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug) {
+  int status = 0;
+  std::vector<hwc2_display_t> pending_hotplugs = {};
+
+  for (auto &iter : *hw_displays_info) {
+    auto &info = iter.second;
+
+    // Do not recreate primary display or if display is not connected.
+    if (info.is_primary || info.display_type != kPluggable || !info.is_connected) {
+      continue;
+    }
+
+    // find an empty slot to create display.
+    for (auto &map_info : map_info_pluggable_) {
+      hwc2_display_t client_id = map_info.client_id;
+
+      // Lock confined to this scope
+      {
+        SCOPE_LOCK(locker_[client_id]);
+        auto &hwc_display = hwc_display_[client_id];
+        if (hwc_display) {
+          // Display is already connected.
+          continue;
+        }
+
+        DLOGI("Create pluggable display, sdm id = %d, client id = %d", info.display_id, client_id);
+
+        // Test pattern generation ?
+        map_info.test_pattern = (hpd_bpp_ > 0) && (hpd_pattern_ > 0);
+        if (!map_info.test_pattern) {
+          status = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
+                                               qservice_, client_id, info.display_id, 0, 0, false,
+                                               &hwc_display);
+        } else {
+          status = HWCDisplayPluggableTest::Create(core_intf_, &buffer_allocator_, &callbacks_,
+                                                   this, qservice_, client_id, info.display_id,
+                                                   UINT32(hpd_bpp_), UINT32(hpd_pattern_),
+                                                   &hwc_display);
+        }
+
+        if (status) {
+          DLOGE("Pluggable display creation failed.");
+          return status;
+        }
+
+        DLOGI("Created pluggable display successfully.");
+      }
+
+      map_info.disp_type = info.display_type;
+      map_info.sdm_id = info.display_id;
+
+      pending_hotplugs.push_back((hwc2_display_t)client_id);
+
+      // Display is created for this sdm id, move to next connected display.
+      break;
+    }
+  }
+
+  // No display was created.
+  if (!pending_hotplugs.size()) {
+    return 0;
+  }
+
+  // Primary display needs revalidation
+  {
+    SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+    hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
+  }
+
+  Refresh(0);
+
+  // Do not sleep if this method is called from client thread.
+  if (delay_hotplug) {
+    // wait sufficient time to ensure resources are available for new display connection.
+    usleep(UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)) * 2 / 1000);
+  }
+
+  for (auto client_id : pending_hotplugs) {
+    DLOGI("Notify hotplug connected: client id = %d", client_id);
+    callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
+  }
+
+  return 0;
+}
+
+int HWCSession::HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info) {
+  // Destroy pluggable displays which were connected earlier but got disconnected now.
+  for (auto &map_info : map_info_pluggable_) {
+    bool disconnect = true;   // disconnect in case display id is not found in list.
+
+    for (auto &iter : *hw_displays_info) {
+      auto &info = iter.second;
+      if (info.display_id != map_info.sdm_id) {
+        continue;
+      }
+      if (info.is_connected) {
+        disconnect = false;
+      }
+    }
+
+    if (disconnect) {
+      DestroyDisplay(&map_info);
+    }
+  }
+
+  return 0;
+}
+
+void HWCSession::DestroyDisplay(DisplayMapInfo *map_info) {
+  hwc2_display_t client_id = map_info->client_id;
+  int notify_hotplug = false;
+
+  // Lock confined to this scope. Do not notify hotplug while holding a lock.
+  {
+    SCOPE_LOCK(locker_[client_id]);
+
+    auto &hwc_display = hwc_display_[client_id];
+    if (!hwc_display) {
+      return;
+    }
+
+    DLOGI("Destroy display type = %d, client id = %d", map_info->disp_type, client_id);
+    switch (map_info->disp_type) {
+      case kBuiltIn:
+        HWCDisplayBuiltIn::Destroy(hwc_display);
+        break;
+
+      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;
+    }
+    hwc_display = nullptr;
+    map_info->Reset();
+  }
+
+  if (notify_hotplug) {
+    callbacks_.Hotplug(client_id, HWC2::Connection::Disconnected);
+  }
+}
 
 HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
                                                 uint32_t *out_num_requests) {
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 119c931..7bcfe00 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -20,7 +20,9 @@
 #ifndef __HWC_SESSION_H__
 #define __HWC_SESSION_H__
 
-#ifdef DISPLAY_CONFIG_1_1
+#ifdef DISPLAY_CONFIG_1_2
+#include <vendor/display/config/1.2/IDisplayConfig.h>
+#elif DISPLAY_CONFIG_1_1
 #include <vendor/display/config/1.1/IDisplayConfig.h>
 #else
 #include <vendor/display/config/1.0/IDisplayConfig.h>
@@ -28,20 +30,26 @@
 
 #include <core/core_interface.h>
 #include <utils/locker.h>
+#include <qd_utils.h>
+#include <display_config.h>
+#include <vector>
 
 #include "hwc_callbacks.h"
 #include "hwc_layers.h"
 #include "hwc_display.h"
-#include "hwc_display_primary.h"
-#include "hwc_display_external.h"
+#include "hwc_display_builtin.h"
+#include "hwc_display_pluggable.h"
 #include "hwc_display_virtual.h"
+#include "hwc_display_pluggable_test.h"
 #include "hwc_color_manager.h"
 #include "hwc_socket_handler.h"
 #include "hwc_display_event_handler.h"
 
 namespace sdm {
 
-#ifdef DISPLAY_CONFIG_1_1
+#ifdef DISPLAY_CONFIG_1_2
+using vendor::display::config::V1_2::IDisplayConfig;
+#elif DISPLAY_CONFIG_1_1
 using vendor::display::config::V1_1::IDisplayConfig;
 #else
 using ::vendor::display::config::V1_0::IDisplayConfig;
@@ -80,6 +88,12 @@
 class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qClient::BnQClient,
                    public HWCDisplayEventHandler {
  public:
+  static const int kNumBuiltIn = 4;
+  static const int kNumPluggable = 4;
+  static const int kNumVirtual = 4;
+  // Add 1 primary display which can be either a builtin or pluggable.
+  static const int kNumDisplays = 1 + kNumBuiltIn + kNumPluggable + kNumVirtual;
+
   struct HWCModuleMethods : public hw_module_methods_t {
     HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; }
   };
@@ -93,7 +107,8 @@
   explicit HWCSession(const hw_module_t *module);
   int Init();
   int Deinit();
-  HWC2::Error CreateVirtualDisplayObject(uint32_t width, uint32_t height, int32_t *format);
+  HWC2::Error CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
+                                      hwc2_display_t *out_display_id);
 
   template <typename... Args>
   static int32_t CallDisplayFunction(hwc2_device_t *device, hwc2_display_t display,
@@ -102,7 +117,7 @@
       return HWC2_ERROR_BAD_PARAMETER;
     }
 
-    if (display >= HWC_NUM_DISPLAY_TYPES) {
+    if (display >= kNumDisplays) {
       return HWC2_ERROR_BAD_DISPLAY;
     }
 
@@ -124,7 +139,7 @@
       return HWC2_ERROR_BAD_PARAMETER;
     }
 
-    if (display >= HWC_NUM_DISPLAY_TYPES) {
+    if (display >= kNumDisplays) {
       return HWC2_ERROR_BAD_DISPLAY;
     }
 
@@ -181,9 +196,22 @@
   // HWCDisplayEventHandler
   virtual void DisplayPowerReset();
 
-  static Locker locker_[HWC_NUM_DISPLAY_TYPES];
+  static Locker locker_[kNumDisplays];
 
  private:
+  struct DisplayMapInfo {
+    hwc2_display_t client_id = kNumDisplays;        // mapped sf id for this display
+    int32_t sdm_id = -1;                            // sdm id for this display
+    sdm:: DisplayType disp_type = kDisplayTypeMax;  // sdm display type
+    bool test_pattern = false;                      // display will show test pattern
+    void Reset() {
+      // Do not clear client id
+      sdm_id = -1;
+      disp_type = kDisplayTypeMax;
+      test_pattern = false;
+    }
+  };
+
   static const int kExternalConnectionTimeoutMs = 500;
   static const int kPartialUpdateControlTimeoutMs = 100;
 
@@ -196,12 +224,15 @@
 
   // Uevent handler
   virtual void UEventHandler(const char *uevent_data, int length);
-  int GetEventValue(const char *uevent_data, int length, const char *event_info);
-  void HandleExtHPD(const char *uevent_data, int length);
-  int HotPlugHandler(bool connected);
   void ResetPanel();
-  int32_t ConnectDisplay(int disp);
-  int DisconnectDisplay(int disp);
+  void InitDisplaySlots();
+  int GetDisplayIndex(int dpy);
+  int CreatePrimaryDisplay();
+  int CreateBuiltInDisplays();
+  int CreatePluggableDisplays(bool delay_hotplug);
+  int HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug);
+  int HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info);
+  void DestroyDisplay(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);
@@ -211,8 +242,6 @@
   int32_t SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status);
   int32_t GetPanelBrightness(int *level);
   int32_t MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level);
-  int32_t CreateExternalDisplay(int disp_id, uint32_t primary_width, uint32_t primary_height,
-                                bool use_primary_res);
 
   // service methods
   void StartServices();
@@ -248,6 +277,11 @@
 #ifdef DISPLAY_CONFIG_1_1
   Return<int32_t> setDisplayAnimating(uint64_t display_id, bool animating) override;
 #endif
+  // Methods from ::android::hardware::display::config::V1_2::IDisplayConfig follow.
+#ifdef DISPLAY_CONFIG_1_2
+  Return<int32_t> setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
+                                  uint32_t base, uint32_t count) override;
+#endif
 
   // QClient methods
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -259,8 +293,8 @@
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
   android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
                                    android::Parcel *output_parcel);
-  android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
-                                                        android::Parcel *output_parcel);
+  android::status_t GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
+                                                  android::Parcel *output_parcel);
   android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
                                           android::Parcel *output_parcel);
   android::status_t SetMixerResolution(const android::Parcel *input_parcel);
@@ -281,12 +315,18 @@
   void HandleHotplugPending(hwc2_display_t disp_id, int retire_fence);
 
   CoreInterface *core_intf_ = nullptr;
-  HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
+  HWCDisplay *hwc_display_[kNumDisplays] = {nullptr};
   HWCCallbacks callbacks_;
   HWCBufferAllocator buffer_allocator_;
   HWCBufferSyncHandler buffer_sync_handler_;
   HWCColorManager *color_mgr_ = nullptr;
+  DisplayMapInfo map_info_primary_;                 // Primary display (either builtin or pluggable)
+  std::vector<DisplayMapInfo> map_info_builtin_;    // Builtin displays excluding primary
+  std::vector<DisplayMapInfo> map_info_pluggable_;  // Pluggable displays excluding primary
+  std::vector<DisplayMapInfo> map_info_virtual_;    // Virtual displays
   bool reset_panel_ = false;
+  bool primary_ready_ = false;
+  bool client_connected_ = false;
   bool new_bw_mode_ = false;
   bool need_invalidate_ = false;
   int bw_mode_release_fd_ = -1;
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 5a595e3..d1fb02a 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -30,6 +30,7 @@
 #include <core/buffer_allocator.h>
 #include <utils/debug.h>
 #include <sync/sync.h>
+#include <vector>
 
 #include "hwc_buffer_sync_handler.h"
 #include "hwc_session.h"
@@ -52,13 +53,13 @@
 int MapDisplayType(IDisplayConfig::DisplayType dpy) {
   switch (dpy) {
     case IDisplayConfig::DisplayType::DISPLAY_PRIMARY:
-      return HWC_DISPLAY_PRIMARY;
+      return qdutils::DISPLAY_PRIMARY;
 
     case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL:
-      return HWC_DISPLAY_EXTERNAL;
+      return qdutils::DISPLAY_EXTERNAL;
 
     case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL:
-      return HWC_DISPLAY_VIRTUAL;
+      return qdutils::DISPLAY_VIRTUAL;
 
     default:
       break;
@@ -94,36 +95,36 @@
   int32_t error = -EINVAL;
   bool connected = false;
   int disp_id = MapDisplayType(dpy);
+  int disp_idx = GetDisplayIndex(disp_id);
 
-  if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
-    _hidl_cb(error, connected);
-    return Void();
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", disp_id);
+  } else {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+    connected = hwc_display_[disp_idx];
+    error = 0;
   }
-
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
-
-  connected = hwc_display_[disp_id];
-  error = 0;
-
   _hidl_cb(error, connected);
+
   return Void();
 }
 
 int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
-  if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
+  int disp_idx = GetDisplayIndex(disp_id);
+  if (disp_idx == -1) {
     DLOGE("Invalid display = %d", disp_id);
     return -EINVAL;
   }
 
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
-  DLOGI("Display = %d, Status = %d", disp_id, status);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+  DLOGI("Display = %d, Status = %d", disp_idx, status);
 
-  if (disp_id == HWC_DISPLAY_PRIMARY) {
+  if (disp_idx == qdutils::DISPLAY_PRIMARY) {
     DLOGE("Not supported for this display");
-  } else if (!hwc_display_[disp_id]) {
+  } else if (!hwc_display_[disp_idx]) {
     DLOGW("Display is not connected");
   } else {
-    return hwc_display_[disp_id]->SetDisplayStatus(status);
+    return hwc_display_[disp_idx]->SetDisplayStatus(status);
   }
 
   return -EINVAL;
@@ -146,13 +147,13 @@
 
   switch (op) {
     case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE:
-      return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+      return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
 
     case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE:
-      return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+      return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
 
     case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE:
-      return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
+      return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
 
     default:
       DLOGW("Invalid operation %d", op);
@@ -163,14 +164,16 @@
 }
 
 int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
-  if (disp_id < 0) {
+  int disp_idx = GetDisplayIndex(disp_id);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", disp_id);
     return -EINVAL;
   }
 
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
 
-  if (hwc_display_[disp_id]) {
-    return hwc_display_[disp_id]->GetDisplayConfigCount(count);
+  if (hwc_display_[disp_idx]) {
+    return hwc_display_[disp_idx]->GetDisplayConfigCount(count);
   }
 
   return -EINVAL;
@@ -187,14 +190,16 @@
 }
 
 int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
-  if (disp_id < 0) {
+  int disp_idx = GetDisplayIndex(disp_id);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", disp_id);
     return -EINVAL;
   }
 
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
 
-  if (hwc_display_[disp_id]) {
-    return hwc_display_[disp_id]->GetActiveDisplayConfig(config);
+  if (hwc_display_[disp_idx]) {
+    return hwc_display_[disp_idx]->GetActiveDisplayConfig(config);
   }
 
   return -EINVAL;
@@ -211,14 +216,16 @@
 }
 
 int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
-  if (disp_id < 0) {
+  int disp_idx = GetDisplayIndex(disp_id);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", disp_id);
     return -EINVAL;
   }
 
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
   int32_t error = -EINVAL;
-  if (hwc_display_[disp_id]) {
-    error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
+  if (hwc_display_[disp_idx]) {
+    error = hwc_display_[disp_idx]->SetActiveDisplayConfig(config);
     if (!error) {
       Refresh(0);
     }
@@ -237,21 +244,23 @@
   int32_t error = -EINVAL;
   IDisplayConfig::DisplayAttributes display_attributes = {};
   int disp_id = MapDisplayType(dpy);
+  int disp_idx = GetDisplayIndex(disp_id);
 
-  if (disp_id >= HWC_DISPLAY_PRIMARY && disp_id < HWC_NUM_DISPLAY_TYPES) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
-    if (hwc_display_[disp_id]) {
-      DisplayConfigVariableInfo hwc_display_attributes;
-      error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(static_cast<int>(configIndex),
-                                                                   &hwc_display_attributes);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", disp_id);
+  } else {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+    if (hwc_display_[disp_idx]) {
+      DisplayConfigVariableInfo var_info;
+      error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(INT(configIndex), &var_info);
       if (!error) {
-        display_attributes.vsyncPeriod = hwc_display_attributes.vsync_period_ns;
-        display_attributes.xRes = hwc_display_attributes.x_pixels;
-        display_attributes.yRes = hwc_display_attributes.y_pixels;
-        display_attributes.xDpi = hwc_display_attributes.x_dpi;
-        display_attributes.yDpi = hwc_display_attributes.y_dpi;
+        display_attributes.vsyncPeriod = var_info.vsync_period_ns;
+        display_attributes.xRes = var_info.x_pixels;
+        display_attributes.yRes = var_info.y_pixels;
+        display_attributes.xDpi = var_info.x_dpi;
+        display_attributes.yDpi = var_info.y_dpi;
         display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
-        display_attributes.isYuv = hwc_display_attributes.is_yuv;
+        display_attributes.isYuv = var_info.is_yuv;
       }
     }
   }
@@ -265,7 +274,7 @@
   int32_t error = -EINVAL;
 
   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
-    error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(static_cast<int>(level));
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(INT(level));
     if (error) {
       DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
     }
@@ -402,22 +411,23 @@
   int32_t error = -EINVAL;
   IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
 
-  if (!_hidl_cb) {
-    DLOGE("_hidl_cb callback not provided.");
-    return Void();
-  }
-
   do {
-    int disp_id = MapDisplayType(dpy);
-    if ((disp_id < 0) || (disp_id >= HWC_NUM_DISPLAY_TYPES)) {
-      DLOGE("Invalid display id = %d", disp_id);
+    if (!_hidl_cb) {
+      DLOGE("_hidl_cb callback not provided.");
       break;
     }
 
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
-    HWCDisplay *hwc_display = hwc_display_[disp_id];
+    int disp_id = MapDisplayType(dpy);
+    int disp_idx = GetDisplayIndex(disp_id);
+    if (disp_idx == -1) {
+      DLOGE("Invalid display = %d", disp_id);
+      break;
+    }
+
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+    HWCDisplay *hwc_display = hwc_display_[disp_idx];
     if (!hwc_display) {
-      DLOGW("Display = %d is not connected.", disp_id);
+      DLOGW("Display = %d is not connected.", disp_idx);
       error = -ENODEV;
       break;
     }
@@ -442,8 +452,7 @@
     float out_min_luminance = 0.0f;
     if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
                                         &out_max_luminance, &out_max_average_luminance,
-                                        &out_min_luminance)
-        == HWC2::Error::None) {
+                                        &out_min_luminance) == HWC2::Error::None) {
       error = 0;
     }
   } while (false);
@@ -517,4 +526,71 @@
   return Void();
 }
 
+#ifdef DISPLAY_CONFIG_1_1
+Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
+  return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+                             &HWCDisplay::SetDisplayAnimating, animating);
+}
+#endif
+
+#ifdef DISPLAY_CONFIG_1_2
+static const char * GetDisplayTypeName(IDisplayConfig::DisplayTypeExt disp_type) {
+  switch (disp_type) {
+    case IDisplayConfig::DisplayTypeExt::DISPLAY_BUILTIN:   return "Built-in";
+    case IDisplayConfig::DisplayTypeExt::DISPLAY_PLUGGABLE: return "Pluggable";
+    case IDisplayConfig::DisplayTypeExt::DISPLAY_VIRTUAL:   return "Virtual";
+    case IDisplayConfig::DisplayTypeExt::DISPLAY_PRIMARY:   return "Primary";
+    default:                                                return "Unknown";
+  }
+}
+
+Return<int32_t> HWCSession::setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
+                                            uint32_t base, uint32_t count) {
+  if (client_connected_) {
+    DLOGW("Not supported after client connection is completed.");
+    return -1;
+  }
+
+  DLOGI("%s display: base = %d, count = %d", GetDisplayTypeName(disp_type), base, count);
+
+  // Is display slots capacity smaller than what client can support?
+  if ((base + count) > kNumDisplays) {
+    DLOGE("Exceeds max supported display slots = %d", kNumDisplays);
+    return -1;
+  }
+
+  std::vector<DisplayMapInfo> *map_info_v = nullptr;
+  switch (disp_type) {
+    case IDisplayConfig::DisplayTypeExt::DISPLAY_BUILTIN:
+      map_info_v = &map_info_builtin_;
+      break;
+    case IDisplayConfig::DisplayTypeExt::DISPLAY_PLUGGABLE:
+      map_info_v = &map_info_pluggable_;
+      break;
+    case IDisplayConfig::DisplayTypeExt::DISPLAY_VIRTUAL:
+      map_info_v = &map_info_virtual_;
+      break;
+    case IDisplayConfig::DisplayTypeExt::DISPLAY_PRIMARY:
+      // nothing to do
+      return 0;
+    default:
+      return -1;
+  }
+
+  // Reset default client id for each display with a new client id in given range.
+  // Remove remaining elements as client as client can not handle these displays.
+  DLOGI("Change %s display capacity to %d", GetDisplayTypeName(disp_type), count);
+  map_info_v->resize(count);
+
+  uint32_t idx = 0;
+  for (auto &map_info : *map_info_v) {
+    map_info.client_id = base++;
+    DLOGI("Override: %s display: Index = %d, Client ID = %d",
+                  GetDisplayTypeName(disp_type), idx++, map_info.client_id);
+  }
+
+  return 0;
+}
+#endif
+
 }  // namespace sdm