Merge remote-tracking branch 'quic/display.lnx.5.0' into tip

2/7/2019 FF

Change-Id: I78cdd49ab0f4da7ec24e9009ee5dd2cf0cb94ada
CRs-Fixed: 2395201
diff --git a/common.mk b/common.mk
index 0d81828..e2f3c4c 100644
--- a/common.mk
+++ b/common.mk
@@ -3,8 +3,13 @@
 
 #Get the highest display config version available
 display_config_version := $(shell \
+    if [ -d "$(TOP)/vendor/qcom/opensource/interfaces/display/config/1.8" ];\
+    then echo DISPLAY_CONFIG_1_8; fi)
+ifeq ($(display_config_version),)
+display_config_version := $(shell \
     if [ -d "$(TOP)/vendor/qcom/opensource/interfaces/display/config/1.7" ];\
     then echo DISPLAY_CONFIG_1_7; fi)
+endif
 ifeq ($(display_config_version),)
 display_config_version := $(shell \
     if [ -d "$(TOP)/vendor/qcom/opensource/interfaces/display/config/1.6" ];\
@@ -71,6 +76,11 @@
     common_flags += -DDISPLAY_CONFIG_1_6 -DDISPLAY_CONFIG_1_5 -DDISPLAY_CONFIG_1_4
     common_flags += -DDISPLAY_CONFIG_1_3 -DDISPLAY_CONFIG_1_2 -DDISPLAY_CONFIG_1_1
 endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_8)
+    common_flags += -DDISPLAY_CONFIG_1_1 -DDISPLAY_CONFIG_1_2 -DDISPLAY_CONFIG_1_3
+    common_flags += -DDISPLAY_CONFIG_1_4 -DDISPLAY_CONFIG_1_5 -DDISPLAY_CONFIG_1_6
+    common_flags += -DDISPLAY_CONFIG_1_7 -DDISPLAY_CONFIG_1_8
+endif
 
 ifeq ($(TARGET_USES_COLOR_METADATA), true)
     common_flags += -DUSE_COLOR_METADATA
diff --git a/config/msmnile.mk b/config/msmnile.mk
index 8ffac4b..70e755d 100644
--- a/config/msmnile.mk
+++ b/config/msmnile.mk
@@ -28,6 +28,13 @@
 PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_sw43404_amoled_cmd_mode_dsi_boe_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_sw43404_amoled_cmd_mode_dsi_boe_panel_with_DSC.xml
 PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_sw43404_amoled_cmd_mode_dsi_boe_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_sw43404_amoled_video_mode_dsi_boe_panel_with_DSC.xml
 
+#QDCM calibration xml file for primary panel sharp 1080p
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_sharp_1080p_cmd_mode_dsi_panel.xml
+
+#QDCM calibration xml file for secondary panel nt35695b
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_nt35695b_truly_fhd_command_mode_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_nt35695b_truly_fhd_video_mode_dsi_panel.xml
+
 #Enable Charging Icon
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888
 
diff --git a/config/talos.mk b/config/talos.mk
index ba58459..ba69f37 100644
--- a/config/talos.mk
+++ b/config/talos.mk
@@ -30,6 +30,10 @@
 PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_sw43404_amoled_cmd_mode_dsi_boe_panel_with_DSC.xml
 PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_sw43404_amoled_video_mode_dsi_boe_panel_with_DSC.xml
 
+#QDCM calibration xml file for secondary panel nt35695b
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_nt35695b_truly_fhd_command_mode_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_nt35695b_truly_fhd_video_mode_dsi_panel.xml
+
 #Enable Charging Icon
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888
 
diff --git a/config/trinket.mk b/config/trinket.mk
index 3f0cce5..d56de38 100644
--- a/config/trinket.mk
+++ b/config/trinket.mk
@@ -19,7 +19,8 @@
     modetest
 
 #QDCM calibration xml file
-PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_hx83112a_video_mode_dsi_truly_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_td4330_cmd_mode_dsi_truly_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_td4330_video_mode_dsi_truly_panel.xml
 
 #Enable Charging Icon
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888
diff --git a/gralloc/gr_priv_handle.h b/gralloc/gr_priv_handle.h
index ace762e..0968c5c 100644
--- a/gralloc/gr_priv_handle.h
+++ b/gralloc/gr_priv_handle.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution
  *
  * Copyright (C) 2008 The Android Open Source Project
@@ -23,7 +23,9 @@
 #include <log/log.h>
 #include <hardware/gralloc.h>
 #include <hardware/gralloc1.h>
+#ifdef __cplusplus
 #include <cinttypes>
+#endif
 
 #define GRALLOC1_FUNCTION_PERFORM 0x00001000
 
@@ -34,7 +36,12 @@
 #define PRIV_HANDLE_CONST(exp) static_cast<const private_handle_t *>(exp)
 
 #pragma pack(push, 4)
+#ifdef __cplusplus
 struct private_handle_t : public native_handle_t {
+#else
+struct private_handle_t {
+        native_handle_t nativeHandle;
+#endif
   enum {
     PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
     PRIV_FLAGS_USES_ION = 0x00000008,
@@ -85,7 +92,7 @@
   uint64_t base;
   uint64_t base_metadata;
   uint64_t gpuaddr;
-
+#ifdef __cplusplus
   static const int kNumFds = 2;
   static const int kMagic = 'gmsm';
 
@@ -175,6 +182,7 @@
   uint64_t GetUsage() const { return usage; }
 
   uint64_t GetBackingstore() const { return id; }
+#endif
 };
 #pragma pack(pop)
 
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 20e3abc..4a47469 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -585,6 +585,7 @@
   int hmin;
   bool roi_merge;
   uint64_t bit_clk_rate;
+  uint32_t transfer_time_us;
 };
 
 /* Per Connector Info*/
@@ -604,7 +605,6 @@
   uint32_t max_linewidth;
   DRMRotation panel_orientation;
   drm_panel_hdr_properties panel_hdr_prop;
-  uint32_t transfer_time_us;
   drm_msm_ext_hdr_properties ext_hdr_prop;
   bool qsync_support;
   // Connection status of this connector
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 569c4ea..e19eccc 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, 2016-2019 The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -84,6 +84,7 @@
         SET_DSI_CLK = 42, // Set DSI Clk.
         GET_DSI_CLK = 43, // Get DSI Clk.
         GET_SUPPORTED_DSI_CLK = 44, // Get supported DSI Clk.
+        SET_COLOR_MODE_FROM_CLIENT = 45, // Overrides the QDCM mode using the given mode ID
         COMMAND_LIST_END = 400,
     };
 
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 7ef2f6f..1b4d063 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -797,6 +797,11 @@
   */
   virtual bool IsSupportSsppTonemap() = 0;
 
