composer: Add VRR related Composer 2.4 APIs

Define SetActiveConfigWithConstraints and GetDisplayVsyncPeriod
APIs for VRR on Composer 2.4 .

CRs-Fixed: 2632089
Change-Id: Id64e71a9756e183b1d47a285fb6be0cae9ca046e
diff --git a/composer/QtiComposerClient.cpp b/composer/QtiComposerClient.cpp
index 28692e9..e913ed6 100644
--- a/composer/QtiComposerClient.cpp
+++ b/composer/QtiComposerClient.cpp
@@ -156,9 +156,9 @@
   auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
   android::hardware::Return<void> ret;
   if (client->callback24_) {
-    uint32_t vsync_period;
-    client->hwc_session_->GetVsyncPeriod(display, &vsync_period);
-    ret = client->callback24_->onVsync_2_4(display, timestamp, vsync_period);
+    VsyncPeriodNanos vsync_period;
+    client->hwc_session_->GetDisplayVsyncPeriod(display, &vsync_period);
+    ret = client->callback24_->onVsync_2_4(display, timestamp, static_cast<uint32_t>(vsync_period));
   } else {
     ret = client->callback_->onVsync(display, timestamp);
   }
@@ -1026,23 +1026,23 @@
 
 Return<void> QtiComposerClient::getDisplayVsyncPeriod(uint64_t display,
                                                       getDisplayVsyncPeriod_cb _hidl_cb) {
-  uint32_t vsync_period;
-  auto error = hwc_session_->GetVsyncPeriod(display, &vsync_period);
+  VsyncPeriodNanos vsync_period;
+  auto error = hwc_session_->GetDisplayVsyncPeriod(display, &vsync_period);
   _hidl_cb(static_cast<composer_V2_4::Error>(error), vsync_period);
   return Void();
 }
 
 Return<void> QtiComposerClient::setActiveConfigWithConstraints(
     uint64_t display, uint32_t config,
-    const composer_V2_4::IComposerClient::VsyncPeriodChangeConstraints
-        &vsyncPeriodChangeConstraints,
+    const VsyncPeriodChangeConstraints &vsyncPeriodChangeConstraints,
     setActiveConfigWithConstraints_cb _hidl_cb) {
-  auto error = hwc_session_->SetActiveConfig(display, config);
-  // TODO(user): implement properly
-  composer_V2_4::VsyncPeriodChangeTimeline timeline;
+  VsyncPeriodChangeTimeline timeline;
   timeline.newVsyncAppliedTimeNanos = systemTime();
   timeline.refreshRequired = false;
   timeline.refreshTimeNanos = 0;
+
+  auto error = hwc_session_->SetActiveConfigWithConstraints(
+      display, config, &vsyncPeriodChangeConstraints, &timeline);
   _hidl_cb(static_cast<composer_V2_4::Error>(error), timeline);
   return Void();
 }
diff --git a/composer/QtiComposerClient.h b/composer/QtiComposerClient.h
index 89180a8..847eedb 100644
--- a/composer/QtiComposerClient.h
+++ b/composer/QtiComposerClient.h
@@ -202,8 +202,7 @@
   Return<void> getDisplayVsyncPeriod(uint64_t display, getDisplayVsyncPeriod_cb _hidl_cb) override;
   Return<void> setActiveConfigWithConstraints(
       uint64_t display, uint32_t config,
-      const composer_V2_4::IComposerClient::VsyncPeriodChangeConstraints
-          &vsyncPeriodChangeConstraints,
+      const VsyncPeriodChangeConstraints &vsyncPeriodChangeConstraints,
       setActiveConfigWithConstraints_cb _hidl_cb) override;
 
   Return<composer_V2_4::Error> setAutoLowLatencyMode(uint64_t display, bool on) override;
