diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
new file mode 100644
index 0000000..e0a5823
--- /dev/null
+++ b/hwc2_device/HwcDisplay.cpp
@@ -0,0 +1,958 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "hwc-display"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "HwcDisplay.h"
+
+#include "DrmHwcTwo.h"
+#include "backend/BackendManager.h"
+#include "bufferinfo/BufferInfoGetter.h"
+#include "utils/log.h"
+#include "utils/properties.h"
+
+namespace android {
+
+std::string HwcDisplay::DumpDelta(HwcDisplay::Stats delta) {
+  if (delta.total_pixops_ == 0)
+    return "No stats yet";
+  double ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_);
+
+  std::stringstream ss;
+  ss << " Total frames count: " << delta.total_frames_ << "\n"
+     << " Failed to test commit frames: " << delta.failed_kms_validate_ << "\n"
+     << " Failed to commit frames: " << delta.failed_kms_present_ << "\n"
+     << ((delta.failed_kms_present_ > 0)
+             ? " !!! Internal failure, FIX it please\n"
+             : "")
+     << " Flattened frames: " << delta.frames_flattened_ << "\n"
+     << " Pixel operations (free units)"
+     << " : [TOTAL: " << delta.total_pixops_ << " / GPU: " << delta.gpu_pixops_
+     << "]\n"
+     << " Composition efficiency: " << ratio;
+
+  return ss.str();
+}
+
+std::string HwcDisplay::Dump() {
+  std::string flattening_state_str;
+  switch (flattenning_state_) {
+    case ClientFlattenningState::Disabled:
+      flattening_state_str = "Disabled";
+      break;
+    case ClientFlattenningState::NotRequired:
+      flattening_state_str = "Not needed";
+      break;
+    case ClientFlattenningState::Flattened:
+      flattening_state_str = "Active";
+      break;
+    case ClientFlattenningState::ClientRefreshRequested:
+      flattening_state_str = "Refresh requested";
+      break;
+    default:
+      flattening_state_str = std::to_string(flattenning_state_) +
+                             " VSync remains";
+  }
+
+  std::stringstream ss;
+  ss << "- Display on: " << connector_->name() << "\n"
+     << "  Flattening state: " << flattening_state_str << "\n"
+     << "Statistics since system boot:\n"
+     << DumpDelta(total_stats_) << "\n\n"
+     << "Statistics since last dumpsys request:\n"
+     << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n";
+
+  memcpy(&prev_stats_, &total_stats_, sizeof(Stats));
+  return ss.str();
+}
+
+HwcDisplay::HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
+                       hwc2_display_t handle, HWC2::DisplayType type,
+                       DrmHwcTwo *hwc2)
+    : hwc2_(hwc2),
+      resource_manager_(resource_manager),
+      drm_(drm),
+      handle_(handle),
+      type_(type),
+      color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
+  // clang-format off
+  color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0,
+                             0.0, 1.0, 0.0, 0.0,
+                             0.0, 0.0, 1.0, 0.0,
+                             0.0, 0.0, 0.0, 1.0};
+  // clang-format on
+}
+
+void HwcDisplay::ClearDisplay() {
+  AtomicCommitArgs a_args = {.clear_active_composition = true};
+  compositor_.ExecuteAtomicCommit(a_args);
+}
+
+HWC2::Error HwcDisplay::Init(std::vector<DrmPlane *> *planes) {
+  int display = static_cast<int>(handle_);
+  int ret = compositor_.Init(resource_manager_, display);
+  if (ret) {
+    ALOGE("Failed display compositor init for display %d (%d)", display, ret);
+    return HWC2::Error::NoResources;
+  }
+
+  // Split up the given display planes into primary and overlay to properly
+  // interface with the composition
+  char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
+  property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
+               "1");
+  bool use_overlay_planes = strtol(use_overlay_planes_prop, nullptr, 10);
+  for (auto &plane : *planes) {
+    if (plane->GetType() == DRM_PLANE_TYPE_PRIMARY)
+      primary_planes_.push_back(plane);
+    else if (use_overlay_planes && (plane)->GetType() == DRM_PLANE_TYPE_OVERLAY)
+      overlay_planes_.push_back(plane);
+  }
+
+  crtc_ = drm_->GetCrtcForDisplay(display);
+  if (!crtc_) {
+    ALOGE("Failed to get crtc for display %d", display);
+    return HWC2::Error::BadDisplay;
+  }
+
+  connector_ = drm_->GetConnectorForDisplay(display);
+  if (!connector_) {
+    ALOGE("Failed to get connector for display %d", display);
+    return HWC2::Error::BadDisplay;
+  }
+
+  ret = vsync_worker_.Init(drm_, display, [this](int64_t timestamp) {
+    const std::lock_guard<std::mutex> lock(hwc2_->callback_lock_);
+    /* vsync callback */
+#if PLATFORM_SDK_VERSION > 29
+    if (hwc2_->vsync_2_4_callback_.first != nullptr &&
+        hwc2_->vsync_2_4_callback_.second != nullptr) {
+      hwc2_vsync_period_t period_ns{};
+      GetDisplayVsyncPeriod(&period_ns);
+      hwc2_->vsync_2_4_callback_.first(hwc2_->vsync_2_4_callback_.second,
+                                       handle_, timestamp, period_ns);
+    } else
+#endif
+        if (hwc2_->vsync_callback_.first != nullptr &&
+            hwc2_->vsync_callback_.second != nullptr) {
+      hwc2_->vsync_callback_.first(hwc2_->vsync_callback_.second, handle_,
+                                   timestamp);
+    }
+  });
+  if (ret) {
+    ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
+    return HWC2::Error::BadDisplay;
+  }
+
+  ret = flattening_vsync_worker_
+            .Init(drm_, display, [this](int64_t /*timestamp*/) {
+              const std::lock_guard<std::mutex> lock(hwc2_->callback_lock_);
+              /* Frontend flattening */
+              if (flattenning_state_ >
+                      ClientFlattenningState::ClientRefreshRequested &&
+                  --flattenning_state_ ==
+                      ClientFlattenningState::ClientRefreshRequested &&
+                  hwc2_->refresh_callback_.first != nullptr &&
+                  hwc2_->refresh_callback_.second != nullptr) {
+                hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second,
+                                               handle_);
+                flattening_vsync_worker_.VSyncControl(false);
+              }
+            });
+  if (ret) {
+    ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
+    return HWC2::Error::BadDisplay;
+  }
+
+  ret = BackendManager::GetInstance().SetBackendForDisplay(this);
+  if (ret) {
+    ALOGE("Failed to set backend for d=%d %d\n", display, ret);
+    return HWC2::Error::BadDisplay;
+  }
+
+  client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED);
+
+  return ChosePreferredConfig();
+}
+
+HWC2::Error HwcDisplay::ChosePreferredConfig() {
+  // Fetch the number of modes from the display
+  uint32_t num_configs = 0;
+  HWC2::Error err = GetDisplayConfigs(&num_configs, nullptr);
+  if (err != HWC2::Error::None || !num_configs)
+    return HWC2::Error::BadDisplay;
+
+  return SetActiveConfig(preferred_config_id_);
+}
+
+HWC2::Error HwcDisplay::AcceptDisplayChanges() {
+  for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_)
+    l.second.AcceptTypeChange();
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) {
+  layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer());
+  *layer = static_cast<hwc2_layer_t>(layer_idx_);
+  ++layer_idx_;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::DestroyLayer(hwc2_layer_t layer) {
+  if (!get_layer(layer))
+    return HWC2::Error::BadLayer;
+
+  layers_.erase(layer);
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetActiveConfig(hwc2_config_t *config) const {
+  if (hwc_configs_.count(active_config_id_) == 0)
+    return HWC2::Error::BadConfig;
+
+  *config = active_config_id_;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetChangedCompositionTypes(uint32_t *num_elements,
+                                                   hwc2_layer_t *layers,
+                                                   int32_t *types) {
+  uint32_t num_changes = 0;
+  for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) {
+    if (l.second.IsTypeChanged()) {
+      if (layers && num_changes < *num_elements)
+        layers[num_changes] = l.first;
+      if (types && num_changes < *num_elements)
+        types[num_changes] = static_cast<int32_t>(l.second.GetValidatedType());
+      ++num_changes;
+    }
+  }
+  if (!layers && !types)
+    *num_elements = num_changes;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height,
+                                               int32_t /*format*/,
+                                               int32_t dataspace) {
+  std::pair<uint32_t, uint32_t> min = drm_->min_resolution();
+  std::pair<uint32_t, uint32_t> max = drm_->max_resolution();
+
+  if (width < min.first || height < min.second)
+    return HWC2::Error::Unsupported;
+
+  if (width > max.first || height > max.second)
+    return HWC2::Error::Unsupported;
+
+  if (dataspace != HAL_DATASPACE_UNKNOWN)
+    return HWC2::Error::Unsupported;
+
+  // TODO(nobody): Validate format can be handled by either GL or planes
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetColorModes(uint32_t *num_modes, int32_t *modes) {
+  if (!modes)
+    *num_modes = 1;
+
+  if (modes)
+    *modes = HAL_COLOR_MODE_NATIVE;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config,
+                                            int32_t attribute_in,
+                                            int32_t *value) {
+  int conf = static_cast<int>(config);
+
+  if (hwc_configs_.count(conf) == 0) {
+    ALOGE("Could not find active mode for %d", conf);
+    return HWC2::Error::BadConfig;
+  }
+
+  auto &hwc_config = hwc_configs_[conf];
+
+  static const int32_t kUmPerInch = 25400;
+  uint32_t mm_width = connector_->mm_width();
+  uint32_t mm_height = connector_->mm_height();
+  auto attribute = static_cast<HWC2::Attribute>(attribute_in);
+  switch (attribute) {
+    case HWC2::Attribute::Width:
+      *value = static_cast<int>(hwc_config.mode.h_display());
+      break;
+    case HWC2::Attribute::Height:
+      *value = static_cast<int>(hwc_config.mode.v_display());
+      break;
+    case HWC2::Attribute::VsyncPeriod:
+      // in nanoseconds
+      *value = static_cast<int>(1E9 / hwc_config.mode.v_refresh());
+      break;
+    case HWC2::Attribute::DpiX:
+      // Dots per 1000 inches
+      *value = mm_width ? static_cast<int>(hwc_config.mode.h_display() *
+                                           kUmPerInch / mm_width)
+                        : -1;
+      break;
+    case HWC2::Attribute::DpiY:
+      // Dots per 1000 inches
+      *value = mm_height ? static_cast<int>(hwc_config.mode.v_display() *
+                                            kUmPerInch / mm_height)
+                         : -1;
+      break;
+#if PLATFORM_SDK_VERSION > 29
+    case HWC2::Attribute::ConfigGroup:
+      /* Dispite ConfigGroup is a part of HWC2.4 API, framework
+       * able to request it even if service @2.1 is used */
+      *value = hwc_config.group_id;
+      break;
+#endif
+    default:
+      *value = -1;
+      return HWC2::Error::BadConfig;
+  }
+  return HWC2::Error::None;
+}
+
+// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme
+HWC2::Error HwcDisplay::GetDisplayConfigs(uint32_t *num_configs,
+                                          hwc2_config_t *configs) {
+  // Since this callback is normally invoked twice (once to get the count, and
+  // once to populate configs), we don't really want to read the edid
+  // redundantly. Instead, only update the modes on the first invocation. While
+  // it's possible this will result in stale modes, it'll all come out in the
+  // wash when we try to set the active config later.
+  if (!configs) {
+    int ret = connector_->UpdateModes();
+    if (ret) {
+      ALOGE("Failed to update display modes %d", ret);
+      return HWC2::Error::BadDisplay;
+    }
+
+    hwc_configs_.clear();
+    preferred_config_id_ = 0;
+    int preferred_config_group_id_ = 0;
+
+    if (connector_->modes().empty()) {
+      ALOGE("No modes reported by KMS");
+      return HWC2::Error::BadDisplay;
+    }
+
+    int last_config_id = 1;
+    int last_group_id = 1;
+
+    /* Group modes */
+    for (const auto &mode : connector_->modes()) {
+      /* Find group for the new mode or create new group */
+      int group_found = 0;
+      for (auto &hwc_config : hwc_configs_) {
+        if (mode.h_display() == hwc_config.second.mode.h_display() &&
+            mode.v_display() == hwc_config.second.mode.v_display()) {
+          group_found = hwc_config.second.group_id;
+        }
+      }
+      if (group_found == 0) {
+        group_found = last_group_id++;
+      }
+
+      bool disabled = false;
+      if (mode.flags() & DRM_MODE_FLAG_3D_MASK) {
+        ALOGI("Disabling display mode %s (Modes with 3D flag aren't supported)",
+              mode.name().c_str());
+        disabled = true;
+      }
+
+      /* Add config */
+      hwc_configs_[last_config_id] = {
+          .id = last_config_id,
+          .group_id = group_found,
+          .mode = mode,
+          .disabled = disabled,
+      };
+
+      /* Chwck if the mode is preferred */
+      if ((mode.type() & DRM_MODE_TYPE_PREFERRED) != 0 &&
+          preferred_config_id_ == 0) {
+        preferred_config_id_ = last_config_id;
+        preferred_config_group_id_ = group_found;
+      }
+
+      last_config_id++;
+    }
+
+    /* We must have preferred mode. Set first mode as preferred
+     * in case KMS haven't reported anything. */
+    if (preferred_config_id_ == 0) {
+      preferred_config_id_ = 1;
+      preferred_config_group_id_ = 1;
+    }
+
+    for (int group = 1; group < last_group_id; group++) {
+      bool has_interlaced = false;
+      bool has_progressive = false;
+      for (auto &hwc_config : hwc_configs_) {
+        if (hwc_config.second.group_id != group || hwc_config.second.disabled) {
+          continue;
+        }
+
+        if (hwc_config.second.IsInterlaced()) {
+          has_interlaced = true;
+        } else {
+          has_progressive = true;
+        }
+      }
+
+      bool has_both = has_interlaced && has_progressive;
+      if (!has_both) {
+        continue;
+      }
+
+      bool group_contains_preferred_interlaced = false;
+      if (group == preferred_config_group_id_ &&
+          hwc_configs_[preferred_config_id_].IsInterlaced()) {
+        group_contains_preferred_interlaced = true;
+      }
+
+      for (auto &hwc_config : hwc_configs_) {
+        if (hwc_config.second.group_id != group || hwc_config.second.disabled) {
+          continue;
+        }
+
+        bool disable = group_contains_preferred_interlaced
+                           ? !hwc_config.second.IsInterlaced()
+                           : hwc_config.second.IsInterlaced();
+
+        if (disable) {
+          ALOGI(
+              "Group %i: Disabling display mode %s (This group should consist "
+              "of %s modes)",
+              group, hwc_config.second.mode.name().c_str(),
+              group_contains_preferred_interlaced ? "interlaced"
+                                                  : "progressive");
+
+          hwc_config.second.disabled = true;
+        }
+      }
+    }
+
+    /* Group should not contain 2 modes with FPS delta less than ~1HZ
+     * otherwise android.graphics.cts.SetFrameRateTest CTS will fail
+     */
+    for (int m1 = 1; m1 < last_config_id; m1++) {
+      for (int m2 = 1; m2 < last_config_id; m2++) {
+        if (m1 != m2 &&
+            hwc_configs_[m1].group_id == hwc_configs_[m2].group_id &&
+            !hwc_configs_[m1].disabled && !hwc_configs_[m2].disabled &&
+            fabsf(hwc_configs_[m1].mode.v_refresh() -
+                  hwc_configs_[m2].mode.v_refresh()) < 1.0) {
+          ALOGI(
+              "Group %i: Disabling display mode %s (Refresh rate value is "
+              "too close to existing mode %s)",
+              hwc_configs_[m2].group_id, hwc_configs_[m2].mode.name().c_str(),
+              hwc_configs_[m1].mode.name().c_str());
+
+          hwc_configs_[m2].disabled = true;
+        }
+      }
+    }
+  }
+
+  uint32_t idx = 0;
+  for (auto &hwc_config : hwc_configs_) {
+    if (hwc_config.second.disabled) {
+      continue;
+    }
+
+    if (configs != nullptr) {
+      if (idx >= *num_configs) {
+        break;
+      }
+      configs[idx] = hwc_config.second.id;
+    }
+
+    idx++;
+  }
+  *num_configs = idx;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetDisplayName(uint32_t *size, char *name) {
+  std::ostringstream stream;
+  stream << "display-" << connector_->id();
+  std::string string = stream.str();
+  size_t length = string.length();
+  if (!name) {
+    *size = length;
+    return HWC2::Error::None;
+  }
+
+  *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
+  strncpy(name, string.c_str(), *size);
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetDisplayRequests(int32_t * /*display_requests*/,
+                                           uint32_t *num_elements,
+                                           hwc2_layer_t * /*layers*/,
+                                           int32_t * /*layer_requests*/) {
+  // TODO(nobody): I think virtual display should request
+  //      HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT here
+  *num_elements = 0;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetDisplayType(int32_t *type) {
+  *type = static_cast<int32_t>(type_);
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetDozeSupport(int32_t *support) {
+  *support = 0;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetHdrCapabilities(uint32_t *num_types,
+                                           int32_t * /*types*/,
+                                           float * /*max_luminance*/,
+                                           float * /*max_average_luminance*/,
+                                           float * /*min_luminance*/) {
+  *num_types = 0;
+  return HWC2::Error::None;
+}
+
+/* Find API details at:
+ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767
+ */
+HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements,
+                                         hwc2_layer_t *layers,
+                                         int32_t *fences) {
+  uint32_t num_layers = 0;
+
+  for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) {
+    ++num_layers;
+    if (layers == nullptr || fences == nullptr)
+      continue;
+
+    if (num_layers > *num_elements) {
+      ALOGW("Overflow num_elements %d/%d", num_layers, *num_elements);
+      return HWC2::Error::None;
+    }
+
+    layers[num_layers - 1] = l.first;
+    fences[num_layers - 1] = l.second.GetReleaseFence().Release();
+  }
+  *num_elements = num_layers;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
+  // order the layers by z-order
+  bool use_client_layer = false;
+  uint32_t client_z_order = UINT32_MAX;
+  std::map<uint32_t, HwcLayer *> z_map;
+  for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) {
+    switch (l.second.GetValidatedType()) {
+      case HWC2::Composition::Device:
+        z_map.emplace(std::make_pair(l.second.GetZOrder(), &l.second));
+        break;
+      case HWC2::Composition::Client:
+        // Place it at the z_order of the lowest client layer
+        use_client_layer = true;
+        client_z_order = std::min(client_z_order, l.second.GetZOrder());
+        break;
+      default:
+        continue;
+    }
+  }
+  if (use_client_layer)
+    z_map.emplace(std::make_pair(client_z_order, &client_layer_));
+
+  if (z_map.empty())
+    return HWC2::Error::BadLayer;
+
+  std::vector<DrmHwcLayer> composition_layers;
+
+  // now that they're ordered by z, add them to the composition
+  for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
+    DrmHwcLayer layer;
+    l.second->PopulateDrmLayer(&layer);
+    int ret = layer.ImportBuffer(drm_);
+    if (ret) {
+      ALOGE("Failed to import layer, ret=%d", ret);
+      return HWC2::Error::NoResources;
+    }
+    composition_layers.emplace_back(std::move(layer));
+  }
+
+  auto composition = std::make_shared<DrmDisplayComposition>(crtc_);
+
+  // TODO(nobody): Don't always assume geometry changed
+  int ret = composition->SetLayers(composition_layers.data(),
+                                   composition_layers.size());
+  if (ret) {
+    ALOGE("Failed to set layers in the composition ret=%d", ret);
+    return HWC2::Error::BadLayer;
+  }
+
+  std::vector<DrmPlane *> primary_planes(primary_planes_);
+  std::vector<DrmPlane *> overlay_planes(overlay_planes_);
+  ret = composition->Plan(&primary_planes, &overlay_planes);
+  if (ret) {
+    ALOGV("Failed to plan the composition ret=%d", ret);
+    return HWC2::Error::BadConfig;
+  }
+
+  a_args.composition = composition;
+  if (staged_mode) {
+    a_args.display_mode = *staged_mode;
+  }
+  ret = compositor_.ExecuteAtomicCommit(a_args);
+
+  if (ret) {
+    if (!a_args.test_only)
+      ALOGE("Failed to apply the frame composition ret=%d", ret);
+    return HWC2::Error::BadParameter;
+  }
+
+  if (!a_args.test_only) {
+    staged_mode.reset();
+  }
+
+  return HWC2::Error::None;
+}
+
+/* Find API details at:
+ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805
+ */
+HWC2::Error HwcDisplay::PresentDisplay(int32_t *present_fence) {
+  HWC2::Error ret;
+
+  ++total_stats_.total_frames_;
+
+  AtomicCommitArgs a_args{};
+  ret = CreateComposition(a_args);
+
+  if (ret != HWC2::Error::None)
+    ++total_stats_.failed_kms_present_;
+
+  if (ret == HWC2::Error::BadLayer) {
+    // Can we really have no client or device layers?
+    *present_fence = -1;
+    return HWC2::Error::None;
+  }
+  if (ret != HWC2::Error::None)
+    return ret;
+
+  *present_fence = a_args.out_fence.Release();
+
+  ++frame_no_;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) {
+  int conf = static_cast<int>(config);
+
+  if (hwc_configs_.count(conf) == 0) {
+    ALOGE("Could not find active mode for %d", conf);
+    return HWC2::Error::BadConfig;
+  }
+
+  auto &mode = hwc_configs_[conf].mode;
+
+  staged_mode = mode;
+
+  active_config_id_ = conf;
+
+  // Setup the client layer's dimensions
+  hwc_rect_t display_frame = {.left = 0,
+                              .top = 0,
+                              .right = static_cast<int>(mode.h_display()),
+                              .bottom = static_cast<int>(mode.v_display())};
+  client_layer_.SetLayerDisplayFrame(display_frame);
+
+  return HWC2::Error::None;
+}
+
+/* Find API details at:
+ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861
+ */
+HWC2::Error HwcDisplay::SetClientTarget(buffer_handle_t target,
+                                        int32_t acquire_fence,
+                                        int32_t dataspace,
+                                        hwc_region_t /*damage*/) {
+  client_layer_.SetLayerBuffer(target, acquire_fence);
+  client_layer_.SetLayerDataspace(dataspace);
+
+  /*
+   * target can be nullptr, this does mean the Composer Service is calling
+   * cleanDisplayResources() on after receiving HOTPLUG event. See more at:
+   * https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h;l=350;drc=944b68180b008456ed2eb4d4d329e33b19bd5166
+   */
+  if (target == nullptr) {
+    return HWC2::Error::None;
+  }
+
+  /* TODO: Do not update source_crop every call.
+   * It makes sense to do it once after every hotplug event. */
+  HwcDrmBo bo{};
+  BufferInfoGetter::GetInstance()->ConvertBoInfo(target, &bo);
+
+  hwc_frect_t source_crop = {.left = 0.0F,
+                             .top = 0.0F,
+                             .right = static_cast<float>(bo.width),
+                             .bottom = static_cast<float>(bo.height)};
+  client_layer_.SetLayerSourceCrop(source_crop);
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::SetColorMode(int32_t mode) {
+  if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
+    return HWC2::Error::BadParameter;
+
+  if (mode != HAL_COLOR_MODE_NATIVE)
+    return HWC2::Error::Unsupported;
+
+  color_mode_ = mode;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) {
+  if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
+      hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
+    return HWC2::Error::BadParameter;
+
+  if (!matrix && hint == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
+    return HWC2::Error::BadParameter;
+
+  color_transform_hint_ = static_cast<android_color_transform_t>(hint);
+  if (color_transform_hint_ == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
+    std::copy(matrix, matrix + MATRIX_SIZE, color_transform_matrix_.begin());
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::SetOutputBuffer(buffer_handle_t /*buffer*/,
+                                        int32_t /*release_fence*/) {
+  // TODO(nobody): Need virtual display support
+  return HWC2::Error::Unsupported;
+}
+
+HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
+  auto mode = static_cast<HWC2::PowerMode>(mode_in);
+  AtomicCommitArgs a_args{};
+
+  switch (mode) {
+    case HWC2::PowerMode::Off:
+      a_args.active = false;
+      break;
+    case HWC2::PowerMode::On:
+      /*
+       * Setting the display to active before we have a composition
+       * can break some drivers, so skip setting a_args.active to
+       * true, as the next composition frame will implicitly activate
+       * the display
+       */
+      return HWC2::Error::None;
+      break;
+    case HWC2::PowerMode::Doze:
+    case HWC2::PowerMode::DozeSuspend:
+      return HWC2::Error::Unsupported;
+    default:
+      ALOGI("Power mode %d is unsupported\n", mode);
+      return HWC2::Error::BadParameter;
+  };
+
+  int err = compositor_.ExecuteAtomicCommit(a_args);
+  if (err) {
+    ALOGE("Failed to apply the dpms composition err=%d", err);
+    return HWC2::Error::BadParameter;
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::SetVsyncEnabled(int32_t enabled) {
+  vsync_worker_.VSyncControl(HWC2_VSYNC_ENABLE == enabled);
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::ValidateDisplay(uint32_t *num_types,
+                                        uint32_t *num_requests) {
+  return backend_->ValidateDisplay(this, num_types, num_requests);
+}
+
+std::vector<HwcLayer *> HwcDisplay::GetOrderLayersByZPos() {
+  std::vector<HwcLayer *> ordered_layers;
+  ordered_layers.reserve(layers_.size());
+
+  for (auto &[handle, layer] : layers_) {
+    ordered_layers.emplace_back(&layer);
+  }
+
+  std::sort(std::begin(ordered_layers), std::end(ordered_layers),
+            [](const HwcLayer *lhs, const HwcLayer *rhs) {
+              return lhs->GetZOrder() < rhs->GetZOrder();
+            });
+
+  return ordered_layers;
+}
+
+#if PLATFORM_SDK_VERSION > 29
+HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) {
+  if (connector_->internal())
+    *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
+  else if (connector_->external())
+    *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::External);
+  else
+    return HWC2::Error::BadConfig;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetDisplayVsyncPeriod(
+    hwc2_vsync_period_t *outVsyncPeriod /* ns */) {
+  return GetDisplayAttribute(active_config_id_, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+                             (int32_t *)(outVsyncPeriod));
+}
+
+HWC2::Error HwcDisplay::SetActiveConfigWithConstraints(
+    hwc2_config_t /*config*/,
+    hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
+    hwc_vsync_period_change_timeline_t *outTimeline) {
+  if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) {
+    return HWC2::Error::BadParameter;
+  }
+
+  return HWC2::Error::BadConfig;
+}
+
+HWC2::Error HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) {
+  return HWC2::Error::Unsupported;
+}
+
+HWC2::Error HwcDisplay::GetSupportedContentTypes(
+    uint32_t *outNumSupportedContentTypes,
+    const uint32_t *outSupportedContentTypes) {
+  if (outSupportedContentTypes == nullptr)
+    *outNumSupportedContentTypes = 0;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::SetContentType(int32_t contentType) {
+  if (contentType != HWC2_CONTENT_TYPE_NONE)
+    return HWC2::Error::Unsupported;
+
+  /* TODO: Map to the DRM Connector property:
+   * https://elixir.bootlin.com/linux/v5.4-rc5/source/drivers/gpu/drm/drm_connector.c#L809
+   */
+
+  return HWC2::Error::None;
+}
+#endif
+
+#if PLATFORM_SDK_VERSION > 28
+HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort,
+                                                     uint32_t *outDataSize,
+                                                     uint8_t *outData) {
+  auto blob = connector_->GetEdidBlob();
+
+  if (!blob) {
+    ALOGE("Failed to get edid property value.");
+    return HWC2::Error::Unsupported;
+  }
+
+  if (outData) {
+    *outDataSize = std::min(*outDataSize, blob->length);
+    memcpy(outData, blob->data, *outDataSize);
+  } else {
+    *outDataSize = blob->length;
+  }
+  *outPort = connector_->id();
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetDisplayCapabilities(uint32_t *outNumCapabilities,
+                                               uint32_t * /*outCapabilities*/) {
+  if (outNumCapabilities == nullptr) {
+    return HWC2::Error::BadParameter;
+  }
+
+  *outNumCapabilities = 0;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::GetDisplayBrightnessSupport(bool *supported) {
+  *supported = false;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::SetDisplayBrightness(float /* brightness */) {
+  return HWC2::Error::Unsupported;
+}
+
+#endif /* PLATFORM_SDK_VERSION > 28 */
+
+#if PLATFORM_SDK_VERSION > 27
+
+HWC2::Error HwcDisplay::GetRenderIntents(
+    int32_t mode, uint32_t *outNumIntents,
+    int32_t * /*android_render_intent_v1_1_t*/ outIntents) {
+  if (mode != HAL_COLOR_MODE_NATIVE) {
+    return HWC2::Error::BadParameter;
+  }
+
+  if (outIntents == nullptr) {
+    *outNumIntents = 1;
+    return HWC2::Error::None;
+  }
+  *outNumIntents = 1;
+  outIntents[0] = HAL_RENDER_INTENT_COLORIMETRIC;
+  return HWC2::Error::None;
+}
+
+HWC2::Error HwcDisplay::SetColorModeWithIntent(int32_t mode, int32_t intent) {
+  if (intent < HAL_RENDER_INTENT_COLORIMETRIC ||
+      intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE)
+    return HWC2::Error::BadParameter;
+
+  if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
+    return HWC2::Error::BadParameter;
+
+  if (mode != HAL_COLOR_MODE_NATIVE)
+    return HWC2::Error::Unsupported;
+
+  if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
+    return HWC2::Error::Unsupported;
+
+  color_mode_ = mode;
+  return HWC2::Error::None;
+}
+
+#endif /* PLATFORM_SDK_VERSION > 27 */
+
+const Backend *HwcDisplay::backend() const {
+  return backend_.get();
+}
+
+void HwcDisplay::set_backend(std::unique_ptr<Backend> backend) {
+  backend_ = std::move(backend);
+}
+
+}  // namespace android
