Merge "sdm: Remove comparison functions from HWSessionConfig"
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index e6693c9..1b59fde 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -183,6 +183,7 @@
         case HAL_PIXEL_FORMAT_RGBX_8888:
         case HAL_PIXEL_FORMAT_RGB_888:
         case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
         case HAL_PIXEL_FORMAT_BGRA_8888:
         case HAL_PIXEL_FORMAT_RGBA_5551:
         case HAL_PIXEL_FORMAT_RGBA_4444:
@@ -330,6 +331,7 @@
             bpp = 3;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
         case HAL_PIXEL_FORMAT_RGBA_5551:
         case HAL_PIXEL_FORMAT_RGBA_4444:
             bpp = 2;
@@ -382,6 +384,8 @@
             return ADRENO_PIXELFORMAT_R8G8B8X8;
         case HAL_PIXEL_FORMAT_RGB_565:
             return ADRENO_PIXELFORMAT_B5G6R5;
+        case HAL_PIXEL_FORMAT_BGR_565:
+            return ADRENO_PIXELFORMAT_R5G6B5;
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
             return ADRENO_PIXELFORMAT_NV12;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
@@ -511,6 +515,7 @@
             case  HAL_PIXEL_FORMAT_RGBX_8888:
             case  HAL_PIXEL_FORMAT_BGRA_8888:
             case  HAL_PIXEL_FORMAT_RGB_565:
