Snap for 7374840 from 2b7727e80fec6be22665509a39ee1dae2a052656 to sc-d2-release

Change-Id: I53e226a2ce1e61d59518b7a1fdbebeef6370e21a
diff --git a/composer/cpuhint.cpp b/composer/cpuhint.cpp
index ca88ead..e63149f 100644
--- a/composer/cpuhint.cpp
+++ b/composer/cpuhint.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015, 2021, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -49,7 +49,6 @@
   debug_handler->GetProperty(PERF_HINT_WINDOW_PROP, &pre_enable_window);
   if (pre_enable_window <= 0) {
     DLOGI("Invalid CPU Hint Pre-enable Window %d", pre_enable_window);
-    return kErrorNotSupported;
   }
 
   DLOGI("CPU Hint Pre-enable Window %d", pre_enable_window);
@@ -57,7 +56,10 @@
 
   if (vendor_ext_lib_.Open(path)) {
     if (!vendor_ext_lib_.Sym("perf_lock_acq", reinterpret_cast<void **>(&fn_lock_acquire_)) ||
-        !vendor_ext_lib_.Sym("perf_lock_rel", reinterpret_cast<void **>(&fn_lock_release_))) {
+        !vendor_ext_lib_.Sym("perf_lock_rel", reinterpret_cast<void **>(&fn_lock_release_)) ||
+        !vendor_ext_lib_.Sym("perf_hint", reinterpret_cast<void **>(&fn_perf_hint_)) ||
+        !vendor_ext_lib_.Sym("perf_hint_offload", reinterpret_cast<void **> \
+        (&fn_perf_hint_offload_))) {
       DLOGW("Failed to load symbols for Vendor Extension Library");
       return kErrorNotSupported;
     }
@@ -67,7 +69,7 @@
     DLOGW("Failed to open %s : %s", path, vendor_ext_lib_.Error());
   }
 
-  return kErrorNone;
+  return enabled_ ? kErrorNone : kErrorNotSupported;
 }
 
 void CPUHint::Set() {
@@ -105,4 +107,15 @@
   lock_acquired_ = false;
 }
 
+void CPUHint::ReqHints(int hint) {
+  if(enabled_ && hint > 0) {
+    fn_perf_hint_(hint, NULL, 0, 0);
+  }
+}
+
+void CPUHint::ReqHintsOffload(int hint, int duration) {
+  if(enabled_ && hint > 0) {
+    fn_perf_hint_offload_(hint, NULL, duration, 0, 0, NULL);
+  }
+}
 }  // namespace sdm
diff --git a/composer/cpuhint.h b/composer/cpuhint.h
index e758763..e080f75 100644
--- a/composer/cpuhint.h
+++ b/composer/cpuhint.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015, 2021, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -42,6 +42,8 @@
   DisplayError Init(HWCDebugHandler *debug_handler);
   void Set();
   void Reset();
+  void ReqHints(int hint);
+  void ReqHintsOffload(int hint, int duration);
 
  private:
   enum { HINT =  0x4501 /* 45-display layer hint, 01-Enable */ };
@@ -54,6 +56,9 @@
   DynLib vendor_ext_lib_;
   int (*fn_lock_acquire_)(int handle, int duration, int *hints, int num_args) = NULL;
   int (*fn_lock_release_)(int value) = NULL;
+  int (*fn_perf_hint_)(int hint, const char *pkg, int duration, int type) = NULL;
+  int (*fn_perf_hint_offload_)(int hint, const char *pkg, int duration, int type,
+                               int numArgs, int *) = NULL;
 };
 
 }  // namespace sdm
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index fb24944..affc189 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -53,7 +53,6 @@
 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) {
@@ -65,7 +64,7 @@
 }
 
 bool IsTimeAfterOrEqualVsyncTime(int64_t time, int64_t vsync_time) {
-  return ((vsync_time != INT64_MAX) && ((time - (vsync_time - kVsyncTimeDriftNs)) >= 0));
+  return ((vsync_time != INT64_MAX) && ((time - vsync_time) >= 0));
 }
 
 HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
@@ -748,8 +747,14 @@
       hdr_largest_layer_px_ = std::max(hdr_largest_layer_px_, hdr_layer_area);
     }
 
+    if (game_supported_ && (hwc_layer->GetType() == kLayerGame)) {
+      layer->flags.is_game = true;
+      layer->input_buffer.flags.game = true;
+    }
+
     if (hwc_layer->IsNonIntegralSourceCrop() && !is_secure && !hdr_layer &&
-        !layer->flags.single_buffer && !layer->flags.solid_fill && !is_video) {
+        !layer->flags.single_buffer && !layer->flags.solid_fill && !is_video &&
+        !layer->flags.is_game) {
       layer->flags.skip = true;
     }
 
@@ -811,11 +816,6 @@
       layer->update_mask.set(kClientCompRequest);
     }
 
-    if (game_supported_ && (hwc_layer->GetType() == kLayerGame)) {
-      layer->flags.is_game = true;
-      layer->input_buffer.flags.game = true;
-    }
-
     layer_stack_.layers.push_back(layer);
   }
 
