sde: Add binder support to set maximum mixer stages.

Add binder support to set maximum mixer stages for each displays.

Syntax:
    adb shell "service call display.qservice 13 i32 <DISPLAY_TYPE>
                                                i32 <MAX_STAGE_COUNT>"
    DISPLAY_TYPE    = Set bit 1 -> To enable dump on primary display
                      Set bit 2 -> To enable dump on hdmi display
                      Set bit 3 -> To enable dump on virtual display
    MAX_STAGE_COUNT = 3 -> Set the max layer mixer stages to 3.

Set max_mixer stages all displays to 3:
    adb shell "service call display.qservice 13 i32 7 i32 3"

Change-Id: I10d521308077efca6a532fb679c04066bae9e8d3
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index c054fae..9aae0a1 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -314,6 +314,14 @@
   */
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
 
+  /*! @brief Method to set maximum number of mixer stages for each display.
+
+    @param[in] max_mixer_stages maximum number of mixer stages.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages) = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 06028a2..cc58465 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -318,6 +318,20 @@
   return false;
 }
 
+DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (display_comp_ctx) {
+    error = res_mgr_.SetMaxMixerStages(display_comp_ctx->display_resource_ctx, max_mixer_stages);
+  }
+
+  return error;
+}
+
 void CompManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
 }
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index 24a0fff..0a21ee0 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -48,6 +48,7 @@
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
   bool ProcessIdleTimeout(Handle display_ctx);
+  DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index d403450..8bfc6dd 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -409,6 +409,18 @@
   hw_intf_->SetIdleTimeoutMs(hw_device_, timeout_ms);
 }
 
+DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  if (comp_manager_) {
+    error = comp_manager_->SetMaxMixerStages(display_comp_ctx_, max_mixer_stages);
+  }
+
+  return error;
+}
+
 DisplayError DisplayBase::VSync(int64_t timestamp) {
   if (vsync_enable_) {
     DisplayEventVSync vsync;
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index d2b67e3..10e11f8 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -60,6 +60,7 @@
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetVSyncState(bool enable);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
 
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 27a4e41..cd439ec 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -325,8 +325,9 @@
       layer_config->right_pipe.z_order = z_order;
     }
     z_order++;
-    if (z_order >= hw_res_info_.num_blending_stages) {
-      DLOGV_IF(kTagResources, "z_order is over the limit: z_order = %d", z_order);
+    if (z_order > display_resource_ctx->max_mixer_stages) {
+      DLOGV_IF(kTagResources, "z_order is over the limit of max_mixer_stages = %d",
+               display_resource_ctx->max_mixer_stages);
       return kErrorResources;
     }
   }
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 14cf11f..238dfa8 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -186,6 +186,8 @@
     display_resource_ctx->display_attributes.split_left =
       display_resource_ctx->display_attributes.x_pixels;
 
+  display_resource_ctx->max_mixer_stages = hw_res_info_.num_blending_stages;
+
   *display_ctx = display_resource_ctx;
   return error;
 }
@@ -271,8 +273,15 @@
 
   DLOGV_IF(kTagResources, "==== Resource reserving start: hw_block = %d ====", hw_block_id);
 
-  if (layer_info.count > num_pipe_ || layer_info.count >= hw_res_info_.num_blending_stages) {
-    DLOGV_IF(kTagResources, "layer count is over the limit: layer count = %d", layer_info.count);
+  if (layer_info.count > num_pipe_) {
+    DLOGV_IF(kTagResources, "layer count exceeds pipe limit of %d, layer count %d", num_pipe_,
+             layer_info.count);
+    return kErrorResources;
+  }
+
+  if (layer_info.count > display_resource_ctx->max_mixer_stages) {
+    DLOGV_IF(kTagResources, "layer count exceeds max mixer stage limit of %d, layer count %d",
+             display_resource_ctx->max_mixer_stages, layer_info.count);
     return kErrorResources;
   }
 
@@ -811,6 +820,26 @@
   DLOGV_IF(kTagResources, "display id = %d", display_resource_ctx->hw_block_id);
 }
 
+DisplayError ResManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
+  SCOPE_LOCK(locker_);
+
+  if (max_mixer_stages < 1 || max_mixer_stages > hw_res_info_.num_blending_stages) {
+    DLOGE("Max mixer stages = %d and that should be in between 1 to %d", max_mixer_stages,
+          hw_res_info_.num_blending_stages);
+
+    return kErrorParameters;
+  }
+
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+
+  if (display_resource_ctx) {
+    display_resource_ctx->max_mixer_stages = max_mixer_stages;
+  }
+
+  return kErrorNone;
+}
+
 uint32_t ResManager::GetMdssPipeId(PipeType type, uint32_t index) {
   uint32_t mdss_id = kPipeIdMax;
   switch (type) {
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index d21984e..8cf08f5 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -49,6 +49,7 @@
   DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
+  DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
@@ -122,9 +123,10 @@
     int32_t session_id;  // applicable for virtual display sessions only
     uint32_t rotate_count;
     bool frame_start;
+    uint32_t max_mixer_stages;
 
     DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1),
-                    rotate_count(0), frame_start(false) { }
+                    rotate_count(0), frame_start(false), max_mixer_stages(0) { }
 
     ~DisplayResourceContext() {
       if (buffer_manager) {
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index dd1beac..1be682d 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -600,6 +600,16 @@
   }
 }
 
+DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetMaxMixerStages(max_mixer_stages);
+  }
+
+  return error;
+}
+
 LayerBufferFormat HWCDisplay::GetSDEFormat(const int32_t &source, const int flags) {
   LayerBufferFormat format = kFormatInvalid;
   if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index a574d6b..8feddf6 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -45,6 +45,7 @@
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
 
  protected:
   // Maximum number of layers supported by display engine.
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 40eae99..b6d0c18 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -562,6 +562,8 @@
                                              android::Parcel */*output_parcel*/) {
   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
 
+  android::status_t status = 0;
+
   switch (command) {
   case qService::IQService::DYNAMIC_DEBUG:
     DynamicDebug(input_parcel);
@@ -573,7 +575,7 @@
 
   case qService::IQService::SET_IDLE_TIMEOUT:
     if (display_primary_) {
-      uint32_t timeout = (uint32_t)input_parcel->readInt32();
+      uint32_t timeout = UINT32(input_parcel->readInt32());
       display_primary_->SetIdleTimeoutMs(timeout);
     }
     break;
@@ -582,11 +584,50 @@
     SetFrameDumpConfig(input_parcel);
     break;
 
+  case qService::IQService::SET_MAX_PIPES_PER_MIXER:
+    status = SetMaxMixerStages(input_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
   }
 
+  return status;
+}
+
+android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
+  DisplayError error = kErrorNone;
+  uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_PRIMARY)) {
+    if (display_primary_) {
+      error = display_primary_->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_EXTERNAL)) {
+    if (display_external_) {
+      error = display_external_->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_VIRTUAL)) {
+    if (display_virtual_) {
+      error = display_virtual_->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
   return 0;
 }
 
@@ -595,19 +636,19 @@
   uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
 
-  if (bit_mask_display_type & (1 << qService::IQService::DUMP_PRIMARY_DISPLAY)) {
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_PRIMARY)) {
     if (display_primary_) {
       display_primary_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
     }
   }
 
-  if (bit_mask_display_type & (1 << qService::IQService::DUMP_HDMI_DISPLAY)) {
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_EXTERNAL)) {
     if (display_external_) {
       display_external_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
     }
   }
 
-  if (bit_mask_display_type & (1 << qService::IQService::DUMP_VIRTUAL_DISPLAY)) {
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_VIRTUAL)) {
     if (display_virtual_) {
       display_virtual_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
     }
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 4b8c8ce..1608ce5 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -85,6 +85,7 @@
                                            android::Parcel *output_parcel);
   void DynamicDebug(const android::Parcel *input_parcel);
   void SetFrameDumpConfig(const android::Parcel *input_parcel);
+  android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
 
   static Locker locker_;
   CoreInterface *core_intf_;
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 932d670..6a9d7f8 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -91,12 +91,6 @@
         ENABLE_PARTIAL_UPDATE,
     };
 
-    enum {
-        DUMP_PRIMARY_DISPLAY,
-        DUMP_HDMI_DISPLAY,
-        DUMP_VIRTUAL_DISPLAY,
-    };
-
     // Register a HWC client that can be notified
     // This client is generic and is intended to get
     // dispatches of all events calling into QService