+            case  HAL_PIXEL_FORMAT_BGR_565:
                 {
                     tileEnabled = true;
                     // check the usage flags
@@ -547,6 +552,7 @@
             size = alignedw * alignedh * 3;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
         case HAL_PIXEL_FORMAT_RGBA_5551:
         case HAL_PIXEL_FORMAT_RGBA_4444:
         case HAL_PIXEL_FORMAT_RAW16:
@@ -879,7 +885,7 @@
     // Existing HAL formats with UBWC support
     switch(format)
     {
-        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
@@ -988,7 +994,7 @@
 
     unsigned int size = 0;
     switch (format) {
-        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
             size = alignedw * alignedh * 2;
             size += getUBwcMetaBufferSize(width, height, 2);
             break;
@@ -1014,7 +1020,7 @@
     int err = 0;
 
     // This api is for RGB* formats
-    if (hnd->format > HAL_PIXEL_FORMAT_BGRA_8888) {
+    if (!isUncompressedRgbFormat(hnd->format)) {
         return -EINVAL;
     }
 
@@ -1026,7 +1032,7 @@
 
     unsigned int meta_size = 0;
     switch (hnd->format) {
-        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
             meta_size = getUBwcMetaBufferSize(hnd->width, hnd->height, 2);
             break;
         case HAL_PIXEL_FORMAT_RGBA_8888:
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9788614..8b512bf 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -95,6 +95,9 @@
         if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
             flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
         }
+        if (usage & GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY) {
+            flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY;
+        }
 
         ColorSpace_t colorSpace = ITU_R_601;
         flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
@@ -287,11 +290,20 @@
             grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21 ZSL
         else if(usage & GRALLOC_USAGE_HW_CAMERA_READ)
             grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
-        else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
-            grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
-        else if(usage & GRALLOC_USAGE_HW_COMPOSER)
+        else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+           if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+               grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21
+           } else {
+               grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; //NV12 preview
+           }
+        } else if(usage & GRALLOC_USAGE_HW_COMPOSER)
             //XXX: If we still haven't set a format, default to RGBA8888
             grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+        else if(format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+            //If no other usage flags are detected, default the
+            //flexible YUV format to NV21_ZSL
+            grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL;
+        }
     }
 
     bool useFbMem = false;
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 2601953..1438546 100755
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -105,6 +105,7 @@
 #define HAL_PIXEL_FORMAT_BGRX_8888               0x112
 #define HAL_PIXEL_FORMAT_NV21_ZSL                0x113
 #define HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS      0x114
+#define HAL_PIXEL_FORMAT_BGR_565                 0x115
 #define HAL_PIXEL_FORMAT_INTERLACE               0x180
 
 //v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
@@ -172,6 +173,7 @@
             PRIV_FLAGS_USES_ION           = 0x00000008,
             PRIV_FLAGS_USES_ASHMEM        = 0x00000010,
             PRIV_FLAGS_NEEDS_FLUSH        = 0x00000020,
+            PRIV_FLAGS_INTERNAL_ONLY      = 0x00000040,
             PRIV_FLAGS_NON_CPU_WRITER     = 0x00000080,
             PRIV_FLAGS_NONCONTIGUOUS_MEM  = 0x00000100,
             PRIV_FLAGS_CACHED             = 0x00000200,
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 8e3fa78..101e230 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -49,6 +49,7 @@
 enum {
     DISPLAY_PRIMARY = 0,
     DISPLAY_EXTERNAL,
+    DISPLAY_TERTIARY,
     DISPLAY_VIRTUAL,
 };
 
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index 524a84b..5d48a04 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -54,9 +54,10 @@
   kFormatRGB888,        //!< 8-bits Red, Green, Blue interleaved in RGB order. No Alpha.
   kFormatBGR888,        //!< 8-bits Blue, Green, Red interleaved in BGR order. No Alpha.
   kFormatRGB565,        //!< 5-bit Red, 6-bit Green, 5-bit Blue interleaved in RGB order. No Alpha.
+  kFormatBGR565,        //!< 5-bit Blue, 6-bit Green, 5-bit Red interleaved in BGR order. No Alpha.
   kFormatRGBA8888Ubwc,  //!< UBWC aligned RGBA8888 format
   kFormatRGBX8888Ubwc,  //!< UBWC aligned RGBX8888 format
-  kFormatRGB565Ubwc,    //!< UBWC aligned RGB565 format
+  kFormatBGR565Ubwc,    //!< UBWC aligned BGR565 format
 
   /* All YUV-Planar formats, Any new format will be added towards end of this group to maintain
      backward compatibility.
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index e36f8e5..a34d84c 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -387,36 +387,10 @@
 
   // Once all features are consumed, destroy/release all TFeatureInfo<T> on the list,
   // then clear dirty_ flag and return the lock to the TFeatureInfo<T> producer.
-  inline void Reset() {
-    for (int i = 0; i < kMaxNumPPFeatures; i++) {
-      if (feature_[i]) {
-        delete feature_[i];
-        feature_[i] = NULL;
-      }
-    }
-    dirty_ = false;
-    next_idx_ = 0;
-  }
+  void Reset();
 
   // Consumer to call this to retrieve all the TFeatureInfo<T> on the list to be programmed.
-  inline DisplayError RetrieveNextFeature(PPFeatureInfo **feature) {
-    DisplayError ret = kErrorNone;
-    int i(0);
-
-    for (i = next_idx_; i < kMaxNumPPFeatures; i++) {
-      if (feature_[i]) {
-        *feature = feature_[i];
-        next_idx_ = i + 1;
-        break;
-      }
-    }
-    if (i == kMaxNumPPFeatures) {
-      ret = kErrorParameters;
-      next_idx_ = 0;
-    }
-
-    return ret;
-  }
+  DisplayError RetrieveNextFeature(PPFeatureInfo **feature);
 
   inline bool IsDirty() { return dirty_; }
   inline void MarkAsDirty() { dirty_ = true; }
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 5a4bdea..37d1f17 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -108,11 +108,9 @@
 struct HWSplitInfo {
   uint32_t left_split = 0;
   uint32_t right_split = 0;
-  bool always_src_split = false;
 
   bool operator !=(const HWSplitInfo &split_info) {
-    return ((left_split != split_info.left_split) || (right_split != split_info.right_split) ||
-            (always_src_split != split_info.always_src_split));
+    return ((left_split != split_info.left_split) || (right_split != split_info.right_split));
   }
 
   bool operator ==(const HWSplitInfo &split_info) {
@@ -271,7 +269,6 @@
 struct HWDisplayAttributes : DisplayConfigVariableInfo {
   bool is_device_split = false;
   uint32_t split_left = 0;
-  bool always_src_split = false;
   uint32_t v_front_porch = 0;  //!< Vertical front porch of panel
   uint32_t v_back_porch = 0;   //!< Vertical back porch of panel
   uint32_t v_pulse_width = 0;  //!< Vertical pulse width of panel
@@ -282,7 +279,6 @@
   bool operator !=(const HWDisplayAttributes &attributes) {
     return ((is_device_split != attributes.is_device_split) ||
             (split_left != attributes.split_left) ||
-            (always_src_split != attributes.always_src_split) ||
             (x_pixels != attributes.x_pixels) || (y_pixels != attributes.y_pixels) ||
             (x_dpi != attributes.x_dpi) || (y_dpi != attributes.y_dpi) || (fps != attributes.fps) ||
             (vsync_period_ns != attributes.vsync_period_ns) ||
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 95efef6..c8a3a98 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -47,6 +47,7 @@
 #define DLOGE(format, ...) DLOGE_IF(kTagNone, format, ##__VA_ARGS__)
 #define DLOGW(format, ...) DLOGW_IF(kTagNone, format, ##__VA_ARGS__)
 #define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)
 
 #define DTRACE_BEGIN(custom_string) Debug::Get()->BeginTrace(__CLASS__, __FUNCTION__, custom_string)
 #define DTRACE_END() Debug::Get()->EndTrace()
diff --git a/sdm/include/utils/sys.h b/sdm/include/utils/sys.h
index 0a90fc1..dc45696 100644
--- a/sdm/include/utils/sys.h
+++ b/sdm/include/utils/sys.h
@@ -45,6 +45,7 @@
   typedef int (*fclose)(FILE* fileptr);
   typedef ssize_t (*getline)(char **lineptr, size_t *linelen, FILE *stream);
   typedef int (*pthread_cancel)(pthread_t thread);
+  typedef int (*dup)(int fd);
 
   static ioctl ioctl_;
   static open open_;
@@ -56,6 +57,7 @@
   static fclose fclose_;
   static getline getline_;
   static pthread_cancel pthread_cancel_;
+  static dup dup_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp
index 0de2078..aea55b0 100644
--- a/sdm/libs/core/color_manager.cpp
+++ b/sdm/libs/core/color_manager.cpp
@@ -42,6 +42,39 @@
 DestroyColorInterface ColorManagerProxy::destroy_intf_ = NULL;
 HWResourceInfo ColorManagerProxy::hw_res_info_;
 
+// Below two functions are part of concrete implementation for SDM core private
+// color_params.h
+void PPFeaturesConfig::Reset() {
+  for (int i = 0; i < kMaxNumPPFeatures; i++) {
+    if (feature_[i]) {
+      delete feature_[i];
+      feature_[i] = NULL;
+    }
+  }
+  dirty_ = false;
+  next_idx_ = 0;
+}
+
+DisplayError PPFeaturesConfig::RetrieveNextFeature(PPFeatureInfo **feature) {
+  DisplayError ret = kErrorNone;
+  int i(0);
+
+  for (i = next_idx_; i < kMaxNumPPFeatures; i++) {
+    if (feature_[i]) {
+      *feature = feature_[i];
+      next_idx_ = i + 1;
+      break;
+    }
+  }
+
+  if (i == kMaxNumPPFeatures) {
+    ret = kErrorParameters;
+    next_idx_ = 0;
+  }
+
+  return ret;
+}
+
 DisplayError ColorManagerProxy::Init(const HWResourceInfo &hw_res_info) {
   DisplayError error = kErrorNone;
 
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 4046ce5..ad67dd0 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -620,9 +620,10 @@
   case kFormatRGB888:                   return "RGB_888";
   case kFormatBGR888:                   return "BGR_888";
   case kFormatRGB565:                   return "RGB_565";
+  case kFormatBGR565:                   return "BGR_565";
   case kFormatRGBA8888Ubwc:             return "RGBA_8888_UBWC";
   case kFormatRGBX8888Ubwc:             return "RGBX_8888_UBWC";
-  case kFormatRGB565Ubwc:               return "RGB_565_UBWC";
+  case kFormatBGR565Ubwc:               return "BGR_565_UBWC";
   case kFormatYCbCr420Planar:           return "Y_CB_CR_420";
   case kFormatYCrCb420Planar:           return "Y_CR_CB_420";
   case kFormatYCrCb420PlanarStride16:   return "Y_CR_CB_420_STRIDE16";
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
old mode 100644
new mode 100755
index 1a00da4..06bbccb
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -148,7 +148,18 @@
 
 DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
   SCOPE_LOCK(locker_);
-  return DisplayBase::SetDisplayState(state);
+  DisplayError error = kErrorNone;
+  error = DisplayBase::SetDisplayState(state);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  // Set vsync enable state to false, as driver disables vsync during display power off.
+  if (state == kStateOff) {
+    vsync_enable_ = false;
+  }
+
+  return kErrorNone;
 }
 
 DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 672e8e7..50e686a 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -228,9 +228,6 @@
         mdp_layer.bg_color = layer.solid_fill_color;
 
         if (pipe_info->scale_data.enable_pixel_ext) {
-          if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f)) {
-            mdp_buffer.width = pipe_info->scale_data.src_width;
-          }
           SetHWScaleData(pipe_info->scale_data, mdp_layer_count);
           mdp_layer.flags |= MDP_LAYER_ENABLE_PIXEL_EXT;
         }
@@ -276,6 +273,9 @@
     mdp_out_layer_.writeback_ndx = 2;
     mdp_out_layer_.buffer.width = output_buffer->width;
     mdp_out_layer_.buffer.height = output_buffer->height;
+    if (output_buffer->flags.secure) {
+      mdp_out_layer_.flags |= MDP_LAYER_SECURE_SESSION;
+    }
     mdp_out_layer_.buffer.comp_ratio.denom = 1000;
     mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
     SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
@@ -433,10 +433,10 @@
       input_buffer = &hw_rotator_session->output_buffer;
     }
 
-    input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+    input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
   }
 
-  hw_layer_info.sync_handle = dup(mdp_commit.release_fence);
+  hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence);
 
   DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
            device_name_);
@@ -488,6 +488,7 @@
   case kFormatRGB888:                   *target = MDP_RGB_888;           break;
   case kFormatBGR888:                   *target = MDP_BGR_888;           break;
   case kFormatRGB565:                   *target = MDP_RGB_565;           break;
+  case kFormatBGR565:                   *target = MDP_BGR_565;           break;
   case kFormatYCbCr420Planar:           *target = MDP_Y_CB_CR_H2V2;      break;
   case kFormatYCrCb420Planar:           *target = MDP_Y_CR_CB_H2V2;      break;
   case kFormatYCrCb420PlanarStride16:   *target = MDP_Y_CR_CB_GH2V2;     break;
@@ -501,7 +502,7 @@
   case kFormatYCbCr420SemiPlanarVenus:  *target = MDP_Y_CBCR_H2V2_VENUS; break;
   case kFormatRGBA8888Ubwc:             *target = MDP_RGBA_8888_UBWC;    break;
   case kFormatRGBX8888Ubwc:             *target = MDP_RGBX_8888_UBWC;    break;
-  case kFormatRGB565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
+  case kFormatBGR565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
   case kFormatYCbCr420SPVenusUbwc:      *target = MDP_Y_CBCR_H2V2_UBWC;  break;
   default:
     DLOGE("Unsupported format type %d", source);
@@ -535,7 +536,8 @@
     *target = width * 3;
     break;
   case kFormatRGB565:
-  case kFormatRGB565Ubwc:
+  case kFormatBGR565:
+  case kFormatBGR565Ubwc:
     *target = width * 2;
     break;
   case kFormatYCbCr420SemiPlanarVenus:
@@ -593,10 +595,10 @@
     if (layer.transform.flip_horizontal) {
       *mdp_flags |= MDP_LAYER_FLIP_LR;
     }
-  }
 
-  if (input_buffer->flags.interlace) {
-    *mdp_flags |= MDP_LAYER_DEINTERLACE;
+    if (input_buffer->flags.interlace) {
+      *mdp_flags |= MDP_LAYER_DEINTERLACE;
+    }
   }
 
   if (input_buffer->flags.secure) {
@@ -671,7 +673,6 @@
   DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
   DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
         hw_panel_info_.split_info.right_split);
-  DLOGI("Source Split Always = %d", hw_panel_info_.split_info.always_src_split);
 }
 
 void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
@@ -822,7 +823,7 @@
 
   // Format "left right" space as delimiter
   read = Sys::getline_(&line, &len, fileptr);
-  if (read != -1) {
+  if (read > 0) {
     if (!ParseLine(line, tokens, max_count, &token_count)) {
       panel_info->split_info.left_split = atoi(tokens[0]);
       panel_info->split_info.right_split = atoi(tokens[1]);
@@ -830,24 +831,6 @@
   }
 
   Sys::fclose_(fileptr);
-
-  // SourceSplit enabled - Get More information
-  snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_src_split_info", fb_path_,
-           device_node);
-  fileptr = Sys::fopen_(stringbuffer, "r");
-  if (!fileptr) {
-    DLOGW("File not found %s", stringbuffer);
-    return;
-  }
-
-  read = Sys::getline_(&line, &len, fileptr);
-  if (read != -1) {
-    if (!strncmp(line, "src_split_always", strlen("src_split_always"))) {
-      panel_info->split_info.always_src_split = true;
-    }
-  }
-
-  Sys::fclose_(fileptr);
 }
 
 int HWDevice::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index 61d3df8..c47a0bd 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -483,6 +483,7 @@
   while (true) {
     char config_buffer[kPageSize] = {0};
     msm_hdmi_mode_timing_info *info = reinterpret_cast<msm_hdmi_mode_timing_info *>(config_buffer);
+    RequestNewPage(page_number);
 
     if (!ReadResolutionFile(config_buffer)) {
       break;
@@ -508,7 +509,6 @@
     // Request HDMI driver to populate res_info with more
     // timing information
     page_number++;
-    RequestNewPage(page_number);
   }
 
   if (page_number == MSM_HDMI_INIT_RES_PAGE || config_index == 0) {
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 3c308d7..c548a26 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -325,7 +325,6 @@
       (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
   display_attributes_.split_left = hw_panel_info_.split_info.left_split ?
       hw_panel_info_.split_info.left_split : display_attributes_.x_pixels / 2;
-  display_attributes_.always_src_split = hw_panel_info_.split_info.always_src_split;
   display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
 
   return kErrorNone;
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index 5034bac..8c67b82 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -450,18 +450,13 @@
 DisplayError ResourceDefault::SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
                                         const LayerRect &src_rect, const LayerRect &dst_rect,
                                         HWLayerConfig *layer_config) {
-  HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
   HWPipeInfo *left_pipe = &layer_config->left_pipe;
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
   float src_width = src_rect.right - src_rect.left;
   float dst_width = dst_rect.right - dst_rect.left;
-  float left_mixer_width = FLOAT(display_attributes.split_left);
 
   // Layer cannot qualify for SrcSplit if source or destination width exceeds max pipe width.
-  // For perf/power optimization, even if "always_src_split" is enabled, use 2 pipes only if:
-  // Source width is greater than split_left (left_mixer_width)
-  if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width) ||
-      (display_resource_ctx->display_attributes.always_src_split && src_width > left_mixer_width)) {
+  if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width)) {
     SplitRect(src_rect, dst_rect, &left_pipe->src_roi, &left_pipe->dst_roi, &right_pipe->src_roi,
               &right_pipe->dst_roi);
     left_pipe->valid = true;
@@ -918,7 +913,7 @@
   switch (format) {
   case kFormatRGBA8888Ubwc:
   case kFormatRGBX8888Ubwc:
-  case kFormatRGB565Ubwc:
+  case kFormatBGR565Ubwc:
   case kFormatYCbCr420SPVenusUbwc:
     return true;
   default:
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 6bd9a9c..0b7bd3c 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -50,9 +50,6 @@
 
     error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_,
                                                  hw_panel_info_, &partial_update_intf_);
-    if (error != kErrorNone) {
-      DLOGW("Partial Update creation failed, Continue without partial update.");
-    }
   }
 
   return kErrorNone;
diff --git a/sdm/libs/hwc/blit_engine_c2d.cpp b/sdm/libs/hwc/blit_engine_c2d.cpp
index b34662a..e85e28c 100644
--- a/sdm/libs/hwc/blit_engine_c2d.cpp
+++ b/sdm/libs/hwc/blit_engine_c2d.cpp
@@ -523,7 +523,7 @@
   switch (format) {
   case kFormatRGBA8888Ubwc:
   case kFormatRGBX8888Ubwc:
-  case kFormatRGB565Ubwc:
+  case kFormatBGR565Ubwc:
   case kFormatYCbCr420SPVenusUbwc:
     return true;
   default:
diff --git a/sdm/libs/hwc/cpuhint.cpp b/sdm/libs/hwc/cpuhint.cpp
index f328268..ccf55bf 100644
--- a/sdm/libs/hwc/cpuhint.cpp
+++ b/sdm/libs/hwc/cpuhint.cpp
@@ -29,6 +29,7 @@
 
 #include <cutils/properties.h>
 #include <dlfcn.h>
+#include <utils/debug.h>
 
 #include "cpuhint.h"
 #include "hwc_debugger.h"
diff --git a/sdm/libs/hwc/cpuhint.h b/sdm/libs/hwc/cpuhint.h
index 14ecd93..a4a7758 100644
--- a/sdm/libs/hwc/cpuhint.h
+++ b/sdm/libs/hwc/cpuhint.h
@@ -44,7 +44,7 @@
   void Reset();
 
  private:
-  enum { HINT =  0x4701 /* 47-display layer hint, 01-Enable */ };
+  enum { HINT =  0x4501 /* 45-display layer hint, 01-Enable */ };
   bool enabled_ = false;
   // frames to wait before setting this hint
   int pre_enable_window_ = 0;