@@ -1238,6 +1238,20 @@
     return HWC2::Error::BadParameter;
   }
   client_target_->SetLayerBuffer(target, acquire_fence);
+  client_target_handle_ = target;
+  client_acquire_fence_ = acquire_fence;
+  client_dataspace_     = dataspace;
+  client_damage_region_ = damage;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetClientTarget(buffer_handle_t target, shared_ptr<Fence> acquire_fence,
+                                        int32_t dataspace, hwc_region_t damage) {
+  target        = client_target_handle_;
+  acquire_fence = client_acquire_fence_;
+  dataspace     = client_dataspace_;
+  damage        = client_damage_region_;
 
   return HWC2::Error::None;
 }
@@ -1377,6 +1391,9 @@
     case kInvalidateDisplay:
       validated_ = false;
       break;
+    case kPostIdleTimeout:
+      display_idle_ = true;
+      break;
     default:
       DLOGW("Unknown event: %d", event);
       break;
@@ -1393,6 +1410,7 @@
   layer_changes_.clear();
   layer_requests_.clear();
   has_client_composition_ = false;
+  display_idle_ = false;
 
   DTRACE_SCOPED();
   if (shutdown_pending_) {
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index b396b2e..a156b8f 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -250,6 +250,10 @@
     return false;
   }
 
+  virtual bool VsyncEnablePending() {
+    return false;
+  }
+
   // Display Configurations
   static uint32_t GetThrottlingRefreshRate() { return HWCDisplay::throttling_refresh_rate_; }
   static void SetThrottlingRefreshRate(uint32_t newRefreshRate)
@@ -305,6 +309,8 @@
   }
   virtual HWC2::Error SetClientTarget(buffer_handle_t target, shared_ptr<Fence> acquire_fence,
                                       int32_t dataspace, hwc_region_t damage);
+  virtual HWC2::Error GetClientTarget(buffer_handle_t target, shared_ptr<Fence> acquire_fence,
+                                      int32_t dataspace, hwc_region_t damage);
   virtual HWC2::Error SetColorMode(ColorMode mode) { return HWC2::Error::Unsupported; }
   virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
     return HWC2::Error::Unsupported;
@@ -429,6 +435,11 @@
       uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]);
 
   virtual HWC2::Error GetDisplayVsyncPeriod(VsyncPeriodNanos *vsync_period);
+  virtual HWC2::Error SetDisplayVsyncPeriod(VsyncPeriodNanos vsync_period) {
+    return HWC2::Error::None;
+  }
+
+
   virtual HWC2::Error SetActiveConfigWithConstraints(
       hwc2_config_t config, const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
       VsyncPeriodChangeTimeline *out_timeline);
@@ -438,6 +449,7 @@
 
   HWC2::Error SetDisplayElapseTime(uint64_t time);
   virtual bool HasReadBackBufferSupport() { return false; }
+  virtual bool IsDisplayIdle() { return false; };
 
   virtual bool IsHbmSupported() { return false; }
   virtual HWC2::Error SetHbm(HbmState state, HbmClient client) { return HWC2::Error::None; }
@@ -562,6 +574,11 @@
   bool windowed_display_ = false;
   uint32_t active_refresh_rate_ = 0;
   bool animating_ = false;
+  buffer_handle_t client_target_handle_ = 0;
+  shared_ptr<Fence> client_acquire_fence_ = nullptr;
+  int32_t client_dataspace_ = 0;
+  hwc_region_t client_damage_region_ = {};
+  bool display_idle_ = false;
 
  private:
   void DumpInputBuffers(void);
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index 1c1e37d..6123e82 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2021, 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
@@ -254,6 +254,10 @@
   enhance_idle_time_ = (value == 1);
   DLOGI("enhance_idle_time: %d", enhance_idle_time_);
 
+  HWCDebugHandler::Get()->GetProperty(PERF_HINT_WINDOW_PROP, &perf_hint_window_);
+  HWCDebugHandler::Get()->GetProperty(ENABLE_PERF_HINT_LARGE_COMP_CYCLE,
+                                      &perf_hint_large_comp_cycle_);
+
   return status;
 }
 
@@ -262,23 +266,20 @@
   *os << histogram.Dump();
 }
 
-void HWCDisplayBuiltIn::ValidateScalingForDozeMode() {
-  if (current_power_mode_ == HWC2::PowerMode::Doze) {
-    bool scaling_present = false;
-    for (auto &hwc_layer : layer_set_) {
-      if (hwc_layer->IsScalingPresent()) {
-        scaling_present = true;
-        break;
-      }
-    }
-    if (scaling_present) {
-      scaling_in_doze_ = true;
-    } else {
-      scaling_in_doze_ = false;
-    }
-  } else {
-    scaling_in_doze_ = false;
+void HWCDisplayBuiltIn::ValidateUiScaling() {
+  if (is_primary_ || !is_cmd_mode_) {
+    force_reset_validate_ = false;
+    return;
   }
+
+  for (auto &hwc_layer : layer_set_) {
+    Layer *layer = hwc_layer->GetSDMLayer();
+    if (hwc_layer->IsScalingPresent() && !layer->input_buffer.flags.video) {
+      force_reset_validate_ = true;
+      return;
+    }
+  }
+  force_reset_validate_ = false;
 }
 
 HWC2::Error HWCDisplayBuiltIn::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
@@ -301,7 +302,7 @@
   BuildLayerStack();
 
   // Check for scaling layers during Doze mode
-  ValidateScalingForDozeMode();
+  ValidateUiScaling();
 
   // Add stitch layer to layer stack.
   AppendStitchLayer();
@@ -366,6 +367,7 @@
   }
 
   status = PrepareLayerStack(out_num_types, out_num_requests);
+  SetCpuPerfHintLargeCompCycle();
   pending_commit_ = true;
   return status;
 }
