Merge "composer: Fix TUI state during unprepare"
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index b35a41e..6eb9468 100755
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -489,25 +489,15 @@
 int HWCDisplay::Init() {
   DisplayError error = kErrorNone;
 
-  HWCDebugHandler::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &null_display_mode_);
-
-  if (null_display_mode_) {
-    DisplayNull *disp_null = new DisplayNull();
-    disp_null->Init();
-    layer_stack_.flags.use_metadata_refresh_rate = false;
-    display_intf_ = disp_null;
-    DLOGI("Enabling null display mode for display type %d", type_);
-  } else {
-    error = core_intf_->CreateDisplay(sdm_id_, this, &display_intf_);
-    if (error != kErrorNone) {
-      if (kErrorDeviceRemoved == error) {
-        DLOGW("Display creation cancelled. Display %d-%d removed.", sdm_id_, type_);
-        return -ENODEV;
-      } else {
-        DLOGE("Display create failed. Error = %d display_id = %d event_handler = %p disp_intf = %p",
-              error, sdm_id_, this, &display_intf_);
-        return -EINVAL;
-      }
+  error = core_intf_->CreateDisplay(sdm_id_, this, &display_intf_);
+  if (error != kErrorNone) {
+    if (kErrorDeviceRemoved == error) {
+      DLOGW("Display creation cancelled. Display %d-%d removed.", sdm_id_, type_);
+      return -ENODEV;
+    } else {
+      DLOGE("Display create failed. Error = %d display_id = %d event_handler = %p disp_intf = %p",
+            error, sdm_id_, this, display_intf_);
+      return -EINVAL;
     }
   }
 
@@ -599,15 +589,10 @@
 }
 
 int HWCDisplay::Deinit() {
-  if (null_display_mode_) {
-    delete static_cast<DisplayNull *>(display_intf_);
-    display_intf_ = nullptr;
-  } else {
-    DisplayError error = core_intf_->DestroyDisplay(display_intf_);
-    if (error != kErrorNone) {
-      DLOGE("Display destroy failed. Error = %d", error);
-      return -EINVAL;
-    }
+  DisplayError error = core_intf_->DestroyDisplay(display_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Display destroy failed. Error = %d", error);
+    return -EINVAL;
   }
 
   delete client_target_;
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index 758ee1c..624750b 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -41,7 +41,6 @@
 #include <string>
 #include <utility>
 #include <vector>
-#include "display_null.h"
 #include "histogram_collector.h"
 #include "hwc_buffer_allocator.h"
 #include "hwc_callbacks.h"
@@ -646,6 +645,7 @@
   std::condition_variable cwb_cv_;
   std::map<CWBClient, CWBCaptureResponse> cwb_capture_status_map_;
   static constexpr unsigned int kCwbWaitMs = 100;
+  bool validate_done_ = false;
 
  private:
   bool CanSkipSdmPrepare(uint32_t *num_types, uint32_t *num_requests);
@@ -653,7 +653,6 @@
   qService::QService *qservice_ = NULL;
   DisplayClass display_class_;
   uint32_t geometry_changes_on_doze_suspend_ = GeometryChanges::kNone;
-  int null_display_mode_ = 0;
   bool first_cycle_ = true;  // false if a display commit has succeeded on the device.
   shared_ptr<Fence> release_fence_ = nullptr;
   hwc2_config_t pending_config_index_ = 0;
@@ -662,7 +661,6 @@
   bool game_supported_ = false;
   uint64_t elapse_timestamp_ = 0;
   bool draw_method_set_ = false;
-  bool validate_done_ = false;
   bool client_target_3_1_set_ = false;
   bool is_client_up_ = false;
 };
diff --git a/composer/hwc_display_event_handler.h b/composer/hwc_display_event_handler.h
index 2014283..391ed99 100644
--- a/composer/hwc_display_event_handler.h
+++ b/composer/hwc_display_event_handler.h
@@ -28,42 +28,6 @@
 */
 
 /*
-* Changes from Qualcomm Innovation Center are provided under the following license:
-*
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted (subject to the limitations in the
-* disclaimer below) provided that the following conditions are met:
-*
-*    * Redistributions of source code must retain the above copyright
-*      notice, this list of conditions and the following disclaimer.
-*
-*    * Redistributions in binary form must reproduce the above
-*      copyright notice, this list of conditions and the following
-*      disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*
-*    * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
-*      contributors may be used to endorse or promote products derived
-*      from this software without specific prior written permission.
-*
-* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
-* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
-* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
  * Changes from Qualcomm Innovation Center are provided under the following license:
  *
  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
diff --git a/composer/hwc_display_virtual_gpu.cpp b/composer/hwc_display_virtual_gpu.cpp
index 6e2700f..e8b897f 100644
--- a/composer/hwc_display_virtual_gpu.cpp
+++ b/composer/hwc_display_virtual_gpu.cpp
@@ -27,6 +27,13 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
 #include "hwc_display_virtual_gpu.h"
 #include "hwc_session.h"
 #include "QtiGralloc.h"
@@ -39,8 +46,13 @@
   // Create client target.
   client_target_ = new HWCLayer(id_, buffer_allocator_);
 
-  // Calls into SDM need to be dropped. Create Null Display interface.
-  display_intf_ = new DisplayNull();
+  // Create Null Display interface.
+  DisplayError error = core_intf_->CreateNullDisplay(&display_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Null Display create failed. Error = %d display_id = %d disp_intf = %p",
+          error, sdm_id_, display_intf_);
+    return -EINVAL;
+  }
 
   disable_animation_ = Debug::IsExtAnimDisabled();
 
@@ -53,7 +65,12 @@
     color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeDestroyInstance, nullptr);
   }
 
-  delete static_cast<DisplayNull *>(display_intf_);
+  DisplayError error = core_intf_->DestroyNullDisplay(display_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Null Display destroy failed. Error = %d", error);
+    return -EINVAL;
+  }
+
   delete client_target_;
 
   for (auto hwc_layer : layer_set_) {
@@ -79,7 +96,6 @@
   layer_requests_.clear();
 
   // Mark all layers to GPU if there is no need to bypass.
-  bool fbt_compatible = true;
   bool needs_gpu_bypass = NeedsGPUBypass() || FreezeScreen();
   for (auto hwc_layer : layer_set_) {
     auto layer = hwc_layer->GetSDMLayer();
@@ -104,9 +120,7 @@
   *out_num_types = UINT32(layer_changes_.size());
   *out_num_requests = UINT32(layer_requests_.size());;
   has_client_composition_ = !needs_gpu_bypass;
-
-  // FBT is compatible if all layers are compatible or gpu is bypassed.
-  fbt_compatible_ = has_client_composition_ && fbt_compatible;
+  validate_done_ = true;
 
   return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
 }
@@ -117,12 +131,9 @@
                                                   uint32_t *out_num_requests, bool *needs_commit) {
   // Perform validate and commit.
   auto status = Validate(out_num_types, out_num_requests);
-  if (!fbt_compatible_) {
-    *needs_commit = true;
-    return status;
-  }
 
-  return Present(out_retire_fence);
+  *needs_commit = true;
+  return status;
 }
 
 HWC2::Error HWCDisplayVirtualGPU::SetOutputBuffer(buffer_handle_t buf,
@@ -144,6 +155,16 @@
     if (!buffer_allocator_->GetBufferGeometry(hnd, slice_width, slice_height)) {
       output_buffer_.unaligned_width = slice_width;
       output_buffer_.unaligned_height = slice_height;
+      // Update buffer width and height.
+      int new_aligned_w = 0;
+      int new_aligned_h = 0;
+      int output_handle_format = 0;;
+      buffer_allocator_->GetFormat(hnd, output_handle_format);
+      buffer_allocator_->GetAlignedWidthAndHeight(INT(slice_width), INT(slice_height),
+                                                  output_handle_format, 0, &new_aligned_w,
+                                                  &new_aligned_h);
+      output_buffer_.width = UINT32(new_aligned_w);
+      output_buffer_.height = UINT32(new_aligned_h);
       color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeReset, nullptr);
     }
   }
diff --git a/composer/hwc_display_virtual_gpu.h b/composer/hwc_display_virtual_gpu.h
index 78a0873..e96d86d 100644
--- a/composer/hwc_display_virtual_gpu.h
+++ b/composer/hwc_display_virtual_gpu.h
@@ -27,6 +27,13 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
 #ifndef __HWC_DISPLAY_VIRTUAL_GPU_H__
 #define __HWC_DISPLAY_VIRTUAL_GPU_H__
 
@@ -83,7 +90,6 @@
 
   bool disable_animation_ = false;
   bool animation_in_progress_ = false;
-  bool fbt_compatible_ = false;
 };
 
 }  // namespace sdm
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index d576bb9..9204192 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -82,7 +82,6 @@
 Locker HWCSession::display_config_locker_;
 std::mutex HWCSession::command_seq_mutex_;
 static const int kSolidFillDelay = 100 * 1000;
-int HWCSession::null_display_mode_ = 0;
 static const uint32_t kBrightnessScaleMax = 100;
 static const uint32_t kSvBlScaleMax = 65535;
 Locker HWCSession::vm_release_locker_[HWCCallbacks::kNumDisplays];
@@ -305,8 +304,6 @@
     HWCDebugHandler::DebugAll(value, value);
   }
 
-  HWCDebugHandler::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &null_display_mode_);
-  DLOGI("null_display_mode_: %d", null_display_mode_);
   HWCDebugHandler::Get()->GetProperty(DISABLE_HOTPLUG_BWCHECK, &disable_hotplug_bwcheck_);
   DLOGI("disable_hotplug_bwcheck_: %d", disable_hotplug_bwcheck_);
   HWCDebugHandler::Get()->GetProperty(DISABLE_MASK_LAYER_HINT, &disable_mask_layer_hint_);
@@ -315,12 +312,8 @@
                                       &enable_primary_reconfig_req_);
   DLOGI("enable_primary_reconfig_req_: %d", enable_primary_reconfig_req_);
 
-  if (!null_display_mode_) {
-    g_hwc_uevent_.Register(this);
-    DLOGI("Registered HWCSession as the HWCUEvent handler");
-  } else {
-    DLOGI("Did not register HWCSession as the HWCUEvent handler");
-  }
+  g_hwc_uevent_.Register(this);
+  DLOGI("Registered HWCSession as the HWCUEvent handler");
 
   value = 0;
   Debug::Get()->GetProperty(ENABLE_ASYNC_VDS_CREATION, &value);
@@ -354,10 +347,6 @@
 }
 
 void HWCSession::PostInit() {
-  if (null_display_mode_) {
-    return;
-  }
-
   // Start services which need IDisplayConfig to be up.
   // This avoids deadlock between composer and its clients.
   auto hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
@@ -384,13 +373,11 @@
     color_mgr_->DestroyColorManager();
   }
 
-  if (!null_display_mode_) {
-    g_hwc_uevent_.Register(nullptr);
+  g_hwc_uevent_.Register(nullptr);
 
-    DisplayError error = CoreInterface::DestroyCore();
-    if (error != kErrorNone) {
-      DLOGE("Display core de-initialization failed. Error = %d", error);
-    }
+  DisplayError error = CoreInterface::DestroyCore();
+  if (error != kErrorNone) {
+    DLOGE("Display core de-initialization failed. Error = %d", error);
   }
 
   return 0;
@@ -407,11 +394,6 @@
 
   map_info_primary_.client_id = qdutils::DISPLAY_PRIMARY;
 
-  if (null_display_mode_) {
-    InitSupportedNullDisplaySlots();
-    return;
-  }
-
   ipc_intf_ = std::make_shared<IPCImpl>(IPCImpl());
   ipc_intf_->Init();
 
@@ -491,17 +473,6 @@
   is_hdr_display_.resize(UINT32(base_id));
 }
 
-void HWCSession::InitSupportedNullDisplaySlots() {
-  if (!null_display_mode_) {
-    DLOGE("Should only be invoked during null display");
-    return;
-  }
-
-  map_info_primary_.client_id = 0;
-  // Resize HDR supported map to total number of displays
-  is_hdr_display_.resize(1);
-}
-
 int HWCSession::GetDisplayIndex(int dpy) {
   DisplayMapInfo *map_info = nullptr;
   switch (dpy) {
@@ -587,10 +558,6 @@
     return  HWC2_ERROR_BAD_PARAMETER;
   }
 
-  if (null_display_mode_) {
-    return 0;
-  }
-
   auto status = CreateVirtualDisplayObj(width, height, format, out_display_id);
   if (status == HWC2::Error::None) {
     DLOGI("Created virtual display id:%" PRIu64 ", res: %dx%d", *out_display_id, width, height);
@@ -1342,11 +1309,6 @@
 }
 
 void HWCSession::GetVirtualDisplayList() {
-  if (null_display_mode_) {
-    DLOGI("In null display mode, skip handling of virtual displays list");
-    return;
-  }
-
   HWDisplaysInfo hw_displays_info = {};
   core_intf_->GetDisplaysStatus(&hw_displays_info);
 
@@ -2863,20 +2825,10 @@
   int status = -EINVAL;
   HWDisplaysInfo hw_displays_info = {};
 
-  if (null_display_mode_) {
-    HWDisplayInfo hw_info = {};
-    hw_info.display_type = kBuiltIn;
-    hw_info.is_connected = 1;
-    hw_info.is_primary = 1;
-    hw_info.is_wb_ubwc_supported = 0;
-    hw_info.display_id = 1;
-    hw_displays_info[hw_info.display_id] = hw_info;
-  } else {
-    DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
-    if (error != kErrorNone) {
-      DLOGE("Failed to get connected display list. Error = %d", error);
-      return status;
-    }
+  DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+  if (error != kErrorNone) {
+    DLOGE("Failed to get connected display list. Error = %d", error);
+    return status;
   }
 
   SCOPE_LOCK(primary_display_lock_);
@@ -2951,11 +2903,6 @@
 }
 
 int HWCSession::HandleBuiltInDisplays() {
-  if (null_display_mode_) {
-    DLOGW("Skipped BuiltIn display handling in null-display mode");
-    return 0;
-  }
-
   SCOPE_LOCK(primary_display_lock_);
   while (primary_pending_) {
     primary_display_lock_.Wait();
@@ -3064,10 +3011,6 @@
   HWDisplaysInfo hw_displays_info = {};
   {
     SCOPE_LOCK(pluggable_handler_lock_);
-    if (null_display_mode_) {
-      DLOGW("Skipped pluggable display handling in null-display mode");
-      return 0;
-    }
 
     hwc2_display_t virtual_display_index =
         (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
@@ -4116,7 +4059,7 @@
                                       return session->WaitForCommitDone(display, client_id);
                                      }, this, display, client_id);
   auto ret = (commit_done_future_[display].wait_for(span) == std::future_status::timeout) ?
-             -EINVAL : commit_done_future_[display].get();
+             -ETIMEDOUT : commit_done_future_[display].get();
   return ret;
 }
 
@@ -4347,7 +4290,7 @@
         DLOGE("Device unassign failed with error %d", ret);
       }
       TUITransitionUnPrepare(disp_id);
-      return -EINVAL;
+      return 0;
     }
   }
 
@@ -4386,6 +4329,9 @@
   for (auto &info : map_info) {
     bool needs_refresh = false;
     {
+      if (info.client_id == target_display) {
+        continue;
+      }
       SEQUENCE_WAIT_SCOPE_LOCK(locker_[info.client_id]);
       if (hwc_display_[info.client_id]) {
         if (info.disp_type == kPluggable && pending_hotplug_event_ == kHotPlugEvent) {
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 177b488..283da9d 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -498,7 +498,6 @@
 
   void ResetPanel();
   void InitSupportedDisplaySlots();
-  void InitSupportedNullDisplaySlots();
   int GetDisplayIndex(int dpy);
   int CreatePrimaryDisplay();
   int HandleBuiltInDisplays();
@@ -639,7 +638,6 @@
   bool is_composer_up_ = false;
   std::mutex mutex_lum_;
   static bool pending_power_mode_[HWCCallbacks::kNumDisplays];
-  static int null_display_mode_;
   HotPlugEvent pending_hotplug_event_ = kHotPlugNone;
 
   struct VirtualDisplayData {
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index a69e49b..a069d81 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -526,10 +526,6 @@
 }
 
 int HWCSession::SetCameraLaunchStatus(uint32_t on) {
-  if (null_display_mode_) {
-    return 0;
-  }
-
   if (!core_intf_) {
     DLOGW("core_intf_ not initialized.");
     return -ENOENT;
diff --git a/config/display-product.mk b/config/display-product.mk
index 4eb47e9..4990265 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -85,7 +85,8 @@
     vendor.display.disable_sdr_histogram=1 \
     vendor.display.enable_hdr10_gpu_target=1 \
     debug.sf.predict_hwc_composition_strategy=0 \
-    debug.sf.treat_170m_as_sRGB=1
+    debug.sf.treat_170m_as_sRGB=1 \
+    vendor.display.enable_display_extensions=1
 
 # Enable offline rotator for Bengal.
 ifneq ($(TARGET_BOARD_PLATFORM),bengal)
diff --git a/gralloc/gr_adreno_info.cpp b/gralloc/gr_adreno_info.cpp
index 9e195d5..f1d9b0d 100644
--- a/gralloc/gr_adreno_info.cpp
+++ b/gralloc/gr_adreno_info.cpp
@@ -27,12 +27,17 @@
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
 #include <log/log.h>
 #include <cutils/properties.h>
 #include <dlfcn.h>
 #include <mutex>
+#include <fstream>
 
 #include "gr_adreno_info.h"
 #include "gr_utils.h"
@@ -41,10 +46,12 @@
 
 using std::lock_guard;
 using std::mutex;
+using std::fstream;
 
 namespace gralloc {
 
 AdrenoMemInfo *AdrenoMemInfo::s_instance = nullptr;
+char kgsl_path[] = "/dev/kgsl-3d0";
 
 AdrenoMemInfo *AdrenoMemInfo::GetInstance() {
   static mutex s_lock;
@@ -57,6 +64,18 @@
 }
 
 AdrenoMemInfo::AdrenoMemInfo() {
+  char property[PROPERTY_VALUE_MAX];
+  property_get(DISABLE_UBWC_PROP, property, "0");
+  if (!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+      !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+    gfx_ubwc_disable_ = true;
+  }
+
+  fstream fs(kgsl_path, fstream::in);
+  if (!fs.is_open()) {
+    return;
+  }
+
   libadreno_utils_ = ::dlopen("libadreno_utils.so", RTLD_NOW);
   if (libadreno_utils_) {
     *reinterpret_cast<void **>(&LINK_adreno_compute_aligned_width_and_height) =
@@ -80,12 +99,6 @@
   } else {
     ALOGE(" Failed to load libadreno_utils.so");
   }
-  char property[PROPERTY_VALUE_MAX];
-  property_get(DISABLE_UBWC_PROP, property, "0");
-  if (!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
-      !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
-    gfx_ubwc_disable_ = true;
-  }
 }
 
 AdrenoMemInfo::~AdrenoMemInfo() {
diff --git a/gralloc/gr_buf_mgr.cpp b/gralloc/gr_buf_mgr.cpp
index dbe55c8..4c839a1 100644
--- a/gralloc/gr_buf_mgr.cpp
+++ b/gralloc/gr_buf_mgr.cpp
@@ -18,7 +18,7 @@
  */
 /*
  * Changes from Qualcomm Innovation Center are provided under the following license:
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
 */
 
@@ -281,7 +281,9 @@
 
 void BufferManager::SetGrallocDebugProperties(gralloc::GrallocProperties props) {
   allocator_->SetProperties(props);
-  AdrenoMemInfo::GetInstance()->AdrenoSetProperties(props);
+  if (AdrenoMemInfo::GetInstance()) {
+    AdrenoMemInfo::GetInstance()->AdrenoSetProperties(props);
+  }
 }
 
 Error BufferManager::FreeBuffer(std::shared_ptr<Buffer> buf) {
@@ -333,9 +335,8 @@
   auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta);
 
   if (hnd->base_metadata) {
-    auto metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
 #ifdef METADATA_V2
-    buffer->reserved_size = metadata->reservedSize;
+    buffer->reserved_size = hnd->reserved_size;
     if (buffer->reserved_size > 0) {
       buffer->reserved_region_ptr =
           reinterpret_cast<void *>(hnd->base_metadata + sizeof(MetaData_t));
@@ -351,8 +352,8 @@
       buffer->custom_content_md_region_ptr = nullptr;
     }
 #else
-    buffer->reserved_region_ptr = reinterpret_cast<void *>(&(metadata->reservedRegion.data));
-    buffer->reserved_size = metadata->reservedRegion.size;
+    buffer->reserved_size = hnd->reserved_size;
+    buffer->reserved_region_ptr = reinterpret_cast<void *>(hnd->base_metadata + sizeof(MetaData_t));
 #endif
   }
 
diff --git a/gralloc/gr_camera_info.cpp b/gralloc/gr_camera_info.cpp
index 5f58de5..6eca72c 100644
--- a/gralloc/gr_camera_info.cpp
+++ b/gralloc/gr_camera_info.cpp
@@ -29,6 +29,12 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/* Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
 #include <dlfcn.h>
 #include <log/log.h>
 #include <mutex>
@@ -121,6 +127,15 @@
     case HAL_PIXEL_FORMAT_NV12_UBWC_FLEX_8_BATCH:
       format = CAMERA_PIXEL_FORMAT_UBWC_FLEX_8_BATCH;
       break;
+    case HAL_PIXEL_FORMAT_NV12_FLEX_2_BATCH:
+      format = CAMERA_PIXEL_FORMAT_YUV_FLEX_2_BATCH;
+      break;
+    case HAL_PIXEL_FORMAT_NV12_FLEX_4_BATCH:
+      format = CAMERA_PIXEL_FORMAT_YUV_FLEX_4_BATCH;
+      break;
+    case HAL_PIXEL_FORMAT_NV12_FLEX_8_BATCH:
+      format = CAMERA_PIXEL_FORMAT_YUV_FLEX_8_BATCH;
+      break;
     case HAL_PIXEL_FORMAT_MULTIPLANAR_FLEX:
       format = CAMERA_PIXEL_FORMAT_MULTIPLANAR_FLEX;
       break;
diff --git a/gralloc/gr_camera_info.h b/gralloc/gr_camera_info.h
index 28e02b0..0a0cb2b 100644
--- a/gralloc/gr_camera_info.h
+++ b/gralloc/gr_camera_info.h
@@ -27,6 +27,12 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/* Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
 #ifndef __GR_CAMERA_INFO_H__
 #define __GR_CAMERA_INFO_H__
 
@@ -59,6 +65,12 @@
                                                   // individual APIs
   CAMERA_PIXEL_FORMAT_UBWC_FLEX_8_BATCH = 0x130,  // YUV format with fliexible alignment defined by
                                                   // individual APIs
+  CAMERA_PIXEL_FORMAT_YUV_FLEX_2_BATCH = 0x140,   // YUV format with fliexible alignment defined by
+                                                  // individual APIs
+  CAMERA_PIXEL_FORMAT_YUV_FLEX_4_BATCH = 0x141,   // YUV format with fliexible alignment defined by
+                                                  // individual APIs
+  CAMERA_PIXEL_FORMAT_YUV_FLEX_8_BATCH = 0x142,   // YUV format with fliexible alignment defined by
+                                                  // individual APIs
   CAMERA_PIXEL_FORMAT_NV12_VENUS = 0x7FA30C04,           // NV12 video format
   CAMERA_PIXEL_FORMAT_NV12_HEIF = 0x00000116,            // HEIF video YUV420 format
   CAMERA_PIXEL_FORMAT_YCbCr_420_SP_UBWC = 0x7FA30C06,    // 8 bit YUV 420 semi-planar UBWC format
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 9731d60..9b9b019 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -27,7 +27,7 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Changes from Qualcomm Innovation Center are provided under the following license:
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -117,6 +117,9 @@
     case HAL_PIXEL_FORMAT_NV12_UBWC_FLEX_4_BATCH:
     case HAL_PIXEL_FORMAT_NV12_UBWC_FLEX_8_BATCH:
     case HAL_PIXEL_FORMAT_MULTIPLANAR_FLEX:
+    case HAL_PIXEL_FORMAT_NV12_FLEX_2_BATCH:
+    case HAL_PIXEL_FORMAT_NV12_FLEX_4_BATCH:
+    case HAL_PIXEL_FORMAT_NV12_FLEX_8_BATCH:
       return true;
     default:
       return false;
@@ -215,6 +218,9 @@
     case static_cast<int>(PixelFormat::RAW_OPAQUE):
     case static_cast<int>(PixelFormat::RAW10):
     case static_cast<int>(PixelFormat::RAW12):
+    case HAL_PIXEL_FORMAT_NV12_FLEX_2_BATCH:
+    case HAL_PIXEL_FORMAT_NV12_FLEX_4_BATCH:
+    case HAL_PIXEL_FORMAT_NV12_FLEX_8_BATCH:
       if (usage & GRALLOC_USAGE_HW_COMPOSER) {
         ALOGW("%s: HW_Composer flag is set for camera custom format: 0x%x, Usage: 0x%" PRIx64,
               __FUNCTION__, format, usage);
@@ -1388,6 +1394,9 @@
   }
 
   AdrenoMemInfo *adreno_mem_info = AdrenoMemInfo::GetInstance();
+  if (!adreno_mem_info) {
+    return -ENOTSUP;
+  }
   graphics_metadata->size = adreno_mem_info->AdrenoGetMetadataBlobSize();
   uint64_t adreno_usage = info.usage;
   // If gralloc disables UBWC based on any of the checks,
@@ -2288,7 +2297,6 @@
       return metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(
           ::android::gralloc4::MetadataType_BlendMode.value)];
     case QTI_VT_TIMESTAMP:
-    case QTI_COLOR_METADATA:
     case QTI_PP_PARAM_INTERLACED:
     case QTI_VIDEO_PERF_MODE:
     case QTI_GRAPHICS_METADATA:
@@ -2306,6 +2314,16 @@
     case QTI_S3D_FORMAT:
     case QTI_BUFFER_PERMISSION:
       return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(paramType)];
+    case QTI_COLOR_METADATA:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] ||
+             metadata->isStandardMetadataSet[
+             GET_STANDARD_METADATA_STATUS_INDEX((int64_t)StandardMetadataType::DATASPACE)] ||
+             metadata->isStandardMetadataSet[
+             GET_STANDARD_METADATA_STATUS_INDEX((int64_t)StandardMetadataType::SMPTE2086)] ||
+             metadata->isStandardMetadataSet[
+             GET_STANDARD_METADATA_STATUS_INDEX((int64_t)StandardMetadataType::CTA861_3)] ||
+             metadata->isStandardMetadataSet[
+             GET_STANDARD_METADATA_STATUS_INDEX((int64_t)StandardMetadataType::SMPTE2094_40)];
     case QTI_COLORSPACE:
       // QTI_COLORSPACE is derived from QTI_COLOR_METADATA
       return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)];
diff --git a/sde-drm/drm_pp_manager.cpp b/sde-drm/drm_pp_manager.cpp
index e758dda..3ec7080 100644
--- a/sde-drm/drm_pp_manager.cpp
+++ b/sde-drm/drm_pp_manager.cpp
@@ -30,7 +30,7 @@
 /*
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted (subject to the limitations in the
@@ -92,9 +92,11 @@
   /* free previously created blob to avoid memory leak */
   for (int i = 0; i < kPPFeaturesMax; i++) {
     prop_info = pp_prop_map_[i];
-    if (prop_info.blob_id > 0) {
-      drmModeDestroyPropertyBlob(fd_, prop_info.blob_id);
-      prop_info.blob_id = 0;
+    for (int j = 0; j < NUM_CACHED_BLOB_ID; j++) {
+      if (prop_info.blob_id[j] > 0) {
+        drmModeDestroyPropertyBlob(fd_, prop_info.blob_id[j]);
+        prop_info.blob_id[j] = 0;
+      }
     }
   }
 #endif
@@ -330,30 +332,31 @@
 #ifdef PP_DRM_ENABLE
   uint32_t blob_id = 0;
 
-  /* free previously created blob for this feature if exist */
-  if (prop_info->blob_id > 0) {
-    ret = drmModeDestroyPropertyBlob(fd_, prop_info->blob_id);
-    if (ret) {
-      DRM_LOGE("failed to destroy property blob for feature %d, ret = %d", feature.id, ret);
-      return ret;
-    } else {
-      prop_info->blob_id = 0;
-    }
-  }
-
   if (!feature.payload) {
     // feature disable case
     drmModeAtomicAddProperty(req, obj_id, prop_info->prop_id, 0);
     return 0;
   }
 
+  /* free previously created blob for this feature if exist */
+  if (prop_info->blob_id[prop_info->blob_id_index] > 0) {
+    ret = drmModeDestroyPropertyBlob(fd_, prop_info->blob_id[prop_info->blob_id_index]);
+    if (ret) {
+      DRM_LOGE("failed to destroy property blob for feature %d, ret = %d", feature.id, ret);
+      return ret;
+    } else {
+      prop_info->blob_id[prop_info->blob_id_index] = 0;
+    }
+  }
+
   ret = drmModeCreatePropertyBlob(fd_, feature.payload, feature.payload_size, &blob_id);
   if (ret || blob_id == 0) {
     DRM_LOGE("failed to create property blob ret %d, blob_id = %d", ret, blob_id);
     return DRM_ERR_INVALID;
   }
 
-  prop_info->blob_id = blob_id;
+  prop_info->blob_id[prop_info->blob_id_index] = blob_id;
+  prop_info->blob_id_index = (++prop_info->blob_id_index) % NUM_CACHED_BLOB_ID;
   drmModeAtomicAddProperty(req, obj_id, prop_info->prop_id, blob_id);
 
 #endif
diff --git a/sde-drm/drm_pp_manager.h b/sde-drm/drm_pp_manager.h
index 6837475..e50224b 100644
--- a/sde-drm/drm_pp_manager.h
+++ b/sde-drm/drm_pp_manager.h
@@ -35,13 +35,16 @@
 #include "drm_interface.h"
 #include "drm_property.h"
 
+#define NUM_CACHED_BLOB_ID 2
+
 namespace sde_drm {
 
 struct DRMPPPropInfo {
   DRMProperty prop_enum;
   uint32_t version = std::numeric_limits<uint32_t>::max();
   uint32_t prop_id;
-  uint32_t blob_id;
+  uint32_t blob_id[NUM_CACHED_BLOB_ID];
+  uint32_t blob_id_index;
 };
 
 class DRMPPManager {
diff --git a/sdm/include/core/core_interface.h b/sdm/include/core/core_interface.h
index f7751f9..54741fc 100644
--- a/sdm/include/core/core_interface.h
+++ b/sdm/include/core/core_interface.h
@@ -1,6 +1,5 @@
 /*
 * Copyright (c) 2014 - 2016, 2018 - 2021 The Linux Foundation. All rights reserved.
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -28,6 +27,13 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+/*
+* Changes from Qualcomm Innovation Center are provided under the following license:
+*
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+* SPDX-License-Identifier: BSD-3-Clause-Clear
+*/
+
 /*! @file core_interface.h
   @brief Interface file for core of the display subsystem.
 
@@ -207,6 +213,20 @@
   virtual DisplayError CreateDisplay(int32_t display_id, DisplayEventHandler *event_handler,
                                      DisplayInterface **interface) = 0;
 
+  /*! @brief Method to create a null display.
+
+    @details Client shall use this method to create a DisplayInterface to DisplayNull. A handle
+    to the DisplayInterface is returned via the 'interface' output parameter which can be used to
+    interact further with the display device.
+
+    @param[out] interface \link DisplayInterface \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa DestroyNullDisplay
+  */
+  virtual DisplayError CreateNullDisplay(DisplayInterface **interface) = 0;
+
   /*! @brief Method to destroy a display device.
 
     @details Client shall use this method to destroy each of the created display device objects.
@@ -219,6 +239,18 @@
   */
   virtual DisplayError DestroyDisplay(DisplayInterface *interface) = 0;
 
+  /*! @brief Method to destroy a null display device.
+
+    @details Client shall use this method to destroy null display device objects.
+
+    @param[in] interface \link DisplayInterface \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa CreateNullDisplay
+  */
+  virtual DisplayError DestroyNullDisplay(DisplayInterface *interface) = 0;
+
 #ifdef PROFILE_COVERAGE_DATA
   /*! @brief Method to destroy a display device.
 
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 043f811..c68e77a 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -143,6 +143,7 @@
   virtual uint32_t GetMixerCount() = 0;
   virtual void HandleTUITransition(Handle display_ctx, bool tui_active) = 0;
   virtual DisplayError SetBlendSpace(Handle display_ctx, const PrimariesTransfer &blend_space) = 0;
+  virtual bool IsDisplayHWAvailable() = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/Android.bp b/sdm/libs/core/Android.bp
index aa6395c..dc979b8 100644
--- a/sdm/libs/core/Android.bp
+++ b/sdm/libs/core/Android.bp
@@ -33,11 +33,13 @@
         "display_builtin.cpp",
         "display_pluggable.cpp",
         "display_virtual.cpp",
+        "display_null.cpp",
         "noise_plugin_intf_impl.cpp",
         "comp_manager.cpp",
         "strategy.cpp",
         "resource_default.cpp",
         "color_manager.cpp",
+        "hw_info_default.cpp",
     ],
 
 }
diff --git a/sdm/libs/core/Makefile.am b/sdm/libs/core/Makefile.am
index f18c389..b5fba30 100644
--- a/sdm/libs/core/Makefile.am
+++ b/sdm/libs/core/Makefile.am
@@ -7,10 +7,12 @@
             noise_plugin_intf_impl.cpp \
             display_pluggable.cpp \
             display_virtual.cpp \
+            display_null.cpp \
             comp_manager.cpp \
             strategy.cpp \
             resource_default.cpp \
-            color_manager.cpp
+            color_manager.cpp \
+            hw_info_default.cpp
 
 core_h_sources = $(HEADER_PATH)/core/*.h
 
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 77ca913..b2812ee 100755
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -1,8 +1,6 @@
 /*
 * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
 *
-* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
-*
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright notice, this list of
@@ -27,37 +25,8 @@
 /*
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted (subject to the limitations in the
-* disclaimer below) provided that the following conditions are met:
-*
-*    * Redistributions of source code must retain the above copyright
-*      notice, this list of conditions and the following disclaimer.
-*
-*    * Redistributions in binary form must reproduce the above
-*      copyright notice, this list of conditions and the following
-*      disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*
-*    * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
-*      contributors may be used to endorse or promote products derived
-*      from this software without specific prior written permission.
-*
-* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
-* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
-* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+* SPDX-License-Identifier: BSD-3-Clause-Clear
 */
 
 #include <core/buffer_allocator.h>
@@ -841,6 +810,16 @@
   return false;
 }
 
+bool CompManager::IsDisplayHWAvailable() {
+  std::lock_guard<std::recursive_mutex> obj(comp_mgr_mutex_);
+  if (resource_intf_) {
+    return resource_intf_->IsDisplayHWAvailable();
+  }
+
+  return false;
+}
+
+
 DisplayError CompManager::FreeDemuraFetchResources(const uint32_t &display_id) {
   std::lock_guard<std::recursive_mutex> obj(comp_mgr_mutex_);
   return resource_intf_->FreeDemuraFetchResources(display_id);
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 107921b..d09301d 100755
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -1,8 +1,6 @@
 /*
 * Copyright (c) 2014 - 2021, The Linux Foundation. All rights reserved.
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
-*
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright notice, this list of
@@ -27,37 +25,8 @@
 /*
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted (subject to the limitations in the
-* disclaimer below) provided that the following conditions are met:
-*
-*    * Redistributions of source code must retain the above copyright
-*      notice, this list of conditions and the following disclaimer.
-*
-*    * Redistributions in binary form must reproduce the above
-*      copyright notice, this list of conditions and the following
-*      disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*
-*    * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
-*      contributors may be used to endorse or promote products derived
-*      from this software without specific prior written permission.
-*
-* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
-* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
-* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+* SPDX-License-Identifier: BSD-3-Clause-Clear
 */
 
 #ifndef __COMP_MANAGER_H__
@@ -163,6 +132,7 @@
   std::string Dump();
   uint32_t GetMixerCount();
   uint32_t GetActiveDisplayCount();
+  bool IsDisplayHWAvailable();
 
  private:
   static const int kMaxThermalLevel = 3;
diff --git a/sdm/libs/core/core_impl.cpp b/sdm/libs/core/core_impl.cpp
index 60302bf..209d038 100644
--- a/sdm/libs/core/core_impl.cpp
+++ b/sdm/libs/core/core_impl.cpp
@@ -1,8 +1,6 @@
 /*
 * Copyright (c) 2014 - 2016, 2018, 2020-2021 The Linux Foundation. All rights reserved.
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
-*
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright notice, this list of
@@ -24,6 +22,13 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+/*
+* Changes from Qualcomm Innovation Center are provided under the following license:
+*
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+* SPDX-License-Identifier: BSD-3-Clause-Clear
+*/
+
 #include <dlfcn.h>
 #include <signal.h>
 #include <malloc.h>
@@ -42,6 +47,8 @@
 #include "display_builtin.h"
 #include "display_pluggable.h"
 #include "display_virtual.h"
+#include "display_null.h"
+#include "hw_info_default.h"
 
 #define __CLASS__ "CoreImpl"
 
@@ -91,9 +98,24 @@
 #endif
   }
 
+  int value = 0;
+  Debug::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &value);
+  enable_null_display_ = (value == 1);
+  DLOGI("property: enable_null_display_ = %d", enable_null_display_);
+  if (enable_null_display_) {
+    hw_info_intf_ = new HWInfoDefault();
+    return kErrorNone;
+  }
+
   error = HWInfoInterface::Create(&hw_info_intf_);
   if (error != kErrorNone) {
-    goto CleanupOnError;
+    DisplayError err = HandleNullDisplay();
+
+    if ((err != kErrorNone) || !enable_null_display_) {
+      goto CleanupOnError;
+    }
+    hw_info_intf_ = new HWInfoDefault();
+    return kErrorNone;
   }
 
   error = hw_info_intf_->GetHWResourceInfo(&hw_resource_);
@@ -109,6 +131,15 @@
     goto CleanupOnError;
   }
 
+  enable_null_display_ = !comp_mgr_.IsDisplayHWAvailable();
+  if (enable_null_display_) {
+    if (hw_info_intf_) {
+      HWInfoInterface::Destroy(hw_info_intf_);
+    }
+    hw_info_intf_ = new HWInfoDefault();
+    return kErrorNone;
+  }
+
   error = ColorManagerProxy::Init(hw_resource_);
   // if failed, doesn't affect display core functionalities.
   if (error != kErrorNone) {
@@ -177,7 +208,12 @@
     }
   }
 
-  HWInfoInterface::Destroy(hw_info_intf_);
+  if (enable_null_display_) {
+    delete static_cast<HWInfoDefault *>(hw_info_intf_);
+    hw_info_intf_ = nullptr;
+  } else {
+    HWInfoInterface::Destroy(hw_info_intf_);
+  }
 #ifdef TRUSTED_VM
   // release free memory from the heap, needed for Trusted_VM due to the limited
   // carveout size
@@ -194,6 +230,10 @@
     return kErrorParameters;
   }
 