diff --git a/sdm/libs/hwc/hwc_buffer_allocator.cpp b/sdm/libs/hwc/hwc_buffer_allocator.cpp
index 556780f..3149718 100644
--- a/sdm/libs/hwc/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc/hwc_buffer_allocator.cpp
@@ -32,6 +32,7 @@
 #include <gr.h>
 #include <alloc_controller.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 #include <core/buffer_allocator.h>
 
 #include "hwc_debugger.h"
@@ -155,6 +156,7 @@
   case kFormatRGBX8888:                 *target = HAL_PIXEL_FORMAT_RGBX_8888;             break;
   case kFormatRGB888:                   *target = HAL_PIXEL_FORMAT_RGB_888;               break;
   case kFormatRGB565:                   *target = HAL_PIXEL_FORMAT_RGB_565;               break;
+  case kFormatBGR565:                   *target = HAL_PIXEL_FORMAT_BGR_565;               break;
   case kFormatBGRA8888:                 *target = HAL_PIXEL_FORMAT_BGRA_8888;             break;
   case kFormatYCrCb420PlanarStride16:   *target = HAL_PIXEL_FORMAT_YV12;                  break;
   case kFormatYCrCb420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCrCb_420_SP;          break;
@@ -173,8 +175,8 @@
     *target = HAL_PIXEL_FORMAT_RGBX_8888;
     *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
     break;
