Merge "sdm: Handle idle fall back and idle power collapse with same event"
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index b8e2a9e..142d2c6 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -137,8 +137,9 @@
 
 /*! @brief This enum represents the events received by Display HAL. */
 enum DisplayEvent {
-  kIdleTimeout,    // Event triggered by Idle Timer.
-  kThermalEvent,   // Event triggered by Thermal.
+  kIdleTimeout,        // Event triggered by Idle Timer.
+  kThermalEvent,       // Event triggered by Thermal.
+  kIdlePowerCollapse,  // Event triggered by Idle Power Collapse.
 };
 
 /*! @brief This structure defines configuration for fixed properties of a display device.
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 64a0bcc..8f3d6f0 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -280,10 +280,15 @@
 }
 
 void DisplayPrimary::IdleTimeout() {
-  handle_idle_timeout_ = true;
-  event_handler_->Refresh();
-  comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
-  event_handler_->HandleEvent(kIdleTimeout);
+  if (hw_panel_info_.mode == kModeCommand) {
+    IdlePowerCollapse();
+  } else {
+    event_handler_->HandleEvent(kIdleTimeout);
+    handle_idle_timeout_ = true;
+    event_handler_->Refresh();
+    lock_guard<recursive_mutex> obj(recursive_mutex_);
+    comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+  }
 }
 
 void DisplayPrimary::PingPongTimeout() {
@@ -292,12 +297,13 @@
 }
 
 void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
+  event_handler_->HandleEvent(kThermalEvent);
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
-  event_handler_->HandleEvent(kThermalEvent);
 }
 
 void DisplayPrimary::IdlePowerCollapse() {
+  event_handler_->HandleEvent(kIdlePowerCollapse);
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   comp_manager_->ProcessIdlePowerCollapse(display_comp_ctx_);
 }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index d112b67..380d162 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -40,6 +40,7 @@
 #include "hwc_display.h"
 #include "hwc_debugger.h"
 #include "hwc_tonemapper.h"
+#include "hwc_session.h"
 
 #ifndef USE_GRALLOC1
 #include <gr.h>
@@ -952,6 +953,8 @@
   switch (event) {
     case kIdleTimeout:
     case kThermalEvent:
+    case kIdlePowerCollapse:
+      HWCSession::WaitForSequence(id_);
       validated_.reset();
       break;
     default:
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 2039a46..89de074 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -70,7 +70,7 @@
 namespace sdm {
 
 static HWCUEvent g_hwc_uevent_;
-Locker HWCSession::locker_;
+Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
 
 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
   const char *uevent_thread_name = "HWC_UeventThread";
@@ -135,6 +135,8 @@
 }
 
 int HWCSession::Init() {
+  SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
   int status = -EINVAL;
   const char *qservice_name = "display.qservice";
 
@@ -224,6 +226,10 @@
 }
 
 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]);
+
   HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
   if (primary_display) {
     if (hdmi_is_primary_) {
@@ -249,8 +255,6 @@
 }
 
 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
-  SCOPE_LOCK(locker_);
-
   if (!module || !name || !device) {
     DLOGE("Invalid parameters.");
     return -EINVAL;
@@ -275,8 +279,6 @@
 }
 
 int HWCSession::Close(hw_device_t *device) {
-  SCOPE_LOCK(locker_);
-
   if (!device) {
     return -EINVAL;
   }
@@ -317,20 +319,20 @@
 // Defined in the same order as in the HWC2 header
 
 int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
-  SCOPE_LOCK(locker_);
+  SCOPE_LOCK(locker_[display]);
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
 }
 
 int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display,
                                 hwc2_layer_t *out_layer_id) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
   return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id);
 }
 
 int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
                                          int32_t *format, hwc2_display_t *out_display_id) {
   // TODO(user): Handle concurrency with HDMI
-  SCOPE_LOCK(locker_);
+  SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
   if (!device) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
@@ -349,16 +351,16 @@
 
 int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display,
                                  hwc2_layer_t layer) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
   return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer);
 }
 
 int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
-  SCOPE_LOCK(locker_);
   if (!device || display != HWC_DISPLAY_VIRTUAL) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
+  SCOPE_LOCK(locker_[display]);
   DLOGI("Destroying virtual display id:%" PRIu64, display);
   auto *hwc_session = static_cast<HWCSession *>(device);
 
@@ -372,8 +374,6 @@
 }
 
 void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
-  SCOPE_LOCK(locker_);
-
   if (!device) {
     return;
   }
@@ -387,6 +387,7 @@
     DumpInterface::GetDump(sdm_dump, 4096);  // TODO(user): Fix this workaround
     std::string s("");
     for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) {
+      SEQUENCE_WAIT_SCOPE_LOCK(locker_[id]);
       if (hwc_session->hwc_display_[id]) {
         s += hwc_session->hwc_display_[id]->Dump();
       }
@@ -490,6 +491,7 @@
                                    int32_t *out_retire_fence) {
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   DTRACE_SCOPED();
+  SEQUENCE_EXIT_SCOPE_LOCK(locker_[display]);
   if (!device) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
@@ -541,14 +543,14 @@
 int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
                                  int32_t /*android_color_mode_t*/ int_mode) {
   auto mode = static_cast<android_color_mode_t>(int_mode);
-  SCOPE_LOCK(locker_);
+  SCOPE_LOCK(locker_[display]);
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
 }
 
 int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
                                       const float *matrix,
                                       int32_t /*android_color_transform_t*/ hint) {
-  SCOPE_LOCK(locker_);
+  SCOPE_LOCK(locker_[display]);
   android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
                                          transform_hint);