@@ -620,8 +622,8 @@
 
   pending_commit_ = false;
 
-  // In case of scaling layer in Doze, reset validate
-  if (scaling_in_doze_) {
+  // In case of scaling UI layer for command mode, reset validate
+  if (force_reset_validate_) {
     validated_ = false;
     display_intf_->ClearLUTs();
   }
@@ -949,7 +951,7 @@
 }
 
 void HWCDisplayBuiltIn::ToggleCPUHint(bool set) {
-  if (!cpu_hint_) {
+  if (!cpu_hint_ || !perf_hint_window_) {
     return;
   }
 
@@ -1622,6 +1624,29 @@
   return updating_count;
 }
 
+bool HWCDisplayBuiltIn::IsDisplayIdle() {
+  // Notify only if this display is source of vsync.
+  bool vsync_source = (callbacks_->GetVsyncSource() == id_);
+  return vsync_source && display_idle_;
+}
+
+void HWCDisplayBuiltIn::SetCpuPerfHintLargeCompCycle() {
+  if (!cpu_hint_ || !perf_hint_large_comp_cycle_) {
+    DLOGV_IF(kTagResources, "cpu_hint_ not initialized or property not set");
+    return;
+  }
+
+  for (auto hwc_layer : layer_set_) {
+    Layer *layer = hwc_layer->GetSDMLayer();
+    if (layer->composition == kCompositionGPU) {
+      DLOGV_IF(kTagResources, "Set perf hint for large comp cycle");
+      int hwc_tid = gettid();
+      cpu_hint_->ReqHintsOffload(kPerfHintLargeCompCycle, hwc_tid);
+      break;
+    }
+  }
+}
+
 HWC2::Error HWCDisplayBuiltIn::ApplyHbmLocked() {
   if (!mHasHbmNode)
     return HWC2::Error::Unsupported;
diff --git a/composer/hwc_display_builtin.h b/composer/hwc_display_builtin.h
index b310d3e..f608e7e 100644
--- a/composer/hwc_display_builtin.h
+++ b/composer/hwc_display_builtin.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2021, 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
@@ -148,6 +148,7 @@
   void Dump(std::ostringstream *os) override;
   virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode, bool teardown);
   virtual bool HasReadBackBufferSupport();
+  virtual bool IsDisplayIdle();
 
   virtual bool IsHbmSupported() override;
   virtual HWC2::Error SetHbm(HbmState state, HbmClient client) override;
@@ -178,11 +179,12 @@
   bool AllocateStitchBuffer();
   void CacheAvrStatus();
   void PostCommitStitchLayers();
+  void SetCpuPerfHintLargeCompCycle();
   int GetBwCode(const DisplayConfigVariableInfo &attr);
   void SetBwLimitHint(bool enable);
   void SetPartialUpdate(DisplayConfigFixedInfo fixed_info);
   uint32_t GetUpdatingAppLayersCount();
-  void ValidateScalingForDozeMode();
+  void ValidateUiScaling();
   HWC2::Error ApplyHbmLocked() REQUIRES(hbm_mutex);
 
   // SyncTask methods.
@@ -192,7 +194,7 @@
   constexpr static int kBwLow = 2;
   constexpr static int kBwMedium = 3;
   constexpr static int kBwHigh = 4;
-
+  const int kPerfHintLargeCompCycle = 0x00001097;
   BufferAllocator *buffer_allocator_ = nullptr;
   CPUHint *cpu_hint_ = nullptr;
   CWBClient cwb_client_ = kCWBClientNone;
@@ -232,13 +234,15 @@
   std::mutex sampling_mutex;
   bool api_sampling_vote = false;
   bool vndservice_sampling_vote = false;
+  int perf_hint_window_ = 0;
+  int perf_hint_large_comp_cycle_ = 0;
   int curr_refresh_rate_ = 0;
   bool is_smart_panel_ = false;
   const char *kDisplayBwName = "display_bw";
   bool enable_bw_limits_ = false;
   bool disable_dyn_fps_ = false;
   bool enhance_idle_time_ = false;
-  bool scaling_in_doze_ = false;
+  bool force_reset_validate_ = false;
 
   // Members for HBM feature
   static constexpr const char kHighBrightnessModeNode[] =
diff --git a/composer/hwc_display_dummy.cpp b/composer/hwc_display_dummy.cpp
index 83a5df9..0413ab7 100644
--- a/composer/hwc_display_dummy.cpp
+++ b/composer/hwc_display_dummy.cpp
@@ -91,4 +91,35 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCDisplayDummy::SetVsyncEnabled(HWC2::Vsync enabled) {
+  bool state = false;
+  if (enabled == HWC2::Vsync::Enable) {
+    state = true;
+  }
+  vsync_enable_ = state;
+  return HWC2::Error::None;
+}
+
+bool HWCDisplayDummy::VsyncEnablePending() {
+  return vsync_enable_;
+}
+HWC2::Error HWCDisplayDummy::GetDisplayVsyncPeriod(VsyncPeriodNanos *vsync_period) {
+  *vsync_period = vsync_period_;
+  return HWC2::Error::None;
+}
+HWC2::Error HWCDisplayDummy::SetDisplayVsyncPeriod(VsyncPeriodNanos vsync_period) {
+  vsync_period_ = vsync_period;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplayDummy::SetClientTarget(buffer_handle_t target,
+                                             shared_ptr<Fence> acquire_fence,
+                                             int32_t dataspace, hwc_region_t damage) {
+  client_target_handle_ = target;
+  client_acquire_fence_ = acquire_fence;
+  client_dataspace_     = dataspace;
+  client_damage_region_ = damage;
+  return HWC2::Error::None;
+}
+
 }  // namespace sdm
diff --git a/composer/hwc_display_dummy.h b/composer/hwc_display_dummy.h
index 03ad65a..efd8a4b 100644
--- a/composer/hwc_display_dummy.h
+++ b/composer/hwc_display_dummy.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020, 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,12 +47,19 @@
   virtual HWC2::Error GetActiveConfig(hwc2_config_t *out_config);
   virtual HWC2::Error UpdatePowerMode(HWC2::PowerMode mode);
   virtual HWC2::Error SetColorMode(ColorMode mode);
-
+  virtual HWC2::Error SetVsyncEnabled(HWC2::Vsync enabled);
+  virtual bool VsyncEnablePending();
+  virtual HWC2::Error SetClientTarget(buffer_handle_t target, shared_ptr<Fence> acquire_fence,
+                                      int32_t dataspace, hwc_region_t damage);
+  virtual HWC2::Error GetDisplayVsyncPeriod(VsyncPeriodNanos *vsync_period);
+  virtual HWC2::Error SetDisplayVsyncPeriod(VsyncPeriodNanos vsync_period);
  private:
   HWCDisplayDummy(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
                   HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
                   qService::QService *qservice, hwc2_display_t id, int32_t sdm_id);
   DisplayNull display_null_;
+  bool vsync_enable_ = false;
+  VsyncPeriodNanos vsync_period_ = 16600000;
 };
 
 }  // namespace sdm
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index 9753166..fe52a52 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -743,6 +743,18 @@
   }
 }
 