-  case kFormatRGB565Ubwc:
-    *target = HAL_PIXEL_FORMAT_RGB_565;
+  case kFormatBGR565Ubwc:
+    *target = HAL_PIXEL_FORMAT_BGR_565;
     *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
     break;
   default:
diff --git a/sdm/libs/hwc/hwc_buffer_sync_handler.cpp b/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
index 949745e..581bcd6 100644
--- a/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
+++ b/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
@@ -29,6 +29,7 @@
 
 #include <sync/sync.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 
 #include "hwc_debugger.h"
 #include "hwc_buffer_sync_handler.h"
diff --git a/sdm/libs/hwc/hwc_color_manager.cpp b/sdm/libs/hwc/hwc_color_manager.cpp
index 463014e..456fd7d 100644
--- a/sdm/libs/hwc/hwc_color_manager.cpp
+++ b/sdm/libs/hwc/hwc_color_manager.cpp
@@ -40,6 +40,7 @@
 
 #include <core/dump_interface.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 #include <core/buffer_allocator.h>
 #include <private/color_params.h>
 #include "hwc_buffer_allocator.h"
@@ -141,9 +142,16 @@
   return color_mgr;
 }
 
-HWCColorManager::~HWCColorManager() {}
+HWCColorManager::~HWCColorManager() {
+}
 
 void HWCColorManager::DestroyColorManager() {
+  if (qdcm_mode_mgr_) {
+    delete qdcm_mode_mgr_;
+  }
+  if (qdcm_diag_deinit_) {
+    qdcm_diag_deinit_();
+  }
   if (diag_client_lib_) {
     ::dlclose(diag_client_lib_);
   }
@@ -156,24 +164,16 @@
 int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
   int ret = 0;
 
-  if (enable) {  // entering QDCM mode, disable all active features and acquire Android wakelock
+  if (!qdcm_mode_mgr_) {
     qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
     if (!qdcm_mode_mgr_) {
-      DLOGE("failing to create QDCM operating mode manager.");
+      DLOGE("Unable to create QDCM operating mode manager.");
       ret = -EFAULT;
-    } else {
-      ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
     }
-  } else {  // exiting QDCM mode, reverse the effect of entering.
-    if (!qdcm_mode_mgr_) {
-      DLOGE("failing to disable QDCM operating mode manager.");
-      ret = -EFAULT;
-    } else {  // once exiting from QDCM operating mode, destroy QDCMModeMgr and release the
-              // resources
-      ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
-      delete qdcm_mode_mgr_;
-      qdcm_mode_mgr_ = NULL;
-    }
+  }
+
+  if (qdcm_mode_mgr_) {
+    ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
   }
 
   return ret;
@@ -406,6 +406,7 @@
                                              const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
                                              bool *was_running) {
   int ret = 0;
+  ssize_t size = 0;
   char response[kSocketCMDMaxLength] = {
       0,
   };
@@ -417,25 +418,31 @@
 
   if (!enable) {  // if client requesting to disable it.
     // query CABL status, if off, no action. keep the status.
-    if (::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status)) < 0) {
+    size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
+    if (size < 0) {
       DLOGW("Unable to send data over socket %s", ::strerror(errno));
       ret = -EFAULT;
-    } else if (::read(socket_fd_, response, kSocketCMDMaxLength) < 0) {
-      DLOGW("Unable to read data over socket %s", ::strerror(errno));
-      ret = -EFAULT;
-    } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
-      *was_running = true;
+    } else {
+      size = ::read(socket_fd_, response, kSocketCMDMaxLength);
+      if (size < 0) {
+        DLOGW("Unable to read data over socket %s", ::strerror(errno));
+        ret = -EFAULT;
+      } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
+        *was_running = true;
+      }
     }
 
     if (*was_running) {  // if was running, it's requested to disable it.
-      if (::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off)) < 0) {
+      size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
+      if (size < 0) {
         DLOGW("Unable to send data over socket %s", ::strerror(errno));
         ret = -EFAULT;
       }
     }
   } else {  // if was running, need enable it back.
     if (*was_running) {
-      if (::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on)) < 0) {
+      size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
+      if (size < 0) {
         DLOGW("Unable to send data over socket %s", ::strerror(errno));
         ret = -EFAULT;
       }
diff --git a/sdm/libs/hwc/hwc_debugger.h b/sdm/libs/hwc/hwc_debugger.h
index 474e1c5..e4e1ea3 100644
--- a/sdm/libs/hwc/hwc_debugger.h
+++ b/sdm/libs/hwc/hwc_debugger.h
@@ -37,19 +37,6 @@
 #include <cutils/log.h>
 #include <utils/Trace.h>
 
-#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
-
-#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
-#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
-#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
-#define DLOGD(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
-#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
-
-#define DTRACE_BEGIN(custom_string) HWCDebugHandler::Get()->BeginTrace(__CLASS__, __FUNCTION__, \
-                                                                       custom_string)
-#define DTRACE_END() HWCDebugHandler::Get()->EndTrace()
-#define DTRACE_SCOPED() ScopeTracer<HWCDebugHandler> scope_tracer(__CLASS__, __FUNCTION__)
-
 namespace sdm {
 
 class HWCDebugHandler : public DebugHandler {
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 413db19..63c19a9 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -32,6 +32,8 @@
 #include <gralloc_priv.h>
 #include <gr.h>
 #include <utils/constants.h>
+#include <utils/rect.h>
+#include <utils/debug.h>
 #include <sync/sync.h>
 #include <cutils/properties.h>
 
@@ -55,6 +57,14 @@
   }
 }
 