@@ -634,7 +636,7 @@
 
 int32_t HWCSession::SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display,
                                    hwc2_layer_t layer, uint32_t z) {
-  SCOPE_LOCK(locker_);
+  SCOPE_LOCK(locker_[display]);
   return CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
 }
 
@@ -648,6 +650,7 @@
     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]);
@@ -660,7 +663,7 @@
 
 int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
   auto mode = static_cast<HWC2::PowerMode>(int_mode);
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
   return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
 }
 
@@ -672,7 +675,6 @@
 int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
                                     uint32_t *out_num_types, uint32_t *out_num_requests) {
   DTRACE_SCOPED();
-  SCOPE_LOCK(locker_);
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   if (!device) {
     return HWC2_ERROR_BAD_DISPLAY;
@@ -681,25 +683,35 @@
   // TODO(user): Handle secure session, handle QDCM solid fill
   // Handle external_pending_connect_ in CreateVirtualDisplay
   auto status = HWC2::Error::BadDisplay;
-  if (hwc_session->hwc_display_[display]) {
-    if (display == HWC_DISPLAY_PRIMARY) {
-      // TODO(user): This can be moved to HWCDisplayPrimary
-      if (hwc_session->reset_panel_) {
-        DLOGW("panel is in bad state, resetting the panel");
-        hwc_session->ResetPanel();
+  {
+    SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
+    if (hwc_session->hwc_display_[display]) {
+      if (display == HWC_DISPLAY_PRIMARY) {
+        // TODO(user): This can be moved to HWCDisplayPrimary
+        if (hwc_session->reset_panel_) {
+          DLOGW("panel is in bad state, resetting the panel");
+          hwc_session->ResetPanel();
+        }
+
+        if (hwc_session->need_invalidate_) {
+          hwc_session->Refresh(display);
+        }
+
+        if (hwc_session->color_mgr_) {
+          hwc_session->color_mgr_->SetColorModeDetailEnhancer(hwc_session->hwc_display_[display]);
+        }
       }
 
-      if (hwc_session->need_invalidate_) {
-        hwc_session->Refresh(display);
-      }
-
-      if (hwc_session->color_mgr_) {
-        hwc_session->color_mgr_->SetColorModeDetailEnhancer(hwc_session->hwc_display_[display]);
-      }
+      status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests);
     }
-
-    status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests);
   }
+
+  // If validate fails, cancel the sequence lock so that other operations
+  // (such as Dump or SetPowerMode) may succeed without blocking on the condition
+  if (status == HWC2::Error::BadDisplay) {
+    SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
+  }
+
   return INT32(status);
 }
 
@@ -1013,8 +1025,6 @@
 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
                                                                   *input_parcel,
                                                                   android::Parcel *output_parcel) {
-  SCOPE_LOCK(locker_);
-
   int config = input_parcel->readInt32();
   int dpy = input_parcel->readInt32();
   int error = android::BAD_VALUE;
@@ -1024,6 +1034,7 @@
     return android::BAD_VALUE;
   }
 
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
   if (hwc_display_[dpy]) {
     error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
     if (error == 0) {
@@ -1040,7 +1051,7 @@
 }
 
 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
   uint32_t operation = UINT32(input_parcel->readInt32());
   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
@@ -1066,20 +1077,19 @@
 }
 
 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
   uint32_t mode = UINT32(input_parcel->readInt32());
   return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
 }
 
 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