+  if (enable_null_display_) {
+    return CreateNullDisplayLocked(intf);
+  }
+
   DisplayBase *display_base = NULL;
 
   switch (type) {
@@ -236,6 +276,10 @@
     return kErrorParameters;
   }
 
+  if (enable_null_display_) {
+    return CreateNullDisplayLocked(intf);
+  }
+
   auto iter = hw_displays_info_.find(display_id);
 
   if (iter == hw_displays_info_.end()) {
@@ -279,6 +323,34 @@
   return kErrorNone;
 }
 
+DisplayError CoreImpl::CreateNullDisplay(DisplayInterface **intf) {
+  SCOPE_LOCK(locker_);
+
+  if (!intf) {
+    return kErrorParameters;
+  }
+
+  return CreateNullDisplayLocked(intf);
+}
+
+DisplayError CoreImpl::CreateNullDisplayLocked(DisplayInterface **intf) {
+  DisplayNull *display_null = new DisplayNull();
+
+  if (!display_null) {
+    return kErrorMemory;
+  }
+
+  DisplayError error = display_null->Init();
+  if (error != kErrorNone) {
+    delete display_null;
+    return error;
+  }
+
+  *intf = display_null;
+
+  return kErrorNone;
+}
+
 DisplayError CoreImpl::DestroyDisplay(DisplayInterface *intf) {
   SCOPE_LOCK(locker_);
 
@@ -286,6 +358,11 @@
     return kErrorParameters;
   }
 