diff --git a/composer/hwc_callbacks.cpp b/composer/hwc_callbacks.cpp
index e36a60f..29e737f 100644
--- a/composer/hwc_callbacks.cpp
+++ b/composer/hwc_callbacks.cpp
@@ -83,6 +83,27 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCCallbacks::Vsync_2_4(hwc2_display_t display, int64_t timestamp, uint32_t period) {
+  DTRACE_SCOPED();
+  if (!vsync_2_4_) {
+    return HWC2::Error::NoResources;
+  }
+
+  vsync_2_4_(vsync_2_4_data_, display, timestamp, period);
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCCallbacks::VsyncPeriodTimingChanged(
+    hwc2_display_t display, hwc_vsync_period_change_timeline_t *updated_timeline) {
+  DTRACE_SCOPED();
+  if (!vsync_period_timing_changed_) {
+    return HWC2::Error::NoResources;
+  }
+
+  vsync_period_timing_changed_(vsync_period_timing_changed_data_, display, updated_timeline);
+  return HWC2::Error::None;
+}
+
 HWC2::Error HWCCallbacks::Register(HWC2::Callback descriptor, hwc2_callback_data_t callback_data,
                                    hwc2_function_pointer_t pointer) {
   SCOPE_LOCK(callbacks_lock_);
@@ -101,6 +122,15 @@
       vsync_data_ = callback_data;
       vsync_ = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
       break;
+    case HWC2::Callback::Vsync_2_4:
+      vsync_2_4_data_ = callback_data;
+      vsync_2_4_ = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(pointer);
+      break;
+    case HWC2::Callback::VsyncPeriodTimingChanged:
+      vsync_period_timing_changed_data_ = callback_data;
+      vsync_period_timing_changed_ =
+          reinterpret_cast<HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED>(pointer);
+      break;
     default:
       return HWC2::Error::BadParameter;
   }
diff --git a/composer/hwc_callbacks.h b/composer/hwc_callbacks.h
index 6db3139..eb92da2 100644
--- a/composer/hwc_callbacks.h
+++ b/composer/hwc_callbacks.h
@@ -54,6 +54,9 @@
   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);