+void HWCSession::PerformIdleStatusCallback(hwc2_display_t display) {
+  std::shared_ptr<DisplayConfig::ConfigCallback> callback = idle_callback_.lock();
+  if (!callback) {
+    return;
+  }
+
+  if (hwc_display_[display]->IsDisplayIdle()) {
+    DTRACE_SCOPED();
+    callback->NotifyIdleStatus(true);
+  }
+}
+
 int32_t HWCSession::PresentDisplay(hwc2_display_t display, shared_ptr<Fence> *out_retire_fence) {
   auto status = HWC2::Error::BadDisplay;
   DTRACE_SCOPED();
@@ -791,6 +803,7 @@
         status = hwc_display_[target_display]->Present(out_retire_fence);
         if (status == HWC2::Error::None) {
           PerformQsyncCallback(target_display);
+          PerformIdleStatusCallback(target_display);
         }
       }
     }
@@ -1098,7 +1111,20 @@
     return HWC2_ERROR_UNSUPPORTED;
   }
 
-  bool override_mode = async_powermode_ && display_ready_.test(UINT32(display));
+  // async_powermode supported for power on and off
+  bool override_mode = async_powermode_ && display_ready_.test(UINT32(display)) &&
+                       async_power_mode_triggered_;
+  HWC2::PowerMode last_power_mode = hwc_display_[display]->GetCurrentPowerMode();
+
+  if (last_power_mode == mode) {
+    return HWC2_ERROR_NONE;
+  }
+
+  if (!((last_power_mode == HWC2::PowerMode::Off && mode == HWC2::PowerMode::On) ||
+     (last_power_mode == HWC2::PowerMode::On && mode == HWC2::PowerMode::Off))) {
+    override_mode = false;
+  }
+
   if (!override_mode) {
     auto error = CallDisplayFunction(display, &HWCDisplay::SetPowerMode, mode,
                                      false /* teardown */);
@@ -3165,6 +3191,8 @@
 
   Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]);
   bool pending_power_mode = false;