+  /*! @brief Method to free concurrent writeback resoures for primary display.
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError TeardownConcurrentWriteback(void) = 0;
+
   /*
    * Returns a string consisting of a dump of SDM's display and layer related state
    * as programmed to driver
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 14f156b..fa4efb6 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -36,6 +36,7 @@
     kCmdResetLUT,
     kCmdGetDefaultClk,
     kCmdDisableRotatorOneFrame,
+    kCmdSetDisplayState,
     kCmdMax,
   };
 
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index d053c84..eadb497 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -545,6 +545,9 @@
   DisplayCompositionContext *display_comp_ctx =
       reinterpret_cast<DisplayCompositionContext *>(display_ctx);
 
+  resource_intf_->Perform(ResourceInterface::kCmdSetDisplayState,
+                          display_comp_ctx->display_resource_ctx, state);
+
   switch (state) {
   case kStateOff:
     Purge(display_ctx);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 1db20ba..fb88ae3 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1423,7 +1423,8 @@
   uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
 
   for (uint32_t i = 0; i < hw_layers_count; i++) {
-    Layer *sdm_layer = layer_stack->layers.at(hw_layers_.info.index.at(i));
+    uint32_t sdm_layer_index = hw_layers_.info.index.at(i);
+    Layer *sdm_layer = layer_stack->layers.at(sdm_layer_index);
     Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
 
     hw_layer.input_buffer.planes[0].fd = sdm_layer->input_buffer.planes[0].fd;
@@ -1432,6 +1433,12 @@
     hw_layer.input_buffer.size = sdm_layer->input_buffer.size;
     hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd;
     hw_layer.input_buffer.handle_id = sdm_layer->input_buffer.handle_id;
+    // TODO(user): Other FBT layer attributes like surface damage, dataspace, secure camera and
+    // secure display flags are also updated during SetClientTarget() called between validate and
+    // commit. Need to revist this and update it accordingly for FBT layer.
+    if (hw_layers_.info.gpu_target_index == sdm_layer_index) {
+      hw_layer.input_buffer.flags.secure = sdm_layer->input_buffer.flags.secure;
+    }
   }
 
   return;
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index ab6ec16..c8496ac 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -275,6 +275,12 @@
   return error;
 }
 
+DisplayError DisplayBuiltIn::TeardownConcurrentWriteback(void) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  return hw_intf_->TeardownConcurrentWriteback();
+}
+
 DisplayError DisplayBuiltIn::SetRefreshRate(uint32_t refresh_rate, bool final_rate) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
 
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index ffebcb3..a399a67 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -88,6 +88,7 @@
   virtual void PingPongTimeout();
   virtual void PanelDead();
   virtual void HwRecovery(const HWRecoveryEvent sdm_event_code);
+  virtual DisplayError TeardownConcurrentWriteback(void);
 
   // Implement the DppsPropIntf
   virtual DisplayError DppsProcessOps(enum DppsOps op, void *payload, size_t size);
diff --git a/sdm/libs/core/display_pluggable.h b/sdm/libs/core/display_pluggable.h
index d15129c..7716da3 100644
--- a/sdm/libs/core/display_pluggable.h
+++ b/sdm/libs/core/display_pluggable.h
@@ -56,6 +56,7 @@
   virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform) {
     return kErrorNone;
   }
+  virtual DisplayError TeardownConcurrentWriteback(void) { return kErrorNotSupported; }
 
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index 21a7890..bf53c66 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -131,16 +131,16 @@
     fb_config = display_attributes;
   }
 
-  // if display is already connected, unregister display from composition manager and register
-  // the display with new configuration.
-  if (display_comp_ctx_) {
-    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  // if display is already connected, reconfigure the display with new configuration.
+  if (!display_comp_ctx_) {
+    error = comp_manager_->RegisterDisplay(display_id_, display_type_, display_attributes,
+                                           hw_panel_info, mixer_attributes, fb_config,
+                                           &display_comp_ctx_, &(default_qos_data_.clock_hz));
+  } else {
+    error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
+                                              mixer_attributes, fb_config,
+                                              &(default_qos_data_.clock_hz));
   }
-
-  error =
-      comp_manager_->RegisterDisplay(display_id_, display_type_, display_attributes, hw_panel_info,
-                                     mixer_attributes, fb_config, &display_comp_ctx_,
-                                     &(default_qos_data_.clock_hz));
   if (error != kErrorNone) {
     return error;
   }
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index e3daec6..1a672e1 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -69,6 +69,7 @@
   virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform) {
     return kErrorNone;
   }
+  virtual DisplayError TeardownConcurrentWriteback(void) { return kErrorNotSupported; }
   virtual DisplayError GetColorModeCount(uint32_t *mode_count);
 };
 
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index d8a82f7..51a47c8 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -648,6 +648,7 @@
   hw_panel_info_.min_roi_width = connector_info_.modes[index].wmin;
   hw_panel_info_.min_roi_height = connector_info_.modes[index].hmin;
   hw_panel_info_.needs_roi_merge = connector_info_.modes[index].roi_merge;
+  hw_panel_info_.transfer_time_us = connector_info_.modes[index].transfer_time_us;
   hw_panel_info_.dynamic_fps = connector_info_.dynamic_fps;
   hw_panel_info_.qsync_support = connector_info_.qsync_support;
   drmModeModeInfo current_mode = connector_info_.modes[current_mode_index_].mode;
@@ -686,7 +687,6 @@
   hw_panel_info_.primaries.green[1] = connector_info_.panel_hdr_prop.display_primaries[5];
   hw_panel_info_.primaries.blue[0] = connector_info_.panel_hdr_prop.display_primaries[6];
   hw_panel_info_.primaries.blue[1] = connector_info_.panel_hdr_prop.display_primaries[7];
-  hw_panel_info_.transfer_time_us = connector_info_.transfer_time_us;
   hw_panel_info_.dyn_bitclk_support = connector_info_.dyn_bitclk_support;
 
   // no supprt for 90 rotation only flips or 180 supported
@@ -1940,6 +1940,11 @@
     AddSolidfillStage(sf, 0xFF);
     SetSolidfillStages();
   }
+
+  if (!secure_display_active_) {
+    DRMSecurityLevel crtc_security_level = DRMSecurityLevel::SECURE_NON_SECURE;
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SECURITY_LEVEL, token_.crtc_id, crtc_security_level);
+  }
 }
 
 DisplayError HWDeviceDRM::NullCommit(bool synchronous, bool retain_planes) {
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index f8ae241..5be5fad 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -113,6 +113,7 @@
   virtual void PopulateHWPanelInfo();
   virtual DisplayError SetDppsFeature(void *payload, size_t size) { return kErrorNotSupported; }
   virtual DisplayError GetDppsFeatureInfo(void *payload, size_t size) { return kErrorNotSupported; }
+  virtual DisplayError TeardownConcurrentWriteback(void) { return kErrorNotSupported; }
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers) {
     return kErrorNotSupported;
   }
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index ecd0651..0bc95cd 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -334,6 +334,16 @@
   }
 }
 
+DisplayError HWPeripheralDRM::TeardownConcurrentWriteback(void) {
+  if (cwb_config_.enabled) {
+    drm_mgr_intf_->UnregisterDisplay(cwb_config_.token);
+    cwb_config_.enabled = false;
+    registry_.Clear();
+  }
+
+  return kErrorNone;
+}
+
 DisplayError HWPeripheralDRM::SetupConcurrentWritebackModes() {
   // To setup Concurrent Writeback topology, get the Connector ID of Virtual display
   if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::VIRTUAL, &cwb_config_.token)) {
@@ -402,9 +412,7 @@
   bool enabled = hw_resource_.has_concurrent_writeback && output_buffer;
 
   if (!enabled) {
-    drm_mgr_intf_->UnregisterDisplay(cwb_config_.token);
-    cwb_config_.enabled = false;
-    registry_.Clear();
+    TeardownConcurrentWriteback();
   }
 }
 
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index 12d2e6c..518657d 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -60,6 +60,7 @@
   virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
   virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError TeardownConcurrentWriteback(void);
 
  private:
   void SetDestScalarData(HWLayersInfo hw_layer_info, bool validate);
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index dad5fe5..5f451dc 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -112,6 +112,7 @@
   virtual DisplayError SetDisplayDppsAdROI(void *payload) { return kErrorNotSupported; }
   virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
   virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
+  virtual DisplayError TeardownConcurrentWriteback(void) { return kErrorNotSupported; }
 
   enum {
     kHWEventVSync,
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 119a95f..240517a 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -123,6 +123,7 @@
   virtual DisplayError SetDisplayDppsAdROI(void *payload) = 0;
   virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate) = 0;
   virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate) = 0;
+  virtual DisplayError TeardownConcurrentWriteback(void) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index 14ae3ba..a9052e0 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -69,7 +69,16 @@
 LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.6
 LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.7
 endif
-
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_8)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.5
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.6
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.7
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.8
+endif
 
 LOCAL_SRC_FILES               := hwc_session.cpp \
                                  hwc_session_services.cpp \
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index 29f31b0..2dcb9c9 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -58,6 +58,7 @@
   virtual std::string Dump() { return ""; }
   virtual bool IsSupportSsppTonemap() { return false; }
 
+  MAKE_NO_OP(TeardownConcurrentWriteback(void))
   MAKE_NO_OP(Commit(LayerStack *))
   MAKE_NO_OP(GetDisplayState(DisplayState *))
   MAKE_NO_OP(SetDisplayState(DisplayState, bool, int*))
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 0e2e117..d49da4c 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -802,6 +802,9 @@
   // Append client target to the layer stack
   Layer *sdm_client_target = client_target_->GetSDMLayer();
   sdm_client_target->flags.updating = IsLayerUpdating(client_target_);
+  // Derive client target dataspace based on the color mode - bug/115482728
+  int32_t client_target_dataspace = GetDataspaceFromColorMode(GetCurrentColorMode());
+  SetClientTargetDataSpace(client_target_dataspace);
   layer_stack_.layers.push_back(sdm_client_target);
 
   // fall back frame composition to GPU when client target is 10bit
@@ -826,7 +829,7 @@
 HWC2::Error HWCDisplay::SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z) {
   const auto map_layer = layer_map_.find(layer_id);
   if (map_layer == layer_map_.end()) {
-    DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
+    DLOGW("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
     return HWC2::Error::BadLayer;
   }
 
@@ -1154,12 +1157,11 @@
   Layer *sdm_layer = client_target_->GetSDMLayer();
   sdm_layer->frame_rate = std::min(current_refresh_rate_, HWCDisplay::GetThrottlingRefreshRate());
   client_target_->SetLayerSurfaceDamage(damage);
-  if (client_target_->GetLayerDataspace() != dataspace) {
-    client_target_->SetLayerDataspace(dataspace);
-    Layer *sdm_layer = client_target_->GetSDMLayer();
-    // Data space would be validated at GetClientTargetSupport, so just use here.
-    sdm::GetSDMColorSpace(client_target_->GetLayerDataspace(),
-                          &sdm_layer->input_buffer.color_metadata);
+  int translated_dataspace = TranslateFromLegacyDataspace(dataspace);
+  if (client_target_->GetLayerDataspace() != translated_dataspace) {
+    DLOGW("New Dataspace = %d not matching Dataspace from color mode = %d",
+           translated_dataspace, client_target_->GetLayerDataspace());
+    return HWC2::Error::BadParameter;
   }
   client_target_->SetLayerBuffer(target, acquire_fence);
 
@@ -1847,11 +1849,6 @@
       return -EINVAL;
   }
 
-  if (display_status == kDisplayStatusResume || display_status == kDisplayStatusPause) {
-    callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
-    validated_ = false;
-  }
-
   return status;
 }
 
@@ -2305,4 +2302,16 @@
   }
 }
 
+int32_t HWCDisplay::SetClientTargetDataSpace(int32_t dataspace) {
+  if (client_target_->GetLayerDataspace() != dataspace) {
+    client_target_->SetLayerDataspace(dataspace);
+    Layer *sdm_layer = client_target_->GetSDMLayer();
+    // Data space would be validated at GetClientTargetSupport, so just use here.
+    sdm::GetSDMColorSpace(client_target_->GetLayerDataspace(),
+                          &sdm_layer->input_buffer.color_metadata);
+  }
+
+  return 0;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index dd89f97..c38c6bb 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -157,6 +157,9 @@
   virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
   virtual void GetPanelResolution(uint32_t *width, uint32_t *height);
   virtual std::string Dump();
+  virtual DisplayError TeardownConcurrentWriteback(void) {
+    return kErrorNotSupported;
+  }
 
   // Captures frame output in the buffer specified by output_buffer_info. The API is
   // non-blocking and the client is expected to check operation status later on.
@@ -339,6 +342,7 @@
   bool IsLayerUpdating(HWCLayer *layer);
   uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
   virtual void GetUnderScanConfig() { }
+  int32_t SetClientTargetDataSpace(int32_t dataspace);
 
   enum {
     INPUT_LAYER_DUMP,
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index dbac21a..4948c14 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -287,7 +287,7 @@
     DLOGE("failed for mode = %d intent = %d", mode, intent);
     return status;
   }
-  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  callbacks_->Refresh(id_);
   validated_ = false;
   return status;
 }
@@ -299,7 +299,7 @@
     return status;
   }
 
-  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  callbacks_->Refresh(id_);
   validated_ = false;
 
   return status;
@@ -331,7 +331,7 @@
     return status;
   }
 
-  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  callbacks_->Refresh(id_);
 
   return status;
 }
@@ -349,7 +349,7 @@
     return status;
   }
 
-  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  callbacks_->Refresh(id_);
   color_tranform_failed_ = false;
   validated_ = false;
 
@@ -402,6 +402,28 @@
   return status;
 }
 
+DisplayError HWCDisplayBuiltIn::TeardownConcurrentWriteback(void) {
+  DisplayError error = kErrorNotSupported;
+
+  if (output_buffer_.release_fence_fd >= 0) {
+    int32_t release_fence_fd = dup(output_buffer_.release_fence_fd);
+    int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
+    if (ret < 0) {
+      DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+    }
+
+    ::close(release_fence_fd);
+    if (ret)
+      return kErrorResources;
+  }
+
+  if (display_intf_) {
+    error = display_intf_->TeardownConcurrentWriteback();
+  }
+
+  return error;
+}
+
 HWC2::Error HWCDisplayBuiltIn::SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end,
                                                    uint32_t v_start, uint32_t v_end,
                                                    uint32_t factor_in, uint32_t factor_out) {
@@ -437,7 +459,7 @@
   if (error)
     return HWC2::Error::BadConfig;
 
-  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  callbacks_->Refresh(id_);
 
   return HWC2::Error::None;
 }
@@ -538,6 +560,10 @@
     return -EINVAL;
   }
 
+  if (current_power_mode_ != HWC2::PowerMode::On) {
+    return 0;
+  }
+
   if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
     SecureEvent secure_event =
         secure_sessions.test(kSecureDisplay) ? kSecureDisplayStart : kSecureDisplayEnd;
@@ -565,7 +591,7 @@
 
   force_refresh_rate_ = refresh_rate;
 
-  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  callbacks_->Refresh(id_);
 
   return;
 }
@@ -583,7 +609,7 @@
 DisplayError HWCDisplayBuiltIn::Refresh() {
   DisplayError error = kErrorNone;
 
-  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  callbacks_->Refresh(id_);
 
   return error;
 }
diff --git a/sdm/libs/hwc2/hwc_display_builtin.h b/sdm/libs/hwc2/hwc_display_builtin.h
index 682e54f..d4c81e2 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -87,6 +87,7 @@
   virtual DisplayError SetDynamicDSIClock(uint64_t bitclk);
   virtual DisplayError GetDynamicDSIClock(uint64_t *bitclk);
   virtual DisplayError GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates);
+  virtual DisplayError TeardownConcurrentWriteback(void);
 
  private:
   HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 7e9deb9..acad061 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -104,6 +104,9 @@
 int HWCDisplayVirtual::Deinit() {
   int status = 0;
   if (output_buffer_) {
+    if (output_buffer_->acquire_fence_fd >= 0) {
+      close(output_buffer_->acquire_fence_fd);
+    }
     delete output_buffer_;
     output_buffer_ = nullptr;
   }
@@ -195,10 +198,6 @@
 
   status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
 
-  if (output_buffer_->acquire_fence_fd >= 0) {
-    close(output_buffer_->acquire_fence_fd);
-    output_buffer_->acquire_fence_fd = -1;
-  }
   return status;
 }
 
@@ -221,6 +220,11 @@
   }
   const private_handle_t *output_handle = static_cast<const private_handle_t *>(buf);
 
+  // Close the previous acquire fence and update with the latest release fence to avoid fence leak
+  // in case if this function gets invoked multiple times from the client.
+  if (output_buffer_->acquire_fence_fd >= 0) {
+    close(output_buffer_->acquire_fence_fd);
+  }
   // Fill output buffer parameters (width, height, format, plane information, fence)
   output_buffer_->acquire_fence_fd = dup(release_fence);
 
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 45cfb16..4caad2a 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -182,6 +182,10 @@
     }
   }
 
+  if (dataspace == HAL_DATASPACE_UNKNOWN) {
+    dataspace = HAL_DATASPACE_V0_SRGB;
+  }
+
   return dataspace;
 }
 
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 6c6e56f..cf52eec 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -77,7 +77,7 @@
 int HWCSession::null_display_mode_ = 0;
 
 // Map the known color modes to dataspace.
-static int32_t GetDataspace(ColorMode mode) {
+int32_t GetDataspaceFromColorMode(ColorMode mode) {
   switch (mode) {
     case ColorMode::SRGB:
     case ColorMode::NATIVE:
@@ -449,15 +449,15 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
   auto *hwc_session = static_cast<HWCSession *>(device);
+  hwc2_display_t active_builtin_disp_id = hwc_session->GetActiveBuiltinDisplay();
 
-  if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
+  if (active_builtin_disp_id < kNumDisplays) {
+    Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
     std::bitset<kSecureMax> secure_sessions = 0;
-    hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]->GetActiveSecureSession(&secure_sessions);
+    hwc_session->hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
     if (secure_sessions.any()) {
-      DLOGI("Destroying virtual display id:%" PRIu64, display);
-      DLOGW("Secure session is active, deferring destruction of virtual display");
+      DLOGW("Secure session is active, defer destruction of virtual display id:%" PRIu64, display);
       hwc_session->destroy_virtual_disp_pending_ = true;
       return HWC2_ERROR_NONE;
     }
@@ -682,7 +682,7 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  hwc_session->HandleSecureSession(display);
+  hwc_session->HandleSecureSession();
   {
     SEQUENCE_EXIT_SCOPE_LOCK(locker_[display]);
     if (!hwc_session->hwc_display_[display]) {
@@ -1003,7 +1003,7 @@
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   // TODO(user): Handle secure session, handle QDCM solid fill
   auto status = HWC2::Error::BadDisplay;
-  hwc_session->HandleSecureSession(display);
+  hwc_session->HandleSecureSession();
   {
     SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
     if (power_on_pending_[display]) {
@@ -1157,10 +1157,13 @@
     return HWC2::Error::NoResources;
   }
 
-  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+  if (active_builtin_disp_id < kNumDisplays) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
     std::bitset<kSecureMax> secure_sessions = 0;
-    hwc_display_[HWC_DISPLAY_PRIMARY]->GetActiveSecureSession(&secure_sessions);
+    if (hwc_display_[active_builtin_disp_id]) {
+      hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
+    }
     if (secure_sessions.any()) {
       DLOGE("Secure session is active, cannot create virtual display.");
       return HWC2::Error::Unsupported;
@@ -1196,6 +1199,13 @@
         continue;
       }
 
+    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+      error = hwc_display_[HWC_DISPLAY_PRIMARY]->TeardownConcurrentWriteback();
+      if (error) {
+        return HWC2::Error::NoResources;
+      }
+    }
+
       status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, client_id,
                                          info.display_id, width, height, format, &hwc_display);
       // TODO(user): validate width and height support
@@ -1210,12 +1220,14 @@
     }
 
     if (status) {
-      return HWC2::Error::BadDisplay;
+      return HWC2::Error::NoResources;
     }
   }
 
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
-  hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
+  if (active_builtin_disp_id < kNumDisplays) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
+    hwc_display_[active_builtin_disp_id]->ResetValidation();
+  }
 
   return HWC2::Error::None;
 }
@@ -1546,6 +1558,14 @@
       status = GetSupportedDsiClk(input_parcel, output_parcel);
       break;
 
+    case qService::IQService::SET_COLOR_MODE_FROM_CLIENT:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = SetColorModeFromClient(input_parcel);
+      break;
+
     default:
       DLOGW("QService command = %d is not supported.", command);
       break;
@@ -1818,6 +1838,27 @@
   return 0;
 }
 
+android::status_t HWCSession::SetColorModeFromClient(const android::Parcel *input_parcel) {
+  int display = input_parcel->readInt32();
+  auto mode = input_parcel->readInt32();
+  auto device = static_cast<hwc2_device_t *>(this);
+
+  int disp_idx = GetDisplayIndex(display);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", display);
+    return -EINVAL;
+  }
+
+  auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
+                                 &HWCDisplay::SetColorModeFromClientApi, mode);
+  if (err != HWC2_ERROR_NONE)
+    return -EINVAL;
+
+  Refresh(static_cast<hwc2_display_t>(disp_idx));
+
+  return 0;
+}
+
 android::status_t HWCSession::RefreshScreen(const android::Parcel *input_parcel) {
   int display = input_parcel->readInt32();
 
@@ -2185,9 +2226,10 @@
         (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
 
     std::bitset<kSecureMax> secure_sessions = 0;
-    {
-      Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
-      hwc_display_[HWC_DISPLAY_PRIMARY]->GetActiveSecureSession(&secure_sessions);
+    hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+    if (active_builtin_disp_id < kNumDisplays) {
+      Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
+      hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
     }
     if (secure_sessions[kSecureDisplay] || hwc_display_[virtual_display_index]) {
       // Defer hotplug events.
@@ -2518,20 +2560,23 @@
     return status;
   }
 
-  // Primary display needs revalidation
-  {
-    SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
-    hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
-  }
+  // Active builtin display needs revalidation
+  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+  if (active_builtin_disp_id < kNumDisplays) {
+    {
+      SCOPE_LOCK(locker_[active_builtin_disp_id]);
+      hwc_display_[active_builtin_disp_id]->ResetValidation();
+    }
 
-  if (client_connected_) {
-    Refresh(HWC_DISPLAY_PRIMARY);
-  }
+    if (client_connected_) {
+      Refresh(active_builtin_disp_id);
+    }
 
-  // Do not sleep if this method is called from client thread.
-  if (delay_hotplug) {
-    // wait sufficient time to ensure resources are available for new display connection.
-    usleep(UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)) * 2 / 1000);
+    // Do not sleep if this method is called from client thread.
+    if (delay_hotplug) {
+      // wait sufficient time to ensure resources are available for new display connection.
+      usleep(UINT32(GetVsyncPeriod(INT32(active_builtin_disp_id))) * 2 / 1000);
+    }
   }
 
   for (auto client_id : pending_hotplugs) {
@@ -2723,16 +2768,18 @@
   Refresh(HWC_DISPLAY_PRIMARY);
 }
 
-void HWCSession::HandleSecureSession(hwc2_display_t disp_id) {
+void HWCSession::HandleSecureSession() {
   std::bitset<kSecureMax> secure_sessions = 0;
   {
-    Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
-    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
-      hwc_display_[HWC_DISPLAY_PRIMARY]->GetActiveSecureSession(&secure_sessions);
+    hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+    if (active_builtin_disp_id >= kNumDisplays) {
+      return;
     }
+    Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
+    hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
   }
 
-  // If it is called during primary prepare/commit, we need to pause any onging commit on
+  // If it is called during primary prepare/commit, we need to pause any ongoing commit on
   // external/virtual display.
   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
     Locker::ScopeLock lock_d(locker_[display]);
@@ -2743,17 +2790,20 @@
 }
 
 void HWCSession::HandlePowerOnPending(hwc2_display_t disp_id, int retire_fence) {
-  if (disp_id != HWC_DISPLAY_PRIMARY) {
+  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+  if (disp_id != active_builtin_disp_id) {
     return;
   }
 
-  Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
+  Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
   bool power_on_pending = false;
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1; display < kNumDisplays; display++) {
-    Locker::ScopeLock lock_d(locker_[display]);
-    if (power_on_pending_[display]) {
-      power_on_pending = true;
-      break;
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+    if (display != active_builtin_disp_id) {
+      Locker::ScopeLock lock_d(locker_[display]);
+      if (power_on_pending_[display]) {
+        power_on_pending = true;
+        break;
+      }
     }
   }
   if (power_on_pending) {
@@ -2771,56 +2821,59 @@
     return;
   }
 
-  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1; display < kNumDisplays; display++) {
-    Locker::ScopeLock lock_d(locker_[display]);
-    if (power_on_pending_[display] && hwc_display_[display]) {
-      HWC2::Error status =
+  for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < kNumDisplays; display++) {
+    if (display != active_builtin_disp_id) {
+      Locker::ScopeLock lock_d(locker_[display]);
+      if (power_on_pending_[display] && hwc_display_[display]) {
+        HWC2::Error status =
           hwc_display_[display]->SetPowerMode(HWC2::PowerMode::On, false /* teardown */);
