Merge "hwc2: Clean up acquire fence handling"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 5051bed..87f7bcf 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -378,9 +378,6 @@
   CompRatioMap comp_ratio_rt_map;
   CompRatioMap comp_ratio_nrt_map;
   uint32_t hw_version;
-  uint64_t min_core_ib;
-  uint64_t min_llcc_ib;
-  uint64_t min_dram_ib;
   uint32_t dest_scaler_count = 0;
   uint32_t max_dest_scaler_input_width = 0;
   uint32_t max_dest_scaler_output_width = 0;
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 35c4b02..eb97f15 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -725,7 +725,7 @@
         return GRALLOC1_ERROR_BAD_VALUE;
       }
 
-      if (getMetaData(hnd, GET_MAP_SECURE_BUFFER, map_secure_buffer) == 0) {
+      if (getMetaData(hnd, GET_MAP_SECURE_BUFFER, map_secure_buffer) != 0) {
         *map_secure_buffer = 0;
       }
     } break;
@@ -853,8 +853,8 @@
     return GRALLOC1_ERROR_UNSUPPORTED;
   }
 
-  android_ycbcr ycbcr;
-  int err = GetYUVPlaneInfo(hnd, &ycbcr);
+  android_ycbcr yuvPlaneInfo[2];
+  int err = GetYUVPlaneInfo(hnd, yuvPlaneInfo);
 
   if (err != 0) {
     return GRALLOC1_ERROR_BAD_HANDLE;
@@ -872,6 +872,8 @@
     layout->planes[i].v_subsampling = 2;
   }
 
+  // We are only returning flex layout for progressive or single field formats.
+  struct android_ycbcr ycbcr = yuvPlaneInfo[0];
   layout->planes[0].top_left = static_cast<uint8_t *>(ycbcr.y);
   layout->planes[0].component = FLEX_COMPONENT_Y;
   layout->planes[0].v_increment = static_cast<int32_t>(ycbcr.ystride);
diff --git a/libgralloc1/gr_utils.cpp b/libgralloc1/gr_utils.cpp
index 945dea4..a7e8c91 100644
--- a/libgralloc1/gr_utils.cpp
+++ b/libgralloc1/gr_utils.cpp
@@ -312,7 +312,7 @@
 }
 
 void GetYuvUbwcInterlacedSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
-                                     int color_format, struct android_ycbcr *ycbcr) {
+                                     int color_format, struct android_ycbcr ycbcr[2]) {
   unsigned int uv_stride, uv_height, uv_size;
   unsigned int alignment = 4096;
   uint64_t field_base;
@@ -329,6 +329,7 @@
   field_base = base;
   GetYuvUbwcSPPlaneInfo(field_base, width, height, COLOR_FMT_NV12_UBWC, &ycbcr[0]);
 
+  memset(ycbcr[1].reserved, 0, sizeof(ycbcr[1].reserved));
   field_base = reinterpret_cast<uint64_t>(ycbcr[0].cb) + uv_size;
   GetYuvUbwcSPPlaneInfo(field_base, width, height, COLOR_FMT_NV12_UBWC, &ycbcr[1]);
 }
@@ -346,7 +347,7 @@
   ycbcr->chroma_step = 2 * bpp;
 }
 
-int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr *ycbcr) {
+int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr ycbcr[2]) {
   int err = 0;
   uint32_t width = UINT(hnd->width);
   uint32_t height = UINT(hnd->height);
@@ -382,7 +383,7 @@
   // Check metadata for interlaced content.
   int interlace_flag = 0;
   if (getMetaData(const_cast<private_handle_t *>(hnd),
-                  GET_PP_PARAM_INTERLACED, &interlace_flag) != 0) {
+                  GET_PP_PARAM_INTERLACED, &interlace_flag) == 0) {
     interlaced = interlace_flag;
   }
 
@@ -772,7 +773,7 @@
     return -EINVAL;
   }
 