+static void ApplyDeInterlaceAdjustment(Layer *layer) {
+  // De-interlacing adjustment
+  if (layer->input_buffer->flags.interlace) {
+    float height = (layer->src_rect.bottom - layer->src_rect.top) / 2.0f;
+    layer->src_rect.bottom = layer->src_rect.top + floorf(height);
+  }
+}
+
 HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
                        int id, bool needs_blit)
   : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), needs_blit_(needs_blit) {
@@ -464,13 +474,10 @@
   }
 
   size_t num_hw_layers = content_list->numHwLayers;
-  if (num_hw_layers <= 1) {
-    flush_ = true;
-    return 0;
-  }
 
   use_blit_comp_ = false;
   metadata_refresh_rate_ = 0;
+  display_rect_ = LayerRect();
 
   // Configure each layer
   for (size_t i = 0; i < num_hw_layers; i++) {
@@ -490,6 +497,8 @@
 
     SetRect(scaled_display_frame, &layer.dst_rect);
     SetRect(hwc_layer.sourceCropf, &layer.src_rect);
+    ApplyDeInterlaceAdjustment(&layer);
+
     for (size_t j = 0; j < hwc_layer.visibleRegionScreen.numRects; j++) {
       SetRect(hwc_layer.visibleRegionScreen.rects[j], &layer.visible_regions.rect[j]);
     }
@@ -498,6 +507,11 @@
     }
     SetComposition(hwc_layer.compositionType, &layer.composition);
 
+    if (hwc_layer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+      display_rect_ = Union(display_rect_, layer.dst_rect);
+    }
+
+
     // For dim layers, SurfaceFlinger
     //    - converts planeAlpha to per pixel alpha,
     //    - sets RGB color to 000,
