hwc2: Avoid drawcycles with non-empty dirty region

--Reject drawcycle if following conditions are met.
    1. No change in layerstack attributes.
    2. No new buffer latched.
    3. No refresh request triggered by HWC.
    4. This display is not source of vsync.

--Do not return Present failed error if display is inactive.
  SF wouldn't query for release fence upon errors.

CRs-Fixed: 2354696
Change-Id: I28174a09f4b5046d25c953f568f981fdb80b42a8
diff --git a/sdm/libs/hwc2/hwc_callbacks.cpp b/sdm/libs/hwc2/hwc_callbacks.cpp
index 92d0f6d..b26d633 100644
--- a/sdm/libs/hwc2/hwc_callbacks.cpp
+++ b/sdm/libs/hwc2/hwc_callbacks.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, 2019 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
@@ -47,6 +47,7 @@
     return HWC2::Error::NoResources;
   }
   refresh_(refresh_data_, display);
+  pending_refresh_.set(UINT32(display));
   return HWC2::Error::None;
 }
 
diff --git a/sdm/libs/hwc2/hwc_callbacks.h b/sdm/libs/hwc2/hwc_callbacks.h
index 9a37587..6b39963 100644
--- a/sdm/libs/hwc2/hwc_callbacks.h
+++ b/sdm/libs/hwc2/hwc_callbacks.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, 2019 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
@@ -40,6 +40,12 @@
 
 class HWCCallbacks {
  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;
+
   HWC2::Error Hotplug(hwc2_display_t display, HWC2::Connection state);
   HWC2::Error Refresh(hwc2_display_t display);
   HWC2::Error Vsync(hwc2_display_t display, int64_t timestamp);
@@ -53,6 +59,8 @@
   hwc2_display_t GetVsyncSource() { return vsync_from_; }
 
   bool VsyncCallbackRegistered() { return (vsync_ != nullptr && vsync_data_ != nullptr); }
+  bool NeedsRefresh(hwc2_display_t display) { return pending_refresh_.test(UINT32(display)); }
+  void ResetRefresh(hwc2_display_t display) { pending_refresh_.reset(UINT32(display)); }
 
  private:
   hwc2_callback_data_t hotplug_data_ = nullptr;
@@ -64,6 +72,7 @@
   HWC2_PFN_VSYNC vsync_ = nullptr;
   hwc2_display_t vsync_from_ = HWC_DISPLAY_PRIMARY;   // hw vsync is active on this display
   hwc2_display_t vsync_to_ = HWC_DISPLAY_PRIMARY;     // vsync will be reported as this display
+  std::bitset<kNumDisplays> pending_refresh_;         // Displays waiting to get refreshed
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 65f5de4..d2ffe03 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1286,16 +1286,17 @@
   if (error != kErrorNone) {
     if (error == kErrorShutDown) {
       shutdown_pending_ = true;
-    } else if (error != kErrorPermission) {
+    } else if (error == kErrorPermission) {
+      WaitOnPreviousFence();
+      MarkLayersForGPUBypass();
+    } else {
       DLOGE("Prepare failed. Error = %d", error);
       // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
       // so that previous buffer and fences are released, and override the error.
       flush_ = true;
-    } else {
-      WaitOnPreviousFence();
+      validated_ = false;
+      return HWC2::Error::BadDisplay;
     }
-    validated_ = false;
-    return HWC2::Error::BadDisplay;
   }
 
   for (auto hwc_layer : layer_set_) {
@@ -1485,6 +1486,11 @@
     return HWC2::Error::None;
   }
 
+  if (skip_commit_) {
+    DLOGV_IF(kTagClient, "Skipping Refresh on display %d", id_);
+    return HWC2::Error::None;
+  }
+
   DumpInputBuffers();
 
   DisplayError error = kErrorUndefined;
@@ -1566,9 +1572,9 @@
         hwc_layer->PushBackReleaseFence(-1);
       }
     } else {
-      // In case of flush, we don't return an error to f/w, so it will get a release fence out of
-      // the hwc_layer's release fence queue. We should push a -1 to preserve release fence
-      // circulation semantics.
+      // In case of flush or display paused, we don't return an error to f/w, so it will
+      // get a release fence out of the hwc_layer's release fence queue
+      // We should push a -1 to preserve release fence circulation semantics.
       hwc_layer->PushBackReleaseFence(-1);
     }
 