-  struct android_ycbcr yuvInfo = {};
+  struct android_ycbcr yuvPlaneInfo[2] = {};
   *num_planes = 1;
   stride[0] = 0;
 
@@ -808,12 +809,14 @@
   }
 
   (*num_planes)++;
-  int ret = GetYUVPlaneInfo(hnd, &yuvInfo);
+  int ret = GetYUVPlaneInfo(hnd, yuvPlaneInfo);
   if (ret < 0) {
     ALOGE("%s failed", __FUNCTION__);
     return ret;
   }
 
+  // We are only returning buffer layout for progressive or single field formats.
+  struct android_ycbcr yuvInfo = yuvPlaneInfo[0];
   stride[0] = static_cast<uint32_t>(yuvInfo.ystride);
   offset[0] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base);
   stride[1] = static_cast<uint32_t>(yuvInfo.cstride);
diff --git a/libgralloc1/gr_utils.h b/libgralloc1/gr_utils.h
index 2a08539..4b2f136 100644
--- a/libgralloc1/gr_utils.h
+++ b/libgralloc1/gr_utils.h
@@ -71,7 +71,7 @@
                                 unsigned int *alignedw, unsigned int *alignedh);
 void GetAlignedWidthAndHeight(const BufferInfo &d, unsigned int *aligned_w,
                               unsigned int *aligned_h);
-int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr *ycbcr);
+int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr ycbcr[2]);
 int GetRgbDataAddress(private_handle_t *hnd, void **rgb_data);
 bool IsUBwcFormat(int format);
 bool IsUBwcSupported(int format);
@@ -84,7 +84,7 @@
 void GetYuvUbwcSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, int color_format,
                            struct android_ycbcr *ycbcr);
 void GetYuvUbwcInterlacedSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
-                                     int color_format, struct android_ycbcr *ycbcr);
+                                     int color_format, struct android_ycbcr ycbcr[2]);
 void GetRgbUBwcBlockSize(uint32_t bpp, int *block_width, int *block_height);
 unsigned int GetRgbUBwcMetaBufferSize(int width, int height, uint32_t bpp);
 unsigned int GetUBwcSize(int width, int height, int format, unsigned int alignedw,
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 0837c99..af2adf7 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -44,9 +44,8 @@
         ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle);
         return -1;
     }
