sdm: Support ControlPartialUpdate api in libqdutils

Implement CONTROL_PARTIAL_UPDATE binder support. DPSS module
use this api to control partial update feature.

Remove support for sdm.partial_update property as it is no
longer applicable.

Change-Id: Ib463aff0042dcfc0d0b2f296b54016b1ee70115d
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 3941137..7849d7f 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -286,7 +286,26 @@
 // Screen refresh for native daemons linking dynamically to libqdutils
 // ----------------------------------------------------------------------------
 extern "C" int refreshScreen() {
-  int ret = 0;
-  ret = screenRefresh();
-  return ret;
+    int ret = 0;
+    ret = screenRefresh();
+    return ret;
 }
+
+extern "C" int controlPartialUpdate(int dpy, int mode) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    if(binder != NULL) {
+        Parcel inParcel, outParcel;
+        inParcel.writeInt32(dpy);
+        inParcel.writeInt32(mode);
+        err = binder->dispatch(IQService::CONTROL_PARTIAL_UPDATE, &inParcel, &outParcel);
+        if(err != 0) {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        } else {
+            return outParcel.readInt32();
+        }
+    }
+
+    return err;
+}
+
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index c877d06..4c0271a 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -58,7 +58,7 @@
         TOGGLE_BWC = 17,           // Toggle BWC On/Off on targets that support
         /* Enable/Disable/Set refresh rate dynamically */
         CONFIGURE_DYN_REFRESH_RATE = 18,
-        SET_PARTIAL_UPDATE = 19,   // Preference on partial update feature
+        CONTROL_PARTIAL_UPDATE = 19,   // Provides ability to enable/disable partial update
         CONTROL_BACKLIGHT = 20, // Provides ability to control backlight
         SET_FRAME_DUMP_CONFIG = 21,  // Provides ability to set the frame dump config
         SET_S3D_MODE = 22, // Set the 3D mode as specified in msm_hdmi_modes.h
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index b677188..fbad484 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -79,10 +79,6 @@
     return sendSingleParam(qService::IQService::CONTROL_BACKLIGHT, on);
 }
 
-inline android::status_t setPartialUpdate(uint32_t enable) {
-    return sendSingleParam(qService::IQService::SET_PARTIAL_UPDATE, enable);
-}
-
 inline android::status_t setExtOrientation(uint32_t orientation) {
     return sendSingleParam(qService::IQService::EXTERNAL_ORIENTATION,
             orientation);
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 40ef738..f9b3fa4 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -327,6 +327,15 @@
   */
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages) = 0;
 