@@ -1599,6 +1605,7 @@
   layer_stack_.flags.geometry_changed = false;
   geometry_changes_ = GeometryChanges::kNone;
   flush_ = false;
+  skip_commit_ = false;
 
   return status;
 }
@@ -1968,7 +1975,7 @@
 
 int HWCDisplay::ToggleScreenUpdates(bool enable) {
   display_paused_ = enable ? false : true;
-  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  callbacks_->Refresh(id_);
   validated_ = false;
   return 0;
 }
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 8c8e5f4..84a1a1e 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -272,6 +272,12 @@
   virtual DisplayError GetSupportedDSIClock(std::vector<uint64_t> *bitclk) {
     return kErrorNotSupported;
   }
+  virtual HWC2::Error UpdateDisplayId(hwc2_display_t id) {
+    return HWC2::Error::Unsupported;
+  }
+  virtual HWC2::Error SetPendingRefresh() {
+    return HWC2::Error::Unsupported;
+  }
   virtual HWC2::Error GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs);
   virtual HWC2::Error GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
                                           int32_t *out_value);
@@ -317,6 +323,7 @@
   }
   virtual HWC2::Error GetDisplayIdentificationData(uint8_t *out_port, uint32_t *out_data_size,
                                                    uint8_t *out_data);
+  virtual void SetVsyncSource(bool enable) { vsync_source_ = enable; }
 
  protected:
   static uint32_t throttling_refresh_rate_;
@@ -402,6 +409,8 @@
   bool is_cmd_mode_ = false;
   bool partial_update_enabled_ = false;
   bool fast_path_composition_ = false;
+  bool vsync_source_ = false;
+  bool skip_commit_ = false;
   std::map<uint32_t, DisplayConfigVariableInfo> variable_config_map_;
   std::vector<uint32_t> hwc_config_map_;
 
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index 41ce1b1..53c9dc4 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -122,6 +122,13 @@
   HWCDebugHandler::Get()->GetProperty(ENABLE_DEFAULT_COLOR_MODE,
                                       &default_mode_status_);
 
+  int drop_refresh = 0;
+  HWCDebugHandler::Get()->GetProperty(ENABLE_DROP_REFRESH, &drop_refresh);
+  enable_drop_refresh_ = (drop_refresh == 1);
+  if (enable_drop_refresh_) {
+    DLOGI("Drop redundant drawcycles %d", id_);
+  }
+
   return status;
 }
 
@@ -193,6 +200,34 @@
   return status;
 }
 