-    if (handle->fd_metadata == -1) {
-        ALOGE("%s: Invalid metadata fd - handle:%p fd: %d",
-                __func__, handle, handle->fd_metadata);
+    if (handle->fd_metadata < 0) {
+        // Silently return, metadata cannot be used
         return -1;
     }
 
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index b6c4690..173dc4f 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -39,8 +39,10 @@
 const int kMaxSDELayers = 16;   // Maximum number of layers that can be handled by MDP5 hardware
                                 // in a given layer stack.
 #define MAX_PLANES 4
-
 #define MAX_DETAIL_ENHANCE_CURVE 3
+#define MAJOR 28
+#define MINOR 16
+#define SDEVERSION(major, minor, hw_rev) ((major) << MAJOR) | ((minor) << MINOR) | (hw_rev)
 
 enum HWDeviceType {
   kDevicePrimary,
@@ -226,9 +228,6 @@
   CompRatioMap comp_ratio_nrt_map;
   uint32_t cache_size = 0;  // cache size in bytes
   HWQseedStepVersion pipe_qseed3_version = kQseed3v2;  // only valid when has_qseed3=true
-  uint64_t min_core_ib_kbps = 0;
-  uint64_t min_llcc_ib_kbps = 0;
-  uint64_t min_dram_ib_kbps = 0;
 
   void Reset() { *this = HWResourceInfo(); }
 };
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 6f933eb..8c08451 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -193,7 +193,7 @@
   hw_resource->has_concurrent_writeback = false;
   hw_resource->has_hdr = true;
 
-  hw_resource->hw_version = kHWMdssVersion5;
+  hw_resource->hw_version = SDEVERSION(4, 0, 1);
   hw_resource->hw_revision = 0;
 
   // TODO(user): Deprecate
@@ -286,10 +286,7 @@
   hw_resource->max_bandwidth_low = info.max_bandwidth_low / kKiloUnit;
   hw_resource->max_bandwidth_high = info.max_bandwidth_high / kKiloUnit;
   hw_resource->max_sde_clk = info.max_sde_clk;
-  hw_resource->hw_revision = info.hw_version;
-  hw_resource->min_core_ib_kbps = info.min_core_ib / kKiloUnit;
-  hw_resource->min_llcc_ib_kbps = info.min_llcc_ib / kKiloUnit;
-  hw_resource->min_dram_ib_kbps = info.min_dram_ib / kKiloUnit;
+  hw_resource->hw_version = info.hw_version;
 
   std::vector<LayerBufferFormat> sdm_format;
   for (auto &it : info.comp_ratio_rt_map) {
diff --git a/sdm/libs/core/drm/hw_info_drm.h b/sdm/libs/core/drm/hw_info_drm.h
index 7883592..82fb175 100644
--- a/sdm/libs/core/drm/hw_info_drm.h
+++ b/sdm/libs/core/drm/hw_info_drm.h
@@ -67,8 +67,6 @@
   sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
   bool default_mode_ = false;
 
-  // TODO(user): Read Mdss version from the driver
-  static const int kHWMdssVersion5 = 500;  // MDSS_V5
   static const int kMaxStringLength = 1024;
   static const int kKiloUnit = 1000;
 
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index ec16b79..0530db8 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -594,6 +594,7 @@
   layer_stack_.flags.geometry_changed = UINT32(geometry_changes_ > 0);
   // Append client target to the layer stack
   Layer *sdm_client_target = client_target_->GetSDMLayer();
+  sdm_client_target->flags.updating = IsLayerUpdating(sdm_client_target);
   layer_stack_.layers.push_back(sdm_client_target);
   // fall back frame composition to GPU when client target is 10bit
   // TODO(user): clarify the behaviour from Client(SF) and SDM Extn -
@@ -1956,6 +1957,10 @@
 }
 
 bool HWCDisplay::CanSkipValidate() {
+  if (solid_fill_enable_) {
+    return false;
+  }
+
   // Layer Stack checks
   if (layer_stack_.flags.hdr_present && (tone_mapper_ && tone_mapper_->IsActive())) {
     return false;
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 250b491..654cba5 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -160,7 +160,7 @@
   int GetVisibleDisplayRect(hwc_rect_t *rect);
   void BuildLayerStack(void);
   void BuildSolidFillStack(void);
-  HWCLayer *GetHWCLayer(hwc2_layer_t layer);
+  HWCLayer *GetHWCLayer(hwc2_layer_t layer_id);
   void ResetValidation() { validated_ = false; }
   uint32_t GetGeometryChanges() { return geometry_changes_; }
 
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 7761791..6a33b8f 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -326,6 +326,10 @@
 }
 
 HWC2::Error HWCLayer::SetLayerCompositionType(HWC2::Composition type) {
+  // Validation is required when the client changes the composition type
+  if (client_requested_ != type) {
+    needs_validate_ = true;
+  }
   client_requested_ = type;
   switch (type) {
     case HWC2::Composition::Client:
@@ -412,8 +416,13 @@
 }
 
 HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) {
-  // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
+  if (alpha < 0.0f || alpha > 1.0f) {
+    return HWC2::Error::BadParameter;
+  }
+
+  //  Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
   uint8_t plane_alpha = static_cast<uint8_t>(std::round(255.0f * alpha));
+
   if (layer_->plane_alpha != plane_alpha) {
     geometry_changes_ |= kPlaneAlpha;
     layer_->plane_alpha = plane_alpha;
@@ -463,8 +472,10 @@
       layer_transform.flip_vertical = true;
       break;
     case HWC2::Transform::None:
-      // do nothing
       break;
+    default:
+      //  bad transform
+      return HWC2::Error::BadParameter;
   }
 
   if (layer_transform_ != layer_transform) {
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index f8a0d28..99fbc1a 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -483,14 +483,20 @@
 }
 
 static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
+  if (!device || !out_support) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
+  if (display >= HWC_NUM_DISPLAY_TYPES) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
   if (display == HWC_DISPLAY_PRIMARY) {
     *out_support = 1;
   } else {
-    // TODO(user): Port over connect_display_ from HWC1
-    // Return no error for connected displays
     *out_support = 0;
-    return HWC2_ERROR_BAD_DISPLAY;
   }
+
   return HWC2_ERROR_NONE;
 }
 
@@ -663,14 +669,19 @@
 
 int32_t HWCSession::SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display,
                                    hwc2_layer_t layer, uint32_t z) {
+  if (display >= HWC_NUM_DISPLAY_TYPES) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
   SCOPE_LOCK(locker_[display]);
+
   return CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
 }
 
 int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
                                     buffer_handle_t buffer, int32_t releaseFence) {
   if (!device) {
-    return HWC2_ERROR_BAD_DISPLAY;
+    return HWC2_ERROR_BAD_PARAMETER;
   }
 
   if (display != HWC_DISPLAY_VIRTUAL) {
@@ -689,24 +700,51 @@
 }
 
 int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
+  if (display >= HWC_NUM_DISPLAY_TYPES) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  //  validate device and also avoid undefined behavior in cast to HWC2::PowerMode
+  if (!device || int_mode < HWC2_POWER_MODE_OFF || int_mode > HWC2_POWER_MODE_DOZE_SUSPEND) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
   auto mode = static_cast<HWC2::PowerMode>(int_mode);
+
+  //  all displays support on/off. Check for doze modes
+  int support = 0;
+  GetDozeSupport(device, display, &support);
+  if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) {
+    return HWC2_ERROR_UNSUPPORTED;
+  }
+
   SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
   return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
 }
 
 static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) {
+  //  avoid undefined behavior in cast to HWC2::Vsync
+  if (int_enabled < HWC2_VSYNC_INVALID || int_enabled > HWC2_VSYNC_DISABLE) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
   auto enabled = static_cast<HWC2::Vsync>(int_enabled);
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
 }
 
 int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
                                     uint32_t *out_num_types, uint32_t *out_num_requests) {
-  DTRACE_SCOPED();
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  //  out_num_types and out_num_requests will be non-NULL
   if (!device) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
+  if (display >= HWC_NUM_DISPLAY_TYPES) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
+  DTRACE_SCOPED();
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
   // TODO(user): Handle secure session, handle QDCM solid fill
   // Handle external_pending_connect_ in CreateVirtualDisplay
   auto status = HWC2::Error::BadDisplay;
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 3659370..df58093 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -99,6 +99,10 @@
                                    hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args...),
                                    Args... args) {
     if (!device) {
+      return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    if (display >= HWC_NUM_DISPLAY_TYPES) {
       return HWC2_ERROR_BAD_DISPLAY;
     }
 
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index a5cf66a..52eaf7a 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -94,22 +94,25 @@
                                             isDisplayConnected_cb _hidl_cb) {
   int32_t error = -EINVAL;
   bool connected = false;
-
   int disp_id = MapDisplayType(dpy);
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
 
-  if (disp_id >= 0) {
-    connected = hwc_display_[disp_id];
-    error = 0;
+  if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
+    _hidl_cb(error, connected);
+    return Void();
   }
 
-  _hidl_cb(error, connected);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
 
+  connected = hwc_display_[disp_id];
+  error = 0;
+
+  _hidl_cb(error, connected);
   return Void();
 }
 
 int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
-  if (disp_id < 0) {
+  if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
+    DLOGE("Invalid display = %d", disp_id);
     return -EINVAL;
   }