+  std::bitset<kSecureMax> secure_sessions = 0;
+  hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1;
     display < HWCCallbacks::kNumDisplays; display++) {
     if (display != active_builtin_disp_id) {
@@ -3177,6 +3205,9 @@
   }
 
   if (!pending_power_mode) {
+    if (!secure_sessions.any()) {
+      secure_session_active_ = false;
+    }
     return;
   }
 
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 105d592..7f198ac 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -399,6 +399,7 @@
     virtual int IsSmartPanelConfig(uint32_t disp_id, uint32_t config_id, bool *is_smart);
     virtual int IsRotatorSupportedFormat(int hal_format, bool ubwc, bool *supported);
     virtual int ControlQsyncCallback(bool enable);
+    virtual int ControlIdleStatusCallback(bool enable);
 
     std::weak_ptr<DisplayConfig::ConfigCallback> callback_;
     HWCSession *hwc_session_ = nullptr;
@@ -519,6 +520,7 @@
   int32_t GetVirtualDisplayId();
   void PerformQsyncCallback(hwc2_display_t display);
   bool isSmartPanelConfig(uint32_t disp_id, uint32_t config_id);
+  void PerformIdleStatusCallback(hwc2_display_t display);
 
   int SendLTMCommand(const char *cmd);
 
@@ -562,7 +564,9 @@
   std::bitset<HWCCallbacks::kNumDisplays> pending_refresh_;
   CWB cwb_;
   std::weak_ptr<DisplayConfig::ConfigCallback> qsync_callback_;
+  std::weak_ptr<DisplayConfig::ConfigCallback> idle_callback_;
   bool async_powermode_ = false;
+  bool async_power_mode_triggered_ = false;
   bool async_vds_creation_ = false;
   bool power_state_transition_[HWCCallbacks::kNumDisplays] = {};
   std::bitset<HWCCallbacks::kNumDisplays> display_ready_;
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index 0a7f8ca..ceff82b 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -502,32 +502,9 @@
     return -EINVAL;
   }
 
-  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-  if (active_builtin_disp_id < HWCCallbacks::kNumRealDisplays) {
-    std::vector<DisplayMapInfo> map_info = {map_info_primary_};
-    std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
+  // trigger invalidate to apply new bw caps.
+  callbacks_.Refresh(0);
 
-    for (auto &info : map_info) {
-      hwc2_display_t target_display = info.client_id;
-      {
-        SCOPE_LOCK(power_state_[target_display]);
-        if (power_state_transition_[target_display]) {
-          // Route all interactions with client to dummy display.
-          target_display = map_hwc_display_.find(target_display)->second;
-        }
-      }
-      {
-        SEQUENCE_WAIT_SCOPE_LOCK(locker_[target_display]);
-        auto &hwc_display = hwc_display_[target_display];
-        if (hwc_display && hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
-          hwc_display->ResetValidation();
-        }
-      }
-    }
-
-    // trigger invalidate to apply new bw caps.
-    callbacks_.Refresh(active_builtin_disp_id);
-  }
   return 0;
 }
 
@@ -718,12 +695,15 @@
   if (!supported) {
     return 0;
   }
-
+  // Added this flag for pixel
+  hwc_session_->async_power_mode_triggered_  = true;
   // Active builtin display needs revalidation
   hwc2_display_t active_builtin_disp_id = hwc_session_->GetActiveBuiltinDisplay();
   HWC2::PowerMode previous_mode = hwc_session_->hwc_display_[disp_id]->GetCurrentPowerMode();
 
   DLOGI("disp_id: %d power_mode: %d", disp_id, power_mode);
+  auto mode = static_cast<HWC2::PowerMode>(power_mode);
+
   HWCDisplay::HWCLayerStack stack = {};
   hwc2_display_t dummy_disp_id = hwc_session_->map_hwc_display_.at(disp_id);
 
@@ -740,6 +720,21 @@
   hwc_session_->hwc_display_[dummy_disp_id]->UpdatePowerMode(
                                        hwc_session_->hwc_display_[disp_id]->GetCurrentPowerMode());
 
+  buffer_handle_t target = 0;
+  shared_ptr<Fence> acquire_fence = nullptr;
+  int32_t dataspace = 0;
+  hwc_region_t damage = {};
+  VsyncPeriodNanos vsync_period = 16600000;
+  hwc_session_->hwc_display_[disp_id]->GetClientTarget(
+                                 target, acquire_fence, dataspace, damage);
+  hwc_session_->hwc_display_[dummy_disp_id]->SetClientTarget(
+                                       target, acquire_fence, dataspace, damage);
+
+
+
+  hwc_session_->hwc_display_[disp_id]->GetDisplayVsyncPeriod(&vsync_period);
+  hwc_session_->hwc_display_[dummy_disp_id]->SetDisplayVsyncPeriod(vsync_period);
+
   hwc_session_->locker_[dummy_disp_id].Unlock();  // Release the dummy display.
   // Release the display's power-state transition var read lock.
   hwc_session_->power_state_[disp_id].Unlock();
@@ -748,8 +743,7 @@
   // those operations on the dummy display.
 
   // Perform the actual [synchronous] power-state change.
-  hwc_session_->hwc_display_[disp_id]->SetPowerMode(static_cast<HWC2::PowerMode>(power_mode),
-                                                    false /* teardown */);
+  hwc_session_->hwc_display_[disp_id]->SetPowerMode(mode, false /* teardown */);
 
   // Power state transition end.
   // Acquire the display's power-state transition var read lock.