+  /*! @brief Method to control partial update feature for each display.
+
+    @param[in] enable partial update feature control flag
+    @param[out] pending whether the operation is completed or pending for completion
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) = 0;
+
   /*! @brief Method to set the mode of the primary display.
 
     @param[in] mode the new display mode.
diff --git a/sdm/include/private/partial_update_interface.h b/sdm/include/private/partial_update_interface.h
index 8b421c4..3159b56 100644
--- a/sdm/include/private/partial_update_interface.h
+++ b/sdm/include/private/partial_update_interface.h
@@ -36,6 +36,7 @@
 class PartialUpdateInterface {
  public:
   virtual DisplayError GenerateROI(HWLayersInfo *hw_layers_info) = 0;
+  virtual void ControlPartialUpdate(bool enable) = 0;
 
  protected:
   virtual ~PartialUpdateInterface() { }
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index a384509..943747b 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -65,7 +65,6 @@
   static int GetIdleTimeoutMs();
   static bool IsRotatorDownScaleDisabled();
   static bool IsDecimationDisabled();
-  static bool IsPartialUpdateEnabled();
   static int GetMaxPipesPerMixer(DisplayType display_type);
   static bool IsVideoModeEnabled();
   static bool IsRotatorUbwcDisabled();
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 078b7dc..5ee904f 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -191,7 +191,8 @@
   SCOPE_LOCK(locker_);
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
-  display_comp_ctx->strategy->Start(&hw_layers->info, &display_comp_ctx->max_strategies);
+  display_comp_ctx->strategy->Start(&hw_layers->info, &display_comp_ctx->max_strategies,
+                                    display_comp_ctx->partial_update_enable);
   display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
 
   // Avoid idle fallback, if there is only one app layer.
@@ -366,6 +367,14 @@
   return error;
 }
 
+void CompManager::ControlPartialUpdate(Handle display_ctx, bool enable) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  display_comp_ctx->partial_update_enable = enable;
+}
+
 void CompManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
 }
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index f7143ff..3f46d52 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -56,6 +56,7 @@
   void ProcessIdleTimeout(Handle display_ctx);
   void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
   DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+  void ControlPartialUpdate(Handle display_ctx, bool enable);
   DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
 
   // DumpImpl method
@@ -76,11 +77,12 @@
     bool idle_fallback;
     bool handle_idle_timeout;
     bool fallback_;
+    uint32_t partial_update_enable;
 
     DisplayCompositionContext()
       : display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
         remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true),
-        fallback_(false) { }
+        fallback_(false), partial_update_enable(true) { }
   };
 
   Locker locker_;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index c1d2905..68423bf 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -43,7 +43,7 @@
     rotator_intf_(rotator_intf), state_(kStateOff), hw_device_(0), display_comp_ctx_(0),
     display_attributes_(NULL), num_modes_(0), active_mode_index_(0), pending_commit_(false),
     vsync_enable_(false), underscan_supported_(false), max_mixer_stages_(0),
-    hw_info_intf_(hw_info_intf), color_mgr_(NULL) {
+    hw_info_intf_(hw_info_intf), color_mgr_(NULL), partial_update_control_(true) {
 }
 
 DisplayError DisplayBase::Init() {
@@ -420,17 +420,44 @@
 DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
   DisplayError error = kErrorNone;
 
-  if (comp_manager_) {
-    error = comp_manager_->SetMaxMixerStages(display_comp_ctx_, max_mixer_stages);
+  error = comp_manager_->SetMaxMixerStages(display_comp_ctx_, max_mixer_stages);
 
-    if (error == kErrorNone) {
-      max_mixer_stages_ = max_mixer_stages;
-    }
+  if (error == kErrorNone) {
+    max_mixer_stages_ = max_mixer_stages;
   }
 
   return error;
 }
 
+DisplayError DisplayBase::ControlPartialUpdate(bool enable, uint32_t *pending) {
+  if (!pending) {
+    return kErrorParameters;
+  }
+
+  if (!hw_panel_info_.partial_update) {
+    // Nothing to be done.
+    DLOGI("partial update is not applicable for display=%d", display_type_);
+    return kErrorNotSupported;
+  }
+
+  *pending = false;
+  if (enable == partial_update_control_) {
+    DLOGI("Same state transition is requested.");
+    return kErrorNone;
+  }
+
+  partial_update_control_ = enable;
+  comp_manager_->ControlPartialUpdate(display_comp_ctx_, enable);
+
+  if (!enable) {
+    // If the request is to turn off feature, new draw call is required to have
+    // the new setting into effect.
+    *pending = true;
+  }
+
+  return kErrorNone;
+}
+
 DisplayError DisplayBase::SetDisplayMode(uint32_t mode) {
   return kErrorNotSupported;
 }
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 531217e..4289c6b 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -61,6 +61,7 @@
   virtual DisplayError SetDisplayState(DisplayState state);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
   virtual bool IsUnderscanSupported();
@@ -101,6 +102,7 @@
   uint32_t max_mixer_stages_;
   HWInfoInterface *hw_info_intf_;
   ColorManagerProxy *color_mgr_;  // each display object owns its ColorManagerProxy
+  bool partial_update_control_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index f009d3a..076aa20 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -70,7 +70,8 @@
   return kErrorNone;
 }
 
-DisplayError Strategy::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) {
+DisplayError Strategy::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts,
+                             bool partial_update_enable) {
   DisplayError error = kErrorNone;
 
   hw_layers_info_ = hw_layers_info;
@@ -90,6 +91,9 @@
     return kErrorUndefined;
   }
 
+  if (partial_update_intf_) {
+    partial_update_intf_->ControlPartialUpdate(partial_update_enable);
+  }
   GenerateROI();
 
   if (strategy_intf_) {
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
index c7a67d9..22fd82a 100644
--- a/sdm/libs/core/strategy.h
+++ b/sdm/libs/core/strategy.h
@@ -38,7 +38,8 @@
   DisplayError Init();
   DisplayError Deinit();
 
-  DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts);
+  DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts,
+                     bool partial_update_enable);
   DisplayError GetNextStrategy(StrategyConstraints *constraints);
   DisplayError Stop();
 
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index c9828d8..733914a 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -872,6 +872,16 @@
   return error;
 }
 
+DisplayError HWCDisplay:: ControlPartialUpdate(bool enable, uint32_t *pending) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->ControlPartialUpdate(enable, pending);
+  }
+
+  return error;
+}
+
 LayerBufferFormat HWCDisplay::GetSDMFormat(const int32_t &source, const int flags) {
   LayerBufferFormat format = kFormatInvalid;
   if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 7020fce..e2b860c 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -49,6 +49,7 @@
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
   virtual uint32_t GetLastPowerMode();
   virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
   virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 058b933..c8c9da9 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -525,6 +525,10 @@
     status = QdcmCMDHandler(*input_parcel, output_parcel);
     break;
 
+  case qService::IQService::CONTROL_PARTIAL_UPDATE:
+    status = ControlPartialUpdate(input_parcel, output_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
@@ -572,6 +576,55 @@
   return display->SetDisplayStatus(display_status);
 }
 
+android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
+                                                   android::Parcel *out) {
+  DisplayError error = kErrorNone;
+  int ret = 0;
+  uint32_t disp_id = UINT32(input_parcel->readInt32());
+  uint32_t enable = UINT32(input_parcel->readInt32());
+
+  if (disp_id != HWC_DISPLAY_PRIMARY) {
+    DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
+    ret = -EINVAL;
+    out->writeInt32(ret);
+    return ret;
+  }
+
+  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    DLOGE("primary display object is not instantiated");
+    ret = -EINVAL;
+    out->writeInt32(ret);
+    return ret;
+  }
+
+  uint32_t pending = 0;
+  error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
+
+  if (error == kErrorNone) {
+    if (!pending) {
+      out->writeInt32(ret);
+      return ret;
+    }
+  } else if (error == kErrorNotSupported) {
+    out->writeInt32(ret);
+    return ret;
+  } else {
+    ret = -EINVAL;
+    out->writeInt32(ret);
+    return ret;
+  }
+
+  hwc_procs_->invalidate(hwc_procs_);
+
+  // Wait until partial update control is complete
+  ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
+  locker_.Unlock();
+
+  out->writeInt32(ret);
+
+  return ret;
+}
+
 android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel) {
   uint32_t display_id = UINT32(input_parcel->readInt32());
   uint32_t display_status = UINT32(input_parcel->readInt32());
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index c8550d5..04aeb70 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -51,6 +51,7 @@
 
  private:
   static const int kExternalConnectionTimeoutMs = 500;
+  static const int kPartialUpdateControlTimeoutMs = 100;
 
   // hwc methods
   static int Open(const hw_module_t *module, const char* name, hw_device_t **device);
@@ -90,6 +91,7 @@
   android::status_t ControlBackLight(const android::Parcel *input_parcel);
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
   android::status_t QdcmCMDHandler(const android::Parcel &in, android::Parcel *out);
+  android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out);
 
   static Locker locker_;
   CoreInterface *core_intf_;
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index 98f5626..4df63d9 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -73,13 +73,6 @@
   return (value == 1);
 }
 
-bool Debug::IsPartialUpdateEnabled() {
-  int value = 0;
-  debug_.debug_handler_->GetProperty("sdm.partial_update", &value);
-
-  return (value == 1);
-}
-
 int Debug::GetMaxPipesPerMixer(DisplayType display_type) {
   int value = -1;
   switch (display_type) {