@@ -888,7 +902,7 @@
     switch (source) {
     case HAL_PIXEL_FORMAT_RGBA_8888:          format = kFormatRGBA8888Ubwc;            break;
     case HAL_PIXEL_FORMAT_RGBX_8888:          format = kFormatRGBX8888Ubwc;            break;
-    case HAL_PIXEL_FORMAT_RGB_565:            format = kFormatRGB565Ubwc;              break;
+    case HAL_PIXEL_FORMAT_BGR_565:            format = kFormatBGR565Ubwc;              break;
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
     case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:    format = kFormatYCbCr420SPVenusUbwc;     break;
@@ -908,6 +922,7 @@
   case HAL_PIXEL_FORMAT_BGRX_8888:                format = kFormatBGRX8888;                 break;
   case HAL_PIXEL_FORMAT_RGB_888:                  format = kFormatRGB888;                   break;
   case HAL_PIXEL_FORMAT_RGB_565:                  format = kFormatRGB565;                   break;
+  case HAL_PIXEL_FORMAT_BGR_565:                  format = kFormatBGR565;                   break;
   case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
   case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:       format = kFormatYCbCr420SemiPlanarVenus;  break;
   case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:  format = kFormatYCbCr420SPVenusUbwc;      break;
@@ -985,6 +1000,8 @@
     return "RGB_888";
   case HAL_PIXEL_FORMAT_RGB_565:
     return "RGB_565";
+  case HAL_PIXEL_FORMAT_BGR_565:
+    return "BGR_565";
   case HAL_PIXEL_FORMAT_BGRA_8888:
     return "BGRA_8888";
   case HAL_PIXEL_FORMAT_RGBA_5551:
@@ -1297,6 +1314,21 @@
   return ret;
 }
 
+int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t* visible_rect) {
+  if (!IsValid(display_rect_)) {
+    return -EINVAL;
+  }
+
+  visible_rect->left = INT(display_rect_.left);
+  visible_rect->top = INT(display_rect_.top);
+  visible_rect->right = INT(display_rect_.right);
+  visible_rect->bottom = INT(display_rect_.bottom);
+  DLOGI("Dpy = %d Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
+        visible_rect->right, visible_rect->bottom);
+
+  return 0;
+}
+
 void HWCDisplay::ResetLayerCacheStack() {
   uint32_t layer_count = layer_stack_cache_.layer_count;
   for (uint32_t i = 0; i < layer_count; i++) {
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 15e62f3..ce624a3 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -76,6 +76,7 @@
   int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
                            PPDisplayAPIPayload *out_payload,
                            PPPendingParams *pending_action);
+  int GetVisibleDisplayRect(hwc_rect_t* rect);
 
  protected:
   enum DisplayStatus {
@@ -86,7 +87,7 @@
   };
 
   // Dim layer flag set by SurfaceFlinger service.
-  static const uint32_t kDimLayer = 0x8000;
+  static const uint32_t kDimLayer = 0x80000000;
 
   // Maximum number of layers supported by display manager.
   static const uint32_t kMaxLayerCount = 32;
@@ -186,7 +187,8 @@
   bool skip_prepare_ = false;
 
   bool solid_fill_enable_ = false;
-  uint32_t solid_fill_color_ = 0;;
+  uint32_t solid_fill_color_ = 0;
+  LayerRect display_rect_;
 
  private:
   bool IsFrameBufferScaled();
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index 2e91750..a02be81 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -29,6 +29,7 @@
 
 #include <cutils/properties.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 
 #include "hwc_display_external.h"
 #include "hwc_debugger.h"
@@ -53,7 +54,7 @@
   hwc_display_external->GetPanelResolution(&external_width, &external_height);
 
   int downscale_enabled = 0;
-  HWCDebugHandler::Get()->GetProperty("sdm.debug.sde_downscale_external", &downscale_enabled);
+  HWCDebugHandler::Get()->GetProperty("sdm.debug.downscale_external", &downscale_enabled);
   if (downscale_enabled) {
     GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
   }
@@ -91,6 +92,12 @@
     return status;
   }
 
+  size_t num_hw_layers = content_list->numHwLayers;
+  if (num_hw_layers <= 1) {
+    flush_ = true;
+    return 0;
+  }
+
   status = PrepareLayerStack(content_list);
   if (status) {
     return status;
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index 115af3e..9842b61 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -29,6 +29,7 @@
 
 #include <cutils/properties.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 #include <stdarg.h>
 #include "hwc_display_primary.h"
 #include "hwc_debugger.h"
@@ -126,6 +127,12 @@
     return status;
   }
 
+  size_t num_hw_layers = content_list->numHwLayers;
+  if (num_hw_layers <= 1) {
+    flush_ = true;
+    return 0;
+  }
+
   status = PrepareLayerStack(content_list);
   if (status) {
     return status;
diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp
index 4dfa1ee..219a81b 100644
--- a/sdm/libs/hwc/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -28,6 +28,7 @@
 */
 
 #include <utils/constants.h>
+#include <utils/debug.h>
 #include <sync/sync.h>
 #include <stdarg.h>
 #include <gr.h>
@@ -86,7 +87,7 @@
 
   *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
 
-  return status;
+  return 0;
 }
 
 void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
@@ -200,7 +201,12 @@
   int status = 0;
 
   if (output_handle) {
-    LayerBufferFormat format = GetSDMFormat(output_handle->format, output_handle->flags);
+    int output_handle_format = output_handle->format;
+    if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+      output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+    }
+
+    LayerBufferFormat format = GetSDMFormat(output_handle_format, output_handle->flags);
     if (format == kFormatInvalid) {
       return -EINVAL;
     }
@@ -245,7 +251,14 @@
   output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
 
   if (output_handle) {
-    output_buffer_->format = GetSDMFormat(output_handle->format, output_handle->flags);
+    int output_handle_format = output_handle->format;
+
+    if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+      output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+    }
+
+    output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
+
     if (output_buffer_->format == kFormatInvalid) {
       return -EINVAL;
     }
@@ -259,6 +272,11 @@
     output_buffer_->flags.secure = 0;
     output_buffer_->flags.video = 0;
 
+    // TZ Protected Buffer - L1
+    if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+      output_buffer_->flags.secure = 1;
+    }
+
     // ToDo: Need to extend for non-RGB formats
     output_buffer_->planes[0].fd = output_handle->fd;
     output_buffer_->planes[0].offset = output_handle->offset;
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 98444e1..f938f0d 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -41,6 +41,7 @@
 #include <gr.h>
 #include <gralloc_priv.h>
 #include <display_config.h>