@@ -760,6 +754,15 @@
   // Retrieve the real display's layer-stack from the dummy display.
   hwc_session_->hwc_display_[dummy_disp_id]->GetLayerStack(&stack);
   hwc_session_->hwc_display_[disp_id]->SetLayerStack(&stack);
+  bool vsync_pending = hwc_session_->hwc_display_[dummy_disp_id]->VsyncEnablePending();
+  if (vsync_pending) {
+    hwc_session_->hwc_display_[disp_id]->SetVsyncEnabled(HWC2::Vsync::Enable);
+  }
+  hwc_session_->hwc_display_[dummy_disp_id]->GetClientTarget(
+                                       target, acquire_fence, dataspace, damage);
+  hwc_session_->hwc_display_[disp_id]->SetClientTarget(
+                                 target, acquire_fence, dataspace, damage);
+
   // Read display has got layerstack. Update the fences.
   hwc_session_->hwc_display_[disp_id]->PostPowerMode();
 
@@ -1206,4 +1209,14 @@
   return 0;
 }
 
+int HWCSession::DisplayConfigImpl::ControlIdleStatusCallback(bool enable) {
+  if (enable) {
+    hwc_session_->idle_callback_ = callback_;
+  } else {
+    hwc_session_->idle_callback_.reset();
+  }
+
+  return 0;
+}
+
 }  // namespace sdm
diff --git a/config/display-product.mk b/config/display-product.mk
index 2922b97..f349a1d 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -53,10 +53,6 @@
     debug.sf.enable_gl_backpressure=1
 endif
 
-ifneq ($(PLATFORM_VERSION), 10)
-    PRODUCT_PROPERTY_OVERRIDES +=  vendor.display.enable_async_powermode=0
-endif
-
 #Set WCG properties
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_wide_color_display=true
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_HDR_display=true
@@ -75,6 +71,9 @@
     vendor.display.disable_hw_recovery_dump=1
 endif
 
+# Enable power async mode
+#PRODUCT_PROPERTY_OVERRIDES +=  vendor.display.enable_async_powermode=1
+
 QMAA_ENABLED_HAL_MODULES += display
 ifeq ($(TARGET_USES_QMAA),true)
 ifeq ($(TARGET_USES_QMAA_OVERRIDE_DISPLAY),true)
diff --git a/gralloc/gr_utils.h b/gralloc/gr_utils.h
index a29dceb..5044213 100644
--- a/gralloc/gr_utils.h
+++ b/gralloc/gr_utils.h
@@ -31,6 +31,9 @@
 #define __GR_UTILS_H__
 
 #include <android/hardware/graphics/common/1.2/types.h>
+
+#include <limits>
+
 #include "gralloc_priv.h"
 #include "qdMetaData.h"
 
@@ -71,6 +74,11 @@
 
 template <class Type1, class Type2>
 inline Type1 ALIGN(Type1 x, Type2 align) {
+  Type1 max_val = std::numeric_limits<Type1>::max();
+  if (x > (max_val - (Type1)align)) {
+    return x;
+  }
+
   return (Type1)((x + (Type1)align - 1) & ~((Type1)align - 1));
 }
 
diff --git a/include/display_properties.h b/include/display_properties.h
index 9f004f8..1c0e8a4 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+* Copyright (c) 2018-2021, 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
@@ -123,6 +123,10 @@
 #define ENABLE_POMS_DURING_DOZE              DISPLAY_PROP("enable_poms_during_doze")
 #define DISABLE_DYNAMIC_FPS                  DISPLAY_PROP("disable_dynamic_fps")
 #define ENHANCE_IDLE_TIME                    DISPLAY_PROP("enhance_idle_time")
+#define ENABLE_QSYNC_IDLE                    DISPLAY_PROP("enable_qsync_idle")
+
+// PERF hint properties
+#define ENABLE_PERF_HINT_LARGE_COMP_CYCLE    DISPLAY_PROP("enable_perf_hint_large_comp_cycle")
 
 // Add all vendor.display properties above
 
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 51df12d..a13266b 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -150,6 +150,7 @@
   kDisplayPowerResetEvent,  // Event triggered by Hardware Recovery.
   kInvalidateDisplay,       // Event triggered by DrawCycle thread to Invalidate display.
   kSyncInvalidateDisplay,   // Event triggered by Non-DrawCycle threads to Invalidate display.
+  kPostIdleTimeout,         // Event triggered after entering idle.
 };
 
 /*! @brief This enum represents the secure events received by Display HAL. */
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 990facf..6f81788 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -501,11 +501,8 @@
     hdr_supported = (hdr_supported && hw_panel_info_.hdr_enabled);
   }
 