+HWC2::Error HWCDisplayBuiltIn::CommitLayerStack() {
+  skip_commit_ = CanSkipCommit();
+  return HWCDisplay::CommitLayerStack();
+}
+
+bool HWCDisplayBuiltIn::CanSkipCommit() {
+  if (layer_stack_invalid_) {
+    return false;
+  }
+
+  // Reject repeated drawcycle requests if it satisfies all conditions.
+  // 1. None of the layerstack attributes changed.
+  // 2. No new buffer latched.
+  // 3. No refresh request triggered by HWC.
+  // 4. This display is not source of vsync.
+  bool buffers_latched = false;
+  for (auto &hwc_layer : layer_set_) {
+    buffers_latched |= hwc_layer->BufferLatched();
+    hwc_layer->ResetBufferFlip();
+  }
+
+  bool skip_commit = enable_drop_refresh_ && !pending_commit_ && !buffers_latched &&
+                     !pending_refresh_ && !vsync_source_;
+  pending_refresh_ = false;
+
+  return skip_commit;
+}
+
 HWC2::Error HWCDisplayBuiltIn::Present(int32_t *out_retire_fence) {
   auto status = HWC2::Error::None;
 
@@ -204,7 +239,7 @@
       DLOGE("Flush failed. Error = %d", error);
     }
   } else {
-    status = HWCDisplay::CommitLayerStack();
+    status = CommitLayerStack();
     if (status == HWC2::Error::None) {
       HandleFrameOutput();
       SolidFillCommit();
@@ -840,4 +875,14 @@
   return kErrorNotSupported;
 }
 
+HWC2::Error HWCDisplayBuiltIn::UpdateDisplayId(hwc2_display_t id) {
+  id_ = id;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplayBuiltIn::SetPendingRefresh() {
+  pending_refresh_ = true;
+  return HWC2::Error::None;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_builtin.h b/sdm/libs/hwc2/hwc_display_builtin.h
index 386bd2f..c0483d7 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -57,6 +57,7 @@
   virtual int Init();
   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 CommitLayerStack();
   virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes);
   virtual HWC2::Error SetColorMode(ColorMode mode);
   virtual HWC2::Error GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
@@ -87,6 +88,8 @@
   virtual DisplayError SetDynamicDSIClock(uint64_t bitclk);
   virtual DisplayError GetDynamicDSIClock(uint64_t *bitclk);
   virtual DisplayError GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates);
+  virtual HWC2::Error UpdateDisplayId(hwc2_display_t id);
+  virtual HWC2::Error SetPendingRefresh();
   virtual DisplayError TeardownConcurrentWriteback(void);
   virtual void SetFastPathComposition(bool enable) {
     fast_path_composition_ = enable && !readback_buffer_queued_;
@@ -108,6 +111,7 @@
   void HandleFrameOutput();
   void HandleFrameDump();
   void HandleFrameCapture();
+  bool CanSkipCommit();
   DisplayError SetMixerResolution(uint32_t width, uint32_t height);
   DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
 
@@ -125,6 +129,8 @@
   BufferInfo output_buffer_info_ = {};
   void *output_buffer_base_ = nullptr;
   int default_mode_status_ = 0;
+  bool pending_refresh_ = true;
+  bool enable_drop_refresh_ = false;
 
   // Members for 1 frame capture in a client provided buffer
   bool frame_capture_buffer_queued_ = false;
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 6e11e29..59430eb 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -302,6 +302,7 @@
   layer_buffer->planes[0].offset = handle->offset;
   layer_buffer->planes[0].stride = UINT32(handle->width);
   layer_buffer->size = handle->size;
+  buffer_flipped_ = reinterpret_cast<uint64_t>(handle) != layer_buffer->buffer_id;
   layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle);
   layer_buffer->handle_id = handle->id;
 
@@ -371,6 +372,7 @@
   if (layer_->solid_fill_color != GetUint32Color(color)) {
     layer_->solid_fill_color = GetUint32Color(color);
     surface_updated_ = true;
+    needs_validate_ = true;
   } else {
     surface_updated_ = false;
   }
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index b7d021b..e55aa4f 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -115,6 +115,8 @@
   bool HasMetaDataRefreshRate() { return has_metadata_refresh_rate_; }
   bool IsColorTransformSet() { return color_transform_matrix_set_; }
   void SetLayerAsMask();
+  bool BufferLatched() { return buffer_flipped_; }
+  void ResetBufferFlip() { buffer_flipped_ = false; }
 
  private:
   Layer *layer_ = nullptr;
@@ -136,6 +138,7 @@
   bool non_integral_source_crop_ = false;
   bool has_metadata_refresh_rate_ = false;
   bool color_transform_matrix_set_ = false;
+  bool buffer_flipped_ = false;
 
   // Composition requested by client(SF)
   HWC2::Composition client_requested_ = HWC2::Composition::Device;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 97788df..0f70083 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -70,8 +70,8 @@
 namespace sdm {
 
 static HWCUEvent g_hwc_uevent_;
-Locker HWCSession::locker_[kNumDisplays];
-bool HWCSession::power_on_pending_[kNumDisplays];
+Locker HWCSession::locker_[HWCCallbacks::kNumDisplays];
+bool HWCSession::power_on_pending_[HWCCallbacks::kNumDisplays];
 
 static const int kSolidFillDelay = 100 * 1000;
 int HWCSession::null_display_mode_ = 0;
@@ -290,18 +290,18 @@
 
   map_info_primary_.client_id = qdutils::DISPLAY_PRIMARY;
 
-  map_info_builtin_.resize(kNumBuiltIn);
-  for (size_t i = 0; i < kNumBuiltIn; i++) {
+  map_info_builtin_.resize(HWCCallbacks::kNumBuiltIn);
+  for (size_t i = 0; i < HWCCallbacks::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_.resize(HWCCallbacks::kNumPluggable);
+  for (size_t i = 0; i < HWCCallbacks::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_.resize(HWCCallbacks::kNumVirtual);
+  for (size_t i = 0; i < HWCCallbacks::kNumVirtual; i++) {
     map_info_virtual_[i].client_id = i ? additional_base_id++ : qdutils::DISPLAY_VIRTUAL;
   }
 }
@@ -447,14 +447,14 @@
 }
 
 int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
-  if (!device || display >= kNumDisplays) {
+  if (!device || display >= HWCCallbacks::kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
   auto *hwc_session = static_cast<HWCSession *>(device);
   hwc2_display_t active_builtin_disp_id = hwc_session->GetActiveBuiltinDisplay();
 
-  if (active_builtin_disp_id < kNumDisplays) {
+  if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
     Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
     std::bitset<kSecureMax> secure_sessions = 0;
     hwc_session->hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
@@ -488,7 +488,7 @@
     *out_size = max_dump_size;
   } else {
     std::string s {};
-    for (int id = 0; id < kNumDisplays; id++) {
+    for (int id = 0; id < HWCCallbacks::kNumDisplays; id++) {
       SCOPE_LOCK(locker_[id]);
       if (hwc_session->hwc_display_[id]) {
         s += hwc_session->hwc_display_[id]->Dump();
@@ -678,7 +678,7 @@
   auto status = HWC2::Error::BadDisplay;
   DTRACE_SCOPED();
 
-  if (!hwc_session || (display >= HWCSession::kNumDisplays)) {
+  if (!hwc_session || (display >= HWCCallbacks::kNumDisplays)) {
     DLOGW("Invalid Display : hwc session = %s display = %" PRIu64,
           hwc_session ? "Valid" : "NULL", display);
     return HWC2_ERROR_BAD_DISPLAY;
@@ -700,6 +700,14 @@
       status = HWC2::Error::None;
     } else {
       status = hwc_session->PresentDisplayInternal(display, out_retire_fence);
+      if (status == HWC2::Error::None) {
+        // Check if hwc's refresh trigger is getting exercised.
+        if (hwc_session->callbacks_.NeedsRefresh(display)) {
+          hwc_session->hwc_display_[display]->SetPendingRefresh();
+          hwc_session->callbacks_.ResetRefresh(display);
+        }
+        status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
+      }
     }
   }
 
@@ -932,7 +940,7 @@
 }
 
 int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
-  if (display >= kNumDisplays) {
+  if (display >= HWCCallbacks::kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
@@ -1010,7 +1018,7 @@
   }
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  if (display >= HWCSession::kNumDisplays || (hwc_session->hwc_display_[display] == nullptr)) {
+  if (display >= HWCCallbacks::kNumDisplays || (hwc_session->hwc_display_[display] == nullptr)) {
     DLOGE("Invalid Display %d Handle %s ", display, hwc_session->hwc_display_[display] ?
           "Valid" : "NULL");
     return HWC2_ERROR_BAD_DISPLAY;
@@ -1031,7 +1039,7 @@
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
-  if (display >= kNumDisplays) {
+  if (display >= HWCCallbacks::kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
   DTRACE_SCOPED();
@@ -1198,7 +1206,7 @@
   }
 
   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-  if (active_builtin_disp_id < kNumDisplays) {
+  if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
     SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
     std::bitset<kSecureMax> secure_sessions = 0;
     if (hwc_display_[active_builtin_disp_id]) {
@@ -1264,7 +1272,7 @@
     }
   }
 
-  if (active_builtin_disp_id < kNumDisplays) {
+  if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
     SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
     hwc_display_[active_builtin_disp_id]->ResetValidation();
   }
@@ -1273,8 +1281,9 @@
 }
 
 DisplayClass HWCSession::GetDisplayClass(hwc2_display_t display) {
-  if (display >= kNumDisplays) {
-    DLOGE("display = %d beyond max supported display slots = %d", display, kNumDisplays);
+  if (display >= HWCCallbacks::kNumDisplays) {
+    DLOGE("display = %d beyond max supported display slots = %d",
+      display, HWCCallbacks::kNumDisplays);
     return DISPLAY_CLASS_NULL;
   } else if (!hwc_display_[display]) {
     DLOGE("display = %d slot empty.", display);
@@ -2000,7 +2009,7 @@
   int ret = 0;
   bool is_physical_display = false;
 
-  if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
+  if (display_id >= HWCCallbacks::kNumDisplays || !hwc_display_[display_id]) {
       DLOGW("Invalid display id or display = %d is not connected.", display_id);
       return -ENODEV;
   }
@@ -2136,7 +2145,7 @@
         case kMultiDispProc:
           for (auto &map_info : map_info_builtin_) {
             uint32_t id = UINT32(map_info.client_id);
-            if (id < kNumDisplays && hwc_display_[id]) {
+            if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
               int result = 0;
               resp_payload.DestroyPayload();
               result = hwc_display_[id]->ColorSVCRequestRoute(req_payload,
@@ -2150,19 +2159,19 @@
           }
           break;
         case kMultiDispGetId:
-          ret = resp_payload.CreatePayloadBytes(kNumDisplays, &disp_id);
+          ret = resp_payload.CreatePayloadBytes(HWCCallbacks::kNumDisplays, &disp_id);
           if (ret) {
             DLOGW("Unable to create response payload!");
           } else {
-            for (int i = 0; i < kNumDisplays; i++) {
-              disp_id[i] = kNumDisplays;
+            for (int i = 0; i < HWCCallbacks::kNumDisplays; i++) {
+              disp_id[i] = HWCCallbacks::kNumDisplays;
             }
             if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
               disp_id[HWC_DISPLAY_PRIMARY] = HWC_DISPLAY_PRIMARY;
             }
             for (auto &map_info : map_info_builtin_) {
               uint64_t id = map_info.client_id;
-              if (id < kNumDisplays && hwc_display_[id]) {
+              if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
                 disp_id[id] = (uint8_t)id;
               }
             }
@@ -2298,7 +2307,7 @@
 
     std::bitset<kSecureMax> secure_sessions = 0;
     hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-    if (active_builtin_disp_id < kNumDisplays) {
+    if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
       Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
       hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
     }
@@ -2444,6 +2453,8 @@
       if (!color_mgr_) {
         DLOGW("Failed to load HWCColorManager.");
       }
+      // This display is the source of vsync events.
+      (*hwc_display)->SetVsyncSource(true);
     } else {
       DLOGE("Primary display creation failed.");
     }
@@ -2614,7 +2625,7 @@
       if (client_connected_) {
         // Trigger a display refresh since we depend on PresentDisplay() to handle pending hotplugs.
         hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-        if (active_builtin_disp_id >= kNumDisplays) {
+        if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
           active_builtin_disp_id = HWC_DISPLAY_PRIMARY;
         }
         Refresh(active_builtin_disp_id);
@@ -2680,7 +2691,7 @@
 
   // Active builtin display needs revalidation
   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-  if (active_builtin_disp_id < kNumDisplays) {
+  if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
     {
       SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
       hwc_display_[active_builtin_disp_id]->ResetValidation();
@@ -2842,24 +2853,25 @@
       return HWC2::Error::NotValidated;
     }
   }
-
-  return hwc_display->Present(out_retire_fence);
+  return HWC2::Error::None;
 }
 
 void HWCSession::DisplayPowerReset() {
   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-  if (active_builtin_disp_id >= kNumDisplays) {
+  if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
     active_builtin_disp_id = HWC_DISPLAY_PRIMARY;
   }
   // Acquire lock on all displays.
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+    display < HWCCallbacks::kNumDisplays; display++) {
     locker_[display].Lock();
   }
 
   HWC2::Error status = HWC2::Error::None;
-  HWC2::PowerMode last_power_mode[kNumDisplays] = {};
+  HWC2::PowerMode last_power_mode[HWCCallbacks::kNumDisplays] = {};
 
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+    display < HWCCallbacks::kNumDisplays; display++) {
     if (hwc_display_[display] != NULL) {
       last_power_mode[display] = hwc_display_[display]->GetCurrentPowerMode();
       DLOGI("Powering off display = %d", display);
@@ -2870,7 +2882,8 @@
       }
     }
   }
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+    display < HWCCallbacks::kNumDisplays; display++) {
     if (hwc_display_[display] != NULL) {
       HWC2::PowerMode mode = last_power_mode[display];
       DLOGI("Setting display %d to mode = %d", display, mode);
@@ -2893,7 +2906,8 @@
   }
 
   // Release lock on all displays.
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+    display < HWCCallbacks::kNumDisplays; display++) {
     locker_[display].Unlock();
   }
   Refresh(active_builtin_disp_id);
@@ -2903,7 +2917,7 @@
   std::bitset<kSecureMax> secure_sessions = 0;
   {
     hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-    if (active_builtin_disp_id >= kNumDisplays) {
+    if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
       return;
     }
     Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
@@ -2912,7 +2926,8 @@
 
   // If it is called during primary prepare/commit, we need to pause any ongoing commit on
   // external/virtual display.
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+    display < HWCCallbacks::kNumDisplays; display++) {
     Locker::ScopeLock lock_d(locker_[display]);
     if (hwc_display_[display]) {
       hwc_display_[display]->HandleSecureSession(secure_sessions, &power_on_pending_[display]);
@@ -2928,7 +2943,8 @@
 
   Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
   bool power_on_pending = false;
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+    display < HWCCallbacks::kNumDisplays; display++) {
     if (display != active_builtin_disp_id) {
       Locker::ScopeLock lock_d(locker_[display]);
       if (power_on_pending_[display]) {
@@ -2952,7 +2968,8 @@
     return;
   }
 
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+    display < HWCCallbacks::kNumDisplays; display++) {
     if (display != active_builtin_disp_id) {
       Locker::ScopeLock lock_d(locker_[display]);
       if (power_on_pending_[display] && hwc_display_[display]) {
@@ -2974,12 +2991,12 @@
   }
 
   std :: bitset < kSecureMax > secure_sessions = 0;
-  if (active_builtin_disp_id < kNumDisplays) {
+  if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
     Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
     hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
   }
 
-  if (secure_sessions.any() || active_builtin_disp_id >= kNumDisplays) {
+  if (secure_sessions.any() || active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
     return;
   }
 
@@ -3079,7 +3096,7 @@
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
-  if (display >= kNumDisplays) {
+  if (display >= HWCCallbacks::kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
@@ -3117,8 +3134,12 @@
   }
 
   callbacks_.SetSwapVsync(next_vsync_source, HWC_DISPLAY_PRIMARY);
-  HWC2::PowerMode power_mode = hwc_display_[next_vsync_source]->GetCurrentPowerMode();
+  hwc_display_[next_vsync_source]->SetVsyncSource(true);
+  if (hwc_display_[active_source]) {
+    hwc_display_[active_source]->SetVsyncSource(false);
+  }
 
+  HWC2::PowerMode power_mode = hwc_display_[next_vsync_source]->GetCurrentPowerMode();
   // Skip enabling vsync if display is Off, happens only for default source ie; primary.
   if (power_mode == HWC2::PowerMode::Off) {
     return;
@@ -3171,7 +3192,7 @@
 void HWCSession::UpdateThrottlingRate() {
   uint32_t new_min = 0;
 
-  for (int i=0; i < kNumDisplays; i++) {
+  for (int i=0; i < HWCCallbacks::kNumDisplays; i++) {
     auto &display = hwc_display_[i];
     if (!display)
       continue;
@@ -3199,7 +3220,7 @@
 #else
   {
     hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-    if (active_builtin_disp_id >= kNumDisplays) {
+    if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
       DLOGE("No active displays");
       return -EINVAL;
     }
@@ -3227,7 +3248,7 @@
 }
 
 hwc2_display_t HWCSession::GetActiveBuiltinDisplay() {
-  hwc2_display_t disp_id = kNumDisplays;
+  hwc2_display_t disp_id = HWCCallbacks::kNumDisplays;
   // Get first active display among primary and built-in displays.
   std::vector<DisplayMapInfo> map_info = {map_info_primary_};
   std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index fd5ead9..bbcd4c2 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -117,12 +117,6 @@
 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; }
   };
@@ -145,7 +139,7 @@
       return HWC2_ERROR_BAD_PARAMETER;
     }
 
-    if (display >= kNumDisplays) {
+    if (display >= HWCCallbacks::kNumDisplays) {
       return HWC2_ERROR_BAD_DISPLAY;
     }
 
@@ -167,7 +161,7 @@
       return HWC2_ERROR_BAD_PARAMETER;
     }
 
-    if (display >= kNumDisplays) {
+    if (display >= HWCCallbacks::kNumDisplays) {
       return HWC2_ERROR_BAD_DISPLAY;
     }
 
@@ -233,14 +227,14 @@
   static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
                                 int32_t *out_support);
 
-  static Locker locker_[kNumDisplays];
+  static Locker locker_[HWCCallbacks::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
+    hwc2_display_t client_id = HWCCallbacks::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;
@@ -405,7 +399,7 @@
   void HandlePendingRefresh();
 
   CoreInterface *core_intf_ = nullptr;
-  HWCDisplay *hwc_display_[kNumDisplays] = {nullptr};
+  HWCDisplay *hwc_display_[HWCCallbacks::kNumDisplays] = {nullptr};
   HWCCallbacks callbacks_;
   HWCBufferAllocator buffer_allocator_;
   HWCBufferSyncHandler buffer_sync_handler_;
@@ -428,7 +422,7 @@
   Locker callbacks_lock_;
   int hpd_bpp_ = 0;
   int hpd_pattern_ = 0;
-  static bool power_on_pending_[kNumDisplays];
+  static bool power_on_pending_[HWCCallbacks::kNumDisplays];
   static int null_display_mode_;
   HotPlugEvent hotplug_pending_event_ = kHotPlugNone;
   Locker pluggable_handler_lock_;
@@ -439,7 +433,7 @@
   int32_t registered_builtin_displays_ = 0;
   int32_t disable_hotplug_bwcheck_ = 0;
   int32_t disable_mask_layer_hint_ = 0;
-  std::bitset<kNumDisplays> pending_refresh_;
+  std::bitset<HWCCallbacks::kNumDisplays> pending_refresh_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index f438a08..d61c477 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -139,7 +139,7 @@
 
   if (status == HWCDisplay::kDisplayStatusResume || status == HWCDisplay::kDisplayStatusPause) {
     hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-    if (active_builtin_disp_id < kNumDisplays) {
+    if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
       {
         SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
         hwc_display_[active_builtin_disp_id]->ResetValidation();
@@ -489,7 +489,7 @@
 
 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-  if (active_builtin_disp_id >= kNumDisplays) {
+  if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
     DLOGE("No active displays");
     return -EINVAL;
   }
@@ -584,8 +584,8 @@
   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);
+  if ((base + count) > HWCCallbacks::kNumDisplays) {
+    DLOGE("Exceeds max supported display slots = %d", HWCCallbacks::kNumDisplays);
     return -1;
   }
 
@@ -626,7 +626,7 @@
 #ifdef DISPLAY_CONFIG_1_3
 Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchronous) {
   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-  if (active_builtin_disp_id >= kNumDisplays) {
+  if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
     DLOGE("No active displays");
     return -EINVAL;
   }
@@ -807,7 +807,7 @@
   IDisplayConfig::DisplayAttributes display_attributes = {};
   hwc2_display_t disp_id = GetActiveBuiltinDisplay();
 
-  if (disp_id >= kNumDisplays) {
+  if (disp_id >= HWCCallbacks::kNumDisplays) {
     DLOGE("Invalid display = %d", disp_id);
   } else {
     if (hwc_display_[disp_id]) {