+#include <utils/debug.h>
 
 #include "hwc_buffer_allocator.h"
 #include "hwc_buffer_sync_handler.h"
@@ -73,6 +74,7 @@
 namespace sdm {
 
 Locker HWCSession::locker_;
+Locker HWCSession::concurrency_locker_;
 bool HWCSession::reset_panel_ = false;
 
 static void Invalidate(const struct hwc_procs *procs) {
@@ -292,22 +294,31 @@
 
   for (size_t dpy = 0; dpy < num_displays; dpy++) {
     hwc_display_contents_1_t *content_list = displays[dpy];
-    if (dpy == HWC_DISPLAY_VIRTUAL) {
-      if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-        if (content_list) {
-          for (size_t i = 0; i < content_list->numHwLayers; i++) {
-            if (content_list->hwLayers[i].acquireFenceFd >= 0) {
-              close(content_list->hwLayers[i].acquireFenceFd);
-              content_list->hwLayers[i].acquireFenceFd = -1;
-            }
-          }
-          if (content_list->outbufAcquireFenceFd >= 0) {
-            close(content_list->outbufAcquireFenceFd);
-            content_list->outbufAcquireFenceFd = -1;
-          }
-          content_list->retireFenceFd = -1;
+
+    // Drop virtual display composition if virtual display object could not be created
+    // due to HDMI concurrency.
+    if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      if (!content_list) {
+        continue;
+      }
+
+      for (size_t i = 0; i < content_list->numHwLayers; i++) {
+        int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
+        if (acquireFenceFd >= 0) {
+          close(acquireFenceFd);
+          acquireFenceFd = -1;
         }
       }
+
+      int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
+      if (outbufAcquireFenceFd >= 0) {
+        close(outbufAcquireFenceFd);
+        outbufAcquireFenceFd = -1;
+      }
+
+      content_list->retireFenceFd = -1;
+
+      continue;
     }
 
     if (hwc_session->hwc_display_[dpy]) {
@@ -499,31 +510,35 @@
   return status;
 }
 
-int HWCSession::HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list) {
-  int status = 0;
+void HWCSession::HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list) {
+  // Virtual display & HDMI concurrency is not supported.
+  // Acquire concurrency mutex before creating / destroying virtual display.
+  // Signal concurrency condition on virtual display destroy so that HDMI hotplug could
+  // proceed with connection.
+  SCOPE_LOCK(concurrency_locker_);
 
   if (HWCDisplayVirtual::IsValidContentList(content_list)) {
     if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      DLOGI("Create Virtual Display");
       uint32_t primary_width = 0;
       uint32_t primary_height = 0;
       hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
-      // Create virtual display device
-      status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
-                                         content_list, &hwc_display_[HWC_DISPLAY_VIRTUAL]);
-      if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+
+      int status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width,
+                                             primary_height, content_list,
+                                             &hwc_display_[HWC_DISPLAY_VIRTUAL]);
+      if (!status) {
         hwc_display_[HWC_DISPLAY_VIRTUAL]->SetSecureDisplay(secure_display_active_);
       }
     }
   } else {
     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      DLOGI("Destroy Virtual Display");
       HWCDisplayVirtual::Destroy(hwc_display_[HWC_DISPLAY_VIRTUAL]);
-      hwc_display_[HWC_DISPLAY_VIRTUAL] = 0;
-      // Signal the HotPlug thread to continue with the external display connection
-      locker_.Signal();
+      hwc_display_[HWC_DISPLAY_VIRTUAL] = NULL;
+      concurrency_locker_.Signal();
     }
   }
-
-  return status;
 }
 
 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -559,8 +574,9 @@
   case qService::IQService::SET_DISPLAY_MODE:
     status = SetDisplayMode(input_parcel);
     break;
+
   case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
-    status = SetSecondaryDisplayStatus(input_parcel);
+    status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
     break;
 
   case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
@@ -610,6 +626,10 @@
     status = SetPanelBrightness(input_parcel, output_parcel);
     break;
 
+  case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
+    status = GetVisibleDisplayRect(input_parcel, output_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
@@ -705,11 +725,11 @@
     return ret;
   }
 
+  // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
   hwc_procs_->invalidate(hwc_procs_);
 
   // Wait until partial update control is complete
   ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
-  locker_.Unlock();
 
   out->writeInt32(ret);
 
@@ -803,17 +823,28 @@
   return error;
 }
 
-android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel) {
+android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
+                                                        android::Parcel *output_parcel) {
+  int ret = -EINVAL;
+
   uint32_t display_id = UINT32(input_parcel->readInt32());
   uint32_t display_status = UINT32(input_parcel->readInt32());
 
-  DLOGI("Display %d Status %d", display_id, display_status);
-  if (display_id < HWC_DISPLAY_EXTERNAL || display_id > HWC_DISPLAY_VIRTUAL) {
-    DLOGW("Not supported for display %d", display_id);
-    return -EINVAL;
+  DLOGI("Display = %d, Status = %d", display_id, display_status);
+
+  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+    DLOGE("Invalid display_id");
+  } else if (display_id == HWC_DISPLAY_PRIMARY) {
+    DLOGE("Not supported for this display");
+  } else if (!hwc_display_[display_id]) {
+    DLOGW("Display is not connected");
+  } else {
+    ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
   }
 
-  return hwc_display_[display_id]->SetDisplayStatus(display_status);
+  output_parcel->writeInt32(ret);
+
+  return ret;
 }
 
 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
@@ -1025,10 +1056,13 @@
   uint32_t display_id = UINT32(input_parcel->readInt32());
 
   DLOGI("Display %d", display_id);
-  if (display_id != HWC_DISPLAY_EXTERNAL) {
-    DLOGW("Not supported for display %d", display_id);
+
+  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+    DLOGE("Invalid display_id");
+  } else if (display_id != HWC_DISPLAY_EXTERNAL) {
+    DLOGE("Not supported for display");
   } else if (!hwc_display_[display_id]) {
-    DLOGE("Display %d is not connected", display_id);
+    DLOGW("Display is not connected");
   } else {
     ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange();
   }