+  HWC2::Error Vsync_2_4(hwc2_display_t display, int64_t timestamp, uint32_t period);
+  HWC2::Error VsyncPeriodTimingChanged(hwc2_display_t display,
+                                       hwc_vsync_period_change_timeline_t *updated_timeline);
   HWC2::Error Register(HWC2::Callback, hwc2_callback_data_t callback_data,
                        hwc2_function_pointer_t pointer);
   void UpdateVsyncSource(hwc2_display_t from) {
@@ -62,6 +65,7 @@
   hwc2_display_t GetVsyncSource() { return vsync_source_; }
 
   bool VsyncCallbackRegistered() { return (vsync_ != nullptr && vsync_data_ != nullptr); }
+  bool Vsync_2_4CallbackRegistered() { return (vsync_2_4_ != nullptr); }
   bool NeedsRefresh(hwc2_display_t display) { return pending_refresh_.test(UINT32(display)); }
   void ResetRefresh(hwc2_display_t display) { pending_refresh_.reset(UINT32(display)); }
   bool IsClientConnected() {
@@ -73,10 +77,15 @@
   hwc2_callback_data_t hotplug_data_ = nullptr;
   hwc2_callback_data_t refresh_data_ = nullptr;
   hwc2_callback_data_t vsync_data_ = nullptr;
+  hwc2_callback_data_t vsync_2_4_data_ = nullptr;
+  hwc2_callback_data_t vsync_period_timing_changed_data_ = nullptr;
 
   HWC2_PFN_HOTPLUG hotplug_ = nullptr;
   HWC2_PFN_REFRESH refresh_ = nullptr;
   HWC2_PFN_VSYNC vsync_ = nullptr;
+  HWC2_PFN_VSYNC_2_4 vsync_2_4_ = nullptr;
+  HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED vsync_period_timing_changed_ = nullptr;
+
   hwc2_display_t vsync_source_ = HWC_DISPLAY_PRIMARY;   // hw vsync is active on this display
   std::bitset<kNumDisplays> pending_refresh_;         // Displays waiting to get refreshed
 
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 5e04e30..3e59bd2 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -53,6 +53,7 @@
 namespace sdm {
 
 uint32_t HWCDisplay::throttling_refresh_rate_ = 60;
+constexpr uint32_t kVsyncTimeDriftNs = 1000000;
 
 bool NeedsToneMap(const LayerStack &layer_stack) {
   for (Layer *layer : layer_stack.layers) {
@@ -63,6 +64,10 @@
   return false;
 }
 
+bool IsTimeAfterOrEqualVsyncTime(int64_t time, int64_t vsync_time) {
+  return ((vsync_time != INT64_MAX) && ((time - (vsync_time - kVsyncTimeDriftNs)) >= 0));
+}
+
 HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
 
 HWC2::Error HWCColorMode::Init() {
@@ -875,7 +880,8 @@
   ATRACE_INT("SetVsyncState ", enabled == HWC2::Vsync::Enable ? 1 : 0);
   DisplayError error = kErrorNone;
 
-  if (shutdown_pending_ || !callbacks_->VsyncCallbackRegistered()) {
+  if (shutdown_pending_ ||
+      (!callbacks_->VsyncCallbackRegistered() && !callbacks_->Vsync_2_4CallbackRegistered())) {
     return HWC2::Error::None;
   }
 
@@ -1248,7 +1254,17 @@
 }
 
 DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
-  callbacks_->Vsync(id_, vsync.timestamp);
+  if (callbacks_->Vsync_2_4CallbackRegistered()) {
+    VsyncPeriodNanos vsync_period;
+    if (GetDisplayVsyncPeriod(&vsync_period) != HWC2::Error::None) {
+      vsync_period = 0;
+    }
+    ATRACE_INT("VsyncPeriod", INT32(vsync_period));
+    callbacks_->Vsync_2_4(id_, vsync.timestamp, vsync_period);
+  } else {
+    callbacks_->Vsync(id_, vsync.timestamp);
+  }
+
   return kErrorNone;
 }
 
@@ -2486,4 +2502,176 @@
   return -1;
 }
 
+HWC2::Error HWCDisplay::GetDisplayVsyncPeriod(VsyncPeriodNanos *vsync_period) {
+  if (GetTransientVsyncPeriod(vsync_period)) {
+    return HWC2::Error::None;
+  }
+
+  return GetVsyncPeriodByActiveConfig(vsync_period);
+}
+
+HWC2::Error HWCDisplay::SetActiveConfigWithConstraints(
+    hwc2_config_t config, const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
+    VsyncPeriodChangeTimeline *out_timeline) {
+  if (variable_config_map_.find(config) == variable_config_map_.end()) {
+    DLOGE("Invalid config: %d", config);
+    return HWC2::Error::BadConfig;
+  }
+
+  if (vsync_period_change_constraints->seamlessRequired && !AllowSeamless(config)) {
+    DLOGE("Seamless switch to the config: %d, is not allowed!", config);
+    return HWC2::Error::SeamlessNotAllowed;
+  }
+
+  VsyncPeriodNanos vsync_period;
+  if (GetDisplayVsyncPeriod(&vsync_period) != HWC2::Error::None) {
+    return HWC2::Error::BadConfig;
+  }
+
+  std::tie(out_timeline->refreshTimeNanos, out_timeline->newVsyncAppliedTimeNanos) =
+      RequestActiveConfigChange(config, vsync_period,
+                                vsync_period_change_constraints->desiredTimeNanos);
+
+  out_timeline->refreshRequired = true;
+  return HWC2::Error::None;
+}
+
+void HWCDisplay::ProcessActiveConfigChange() {
+  if (!IsActiveConfigReadyToSubmit(systemTime(SYSTEM_TIME_MONOTONIC))) {
+    return;
+  }
+
+  DTRACE_SCOPED();
+  VsyncPeriodNanos vsync_period;
+  if (GetVsyncPeriodByActiveConfig(&vsync_period) == HWC2::Error::None) {
+    SubmitActiveConfigChange(vsync_period);
+  }
+}
+
+HWC2::Error HWCDisplay::GetVsyncPeriodByActiveConfig(VsyncPeriodNanos *vsync_period) {
+  hwc2_config_t active_config;
+
+  auto error = GetActiveConfig(&active_config);
+  if (error != HWC2::Error::None) {
+    DLOGE("Failed to get active config!");
+    return error;
+  }
+
+  int32_t active_vsync_period;
+  error = GetDisplayAttribute(active_config, HwcAttribute::VSYNC_PERIOD, &active_vsync_period);
+  if (error != HWC2::Error::None) {
+    DLOGE("Failed to get VsyncPeriod of config: %d", active_config);
+    return error;
+  }
+
+  *vsync_period = static_cast<VsyncPeriodNanos>(active_vsync_period);
+  return HWC2::Error::None;
+}
+
+bool HWCDisplay::GetTransientVsyncPeriod(VsyncPeriodNanos *vsync_period) {
+  std::lock_guard<std::mutex> lock(transient_refresh_rate_lock_);
+  auto now = systemTime(SYSTEM_TIME_MONOTONIC);
+
+  while (!transient_refresh_rate_info_.empty()) {
+    if (IsActiveConfigApplied(now, transient_refresh_rate_info_.front().vsync_applied_time)) {
+      transient_refresh_rate_info_.pop_front();
+    } else {
+      *vsync_period = transient_refresh_rate_info_.front().transient_vsync_period;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+std::tuple<int64_t, int64_t> HWCDisplay::RequestActiveConfigChange(
+    hwc2_config_t config, VsyncPeriodNanos current_vsync_period, int64_t desired_time) {
+  int64_t refresh_time, applied_time;
+  std::tie(refresh_time, applied_time) =
+      EstimateVsyncPeriodChangeTimeline(current_vsync_period, desired_time);
+
+  pending_refresh_rate_config_ = config;
+  pending_refresh_rate_refresh_time_ = refresh_time;
+  pending_refresh_rate_applied_time_ = applied_time;
+
+  return std::make_tuple(refresh_time, applied_time);
+}
+
+std::tuple<int64_t, int64_t> HWCDisplay::EstimateVsyncPeriodChangeTimeline(
+    VsyncPeriodNanos current_vsync_period, int64_t desired_time) {
+  const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
+  const auto delta = desired_time - now;
+  const auto refresh_rate_activate_period = current_vsync_period * vsyncs_to_apply_rate_change_;
+  nsecs_t refresh_time;
+
+  if (delta < 0) {
+    refresh_time = now + (delta % current_vsync_period);
+  } else if (delta < refresh_rate_activate_period) {
+    refresh_time = now + (delta % current_vsync_period) - current_vsync_period;
+  } else {
+    refresh_time = desired_time - refresh_rate_activate_period;
+  }
+
+  const auto applied_time = refresh_time + refresh_rate_activate_period;
+  return std::make_tuple(refresh_time, applied_time);
+}
+
+void HWCDisplay::SubmitActiveConfigChange(VsyncPeriodNanos current_vsync_period) {
+  HWC2::Error error = SetActiveConfig(pending_refresh_rate_config_);
+  if (error != HWC2::Error::None) {
+    return;
+  }
+
+  std::lock_guard<std::mutex> lock(transient_refresh_rate_lock_);
+  hwc_vsync_period_change_timeline_t timeline;
+  std::tie(timeline.refreshTimeNanos, timeline.newVsyncAppliedTimeNanos) =
+      EstimateVsyncPeriodChangeTimeline(current_vsync_period, pending_refresh_rate_refresh_time_);
+
+  transient_refresh_rate_info_.push_back({current_vsync_period, timeline.newVsyncAppliedTimeNanos});
+  if (timeline.newVsyncAppliedTimeNanos != pending_refresh_rate_applied_time_) {
+    timeline.refreshRequired = false;
+    callbacks_->VsyncPeriodTimingChanged(id_, &timeline);
+  }
+
+  pending_refresh_rate_config_ = UINT_MAX;
+  pending_refresh_rate_refresh_time_ = INT64_MAX;
+  pending_refresh_rate_applied_time_ = INT64_MAX;
+}
+
+bool HWCDisplay::IsActiveConfigReadyToSubmit(int64_t time) {
+  return ((pending_refresh_rate_config_ != UINT_MAX) &&
+          IsTimeAfterOrEqualVsyncTime(time, pending_refresh_rate_refresh_time_));
+}
+
+bool HWCDisplay::IsActiveConfigApplied(int64_t time, int64_t vsync_applied_time) {
+  return IsTimeAfterOrEqualVsyncTime(time, vsync_applied_time);
+}
+
+bool HWCDisplay::IsSameGroup(hwc2_config_t config_id1, hwc2_config_t config_id2) {
+  const auto &variable_config1 = variable_config_map_.find(config_id1);
+  const auto &variable_config2 = variable_config_map_.find(config_id2);
+
+  if ((variable_config1 == variable_config_map_.end()) ||
+      (variable_config2 == variable_config_map_.end())) {
+    DLOGE("Invalid config: %u, %u", config_id1, config_id2);
+    return false;
+  }
+
+  const DisplayConfigGroupInfo &config_group1 = variable_config1->second;
+  const DisplayConfigGroupInfo &config_group2 = variable_config2->second;
+
+  return (config_group1 == config_group2);
+}
+
+bool HWCDisplay::AllowSeamless(hwc2_config_t config) {
+  hwc2_config_t active_config;
+  auto error = GetActiveConfig(&active_config);
+  if (error != HWC2::Error::None) {
+    DLOGE("Failed to get active config!");
+    return false;
+  }
+
+  return IsSameGroup(active_config, config);
+}
+
 }  // namespace sdm
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index 491d85a..ebbfb74 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -49,6 +49,9 @@
 using android::hardware::graphics::common::V1_2::Hdr;
 namespace composer_V2_4 = ::android::hardware::graphics::composer::V2_4;
 using HwcAttribute = composer_V2_4::IComposerClient::Attribute;
+using VsyncPeriodChangeConstraints = composer_V2_4::IComposerClient::VsyncPeriodChangeConstraints;
+using VsyncPeriodChangeTimeline = composer_V2_4::VsyncPeriodChangeTimeline;
+using VsyncPeriodNanos = composer_V2_4::VsyncPeriodNanos;
 
 namespace sdm {
 
@@ -86,6 +89,11 @@
   kCWBClientComposer,   // Client to HWC i.e. SurfaceFlinger
 };
 
+struct TransientRefreshRateInfo {
+  uint32_t transient_vsync_period;
+  int64_t vsync_applied_time;
+};
+
 class HWCColorMode {
  public:
   explicit HWCColorMode(DisplayInterface *display_intf);
@@ -267,6 +275,7 @@
     return HWC2::Error::Unsupported;
   }
   bool IsFirstCommitDone() { return !first_cycle_; }
+  virtual void ProcessActiveConfigChange();
 
   // HWC2 APIs
   virtual HWC2::Error AcceptDisplayChanges(void);
@@ -396,6 +405,12 @@
       uint64_t max_frames, uint64_t timestamp, uint64_t *numFrames,
       int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
       uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]);
+
+  virtual HWC2::Error GetDisplayVsyncPeriod(VsyncPeriodNanos *vsync_period);
+  virtual HWC2::Error SetActiveConfigWithConstraints(
+      hwc2_config_t config, const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
+      VsyncPeriodChangeTimeline *out_timeline);
+
   HWC2::Error SetDisplayElapseTime(uint64_t time);
 
  protected:
@@ -432,6 +447,19 @@
   int32_t SetClientTargetDataSpace(int32_t dataspace);
   int SetFrameBufferConfig(uint32_t x_pixels, uint32_t y_pixels);
   int32_t GetDisplayConfigGroup(DisplayConfigGroupInfo variable_config);
+  HWC2::Error GetVsyncPeriodByActiveConfig(VsyncPeriodNanos *vsync_period);
+  bool GetTransientVsyncPeriod(VsyncPeriodNanos *vsync_period);
+  std::tuple<int64_t, int64_t> RequestActiveConfigChange(hwc2_config_t config,
+                                                         VsyncPeriodNanos current_vsync_period,
+                                                         int64_t desired_time);
+  std::tuple<int64_t, int64_t> EstimateVsyncPeriodChangeTimeline(
+      VsyncPeriodNanos current_vsync_period, int64_t desired_time);
+  void SubmitActiveConfigChange(VsyncPeriodNanos current_vsync_period);
+  bool IsActiveConfigReadyToSubmit(int64_t time);
+  bool IsActiveConfigApplied(int64_t time, int64_t vsync_applied_time);
+  bool IsSameGroup(hwc2_config_t config_id1, hwc2_config_t config_id2);
+  bool AllowSeamless(hwc2_config_t request_config);
+  void SetVsyncsApplyRateChange(uint32_t vsyncs) { vsyncs_to_apply_rate_change_ = vsyncs; }
 
   bool validated_ = false;
   bool layer_stack_invalid_ = true;
@@ -487,6 +515,12 @@
   bool client_connected_ = true;
   bool pending_config_ = false;
   bool has_client_composition_ = false;
+  uint32_t vsyncs_to_apply_rate_change_ = 1;
+  hwc2_config_t pending_refresh_rate_config_ = UINT_MAX;
+  int64_t pending_refresh_rate_refresh_time_ = INT64_MAX;
+  int64_t pending_refresh_rate_applied_time_ = INT64_MAX;
+  std::deque<TransientRefreshRateInfo> transient_refresh_rate_info_;
+  std::mutex transient_refresh_rate_lock_;
 
  private:
   void DumpInputBuffers(void);
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index 343dc33..bdeb4de 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -134,6 +134,12 @@
     DLOGI("Drop redundant drawcycles %d", id_);
   }
 
+  int vsyncs = 0;
+  HWCDebugHandler::Get()->GetProperty(DEFER_FPS_FRAME_COUNT, &vsyncs);
+  if (vsyncs > 0) {
+    SetVsyncsApplyRateChange(UINT32(vsyncs));
+  }
+
   is_primary_ = display_intf_->IsPrimaryDisplay();
 
   return status;
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index f6dc8c2..1d221e1 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -769,6 +769,7 @@
     if (pending_power_mode_[display]) {
       status = HWC2::Error::None;
     } else {
+      hwc_display_[target_display]->ProcessActiveConfigChange();
       status = PresentDisplayInternal(target_display);
       if (status == HWC2::Error::None) {
         // Check if hwc's refresh trigger is getting exercised.
@@ -3396,4 +3397,24 @@
   }
 }
 
+int32_t HWCSession::GetDisplayVsyncPeriod(hwc2_display_t disp, VsyncPeriodNanos *vsync_period) {
+  if (vsync_period == nullptr) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
+  return CallDisplayFunction(disp, &HWCDisplay::GetDisplayVsyncPeriod, vsync_period);
+}
+
+int32_t HWCSession::SetActiveConfigWithConstraints(
+    hwc2_display_t display, hwc2_config_t config,
+    const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
+    VsyncPeriodChangeTimeline *out_timeline) {
+  if ((vsync_period_change_constraints == nullptr) || (out_timeline == nullptr)) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
+  return CallDisplayFunction(display, &HWCDisplay::SetActiveConfigWithConstraints, config,
+                             vsync_period_change_constraints, out_timeline);
+}
+
 }  // namespace sdm
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 2808f00..9079a91 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -283,6 +283,12 @@
   int32_t GetVsyncPeriod(hwc2_display_t disp, uint32_t *vsync_period);
   void Refresh(hwc2_display_t display);
 
+  int32_t GetDisplayVsyncPeriod(hwc2_display_t display, VsyncPeriodNanos *out_vsync_period);
+  int32_t SetActiveConfigWithConstraints(
+      hwc2_display_t display, hwc2_config_t config,
+      const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
+      VsyncPeriodChangeTimeline *out_timeline);
+
   static Locker locker_[HWCCallbacks::kNumDisplays];
   static Locker power_state_[HWCCallbacks::kNumDisplays];
   static Locker hdr_locker_[HWCCallbacks::kNumDisplays];