Merge "sde: Transition to safe mode in case of resource failures"
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
index e6dcf1c..421ab87 100644
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -106,7 +106,8 @@
 struct LayerBufferFlags {
   uint64_t secure : 1;  //!< This flag shall be set by client to indicate that the buffer need
                         //!< to be handled securely.
-
+  uint64_t video  : 1;  //!< This flag shall be set by client to indicate that the buffer is
+                        //!< video/ui buffer
   LayerBufferFlags() : secure(0) { }
 };
 
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index fddfa8e..e361ac7 100644
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -93,10 +93,13 @@
   @sa LayerBuffer
 */
 struct LayerFlags {
-  uint64_t skip : 1;  //!< This flag shall be set by client to indicate that this layer will be
-                      //!< handled by GPU. Device Device will not consider it for composition.
-
-  LayerFlags() : skip(0) { }
+  uint64_t skip : 1;      //!< This flag shall be set by client to indicate that this layer will be
+                          //!< handled by GPU. Display Device will not consider it for composition.
+  uint64_t updating : 1;  //!< This flag shall be set by client to indicate that this is updating/
+                          //!< non-updating. so strategy manager will mark them for SDE/GPU
+                          //!< composition respectively when the layer stack qualifies for cache
+                          //!< based composition.
+  LayerFlags() : skip(0), updating(0) { }
 };
 
 /*! @brief This structure defines flags associated with a layer stack. The 1-bit flag can be set to
diff --git a/displayengine/include/private/strategy_interface.h b/displayengine/include/private/strategy_interface.h
index 7050929..f14fbfb 100644
--- a/displayengine/include/private/strategy_interface.h
+++ b/displayengine/include/private/strategy_interface.h
@@ -75,11 +75,13 @@
     @sa GetNextStrategy
 */
 struct StrategyConstraints {
-  bool gpu_only;          //!< Select GPU only composition for this layer stack.
+  bool safe_mode;         //!< In this mode, strategy manager chooses the composition strategy
+                          //!< that requires minimum number of pipe for the current frame. i.e.,
+                          //!< video only composition, secure only composition or GPU composition
   uint32_t max_layers;    //!< Maximum number of layers that shall be programmed on hardware for the
                           //!< given layer stack.
 
-  StrategyConstraints() : gpu_only(false), max_layers(kNumLayersMax) { }
+  StrategyConstraints() : safe_mode(false), max_layers(kNumLayersMax) { }
 };
 
 /*! @brief Flag to denote that GPU composition is performed for the given layer stack.
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index 4b18ed6..7d7a39c 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -43,6 +43,9 @@
 
 #define ROUND_UP(number, step) ((((number) + ((step) - 1)) / (step)) * (step))
 
+#define SET_BIT(value, bit) ((value) | (1 << (bit)))
+#define CLEAR_BIT(value, bit) ((value) & (~(1 << (bit))))
+
 namespace sde {
 
   const int kThreadPriorityUrgent = -9;
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
index 10d5ea6..0691dfc 100644
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -46,9 +46,9 @@
 namespace sde {
 
 enum LogTag {
-  kTagNone = 0,   //!< Log tag name is not specified.
-  kTagCore,       //!< Log is tagged for display core.
-  kTagStrategy,   //!< Log is tagged for composition strategy.
+  kTagNone = 0,   // Log tag name is not specified.
+  kTagCore,       // Log is tagged for display core.
+  kTagStrategy,   // Log is tagged for composition strategy.
 };
 
 class Debug {
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 560db52..49572f9 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -34,7 +34,8 @@
 
 namespace sde {
 
-CompManager::CompManager() : strategy_lib_(NULL), strategy_intf_(NULL) {
+CompManager::CompManager() : strategy_lib_(NULL), strategy_intf_(NULL), registered_displays_(0),
+                             configured_displays_(0), safe_mode_(false) {
 }
 
 DisplayError CompManager::Init(const HWResourceInfo &hw_res_info) {
@@ -102,9 +103,12 @@
     delete comp_mgr_device;
     return error;
   }
-
+  SET_BIT(registered_displays_, type);
   comp_mgr_device->device_type = type;
   *device = comp_mgr_device;
+  // New device has been added, so move the composition mode to safe mode until unless resources
+  // for the added display is configured properly.
+  safe_mode_ = true;
 
   return kErrorNone;
 }
@@ -115,11 +119,26 @@
   CompManagerDevice *comp_mgr_device = reinterpret_cast<CompManagerDevice *>(device);
 
   res_mgr_.UnregisterDevice(comp_mgr_device->res_mgr_device);
+  CLEAR_BIT(registered_displays_, comp_mgr_device->device_type);
+  CLEAR_BIT(configured_displays_, comp_mgr_device->device_type);
   delete comp_mgr_device;
 
   return kErrorNone;
 }
 
+void CompManager::PrepareStrategyConstraints(Handle device, HWLayers *hw_layers) {
+  CompManagerDevice *comp_mgr_device = reinterpret_cast<CompManagerDevice *>(device);
+  StrategyConstraints *constraints = &comp_mgr_device->constraints;
+
+  constraints->safe_mode = safe_mode_;
+  // If validation for the best available composition strategy with driver has failed, just
+  // fallback to GPU composition.
+  if (UNLIKELY(hw_layers->info.flags)) {
+    constraints->safe_mode = true;
+    return;
+  }
+}
+
 DisplayError CompManager::Prepare(Handle device, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
 
@@ -128,19 +147,7 @@
 
   DisplayError error = kErrorNone;
 
-  comp_mgr_device->constraints.gpu_only = false;
-
-  // If validation for the best available composition strategy with driver has failed, just
-  // fallback to GPU composition.
-  if (UNLIKELY(hw_layers->info.flags)) {
-    // Did driver reject GPU composition as well? This will never happen.
-    if (UNLIKELY(hw_layers->info.flags & kFlagGPU)) {
-      DLOGE("Unexpected error. GPU composition validation failed.");
-      return kErrorHardware;
-    }
-
-    comp_mgr_device->constraints.gpu_only = true;
-  }
+  PrepareStrategyConstraints(device, hw_layers);
 
   // Select a composition strategy, and try to allocate resources for it.
   res_mgr_.Start(res_mgr_device);
@@ -175,6 +182,10 @@
   SCOPE_LOCK(locker_);
 
   CompManagerDevice *comp_mgr_device = reinterpret_cast<CompManagerDevice *>(device);
+  SET_BIT(configured_displays_, comp_mgr_device->device_type);
+  if (configured_displays_ == registered_displays_) {
+      safe_mode_ = false;
+  }
 
   res_mgr_.PostCommit(comp_mgr_device->res_mgr_device, hw_layers);
 }
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index e6954a8..55ec5d6 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -51,6 +51,7 @@
   virtual uint32_t GetDump(uint8_t *buffer, uint32_t length);
 
  private:
+  void PrepareStrategyConstraints(Handle device, HWLayers *hw_layers);
   struct CompManagerDevice {
     StrategyConstraints constraints;
     Handle res_mgr_device;
@@ -62,6 +63,11 @@
   StrategyInterface *strategy_intf_;
   StrategyDefault strategy_default_;
   ResManager res_mgr_;
+  uint64_t registered_displays_;        // Stores the bit mask of registered displays
+  uint64_t configured_displays_;        // Stores the bit mask of sucessfully configured displays
+  bool safe_mode_;                      // Flag to notify all displays to be in resource crunch
+                                        // mode, where strategy manager chooses the best strategy
+                                        // that uses optimal number of pipes for each display
 };
 
 }  // namespace sde