-  SCOPE_LOCK(locker_);
-
   DisplayError error = kErrorNone;
   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
   uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
 
   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
       error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
       if (error != kErrorNone) {
@@ -1089,6 +1099,7 @@
   }
 
   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
       error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
       if (error != kErrorNone) {
@@ -1098,6 +1109,7 @@
   }
 
   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
       error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
       if (error != kErrorNone) {
@@ -1110,25 +1122,26 @@
 }
 
 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
-  SCOPE_LOCK(locker_);
-
   uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
 
   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
       hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
     }
   }
 
   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
       hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
     }
   }
 
   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
       hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
     }
@@ -1136,8 +1149,6 @@
 }
 
 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
-  SCOPE_LOCK(locker_);
-
   DisplayError error = kErrorNone;
   uint32_t dpy = UINT32(input_parcel->readInt32());
 
@@ -1146,6 +1157,7 @@
     return -EINVAL;
   }
 
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
     DLOGI("Primary display is not initialized");
     return -EINVAL;
@@ -1166,6 +1178,8 @@
   auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
   auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
   auto device = static_cast<hwc2_device_t *>(this);
+
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
   auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
@@ -1181,6 +1195,7 @@
     return -EINVAL;
   }
 
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
   auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorModeById, mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
@@ -1188,7 +1203,7 @@
 }
 
 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
-  SCOPE_LOCK(locker_);
+  // TODO(user): Do we really need a lock here?
 
   int type = input_parcel->readInt32();
   bool enable = (input_parcel->readInt32() > 0);
@@ -1427,13 +1442,12 @@
   // 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 {
-    SCOPE_LOCK(locker_);
-
     // 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 {
@@ -1445,13 +1459,18 @@
       break;
     }
 
-    // Primary display must be connected for HDMI as secondary cases.
-    if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
-      DLOGE("Primary display is not connected.");
-      return -1;
+    {
+      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;
+      }
     }
 
     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.
@@ -1466,6 +1485,7 @@
         external_pending_connect_ = true;
       }
     } else {
+      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.
@@ -1500,7 +1520,7 @@
 }
 
 int HWCSession::GetVsyncPeriod(int disp) {
-  SCOPE_LOCK(locker_);
+  SCOPE_LOCK(locker_[disp]);
   // default value
   int32_t vsync_period = 1000000000l / 60;
   auto attribute = HWC2::Attribute::VsyncPeriod;
@@ -1514,14 +1534,12 @@
 
 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
                                                     android::Parcel *output_parcel) {
-  SCOPE_LOCK(locker_);
-
   int dpy = input_parcel->readInt32();
-
   if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
     return android::BAD_VALUE;
   }
 
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
   if (!hwc_display_[dpy]) {
     return android::NO_INIT;
   }
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index f09ed0e..4dbcf9b 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -140,6 +140,12 @@
   static int32_t SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
                                    const float *matrix, int32_t /*android_color_transform_t*/ hint);
 
+  // Meant to be called by HWCDisplay to preserve sequence of validate/present during events from
+  // polling thread
+  static void WaitForSequence(hwc2_display_t display) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
+  }
+
  private:
   static const int kExternalConnectionTimeoutMs = 500;
   static const int kPartialUpdateControlTimeoutMs = 100;
@@ -221,7 +227,7 @@
   void Refresh(hwc2_display_t display);
   void HotPlug(hwc2_display_t display, HWC2::Connection state);
 