-      if (status == HWC2::Error::None) {
-        power_on_pending_[display] = false;
+        if (status == HWC2::Error::None) {
+          power_on_pending_[display] = false;
+        }
       }
     }
   }
 }
 
 void HWCSession::HandleHotplugPending(hwc2_display_t disp_id, int retire_fence) {
-  if (disp_id != HWC_DISPLAY_PRIMARY ||
+  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+  if (disp_id != active_builtin_disp_id ||
       (kHotPlugNone == hotplug_pending_event_ && !destroy_virtual_disp_pending_)) {
     return;
   }
 
   std :: bitset < kSecureMax > secure_sessions = 0;
-  {
-    Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
-    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
-      if (!hwc_display_[HWC_DISPLAY_PRIMARY]->IsDisplayCommandMode()) {
-        if (destroy_virtual_disp_pending_ || kHotPlugEvent == hotplug_pending_event_) {
-          if (retire_fence >= 0) {
-            int error = sync_wait(retire_fence, 1000);
-            if (error < 0) {
-              DLOGE("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
-            }
-          }
-        }
+  if (active_builtin_disp_id < kNumDisplays) {
+    Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
+    hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
+  }
+
+  if (secure_sessions.any() || active_builtin_disp_id == kNumDisplays) {
+    return;
+  }
+
+  if (destroy_virtual_disp_pending_ || kHotPlugEvent == hotplug_pending_event_) {
+    if (retire_fence >= 0) {
+      int error = sync_wait(retire_fence, 1000);
+      if (error < 0) {
+        DLOGE("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
       }
-      hwc_display_[HWC_DISPLAY_PRIMARY]->GetActiveSecureSession(&secure_sessions);
     }
-  }
-  // Destroy the pending virtual display if secure session not present.
-  if (!secure_sessions.any() && destroy_virtual_disp_pending_) {
-    for (auto &map_info : map_info_virtual_) {
-      DestroyDisplay(&map_info);
-      destroy_virtual_disp_pending_ = false;
+    // Destroy the pending virtual display if secure session not present.
+    if (destroy_virtual_disp_pending_) {
+      for (auto &map_info : map_info_virtual_) {
+        DestroyDisplay(&map_info);
+        destroy_virtual_disp_pending_ = false;
+      }
     }
-  }
-  // Handle connect/disconnect hotplugs if secure session is not present.
-  hwc2_display_t virtual_display_index = (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
-  if (!secure_sessions.any() && !hwc_display_[virtual_display_index] &&
-      kHotPlugEvent == hotplug_pending_event_) {
-    if (HandlePluggableDisplays(true)) {
-      DLOGE("Could not handle hotplug. Event dropped.");
+    // Handle connect/disconnect hotplugs if secure session is not present.
+    hwc2_display_t virtual_display_idx = (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
+    if (!hwc_display_[virtual_display_idx] && kHotPlugEvent == hotplug_pending_event_) {
+      if (HandlePluggableDisplays(true)) {
+        DLOGE("Could not handle hotplug. Event dropped.");
+      }
+      hotplug_pending_event_ = kHotPlugNone;
     }
-    hotplug_pending_event_ = kHotPlugNone;
   }
 }
 
@@ -2839,7 +2892,7 @@
 
   if (hwc_display) {
     *format = HAL_PIXEL_FORMAT_RGB_888;
-    *dataspace = GetDataspace(hwc_display->GetCurrentColorMode());
+    *dataspace = GetDataspaceFromColorMode(hwc_display->GetCurrentColorMode());
     return HWC2_ERROR_NONE;
   }
 
@@ -2976,18 +3029,23 @@
   return static_cast<android::status_t>(controlIdlePowerCollapse(enable, synchronous));
 #else
   {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
-    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+    if (active_builtin_disp_id >= kNumDisplays) {
+      DLOGE("No active displays");
+      return -EINVAL;
+    }
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
+    if (hwc_display_[active_builtin_disp_id]) {
       DLOGE("Primary display is not ready");
       return -EINVAL;
     }
-    auto error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
-    if (error != kErrorNone) {
-      return (error == kErrorNotSupported) ? 0 : -EINVAL;
+    auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable, synchronous);
+    if (err != kErrorNone) {
+      return (err == kErrorNotSupported) ? 0 : -EINVAL;
     }
     if (!enable) {
-      Refresh(HWC_DISPLAY_PRIMARY);
-      int32_t error = locker_[HWC_DISPLAY_PRIMARY].WaitFinite(kCommitDoneTimeoutMs);
+      Refresh(active_builtin_disp_id);
+      int32_t error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
       if (error == ETIMEDOUT) {
         DLOGE("Timed out!! Next frame commit done event not received!!");
         return error;
@@ -2999,4 +3057,18 @@
 #endif
 }
 
+hwc2_display_t HWCSession::GetActiveBuiltinDisplay() {
+  hwc2_display_t disp_id = kNumDisplays;
+  Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
+  Locker::ScopeLock lock_b2(locker_[HWC_DISPLAY_BUILTIN_2]);
+  if (hwc_display_[HWC_DISPLAY_PRIMARY] &&
+      hwc_display_[HWC_DISPLAY_PRIMARY]->GetCurrentPowerMode() == HWC2::PowerMode::On) {
+    disp_id = HWC_DISPLAY_PRIMARY;
+  } else if (hwc_display_[HWC_DISPLAY_BUILTIN_2] &&
+      hwc_display_[HWC_DISPLAY_BUILTIN_2]->GetCurrentPowerMode() == HWC2::PowerMode::On) {
+    disp_id = HWC_DISPLAY_BUILTIN_2;
+  }
+  return disp_id;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index bf66507..676d3a1 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -20,7 +20,9 @@
 #ifndef __HWC_SESSION_H__
 #define __HWC_SESSION_H__
 
-#ifdef DISPLAY_CONFIG_1_7
+#ifdef DISPLAY_CONFIG_1_8
+#include <vendor/display/config/1.8/IDisplayConfig.h>
+#elif DISPLAY_CONFIG_1_7
 #include <vendor/display/config/1.7/IDisplayConfig.h>
 #elif DISPLAY_CONFIG_1_6
 #include <vendor/display/config/1.6/IDisplayConfig.h>
@@ -59,7 +61,9 @@
 
 namespace sdm {
 
-#ifdef DISPLAY_CONFIG_1_7
+#ifdef DISPLAY_CONFIG_1_8
+using vendor::display::config::V1_8::IDisplayConfig;
+#elif DISPLAY_CONFIG_1_7
 using vendor::display::config::V1_7::IDisplayConfig;
 #elif DISPLAY_CONFIG_1_6
 using vendor::display::config::V1_6::IDisplayConfig;
@@ -79,6 +83,8 @@
 using ::android::hardware::Return;
 using ::android::hardware::hidl_string;
 
+int32_t GetDataspaceFromColorMode(ColorMode mode);
+
 // Create a singleton uevent listener thread valid for life of hardware composer process.
 // This thread blocks on uevents poll inside uevent library implementation. This poll exits
 // only when there is a valid uevent, it can not be interrupted otherwise. Tieing life cycle
@@ -339,6 +345,10 @@
                                 getDebugProperty_cb _hidl_cb) override;
 #endif
 
+#ifdef DISPLAY_CONFIG_1_8
+  Return<void> getActiveBuiltinDisplayAttributes(getDisplayAttributes_cb _hidl_cb) override;
+#endif
+
   // QClient methods
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                            android::Parcel *output_parcel);
@@ -362,6 +372,7 @@
   android::status_t SetColorModeWithRenderIntentOverride(const android::Parcel *input_parcel);
 
   android::status_t SetColorModeById(const android::Parcel *input_parcel);
+  android::status_t SetColorModeFromClient(const android::Parcel *input_parcel);
   android::status_t getComposerStatus();
   android::status_t SetQSyncMode(const android::Parcel *input_parcel);
   android::status_t SetIdlePC(const android::Parcel *input_parcel);
@@ -379,13 +390,14 @@
   HWC2::Error ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
                                       uint32_t *out_num_requests);
   HWC2::Error PresentDisplayInternal(hwc2_display_t display, int32_t *out_retire_fence);
-  void HandleSecureSession(hwc2_display_t display);
+  void HandleSecureSession();
   void HandlePowerOnPending(hwc2_display_t display, int retire_fence);
   void HandleHotplugPending(hwc2_display_t disp_id, int retire_fence);
   void UpdateVsyncSource();
   hwc2_display_t GetNextVsyncSource();
   DisplayClass GetDisplayClass(hwc2_display_t display_id);
   bool IsPluggableDisplayConnected();
+  hwc2_display_t GetActiveBuiltinDisplay();
 
   CoreInterface *core_intf_ = nullptr;
   HWCDisplay *hwc_display_[kNumDisplays] = {nullptr};
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 940a55c..30a0863 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -126,7 +126,21 @@
   } else if (!hwc_display_[disp_idx]) {
     DLOGW("Display is not connected");
   } else {
-    return hwc_display_[disp_idx]->SetDisplayStatus(status);
+    int err = hwc_display_[disp_idx]->SetDisplayStatus(status);
+    if (err != 0) {
+      return err;
+    }
+
+    if (status == HWCDisplay::kDisplayStatusResume || status == HWCDisplay::kDisplayStatusPause) {
+      hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+      if (active_builtin_disp_id < kNumDisplays) {
+        {
+          SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
+          hwc_display_[active_builtin_disp_id]->ResetValidation();
+        }
+        callbacks_.Refresh(active_builtin_disp_id);
+      }
+    }
   }
 
   return -EINVAL;
@@ -465,7 +479,12 @@
 }
 
 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+  if (active_builtin_disp_id >= kNumDisplays) {
+    DLOGE("No active displays");
+    return -EINVAL;
+  }
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
 
   if (null_display_mode_) {
     return 0;
@@ -476,15 +495,15 @@
     return -ENOENT;
   }
 
-  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
-    DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
+  if (!hwc_display_[active_builtin_disp_id]) {
+    DLOGW("Display = %d is not connected.", active_builtin_disp_id);
     return -ENODEV;
   }
 
   HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
 
   // trigger invalidate to apply new bw caps.
-  Refresh(HWC_DISPLAY_PRIMARY);
+  Refresh(active_builtin_disp_id);
 
   if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
     return -EINVAL;
@@ -492,7 +511,7 @@
 
   new_bw_mode_ = true;
   need_invalidate_ = true;
-  hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
+  hwc_display_[active_builtin_disp_id]->ResetValidation();
 
   return 0;
 }
@@ -597,17 +616,23 @@
 
 #ifdef DISPLAY_CONFIG_1_3
 Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchronous) {
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
+  if (active_builtin_disp_id >= kNumDisplays) {
+    DLOGE("No active displays");
+    return -EINVAL;
+  }
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
 
-  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+  if (hwc_display_[active_builtin_disp_id]) {
     if (!enable) {
       if (!idle_pc_ref_cnt_) {
-        auto err = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
+        auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
+                                                                                  synchronous);
         if (err != kErrorNone) {
           return (err == kErrorNotSupported) ? 0 : -EINVAL;
         }
-        Refresh(HWC_DISPLAY_PRIMARY);
-        int32_t error = locker_[HWC_DISPLAY_PRIMARY].WaitFinite(kCommitDoneTimeoutMs);
+        Refresh(active_builtin_disp_id);
+        int32_t error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
         if (error == ETIMEDOUT) {
           DLOGE("Timed out!! Next frame commit done event not received!!");
           return error;
@@ -617,7 +642,8 @@
       idle_pc_ref_cnt_++;
     } else if (idle_pc_ref_cnt_ > 0) {
       if (!(idle_pc_ref_cnt_ - 1)) {
-        auto err = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
+        auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
+                                                                                  synchronous);
         if (err != kErrorNone) {
           return (err == kErrorNotSupported) ? 0 : -EINVAL;
         }
@@ -628,7 +654,7 @@
     return 0;
   }
 
-  DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
+  DLOGW("Display = %d is not connected.", active_builtin_disp_id);
   return -ENODEV;
 }
 #endif  // DISPLAY_CONFIG_1_3
@@ -742,4 +768,41 @@
 }
 #endif
 
+#ifdef DISPLAY_CONFIG_1_8
+Return<void> HWCSession::getActiveBuiltinDisplayAttributes(
+                                          getDisplayAttributes_cb _hidl_cb) {
+  int32_t error = -EINVAL;
+  IDisplayConfig::DisplayAttributes display_attributes = {};
+  hwc2_display_t disp_id = GetActiveBuiltinDisplay();
+
+  if (disp_id >= kNumDisplays) {
+    DLOGE("Invalid display = %d", disp_id);
+  } else {
+    if (hwc_display_[disp_id]) {
+      uint32_t config_index = 0;
+      HWC2::Error ret = hwc_display_[disp_id]->GetActiveConfig(&config_index);
+      if (ret != HWC2::Error::None) {
+        goto err;
+      }
+      DisplayConfigVariableInfo var_info;
+      error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(INT(config_index), &var_info);
+      if (!error) {
+        display_attributes.vsyncPeriod = var_info.vsync_period_ns;
+        display_attributes.xRes = var_info.x_pixels;
+        display_attributes.yRes = var_info.y_pixels;
+        display_attributes.xDpi = var_info.x_dpi;
+        display_attributes.yDpi = var_info.y_dpi;
+        display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
+        display_attributes.isYuv = var_info.is_yuv;
+      }
+    }
+  }
+
+err:
+  _hidl_cb(error, display_attributes);
+
+  return Void();
+}
+#endif  // DISPLAY_CONFIG_1_8
+
 }  // namespace sdm