+  if (enable_null_display_) {
+    delete static_cast<DisplayNull *>(intf);
+    return kErrorNone;
+  }
+
   DisplayBase *display_base = static_cast<DisplayBase *>(intf);
   display_base->Deinit();
   delete display_base;
@@ -293,6 +370,31 @@
   return kErrorNone;
 }
 
+DisplayError CoreImpl::DestroyNullDisplay(DisplayInterface *intf) {
+  SCOPE_LOCK(locker_);
+
+  if (!intf) {
+    return kErrorParameters;
+  }
+
+  delete static_cast<DisplayNull *>(intf);
+
+  return kErrorNone;
+}
+
+DisplayError CoreImpl::HandleNullDisplay() {
+  // Initializing comp_mgr with default hw resource
+  DisplayError error = comp_mgr_.Init(hw_resource_, extension_intf_, buffer_allocator_,
+                                      socket_handler_);
+  if (error != kErrorNone) {
+    DLOGW("comp manager initialization failed");
+    return error;
+  }
+  DLOGI("comp manager successfully initialized with default hw resources");
+  enable_null_display_ = !comp_mgr_.IsDisplayHWAvailable();
+  return kErrorNone;
+}
+
 DisplayError CoreImpl::SetMaxBandwidthMode(HWBwModes mode) {
   SCOPE_LOCK(locker_);
 
@@ -306,7 +408,8 @@
 
 DisplayError CoreImpl::GetDisplaysStatus(HWDisplaysInfo *hw_displays_info) {
   SCOPE_LOCK(locker_);
-  DisplayError error = hw_info_intf_->GetDisplaysStatus(hw_displays_info);
+  DisplayError error = kErrorNone;
+  error = hw_info_intf_->GetDisplaysStatus(hw_displays_info);
   if (kErrorNone == error) {
     // Needed for error-checking in CreateDisplay(int32_t display_id, ...) and getting display-type.
     hw_displays_info_ = *hw_displays_info;
diff --git a/sdm/libs/core/core_impl.h b/sdm/libs/core/core_impl.h
index c6de923..f77c577 100644
--- a/sdm/libs/core/core_impl.h
+++ b/sdm/libs/core/core_impl.h
@@ -1,8 +1,6 @@
 /*
 * Copyright (c) 2014 - 2016, 2018, 2020-2021 The Linux Foundation. All rights reserved.
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
-*
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright notice, this list of
@@ -24,6 +22,13 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+/*
+* Changes from Qualcomm Innovation Center are provided under the following license:
+*
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+* SPDX-License-Identifier: BSD-3-Clause-Clear
+*/
+
 #ifndef __CORE_IMPL_H__
 #define __CORE_IMPL_H__
 
@@ -87,7 +92,9 @@
                                      DisplayInterface **intf);
   virtual DisplayError CreateDisplay(int32_t display_id, DisplayEventHandler *event_handler,
                                      DisplayInterface **intf);
+  virtual DisplayError CreateNullDisplay(DisplayInterface **intf);
   virtual DisplayError DestroyDisplay(DisplayInterface *intf);
+  virtual DisplayError DestroyNullDisplay(DisplayInterface *intf);
   virtual DisplayError SetMaxBandwidthMode(HWBwModes mode);
   virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
   virtual DisplayError GetDisplaysStatus(HWDisplaysInfo *hw_displays_info);
@@ -102,6 +109,8 @@
   void InitializeSDMUtils();
   void ReleaseDemuraResources();
   void OverRideDemuraPanelIds(std::vector<uint64_t> *panel_ids);
+  DisplayError CreateNullDisplayLocked(DisplayInterface **intf);
+  DisplayError HandleNullDisplay();
 
   Locker locker_;
   BufferAllocator *buffer_allocator_ = NULL;
@@ -120,9 +129,10 @@
   CoreIPCVmCallbackImpl* vm_cb_intf_ = nullptr;
   std::vector<uint64_t> *panel_ids_;
   std::shared_ptr<DemuraParserManagerIntf> pm_intf_ = nullptr;
-  bool reserve_done_  = false;
+  bool reserve_done_ = false;
   char *raw_mapped_buffer_ = nullptr;
   std::vector<uint32_t> demura_display_ids_;
+  bool enable_null_display_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index fb843ce..6642ca8 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1327,6 +1327,13 @@
     } else {
       DLOGE("Prepare failed: %d", error);
     }
+    // Clear fences
+    DLOGI("Clearing fences on input layers on display %d-%d", display_id_, display_type_);
+    for (auto &layer : layer_stack->layers) {
+      layer->input_buffer.release_fence = nullptr;
+    }
+    layer_stack->retire_fence = nullptr;
+
     return error;
   }
 
