sdm: handle commit failures during shutdown

Handle display commit failures during shutdown. During shutdown
process, SurfaceFlinger doesn't get this information apriori.
Display HAL continues to invoke validate and commit ioctls.
Driver rejects these calls with -ESHUTDOWN failure signature.
Transition display device state to kDisplayStatusOffline for
kErrorShutdown failure.

CRs-Fixed: 828516
Change-Id: I0cee2db7dc57806b5f2fc09a6d2515f5158251e8
diff --git a/sdm/include/core/sdm_types.h b/sdm/include/core/sdm_types.h
index 45c98ef..44985a9 100644
--- a/sdm/include/core/sdm_types.h
+++ b/sdm/include/core/sdm_types.h
@@ -51,6 +51,7 @@
   kErrorResources,        //!< Not enough hardware resources available to execute call.
   kErrorHardware,         //!< A hardware error has occured.
   kErrorTimeOut,          //!< The operation has timed out to prevent client from waiting forever.
+  kErrorShutDown,         //!< Driver is processing shutdown sequence
 };
 
 /*! @brief This structure is defined for client and library compatibility check purpose only. This
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index d18f53c..5d83843 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -186,6 +186,10 @@
           pending_commit_ = true;
           break;
         }
+        if (error == kErrorShutDown) {
+          comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+          return error;
+        }
       }
     }
     comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 0535a44..9d08323 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -129,6 +129,10 @@
   DTRACE_SCOPED();
 
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
     IOCTL_LOGE(FB_BLANK_UNBLANK, device_type_);
     return kErrorHardware;
   }
@@ -282,6 +286,10 @@
 
   mdp_commit.flags |= MDP_VALIDATE_LAYER;
   if (Sys::ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
     DumpLayerCommit(mdp_disp_commit_);
     return kErrorHardware;
@@ -398,6 +406,10 @@
     mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH;
   }
   if (Sys::ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
     DumpLayerCommit(mdp_disp_commit_);
     synchronous_commit_ = false;
@@ -449,6 +461,10 @@
 
   mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
   if (Sys::ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
     DumpLayerCommit(mdp_disp_commit_);
     return kErrorHardware;
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index d8eb251..3416d1b 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -49,7 +49,8 @@
     display_intf_(NULL), flush_(false), dump_frame_count_(0), dump_frame_index_(0),
     dump_input_layers_(false), swap_interval_zero_(false), framebuffer_config_(NULL),
     display_paused_(false), use_metadata_refresh_rate_(false), metadata_refresh_rate_(0),
-    boot_animation_completed_(false), use_blit_comp_(false), blit_engine_(NULL) {
+    boot_animation_completed_(false), shutdown_pending_(false),  use_blit_comp_(false),
+    blit_engine_(NULL) {
 }
 
 int HWCDisplay::Init() {
@@ -116,6 +117,10 @@
 int HWCDisplay::EventControl(int event, int enable) {
   DisplayError error = kErrorNone;
 
+  if (shutdown_pending_) {
+    return 0;
+  }
+
   switch (event) {
   case HWC_EVENT_VSYNC:
     error = display_intf_->SetVSyncState(enable);
@@ -128,6 +133,10 @@
   }
 
   if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return 0;
+    }
     DLOGE("Failed. event = %d, enable = %d, error = %d", event, enable, error);
     return -EINVAL;
   }
@@ -139,6 +148,10 @@
   DLOGI("display = %d, mode = %d", id_, mode);
   DisplayState state = kStateOff;
 
+  if (shutdown_pending_) {
+    return 0;
+  }
+
   switch (mode) {
   case HWC_POWER_MODE_OFF:
     state = kStateOff;
@@ -161,6 +174,10 @@
 
   DisplayError error = display_intf_->SetDisplayState(state);
   if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return 0;
+    }
     DLOGE("Set state failed. Error = %d", error);
     return -EINVAL;
   }
@@ -237,8 +254,16 @@
 int HWCDisplay::SetActiveConfig(int index) {
   DisplayError error = kErrorNone;
 
+  if (shutdown_pending_) {
+    return 0;
+  }
+
   error = display_intf_->SetActiveConfig(index);
   if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return 0;
+    }
     DLOGE("SetActiveConfig failed. Error = %d", error);
     return -1;
   }
@@ -453,6 +478,10 @@
 }
 
 int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
+  if (shutdown_pending_) {
+    return 0;
+  }
+
   if (!content_list || !content_list->numHwLayers) {
     DLOGW("Invalid content list");
     return -EINVAL;
@@ -538,6 +567,10 @@
 
   DisplayError error = display_intf_->Prepare(&layer_stack_);
   if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return 0;
+    }
     DLOGE("Prepare failed. Error = %d", error);
 
     // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
@@ -586,6 +619,10 @@
     return -EINVAL;
   }
 
+  if (shutdown_pending_) {
+    return 0;
+  }
+
   int status = 0;
 
   size_t num_hw_layers = content_list->numHwLayers;
@@ -613,6 +650,10 @@
       status = 0;
     }
     if (error != kErrorNone) {
+      if (error == kErrorShutDown) {
+        shutdown_pending_ = true;
+        return status;
+      }
       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.
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 8882613..87f3c6a 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -149,6 +149,7 @@
   bool use_metadata_refresh_rate_;
   uint32_t metadata_refresh_rate_;
   bool boot_animation_completed_;
+  bool shutdown_pending_;
 
  private:
   bool IsFrameBufferScaled();