@@ -1126,46 +1160,66 @@
 }
 
 int HWCSession::HotPlugHandler(bool connected) {
-  if (!hwc_procs_) {
-     DLOGW("Ignore hotplug - hwc_proc not registered");
-    return -1;
-  }
+  // To prevent sending events to client while a lock is held, acquire scope locks only within
+  // below scope so that those get automatically unlocked after the scope ends.
+  {
+    // Virtual display & HDMI concurrency is not supported. Acquire concurrency lock
+    // and wait for virtual display to tear down if connected.
+    SCOPE_LOCK(concurrency_locker_);
 
-  if (connected) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
-    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-      // Wait for the virtual display to tear down
-      int status = locker_.WaitFinite(kExternalConnectionTimeoutMs);
-      if (status != 0) {
-        DLOGE("Timed out while waiting for virtual display to tear down.");
+    if (connected) {
+      // Acquire global lock and check if virtual display is connected.
+      // Release global lock before waiting for virtual display to disconnect and signal.
+      bool virtual_display_connected = false;
+      {
+        SCOPE_LOCK(locker_);
+        if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+          DLOGE("Primay display is not connected");
+          return -1;
+        }
+
+        if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+          DLOGE("HDMI is already connected");
+          return -1;
+        }
+
+        virtual_display_connected = (hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL);
+        DLOGI("Virtual display connection status = %d", virtual_display_connected);
+      }
+
+      if (virtual_display_connected) {
+        DLOGI("Wait for virtual display to disconnect.");
+        concurrency_locker_.Wait();
+        DLOGI("virtual display is disconnected now.");
+      }
+
+      // Acquire global sequence lock now.
+      SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+      uint32_t primary_width = 0;
+      uint32_t primary_height = 0;
+      hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
+
+      // Create hdmi display
+      int status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width,
+                                              primary_height, &hwc_display_[HWC_DISPLAY_EXTERNAL]);
+      if (status) {
+        return status;
+      }
+
+      hwc_display_[HWC_DISPLAY_EXTERNAL]->SetSecureDisplay(secure_display_active_);
+    } else {
+      // Acquire concurrency lock as well as global sequence lock.
+      SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+      if (!hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+        DLOGE("HDMI not connected");
         return -1;
       }
-    }
-    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-     DLOGE("HDMI already connected");
-     return -1;
-    }
 
-    uint32_t primary_width = 0;
-    uint32_t primary_height = 0;
-    hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
-    // Create hdmi display
-    int status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width,
-                                            primary_height, &hwc_display_[HWC_DISPLAY_EXTERNAL]);
-    if (status) {
-      return status;
+      HWCDisplayExternal::Destroy(hwc_display_[HWC_DISPLAY_EXTERNAL]);
+      hwc_display_[HWC_DISPLAY_EXTERNAL] = NULL;
     }
-    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-      hwc_display_[HWC_DISPLAY_EXTERNAL]->SetSecureDisplay(secure_display_active_);
-    }
-  } else {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
-    if (!hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-     DLOGE("HDMI not connected");
-     return -1;
-    }
-    HWCDisplayExternal::Destroy(hwc_display_[HWC_DISPLAY_EXTERNAL]);
-    hwc_display_[HWC_DISPLAY_EXTERNAL] = 0;
   }
 
   // notify client and trigger a screen refresh
@@ -1204,5 +1258,31 @@
   }
 }
 
+android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
+                                                    android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+
+  if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;;
+  }
+
+  if (!hwc_display_[dpy]) {
+    return android::NO_INIT;
+  }
+
+  hwc_rect_t visible_rect = {0, 0, 0, 0};
+  int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
+  if (error < 0) {
+    return error;
+  }
+
+  output_parcel->writeInt32(visible_rect.left);
+  output_parcel->writeInt32(visible_rect.top);
+  output_parcel->writeInt32(visible_rect.right);
+  output_parcel->writeInt32(visible_rect.bottom);
+
+  return android::NO_ERROR;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index 22574dc..1dde96e 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -80,7 +80,7 @@
   int GetEventValue(const char *uevent_data, int length, const char *event_info);
   int HotPlugHandler(bool connected);
   void ResetPanel();
-  int HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list);
+  void HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list);
   void HandleSecureDisplaySession(hwc_display_contents_1_t **displays);
 
   // QClient methods
@@ -90,7 +90,8 @@
   void SetFrameDumpConfig(const android::Parcel *input_parcel);
   android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
   android::status_t SetDisplayMode(const android::Parcel *input_parcel);
-  android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel);
+  android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
+                                              android::Parcel *output_parcel);
   android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel,
                                         android::Parcel *output_parcel);
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
@@ -112,8 +113,11 @@
                                                 android::Parcel *output_parcel);
   android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
                                                         android::Parcel *output_parcel);
+  android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
+                                          android::Parcel *output_parcel);
 
   static Locker locker_;
+  static Locker concurrency_locker_;
   CoreInterface *core_intf_ = NULL;
   hwc_procs_t hwc_procs_default_;
   hwc_procs_t const *hwc_procs_ = &hwc_procs_default_;
diff --git a/sdm/libs/utils/sys.cpp b/sdm/libs/utils/sys.cpp
index 03310ff..ff66fcf 100644
--- a/sdm/libs/utils/sys.cpp
+++ b/sdm/libs/utils/sys.cpp
@@ -53,6 +53,7 @@
 Sys::fclose Sys::fclose_ = ::fclose;
 Sys::getline Sys::getline_ = ::getline;
 Sys::pthread_cancel Sys::pthread_cancel_ = PthreadCancel;
+Sys::dup Sys::dup_ = ::dup;
 
 #else
 
@@ -66,6 +67,7 @@
 extern FILE* virtual_fopen(const char *fname, const char *mode);
 extern int virtual_fclose(FILE* fileptr);
 extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
+extern int virtual_dup(int fd);
 
 Sys::ioctl Sys::ioctl_ = virtual_ioctl;
 Sys::open Sys::open_ = virtual_open;
@@ -77,6 +79,7 @@
 Sys::fclose Sys::fclose_ = virtual_fclose;
 Sys::getline Sys::getline_ = virtual_getline;
 Sys::pthread_cancel Sys::pthread_cancel_ = ::pthread_cancel;
+Sys::dup Sys::dup_ = virtual_dup;
 
 #endif  // SDM_VIRTUAL_DRIVER