diff --git a/composer/display_null.cpp b/sdm/libs/core/display_null.cpp
similarity index 94%
rename from composer/display_null.cpp
rename to sdm/libs/core/display_null.cpp
index 930749f..6bc340c 100644
--- a/composer/display_null.cpp
+++ b/sdm/libs/core/display_null.cpp
@@ -154,4 +154,14 @@
   return kErrorNone;
 }
 
+DisplayError DisplayNull::GetDisplayId(int32_t *display_id) {
+  *display_id = 1;
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::GetDisplayType(DisplayType *display_type) {
+  *display_type = kBuiltIn;
+  return kErrorNone;
+}
+
 }  // namespace sdm
diff --git a/composer/display_null.h b/sdm/libs/core/display_null.h
similarity index 97%
rename from composer/display_null.h
rename to sdm/libs/core/display_null.h
index 4df3db9..6b6f6ea 100644
--- a/composer/display_null.h
+++ b/sdm/libs/core/display_null.h
@@ -80,8 +80,10 @@
   virtual void ScreenRefresh() { }
   virtual bool IsWriteBackSupportedFormat(const LayerBufferFormat &format) { return false; }
   virtual bool HandleCwbTeardown() { return false; }
-  virtual void Abort() {};
+  virtual void Abort() {}
   virtual uint32_t GetAvailableMixerCount() { return 0; }
