Merge "sdm: Allow draw cycle in doze state." into dev-1.0
diff --git a/sdm/include/core/sdm_types.h b/sdm/include/core/sdm_types.h
index 44985a9..af7a20b 100644
--- a/sdm/include/core/sdm_types.h
+++ b/sdm/include/core/sdm_types.h
@@ -41,6 +41,7 @@
   kErrorNone,             //!< Call executed successfully.
   kErrorUndefined,        //!< An unspecified error has occured.
   kErrorNotSupported,     //!< Requested operation is not supported.
+  kErrorPermission,       //!< Operation is not permitted in current state.
   kErrorVersion,          //!< Client is using advanced version of interfaces and calling into an
                           //!< older version of display library.
   kErrorDataAlignment,    //!< Client data structures are not aligned on naturual boundaries.
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 6107917..96e3fbf 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -175,57 +175,58 @@
     return error;
   }
 
-  if (state_ == kStateOn) {
-    if (color_mgr_) {
-      disable_partial_update = color_mgr_->NeedsPartialUpdateDisable();
-      if (disable_partial_update) {
-        ControlPartialUpdate(false, &pending);
+  if (!active_) {
+    return kErrorPermission;
+  }
+
+  if (color_mgr_) {
+    disable_partial_update = color_mgr_->NeedsPartialUpdateDisable();
+    if (disable_partial_update) {
+      ControlPartialUpdate(false, &pending);
+    }
+  }
+
+  // Clean hw layers for reuse.
+  hw_layers_.info = HWLayersInfo();
+  hw_layers_.info.stack = layer_stack;
+  hw_layers_.output_compression = 1.0f;
+
+  comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
+  while (true) {
+    error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
+    if (error != kErrorNone) {
+      break;
+    }
+
+    if (IsRotationRequired(&hw_layers_)) {
+      if (!rotator_intf_) {
+        continue;
+      }
+      error = rotator_intf_->Prepare(display_rotator_ctx_, &hw_layers_);
+    } else {
+      // Release all the previous rotator sessions.
+      if (rotator_intf_) {
+        error = rotator_intf_->Purge(display_rotator_ctx_);
       }
     }
 
-    // Clean hw layers for reuse.
-    hw_layers_.info = HWLayersInfo();
-    hw_layers_.info.stack = layer_stack;
-    hw_layers_.output_compression = 1.0f;
-
-    comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
-    while (true) {
-      error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
-      if (error != kErrorNone) {
+    if (error == kErrorNone) {
+      error = hw_intf_->Validate(&hw_layers_);
+      if (error == kErrorNone) {
+        // Strategy is successful now, wait for Commit().
+        pending_commit_ = true;
         break;
       }
-
-      if (IsRotationRequired(&hw_layers_)) {
-        if (!rotator_intf_) {
-          continue;
-        }
-        error = rotator_intf_->Prepare(display_rotator_ctx_, &hw_layers_);
-      } else {
-        // Release all the previous rotator sessions.
-        if (rotator_intf_) {
-          error = rotator_intf_->Purge(display_rotator_ctx_);
-        }
-      }
-
-      if (error == kErrorNone) {
-        error = hw_intf_->Validate(&hw_layers_);
-        if (error == kErrorNone) {
-          // Strategy is successful now, wait for Commit().
-          pending_commit_ = true;
-          break;
-        }
-        if (error == kErrorShutDown) {
-          comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
-          return error;
-        }
+      if (error == kErrorShutDown) {
+        comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+        return error;
       }
     }
-    comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
-    if (disable_partial_update) {
-      ControlPartialUpdate(true, &pending);
-    }
-  } else {
-    return kErrorNotSupported;
+  }
+
+  comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+  if (disable_partial_update) {
+    ControlPartialUpdate(true, &pending);
   }
 
   return error;
@@ -238,8 +239,8 @@
     return kErrorParameters;
   }
 
-  if (state_ != kStateOn) {
-    return kErrorNotSupported;
+  if (!active_) {
+    return kErrorPermission;
   }
 
   if (!pending_commit_) {
@@ -300,8 +301,8 @@
 DisplayError DisplayBase::Flush() {
   DisplayError error = kErrorNone;
 
-  if (state_ != kStateOn) {
-    return kErrorNone;
+  if (!active_) {
+    return kErrorPermission;
   }
 
   hw_layers_.info.count = 0;
@@ -369,6 +370,7 @@
 
 DisplayError DisplayBase::SetDisplayState(DisplayState state) {
   DisplayError error = kErrorNone;
+  bool active = false;
 
   DLOGI("Set state = %d, display %d", state, display_type_);
 
@@ -399,10 +401,12 @@
 
   case kStateOn:
     error = hw_intf_->PowerOn();
+    active = true;
     break;
 
   case kStateDoze:
     error = hw_intf_->Doze();
+    active = true;
     break;
 
   case kStateDozeSuspend:
@@ -419,6 +423,7 @@
   }
 
   if (error == kErrorNone) {
+    active_ = active;
     state_ = state;
   }
 
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 74d07d3..436af4f 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -92,6 +92,7 @@
   CompManager *comp_manager_ = NULL;
   RotatorInterface *rotator_intf_ = NULL;
   DisplayState state_ = kStateOff;
+  bool active_ = false;
   Handle hw_device_ = 0;
   Handle display_comp_ctx_ = 0;
   Handle display_rotator_ctx_ = 0;
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 63fe6b2..4936b9b 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -208,7 +208,7 @@
   DisplayError error = kErrorNone;
   HWDisplayMode hw_display_mode = kModeDefault;
 
-  if (state_ != kStateOn) {
+  if (!active_) {
     DLOGW("Invalid display state = %d. Panel must be on.", state_);
     return kErrorNotSupported;
   }
@@ -283,7 +283,7 @@
 DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
   SCOPE_LOCK(locker_);
 
-  if (state_ != kStateOn || !hw_panel_info_.dynamic_fps) {
+  if (!active_ || !hw_panel_info_.dynamic_fps) {
     return kErrorNotSupported;
   }
 
diff --git a/sdm/libs/core/fb/hw_virtual.cpp b/sdm/libs/core/fb/hw_virtual.cpp
index 033159f..27c979a 100644
--- a/sdm/libs/core/fb/hw_virtual.cpp
+++ b/sdm/libs/core/fb/hw_virtual.cpp
@@ -74,5 +74,9 @@
   return HWDevice::Validate(hw_layers);
 }
 
+DisplayError HWVirtual::Flush() {
+  return kErrorNone;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/fb/hw_virtual.h b/sdm/libs/core/fb/hw_virtual.h
index 2b740d5..c0591b3 100644
--- a/sdm/libs/core/fb/hw_virtual.h
+++ b/sdm/libs/core/fb/hw_virtual.h
@@ -39,6 +39,7 @@
   HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
   virtual DisplayError Init(HWEventHandler *eventhandler);
   virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError Flush();
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 1372ee6..50aae41 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -163,6 +163,7 @@
 int HWCDisplay::SetPowerMode(int mode) {
   DLOGI("display = %d, mode = %d", id_, mode);
   DisplayState state = kStateOff;
+  bool flush_on_error = flush_on_error_;
 
   if (shutdown_pending_) {
     return 0;
@@ -170,26 +171,35 @@
 
   switch (mode) {
   case HWC_POWER_MODE_OFF:
+    // During power off, all of the buffers are released.
+    // Do not flush until a buffer is successfully submitted again.
+    flush_on_error = false;
     state = kStateOff;
     break;
+
   case HWC_POWER_MODE_NORMAL:
     state = kStateOn;
     last_power_mode_ = HWC_POWER_MODE_NORMAL;
     break;
+
   case HWC_POWER_MODE_DOZE:
     state = kStateDoze;
     last_power_mode_ = HWC_POWER_MODE_DOZE;
     break;
+
   case HWC_POWER_MODE_DOZE_SUSPEND:
     state = kStateDozeSuspend;
     last_power_mode_ = HWC_POWER_MODE_DOZE_SUSPEND;
     break;
+
   default:
     return -EINVAL;
   }
 
   DisplayError error = display_intf_->SetDisplayState(state);
-  if (error != kErrorNone) {
+  if (error == kErrorNone) {
+    flush_on_error_ = flush_on_error;
+  } else {
     if (error == kErrorShutDown) {
       shutdown_pending_ = true;
       return 0;
@@ -593,6 +603,7 @@
   if (shutdown_pending_) {
     return 0;
   }
+
   size_t num_hw_layers = content_list->numHwLayers;
 
   if (!skip_prepare_) {
@@ -600,12 +611,12 @@
     if (error != kErrorNone) {
       if (error == kErrorShutDown) {
         shutdown_pending_ = true;
-        return 0;
+      } else if (error != kErrorPermission) {
+        DLOGE("Prepare failed. Error = %d", error);
+        // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+        // so that previous buffer and fences are released, and override the error.
+        flush_ = true;
       }
-      DLOGE("Prepare failed. Error = %d", error);
-      // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
-      // previous buffer and fences are released, and override the error.
-      flush_ = true;
 
       return 0;
     }
@@ -685,17 +696,18 @@
     }
 
     if (error == kErrorNone) {
-      // Do no call flush on errors, if a successful buffer is never submitted.
+      // A commit is successfully submitted, start flushing on failure now onwards.
       flush_on_error_ = true;
     } else {
       if (error == kErrorShutDown) {
         shutdown_pending_ = true;
         return status;
+      } else if (error != kErrorPermission) {
+        DLOGE("Commit failed. Error = %d", error);
+        // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+        // so that previous buffer and fences are released, and override the error.
+        flush_ = true;
       }
-      DLOGE("Commit failed. Error = %d", error);
-      // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
-      // previous buffer and fences are released, and override the error.
-      flush_ = true;
     }
   }
 
@@ -706,11 +718,9 @@
   size_t num_hw_layers = content_list->numHwLayers;
   int status = 0;
 
+  // Do no call flush on errors, if a successful buffer is never submitted.
   if (flush_ && flush_on_error_) {
-    DisplayError error = display_intf_->Flush();
-    if (error != kErrorNone) {
-      DLOGE("Flush failed. Error = %d", error);
-    }
+    display_intf_->Flush();
   }
 
   // Set the release fence fd to the blit engine
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 234477c..04d8849 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -187,7 +187,6 @@
   bool use_blit_comp_ = false;
   bool secure_display_active_ = false;
   bool skip_prepare_ = false;
-
   bool solid_fill_enable_ = false;
   uint32_t solid_fill_color_ = 0;
   LayerRect display_rect_;
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
old mode 100644
new mode 100755
index 99c903c..28582f1
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -92,12 +92,6 @@
     return status;
   }
 
-  size_t num_hw_layers = content_list->numHwLayers;
-  if (num_hw_layers <= 1) {
-    flush_ = true;
-    return 0;
-  }
-
   status = PrePrepareLayerStack(content_list);
   if (status) {
     return status;
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
old mode 100644
new mode 100755
index 416e390..fb134a9
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -127,12 +127,6 @@
     return status;
   }
 
-  size_t num_hw_layers = content_list->numHwLayers;
-  if (num_hw_layers <= 1) {
-    flush_ = true;
-    return 0;
-  }
-
   status = PrePrepareLayerStack(content_list);
   if (status) {
     return status;