-  static Locker locker_;
+  static Locker locker_[HWC_NUM_DISPLAY_TYPES];
   CoreInterface *core_intf_ = nullptr;
   HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
   HWCCallbacks callbacks_;
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 425ffbe..a5cf66a 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -92,12 +92,12 @@
 // Methods from ::vendor::hardware::display::config::V1_0::IDisplayConfig follow.
 Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
                                             isDisplayConnected_cb _hidl_cb) {
-  SCOPE_LOCK(locker_);
-
   int32_t error = -EINVAL;
   bool connected = false;
 
   int disp_id = MapDisplayType(dpy);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+
   if (disp_id >= 0) {
     connected = hwc_display_[disp_id];
     error = 0;
@@ -109,12 +109,11 @@
 }
 
 int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
-  SCOPE_LOCK(locker_);
-
   if (disp_id < 0) {
     return -EINVAL;
   }
 
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
   DLOGI("Display = %d, Status = %d", disp_id, status);
 
   if (disp_id == HWC_DISPLAY_PRIMARY) {
@@ -135,8 +134,7 @@
 
 Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
                                                    uint32_t refreshRate) {
-  SCOPE_LOCK(locker_);
-
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
 
   switch (op) {
@@ -158,9 +156,13 @@
 }
 
 int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
-  SCOPE_LOCK(locker_);
+  if (disp_id < 0) {
+    return -EINVAL;
+  }
 
-  if (disp_id >= 0 && hwc_display_[disp_id]) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+
+  if (hwc_display_[disp_id]) {
     return hwc_display_[disp_id]->GetDisplayConfigCount(count);
   }
 
@@ -178,9 +180,13 @@
 }
 
 int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
-  SCOPE_LOCK(locker_);
+  if (disp_id < 0) {
+    return -EINVAL;
+  }
 
-  if (disp_id >= 0 && hwc_display_[disp_id]) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+
+  if (hwc_display_[disp_id]) {
     return hwc_display_[disp_id]->GetActiveDisplayConfig(config);
   }
 
@@ -198,12 +204,11 @@
 }
 
 int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
-  SCOPE_LOCK(locker_);
-
   if (disp_id < 0) {
     return -EINVAL;
   }
 
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
   int32_t error = -EINVAL;
   if (hwc_display_[disp_id]) {
     error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
@@ -222,12 +227,11 @@
 Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
                                               IDisplayConfig::DisplayType dpy,
                                               getDisplayAttributes_cb _hidl_cb) {
-  SCOPE_LOCK(locker_);
-
   int32_t error = -EINVAL;
   IDisplayConfig::DisplayAttributes display_attributes = {};
-
   int disp_id = MapDisplayType(dpy);
+
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
   if (disp_id >= 0 && hwc_display_[disp_id]) {
     DisplayConfigVariableInfo hwc_display_attributes;
     error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(static_cast<int>(configIndex),
@@ -247,9 +251,9 @@
 }
 
 Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
-  SCOPE_LOCK(locker_);
-
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   int32_t error = -EINVAL;
+
   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
     error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(static_cast<int>(level));
     if (error) {
@@ -261,8 +265,7 @@
 }
 
 int32_t HWCSession::GetPanelBrightness(int *level) {
-  SCOPE_LOCK(locker_);
-
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   int32_t error = -EINVAL;
 
   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
@@ -285,14 +288,13 @@
 }
 
 int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
-  SCOPE_LOCK(locker_);
-
   DLOGI("Display %d", disp_id);
 
   if (disp_id < 0) {
     return -EINVAL;
   }
 
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
   if (disp_id != HWC_DISPLAY_EXTERNAL) {
     DLOGE("Not supported for display");
   } else if (!hwc_display_[disp_id]) {
@@ -310,16 +312,13 @@
 }
 
 Return<int32_t> HWCSession::refreshScreen() {
-  SCOPE_LOCK(locker_);
-
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   Refresh(HWC_DISPLAY_PRIMARY);
 
   return 0;
 }
 
 int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
-  SCOPE_LOCK(locker_);
-
   if (disp_id < 0) {
     return -EINVAL;
   }
@@ -329,6 +328,7 @@
     return -EINVAL;
   }
 
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
   if (!hwc_display) {
     DLOGE("primary display object is not instantiated");
@@ -352,7 +352,7 @@
   Refresh(HWC_DISPLAY_PRIMARY);
 
   // Wait until partial update control is complete
-  int32_t error = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
+  int32_t error = locker_[disp_id].WaitFinite(kPartialUpdateControlTimeoutMs);
 
   return error;
 }
@@ -362,7 +362,7 @@
 }
 
 Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
   int32_t error = -EINVAL;
   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
@@ -376,7 +376,7 @@
 }
 
 Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
     hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
@@ -388,8 +388,6 @@
 
 Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
                                             getHDRCapabilities_cb _hidl_cb) {
-  SCOPE_LOCK(locker_);
-
   int32_t error = -EINVAL;
   IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
 
@@ -400,6 +398,7 @@
       break;
     }
 
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
     HWCDisplay *hwc_display = hwc_display_[disp_id];
     if (!hwc_display) {
       DLOGE("Display = %d is not connected.", disp_id);
@@ -438,7 +437,7 @@
 }
 
 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
   HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
 
@@ -457,7 +456,7 @@
 }
 
 int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
     if (sync_wait(bw_mode_release_fd_, 0) < 0) {