+  virtual DisplayError GetDisplayId(int32_t *display_id);
+  virtual DisplayError GetDisplayType(DisplayType *display_type);
 
   MAKE_NO_OP(CommitOrPrepare(LayerStack *))
   MAKE_NO_OP(PrePrepare(LayerStack *))
@@ -122,8 +124,6 @@
   MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t))
   MAKE_NO_OP(SetDetailEnhancerData(const DisplayDetailEnhancerData &))
   MAKE_NO_OP(GetDisplayPort(DisplayPort *))
-  MAKE_NO_OP(GetDisplayId(int32_t *))
-  MAKE_NO_OP(GetDisplayType(DisplayType *))
   MAKE_NO_OP(SetCompositionState(LayerComposition, bool))
   MAKE_NO_OP(GetClientTargetSupport(uint32_t, uint32_t, LayerBufferFormat,
                                     const ColorMetaData &))
diff --git a/sdm/libs/core/hw_info_default.cpp b/sdm/libs/core/hw_info_default.cpp
new file mode 100644
index 0000000..9f8d69f
--- /dev/null
+++ b/sdm/libs/core/hw_info_default.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "hw_info_default.h"
+
+#include <vector>
+#include <map>
+#include <string>
+
+#define __CLASS__ "HWInfoDefault"
+
+namespace sdm {
+
+DisplayError HWInfoDefault::Init() {
+  return kErrorNotSupported;
+}
+
+DisplayError HWInfoDefault::GetHWResourceInfo(HWResourceInfo *hw_resource) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWInfoDefault::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) {
+  hw_disp_info->type = kBuiltIn;
+  hw_disp_info->is_connected = true;
+
+  return kErrorNone;
+}
+
+DisplayError HWInfoDefault::GetDisplaysStatus(HWDisplaysInfo *hw_displays_info) {
+  HWDisplayInfo hw_info = {};
+  hw_info.display_type = kBuiltIn;
+  hw_info.is_connected = 1;
+  hw_info.is_primary = 1;
+  hw_info.is_wb_ubwc_supported = 0;
+  hw_info.display_id = 1;
+  (*hw_displays_info)[hw_info.display_id] = hw_info;
+  DLOGI("display: %4d-%d, connected: %s, primary: %s", hw_info.display_id, hw_info.display_type,
+        hw_info.is_connected ? "true" : "false", hw_info.is_primary ? "true" : "false");
+  return kErrorNone;
+}
+
+DisplayError HWInfoDefault::GetMaxDisplaysSupported(const DisplayType type, int32_t *max_displays) {
+  switch (type) {
+    case kPluggable:
+    case kVirtual:
+      *max_displays = 0;
+      break;
+    case kBuiltIn:
+    case kDisplayTypeMax:
+      *max_displays = 1;
+      break;
+    default:
+      DLOGE("Unknown display type %d.", type);
+      return kErrorParameters;
+  }
+
+  DLOGI("Max %d concurrent displays.", 1);
+  DLOGI("Max %d concurrent displays of type %d (BuiltIn).", 1, kBuiltIn);
+  DLOGI("Max %d concurrent displays of type %d (Pluggable).", 0, kPluggable);
+  DLOGI("Max %d concurrent displays of type %d (Virtual).", 0, kVirtual);
+
+  return kErrorNone;
+}
+
+DisplayError HWInfoDefault::GetRequiredDemuraFetchResourceCount(
+    std::map<uint32_t, uint8_t> *required_demura_fetch_cnt) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWInfoDefault::GetDemuraPanelIds(std::vector<uint64_t> *panel_ids) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWInfoDefault::GetPanelBootParamString(std::string *panel_boot_param_string) {
+  return kErrorNotSupported;
+}
+
+uint32_t HWInfoDefault::GetMaxMixerCount() {
+  return 0;
+}
+
+}  // namespace sdm
diff --git a/sdm/libs/core/hw_info_default.h b/sdm/libs/core/hw_info_default.h
new file mode 100644
index 0000000..2e4486f
--- /dev/null
+++ b/sdm/libs/core/hw_info_default.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#ifndef __HW_INFO_DEFAULT_H__
+#define __HW_INFO_DEFAULT_H__
+
+#include <core/core_interface.h>
+#include <core/sdm_types.h>
+#include <drm_interface.h>
+#include <private/hw_info_types.h>
+#include <private/hw_info_interface.h>
+#include <vector>
+#include <map>
+#include <string>
+
+namespace sdm {
+
+class HWInfoDefault : public HWInfoInterface {
+ public:
+  virtual DisplayError Init();
+  virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource);
+  virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
+  virtual DisplayError GetDisplaysStatus(HWDisplaysInfo *hw_displays_info);
+  virtual DisplayError GetMaxDisplaysSupported(DisplayType type, int32_t *max_displays);
+  virtual DisplayError GetRequiredDemuraFetchResourceCount(
+      std::map<uint32_t, uint8_t> *required_demura_fetch_cnt);
+  virtual DisplayError GetDemuraPanelIds(std::vector<uint64_t> *panel_ids);
+  virtual DisplayError GetPanelBootParamString(std::string *panel_boot_param_string);
+  virtual uint32_t GetMaxMixerCount();
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INFO_DEFAULT_H__
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index 89f6a9b..e5f4198 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -143,6 +143,7 @@
   virtual uint32_t GetMixerCount();
   virtual void HandleTUITransition(Handle display_ctx, bool tui_active);
   virtual DisplayError SetBlendSpace(Handle display_ctx, const PrimariesTransfer &blend_space);
+  virtual bool IsDisplayHWAvailable() { return true; }
 
  private:
   enum PipeOwner {