-  // Built-in displays not support HDR10+ even the target supports HDR to comply with spec. For non-builtins, check
-  // panel capability.
-  if (kBuiltIn == display_type_) {
-    hdr_plus_supported = false;
-  } else if (hdr_supported && hw_panel_info_.hdr_plus_enabled) {
+  // For non-builtin displays, check panel capability for HDR10+
+  if (hdr_supported && hw_panel_info_.hdr_plus_enabled) {
     hdr_plus_supported = true;
   }
 
@@ -749,6 +746,7 @@
   os << " h_total: " << display_attributes_.h_total;
   os << " clk: " << display_attributes_.clock_khz;
   os << " Topology: " << display_attributes_.topology;
+  os << " Qsync mode: " << active_qsync_mode_;
   os << std::noboolalpha;
 
   os << "\nCurrent Color Mode: " << current_color_mode_.c_str();
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index c924bb8..509c025 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -61,7 +61,7 @@
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
   virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
-  virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info);
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
@@ -164,6 +164,7 @@
   virtual DisplayError ClearLUTs() {
     return kErrorNotSupported;
   }
+  QSyncMode active_qsync_mode_ = kQSyncModeNone;
 
  protected:
   const char *kBt2020Pq = "bt2020_pq";
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index f2d69f3..6a869de 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -129,6 +129,13 @@
   DebugHandler::Get()->GetProperty(ENHANCE_IDLE_TIME, &value);
   enhance_idle_time_ = (value == 1);
 
+  value = 0;
+  DebugHandler::Get()->GetProperty(ENABLE_QSYNC_IDLE, &value);
+  enable_qsync_idle_ = hw_panel_info_.qsync_support && (value == 1);
+  if (enable_qsync_idle_) {
+    DLOGI("Enabling qsync on idling");
+  }
+
   return error;
 }
 
@@ -155,8 +162,7 @@
     }
   } else {
     if (CanSkipDisplayPrepare(layer_stack)) {
-      hw_layers_.hw_avr_info.update = needs_avr_update_;
-      hw_layers_.hw_avr_info.mode = GetAvrMode(qsync_mode_);
+      UpdateQsyncMode();
       return kErrorNone;
     }
   }
@@ -164,8 +170,7 @@
   // Clean hw layers for reuse.
   hw_layers_ = HWLayers();
 
-  hw_layers_.hw_avr_info.update = needs_avr_update_;
-  hw_layers_.hw_avr_info.mode = GetAvrMode(qsync_mode_);
+  UpdateQsyncMode();
 
   left_frame_roi_ = {};
   right_frame_roi_ = {};
@@ -183,6 +188,31 @@
   return error;
 }
 
+void DisplayBuiltIn::UpdateQsyncMode() {
+  if (!hw_panel_info_.qsync_support || (hw_panel_info_.mode == kModeCommand)) {
+    return;
+  }
+
+  QSyncMode mode = kQSyncModeNone;
+  if (handle_idle_timeout_ && enable_qsync_idle_) {
+    // Override to continuous mode upon idling.
+    mode = kQSyncModeContinuous;
+    DLOGV_IF(kTagDisplay, "Qsync entering continuous mode");
+  } else {
+    // Set Qsync mode requested by client.
+    mode = qsync_mode_;
+    DLOGV_IF(kTagDisplay, "Restoring client's qsync mode: %d", mode);
+  }
+
+  hw_layers_.hw_avr_info.update = (mode != active_qsync_mode_) || needs_avr_update_;
+  hw_layers_.hw_avr_info.mode = GetAvrMode(mode);
+
+  DLOGV_IF(kTagDisplay, "update: %d mode: %d", hw_layers_.hw_avr_info.update, mode);
+
+  // Store active mode.
+  active_qsync_mode_ = mode;
+}
+
 HWAVRModes DisplayBuiltIn::GetAvrMode(QSyncMode mode) {
   switch (mode) {
      case kQSyncModeNone:
@@ -326,6 +356,18 @@
   }
   dpps_info_.Init(this, hw_panel_info_.panel_name);
 
+  HandleQsyncPostCommit(layer_stack);
+
+  first_cycle_ = false;
+
+  previous_retire_fence_ = layer_stack->retire_fence;
+
+  handle_idle_timeout_ = false;
+
+  return error;
+}
+
+void DisplayBuiltIn::HandleQsyncPostCommit(LayerStack *layer_stack) {
   if (qsync_mode_ == kQsyncModeOneShot) {
     // Reset qsync mode.
     SetQSyncMode(kQSyncModeNone);
@@ -337,11 +379,13 @@
     needs_avr_update_ = false;
   }
 
-  first_cycle_ = false;
+  SetVsyncStatus(true /*Re-enable vsync.*/);
 
-  previous_retire_fence_ = layer_stack->retire_fence;
-
-  return error;
+  bool notify_idle = enable_qsync_idle_ && (active_qsync_mode_ != kQSyncModeNone) &&
+                     handle_idle_timeout_;
+  if (notify_idle) {
+    event_handler_->HandleEvent(kPostIdleTimeout);
+  }
 }
 
 void DisplayBuiltIn::UpdateDisplayModeParams() {
@@ -549,7 +593,7 @@
     return kErrorParameters;
   }
 
