Merge "hwc: hdmi: Use res_info sysfs node to get HDMI timing info"
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index bdeb8a3..ff99cb8 100755
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -207,6 +207,19 @@
   */
   virtual DisplayError Commit(LayerStack *layer_stack) = 0;
 
+  /*! @brief Method to flush any pending buffers/fences submitted previously via Commit() call.
+
+    @details Client shall call this method to request the Display Engine to release all buffers and
+    respective fences currently in use. This operation may result in a blank display on the panel
+    until a new frame is submitted for composition.
+
+    @return \link DisplayError \endlink
+
+    @sa Prepare
+    @sa Commit
+  */
+  virtual DisplayError Flush() = 0;
+
   /*! @brief Method to get current state of the display device.
 
     @param[out] state \link DisplayState \endlink
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
index c069c60..51fa5c5 100755
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -87,6 +87,15 @@
                                       //!< factor of 2
                                       //!<    u(0), y(0), v(0), y(1), u(2), y(2), v(2), y(3)
                                       //!<    u(n-1), y(n-1), v(n-1), y(n)
+
+  /* All UBWC aligned formats. Any new format will be added towards end of this group to maintain
+     backward compatibility.
+  */
+  kFormatRGBA8888Ubwc = 0x400,        //!< UBWC aligned RGBA8888 format
+
+  kFormatRGB565Ubwc,                  //!< UBWC aligned RGB565 format
+
+  kFormatYCbCr420SPVenusUbwc,         //!< UBWC aligned Venus NV12 format
 };
 
 /*! @brief This structure defines a color sample plane belonging to a buffer format. RGB buffer
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 080deb7..4d8f5aa 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -135,6 +135,8 @@
       }
     }
     comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+  } else {
+    return kErrorNotSupported;
   }
 
   return error;
@@ -149,18 +151,19 @@
     return kErrorParameters;
   }
 
-  if (!pending_commit_) {
-    DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
-    return kErrorUndefined;
-  }
-
   if (state_ == kStateOn) {
+    if (!pending_commit_) {
+      DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+      return kErrorUndefined;
+    }
     error = hw_intf_->Commit(hw_device_, &hw_layers_);
     if (error == kErrorNone) {
       comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
     } else {
       DLOGE("Unexpected error. Commit failed on driver.");
     }
+  } else {
+    return kErrorNotSupported;
   }
 
   pending_commit_ = false;
@@ -168,6 +171,27 @@
   return kErrorNone;
 }
 
+DisplayError DisplayBase::Flush() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  if (state_ != kStateOn) {
+    return kErrorNone;
+  }
+
+  hw_layers_.info.count = 0;
+  error = hw_intf_->Flush(hw_device_);
+  if (error == kErrorNone) {
+    comp_manager_->Purge(display_comp_ctx_);
+    pending_commit_ = false;
+  } else {
+    DLOGV("Failed to flush device.");
+  }
+
+  return error;
+}
+
 DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
   SCOPE_LOCK(locker_);
 
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 3f0e24f..187ab8d 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -43,6 +43,7 @@
   virtual DisplayError Deinit();
   virtual DisplayError Prepare(LayerStack *layer_stack);
   virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 14a09f1..07bbca0 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -77,5 +77,29 @@
   return best_config_mode;
 }
 
+DisplayError DisplayHDMI::SetDisplayState(DisplayState state) {
+  DisplayError error = kErrorNone;
+
+  DLOGI("Set state = %d", state);
+
+  if (state == kStateOff) {
+    SCOPE_LOCK(locker_);
+    if (state == state_) {
+      DLOGI("Same state transition is requested.");
+      return kErrorNone;
+    }
+    error = hw_intf_->Flush(hw_device_);
+    if (error == kErrorNone) {
+      comp_manager_->Purge(display_comp_ctx_);
+      state_ = state;
+      hw_layers_.info.count = 0;
+    }
+  } else {
+    error = DisplayBase::SetDisplayState(state);
+  }
+
+  return error;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 0bb9dc8..8de7fdf 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -33,6 +33,7 @@
  public:
   DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
   virtual int GetBestConfig();
+  virtual DisplayError SetDisplayState(DisplayState state);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 38320a4..45d9b60 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -392,17 +392,19 @@
           break;
         }
       }
+
       if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
         return kErrorParameters;
       }
+
       STRUCT_VAR(msmfb_metadata, metadata);
-      memset(&metadata, 0 , sizeof(metadata));
       metadata.op = metadata_op_vic;
       metadata.data.video_info_code = timing_mode->video_format;
       if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) == -1) {
         IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
         return kErrorHardware;
       }
+
       DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
             vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
             vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
@@ -476,19 +478,6 @@
       return kErrorHardware;
     }
     break;
-  case kDeviceHDMI:
-    {
-      hw_context->ResetMDPCommit();
-      mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
-      mdp_commit.input_layer_cnt = 0;
-      mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
-      if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
-        IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
-        return kErrorHardware;
-      }
-    }
-    break;
-  case kDeviceVirtual:
   default:
     break;
   }
@@ -638,6 +627,22 @@
   return kErrorNone;
 }
 
+DisplayError HWFrameBuffer::Flush(Handle device) {
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+
+  hw_context->ResetMDPCommit();
+  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+  mdp_commit.input_layer_cnt = 0;
+  mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
 DisplayError HWFrameBuffer::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
   switch (source) {
   case kFormatARGB8888:                 *target = MDP_ARGB_8888;         break;
@@ -653,6 +658,9 @@
   case kFormatYCrCb420SemiPlanar:       *target = MDP_Y_CRCB_H2V2;       break;
   case kFormatYCbCr422Packed:           *target = MDP_YCBYCR_H2V1;       break;
   case kFormatYCbCr420SemiPlanarVenus:  *target = MDP_Y_CBCR_H2V2_VENUS; break;
+  case kFormatRGBA8888Ubwc:             *target = MDP_RGBA_8888_UBWC;    break;
+  case kFormatRGB565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
+  case kFormatYCbCr420SPVenusUbwc:      *target = MDP_Y_CBCR_H2V2_UBWC;  break;
   default:
     DLOGE("Unsupported format type %d", source);
     return kErrorParameters;
@@ -779,16 +787,16 @@
     // TODO(user): For now, assume primary to be cmd/video/lvds/edp mode panel only
     // Need more concrete info from driver
     if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
-      pri_panel_info_.type = kCommandModePanel;
+      primary_panel_info_.type = kCommandModePanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0))  {
-      pri_panel_info_.type = kVideoModePanel;
+      primary_panel_info_.type = kVideoModePanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
-      pri_panel_info_.type = kLVDSPanel;
+      primary_panel_info_.type = kLVDSPanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
-      pri_panel_info_.type = kEDPPanel;
+      primary_panel_info_.type = kEDPPanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
       fb_node_index_[kDeviceHDMI] = i;
@@ -820,27 +828,27 @@
     char *tokens[max_count] = { NULL };
     if (!ParseLine(line, tokens, max_count, &token_count)) {
       if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
-        pri_panel_info_.partial_update = atoi(tokens[1]);
+        primary_panel_info_.partial_update = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
-        pri_panel_info_.left_align = atoi(tokens[1]);
+        primary_panel_info_.left_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
-        pri_panel_info_.width_align = atoi(tokens[1]);
+        primary_panel_info_.width_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
-        pri_panel_info_.top_align = atoi(tokens[1]);
+        primary_panel_info_.top_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
-        pri_panel_info_.height_align = atoi(tokens[1]);
+        primary_panel_info_.height_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
-        pri_panel_info_.min_roi_width = atoi(tokens[1]);
+        primary_panel_info_.min_roi_width = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
-        pri_panel_info_.min_roi_height = atoi(tokens[1]);
+        primary_panel_info_.min_roi_height = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
-        pri_panel_info_.needs_roi_merge = atoi(tokens[1]);
+        primary_panel_info_.needs_roi_merge = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "dynamic_fps_en", strlen("dyn_fps_en"))) {
-        pri_panel_info_.dynamic_fps = atoi(tokens[1]);
+        primary_panel_info_.dynamic_fps = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
-        pri_panel_info_.min_fps = atoi(tokens[1]);
+        primary_panel_info_.min_fps = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
-        pri_panel_info_.max_fps= atoi(tokens[1]);
+        primary_panel_info_.max_fps= atoi(tokens[1]);
       }
     }
   }
@@ -1074,3 +1082,4 @@
 }
 
 }  // namespace sde
+
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 2fe5078..d9c3a47 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -58,6 +58,7 @@
   virtual DisplayError Standby(Handle device);
   virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
   virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
+  virtual DisplayError Flush(Handle device);
 
  private:
   struct HWContext {
@@ -141,7 +142,6 @@
   bool EnableHotPlugDetection(int enable);
   int GetHDMIModeCount();
   bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
-  void ResetHDMIModes();
 
   // Pointers to system calls which are either mapped to actual system call or virtual driver.
   int (*ioctl_)(int, int, ...);
@@ -166,7 +166,7 @@
   HWResourceInfo hw_resource_;
   int fb_node_index_[kDeviceMax];
   const char* fb_path_;
-  PanelInfo pri_panel_info_;
+  PanelInfo primary_panel_info_;
   bool hotplug_enabled_;
   uint32_t hdmi_mode_count_;
   uint32_t hdmi_modes_[256];
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index c8611f9..29a1905 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -169,6 +169,7 @@
   virtual DisplayError Standby(Handle device) = 0;
   virtual DisplayError Validate(Handle device, HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(Handle device, HWLayers *hw_layers) = 0;
+  virtual DisplayError Flush(Handle device) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 1fc1598..0c8859f 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -47,9 +47,16 @@
   rotate->downscale_ratio_y = scale_y;
 
   // downscale when doing rotation
-  dst_rect.right = src_height / rotate->downscale_ratio_x;
-  dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+  if (IsRotationNeeded(transform.rotation)) {
+    dst_rect.right = src_height / rotate->downscale_ratio_x;
+    dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+  } else {
+    dst_rect.right = src_width / rotate->downscale_ratio_x;
+    dst_rect.bottom = src_height / rotate->downscale_ratio_y;
+  }
 
+  dst_rect.right = floorf(dst_rect.right);
+  dst_rect.bottom = floorf(dst_rect.bottom);
   rotate->src_roi = *src_rect;
   rotate->pipe_id = kPipeIdNeedsAssignment;
   rotate->dst_roi = dst_rect;
@@ -67,8 +74,8 @@
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
   layer_config->is_right_pipe = false;
 
-  if ((src_rect.right - src_rect.left) >= kMaxSourcePipeWidth ||
-      (dst_rect.right - dst_rect.left) >= kMaxInterfaceWidth || hw_res_info_.always_src_split) {
+  if ((src_rect.right - src_rect.left) > kMaxSourcePipeWidth ||
+      (dst_rect.right - dst_rect.left) > kMaxInterfaceWidth || hw_res_info_.always_src_split) {
     SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
     left_pipe->pipe_id = kPipeIdNeedsAssignment;
@@ -107,18 +114,24 @@
   scissor.right = FLOAT(display_attributes.x_pixels);
   scissor.bottom = FLOAT(display_attributes.y_pixels);
   CalculateCropRects(scissor, transform, &crop_right, &dst_right);
-  if ((crop_left.right - crop_left.left) >= kMaxSourcePipeWidth) {
-    if (crop_right.right != crop_right.left)
+  if ((crop_left.right - crop_left.left) > kMaxSourcePipeWidth) {
+    if (crop_right.right != crop_right.left) {
+      DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
+               crop_left.right - crop_left.left, crop_right.right - crop_right.left);
       return kErrorNotSupported;
+    }
     // 2 pipes both are on the left
     SplitRect(transform.flip_horizontal, crop_left, dst_left, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
     left_pipe->pipe_id = kPipeIdNeedsAssignment;
     right_pipe->pipe_id = kPipeIdNeedsAssignment;
     layer_config->is_right_pipe = true;
-  } else if ((crop_right.right - crop_right.left) >= kMaxSourcePipeWidth) {
-    if (crop_left.right != crop_left.left)
+  } else if ((crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
+    if (crop_left.right != crop_left.left) {
+      DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
+               crop_left.right - crop_left.left, crop_right.right - crop_right.left);
       return kErrorNotSupported;
+    }
     // 2 pipes both are on the right
     SplitRect(transform.flip_horizontal, crop_right, dst_right, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
@@ -168,7 +181,7 @@
     Layer& layer = layer_info.stack->layers[layer_info.index[i]];
     float rot_scale_x = 1.0f, rot_scale_y = 1.0f;
     if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
-      DLOGE_IF(kTagResources, "Input is invalid");
+      DLOGV_IF(kTagResources, "Input is invalid");
       LogRectVerbose("input layer src_rect", layer.src_rect);
       LogRectVerbose("input layer dst_rect", layer.dst_rect);
       return kErrorNotSupported;
@@ -231,6 +244,12 @@
              i, layer_config->left_pipe.pipe_id);
     LogRectVerbose("input layer src_rect", layer.src_rect);
     LogRectVerbose("input layer dst_rect", layer.dst_rect);
+    for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
+      DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f, scale_y = %.2f",
+               k, rot_scale_x, rot_scale_y);
+      LogRectVerbose("rotate src", layer_config->rotates[k].src_roi);
+      LogRectVerbose("rotate dst", layer_config->rotates[k].dst_roi);
+    }
     LogRectVerbose("cropped src_rect", src_rect);
     LogRectVerbose("cropped dst_rect", dst_rect);
     LogRectVerbose("left pipe src", layer_config->left_pipe.src_roi);
@@ -414,7 +433,7 @@
       src.top - roundf(src.top)       ||
       src.right - roundf(src.right)   ||
       src.bottom - roundf(src.bottom)) {
-    DLOGE_IF(kTagResources, "Input ROI is not integral");
+    DLOGV_IF(kTagResources, "Input ROI is not integral");
     return false;
   }
 
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 12ef5bd..e3fbdda 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -775,13 +775,23 @@
 void ResManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
   AppendString(buffer, length, "\nresource manager pipe state");
-  for (uint32_t i = 0; i < num_pipe_; i++) {
+  uint32_t i;
+  for (i = 0; i < num_pipe_; i++) {
     SourcePipe *src_pipe = &src_pipes_[i];
     AppendString(buffer, length,
                  "\nindex = %d, id = %x, reserved = %d, state = %d, hw_block = %d, dedicated = %d",
                  src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->reserved_hw_block,
                  src_pipe->state, src_pipe->hw_block_id, src_pipe->dedicated_hw_block);
   }
+
+  for (i = 0; i < hw_res_info_.num_rotator; i++) {
+    if (rotators_[i].client_bit_mask || rotators_[i].request_bit_mask) {
+      AppendString(buffer, length,
+                   "\nrotator = %d, pipe index = %x, client_bit_mask = %x, request_bit_mask = %x",
+                   i, rotators_[i].pipe_index, rotators_[i].client_bit_mask,
+                   rotators_[i].request_bit_mask);
+    }
+  }
 }
 
 DisplayError ResManager::AcquireRotator(DisplayResourceContext *display_resource_ctx,
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index bf54a8a..acddd59 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -35,7 +35,8 @@
 
 HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
                        int id)
-  : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL) {
+  : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
+    flush_(false) {
 }
 
 int HWCDisplay::Init() {
@@ -282,6 +283,7 @@
 
   size_t num_hw_layers = content_list->numHwLayers;
   if (num_hw_layers <= 1) {
+    flush_ = true;
     return 0;
   }
 
@@ -294,7 +296,7 @@
     LayerBuffer *layer_buffer = layer.input_buffer;
 
     if (pvt_handle) {
-      if (SetFormat(pvt_handle->format, &layer_buffer->format)) {
+      if (SetFormat(pvt_handle->format, pvt_handle->flags, &layer_buffer->format)) {
         return -EINVAL;
       }
 
@@ -338,9 +340,14 @@
   layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
 
   DisplayError error = display_intf_->Prepare(&layer_stack_);
-  if (UNLIKELY(error != kErrorNone)) {
+  if (error != kErrorNone) {
     DLOGE("Prepare failed. Error = %d", error);
-    return -EINVAL;
+
+    // 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;
   }
 
   bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
@@ -378,38 +385,39 @@
   int status = 0;
 
   size_t num_hw_layers = content_list->numHwLayers;
-  if (num_hw_layers <= 1) {
-    if (!num_hw_layers) {
-      return 0;
+
+  if (!flush_) {
+    for (size_t i = 0; i < num_hw_layers; i++) {
+      hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+      const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+      LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+
+      if (pvt_handle) {
+        layer_buffer->planes[0].fd = pvt_handle->fd;
+        layer_buffer->planes[0].offset = pvt_handle->offset;
+        layer_buffer->planes[0].stride = pvt_handle->width;
+      }
+
+      layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
     }
 
-    // TODO(user): handle if only 1 layer(fb target) is received.
-    int &acquireFenceFd = content_list->hwLayers[0].acquireFenceFd;
-    if (acquireFenceFd >= 0) {
-      close(acquireFenceFd);
-    }
+    DisplayError error = display_intf_->Commit(&layer_stack_);
+    if (error != kErrorNone) {
+      DLOGE("Commit failed. Error = %d", error);
 
-    return 0;
+      // 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;
+    }
   }
 
-  for (size_t i = 0; i < num_hw_layers; i++) {
-    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
-    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
-    LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
-
-    if (pvt_handle) {
-      layer_buffer->planes[0].fd = pvt_handle->fd;
-      layer_buffer->planes[0].offset = pvt_handle->offset;
-      layer_buffer->planes[0].stride = pvt_handle->width;
+  if (flush_) {
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
     }
 
-    layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
-  }
-
-  DisplayError error = display_intf_->Commit(&layer_stack_);
-  if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Commit failed. Error = %d", error);
-    status = -EINVAL;
+    flush_ = false;
   }
 
   for (size_t i = 0; i < num_hw_layers; i++) {
@@ -518,7 +526,22 @@
   }
 }
 
-int HWCDisplay::SetFormat(const int32_t &source, LayerBufferFormat *target) {
+int HWCDisplay::SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target) {
+
+  if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+    switch (source) {
+      case HAL_PIXEL_FORMAT_RGBA_8888:          *target = kFormatRGBA8888Ubwc;            break;
+      case HAL_PIXEL_FORMAT_RGB_565:            *target = kFormatRGB565Ubwc;              break;
+      case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+      case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+      case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:    *target = kFormatYCbCr420SPVenusUbwc;     break;
+      default:
+        DLOGE("Unsupported format type for UBWC %d", source);
+        return -EINVAL;
+    }
+    return 0;
+  }
+
   switch (source) {
   case HAL_PIXEL_FORMAT_RGBA_8888:            *target = kFormatRGBA8888;                  break;
   case HAL_PIXEL_FORMAT_BGRA_8888:            *target = kFormatBGRA8888;                  break;
@@ -527,6 +550,7 @@
   case HAL_PIXEL_FORMAT_RGB_888:              *target = kFormatRGB888;                    break;
   case HAL_PIXEL_FORMAT_RGB_565:              *target = kFormatRGB565;                    break;
   case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:   *target = kFormatYCbCr420SemiPlanarVenus;   break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:  *target = kFormatYCbCr420SPVenusUbwc;   break;
   default:
     DLOGW("Unsupported format type = %d", source);
     return -EINVAL;
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 0ba9ca7..b396328 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -87,7 +87,7 @@
   inline void SetComposition(const int32_t &source, LayerComposition *target);
   inline void SetComposition(const int32_t &source, int32_t *target);
   inline void SetBlending(const int32_t &source, LayerBlending *target);
-  inline int SetFormat(const int32_t &source, LayerBufferFormat *target);
+  inline int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
 
   CoreInterface *core_intf_;
   hwc_procs_t const **hwc_procs_;
@@ -97,6 +97,7 @@
   LayerStackMemory layer_stack_memory_;
   LayerStack layer_stack_;
   LayerStackCache layer_stack_cache_;
+  bool flush_;
 };
 
 }  // namespace sde