-  if (CanLowerFps(idle_screen) && !final_rate) {
+  if (CanLowerFps(idle_screen) && !final_rate && !enable_qsync_idle_) {
     refresh_rate = hw_panel_info_.min_fps;
   }
 
@@ -575,7 +619,6 @@
 
   // On success, set current refresh rate to new refresh rate
   current_refresh_rate_ = refresh_rate;
-  handle_idle_timeout_ = false;
   deferred_config_.MarkDirty();
 
   return ReconfigureDisplay();
@@ -600,15 +643,38 @@
 }
 
 DisplayError DisplayBuiltIn::VSync(int64_t timestamp) {
-  if (vsync_enable_ && !drop_hw_vsync_) {
-    DisplayEventVSync vsync;
-    vsync.timestamp = timestamp;
-    event_handler_->VSync(vsync);
+  DTRACE_SCOPED();
+  bool qsync_enabled = enable_qsync_idle_ && (active_qsync_mode_ != kQSyncModeNone);
+  // Client isn't aware of underlying qsync mode.
+  // Disable vsync propagation as long as qsync is enabled.
+  bool propagate_vsync = vsync_enable_ && !drop_hw_vsync_ && !qsync_enabled;
+  if (!propagate_vsync) {
+    // Re enable when display updates.
+    SetVsyncStatus(false /*Disable vsync events.*/);
+    return kErrorNone;
   }
 
+  DisplayEventVSync vsync;
+  vsync.timestamp = timestamp;
+  event_handler_->VSync(vsync);
+
   return kErrorNone;
 }
 
+void DisplayBuiltIn::SetVsyncStatus(bool enable) {
+  string trace_name = enable ? "enable" : "disable";
+  DTRACE_BEGIN(trace_name.c_str());
+  if (enable) {
+    // Enable if vsync is still enabled.
+    hw_events_intf_->SetEventState(HWEvent::VSYNC, vsync_enable_);
+    pending_vsync_enable_ = false;
+  } else {
+    hw_events_intf_->SetEventState(HWEvent::VSYNC, false);
+    pending_vsync_enable_ = true;
+  }
+  DTRACE_END();
+}
+
 void DisplayBuiltIn::IdleTimeout() {
   if (hw_panel_info_.mode == kModeVideo) {
     if (event_handler_->HandleEvent(kIdleTimeout) != kErrorNone) {
@@ -940,7 +1006,7 @@
 }
 
 DisplayError DisplayBuiltIn::GetQSyncMode(QSyncMode *qsync_mode) {
-  *qsync_mode = qsync_mode_;
+  *qsync_mode = active_qsync_mode_;
   return kErrorNone;
 }
 
@@ -1262,4 +1328,26 @@
   panel_info->transfer_time_us = hw_panel_info_.transfer_time_us;
 }
 
+DisplayError DisplayBuiltIn::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  fixed_info->is_cmdmode = (hw_panel_info_.mode == kModeCommand);
+
+  HWResourceInfo hw_resource_info = HWResourceInfo();
+  hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+
+  fixed_info->hdr_supported = hw_resource_info.has_hdr;
+  // Built-in displays not support HDR10+ even the target supports HDR to comply with spec
+  fixed_info->hdr_plus_supported = false;
+  // Populate luminance values only if hdr will be supported on that display
+  fixed_info->max_luminance = fixed_info->hdr_supported ? hw_panel_info_.peak_luminance: 0;
+  fixed_info->average_luminance = fixed_info->hdr_supported ? hw_panel_info_.average_luminance : 0;
+  fixed_info->min_luminance = fixed_info->hdr_supported ?  hw_panel_info_.blackness_level: 0;
+  fixed_info->hdr_eotf = hw_panel_info_.hdr_eotf;
+  fixed_info->hdr_metadata_type_one = hw_panel_info_.hdr_metadata_type_one;
+  fixed_info->partial_update = hw_panel_info_.partial_update;
+  fixed_info->readback_supported = hw_resource_info.has_concurrent_writeback;
+
+  return kErrorNone;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 7ec4dec..8e43f0b 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -132,6 +132,7 @@
   virtual DisplayError GetQSyncMode(QSyncMode *qsync_mode);
   virtual DisplayError colorSamplingOn();
   virtual DisplayError colorSamplingOff();
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
 
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
@@ -161,6 +162,9 @@
   void GetFpsConfig(HWDisplayAttributes *display_attributes, HWPanelInfo *panel_info);
   void UpdateDisplayModeParams();
   bool CanLowerFps(bool idle_screen);
+  void HandleQsyncPostCommit(LayerStack *layer_stack);
+  void UpdateQsyncMode();
+  void SetVsyncStatus(bool enable);
 
   const uint32_t kPuTimeOutMs = 1000;
   std::vector<HWEvent> event_list_;
@@ -195,6 +199,8 @@
   bool enhance_idle_time_ = false;
   int idle_time_ms_ = 0;
   struct timespec idle_timer_start_;
+  bool enable_qsync_idle_ = false;
+  bool pending_vsync_enable_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 0da6303..e0cf2d7 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -163,6 +163,9 @@
     case kFormatRGB888:
       *drm_format = DRM_FORMAT_BGR888;
       break;
+    case kFormatBGR888:
+      *drm_format = DRM_FORMAT_RGB888;
+      break;
     case kFormatRGB565:
       *drm_format = DRM_FORMAT_BGR565;
       break;