drm_hwcomposer: Connect ComposerClient with HwcDisplay

Implements the HWC3 frontend by calling the HWC2 interfaces already
exposed through DrmHwc, HwcDisplay, HwcLayer, and so on.

Convert between hwc2 types and hwc3 types in ComposerClient.

The following changes from !238 were used as a basis for this change,
and squashed together:
(drm_hwcomposer: Connect ComposerClient with HwcDisplay)
(drm_hwcomposer: Implement HWC3 frontend by calling down to HWC2)

The projects [1, 2] were used as a reference for the implementation.

[1]: https://android.googlesource.com/platform/hardware/google/graphics/common/+/refs/heads/main/hwc3/
[2]: https://android.googlesource.com/device/generic/goldfish-opengl/+/refs/heads/master/system/hwc3/

Co-authored-by: Normunds Rieksts <normunds.rieksts@arm.com>
Co-authored-by: Dennis Tsiang <dennis.tsiang@arm.com>
Change-Id: I98c10175d5c5f01aec1e192863238e16aa1537ec
Signed-off-by: Drew Davenport <ddavenport@chromium.org>
Signed-off-by: Drew Davenport <ddavenport@google.com>
diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp
index 9ebba31..6c03722 100644
--- a/hwc3/ComposerClient.cpp
+++ b/hwc3/ComposerClient.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -14,283 +14,910 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "drmhwc"
 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
 
 #include "ComposerClient.h"
 
+#include <aidlcommonsupport/NativeHandle.h>
 #include <android-base/logging.h>
 #include <android/binder_ibinder_platform.h>
+#include <hardware/hwcomposer2.h>
+
+#include <cinttypes>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "aidl/android/hardware/graphics/common/Transform.h"
+#include "aidl/android/hardware/graphics/composer3/ClientTarget.h"
+#include "aidl/android/hardware/graphics/composer3/Composition.h"
+#include "aidl/android/hardware/graphics/composer3/DisplayRequest.h"
+#include "aidl/android/hardware/graphics/composer3/IComposerClient.h"
+#include "aidl/android/hardware/graphics/composer3/PowerMode.h"
+#include "aidl/android/hardware/graphics/composer3/PresentOrValidate.h"
+#include "aidl/android/hardware/graphics/composer3/RenderIntent.h"
+#include "android/binder_auto_utils.h"
+#include "cutils/native_handle.h"
+#include "hardware/hwcomposer_defs.h"
+#include "hwc2_device/HwcDisplay.h"
+#include "hwc2_device/HwcLayer.h"
+#include "hwc3/DrmHwcThree.h"
+#include "hwc3/Utils.h"
+
+using ::android::HwcDisplay;
 
 #include "utils/log.h"
 
 namespace aidl::android::hardware::graphics::composer3::impl {
+namespace {
 
-// NOLINTNEXTLINE
-#define DEBUG_FUNC() ALOGV("%s", __func__)
+// clang-format off
+constexpr std::array<float, 16> kIdentityMatrix = {
+    1.0F, 0.0F, 0.0F, 0.0F,
+    0.0F, 1.0F, 0.0F, 0.0F,
+    0.0F, 0.0F, 1.0F, 0.0F,
+    0.0F, 0.0F, 0.0F, 1.0F,
+};
+// clang-format on
 
+}  // namespace
+
+ComposerClient::ComposerClient() {
+  DEBUG_FUNC();
+}
+
+bool ComposerClient::Init() {
+  DEBUG_FUNC();
+  composer_resources_ = ComposerResources::Create();
+  if (composer_resources_) {
+    hwc_ = std::make_unique<DrmHwcThree>(composer_resources_.get());
+  }
+  return composer_resources_ != nullptr;
+}
+
+// NOLINTNEXTLINE(bugprone-exception-escape)
 ComposerClient::~ComposerClient() {
   DEBUG_FUNC();
-
   LOG(DEBUG) << "removed composer client";
 }
 
-// no need to check nullptr for output parameter, the aidl stub code won't pass
-// nullptr
-ndk::ScopedAStatus ComposerClient::createLayer(int64_t /*display*/,
-                                               int32_t /*bufferSlotCount*/,
-                                               int64_t* /*layer*/) {
+ndk::ScopedAStatus ComposerClient::createLayer(int64_t display_id,
+                                               int32_t buffer_slot_count,
+                                               int64_t* layer_id) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  hwc2_layer_t hwc2_layer_id = 0;
+  auto err = Hwc2toHwc3Error(display->CreateLayer(&hwc2_layer_id));
+  if (err != hwc3::Error::kNone) {
+    return ToBinderStatus(err);
+  }
+
+  const int64_t created_layer_id = Hwc2LayerToHwc3(hwc2_layer_id);
+  err = composer_resources_->AddLayer(display_id, created_layer_id,
+                                      buffer_slot_count);
+  if (err != hwc3::Error::kNone) {
+    destroyLayer(display_id, created_layer_id);
+    return ToBinderStatus(err);
+  }
+
+  *layer_id = created_layer_id;
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::createVirtualDisplay(
-    int32_t /*width*/, int32_t /*height*/, AidlPixelFormat /*formatHint*/,
-    int32_t /*outputBufferSlotCount*/, VirtualDisplay* /*display*/) {
+    int32_t width, int32_t height, AidlPixelFormat format_hint,
+    int32_t output_buffer_slot_count, VirtualDisplay* out_display) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+
+  hwc2_display_t hwc2_display_id = 0;
+  // TODO: Format is currently not used in drm_hwcomposer.
+  int32_t hwc2_format = 0;
+  auto err = Hwc2toHwc3Error(hwc_->CreateVirtualDisplay(width, height,
+                                                        &hwc2_format,
+                                                        &hwc2_display_id));
+  if (err != hwc3::Error::kNone) {
+    return ToBinderStatus(err);
+  }
+
+  const int64_t created_display_id = Hwc2DisplayToHwc3(hwc2_display_id);
+  err = composer_resources_->AddVirtualDisplay(hwc2_display_id,
+                                               output_buffer_slot_count);
+  if (err != hwc3::Error::kNone) {
+    hwc_->DestroyVirtualDisplay(hwc2_display_id);
+    return ToBinderStatus(err);
+  }
+
+  out_display->display = created_display_id;
+  out_display->format = format_hint;
   return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t /*display*/,
-                                                int64_t /*layer*/) {
+ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t display_id,
+                                                int64_t layer_id) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  auto err = Hwc2toHwc3Error(display->DestroyLayer(Hwc3LayerToHwc2(layer_id)));
+  if (err != hwc3::Error::kNone) {
+    return ToBinderStatus(err);
+  }
+
+  err = composer_resources_->RemoveLayer(display_id, layer_id);
+  return ToBinderStatus(err);
 }
 
-ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t /*display*/) {
+ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t display_id) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  auto err = Hwc2toHwc3Error(hwc_->DestroyVirtualDisplay(display_id));
+  return ToBinderStatus(err);
+}
+
+hwc3::Error ComposerClient::ValidateDisplayInternal(
+    HwcDisplay& display, std::vector<int64_t>* out_changed_layers,
+    std::vector<Composition>* out_composition_types,
+    int32_t* out_display_request_mask,
+    std::vector<int64_t>* out_requested_layers,
+    std::vector<int32_t>* out_request_masks,
+    ClientTargetProperty* /*out_client_target_property*/,
+    DimmingStage* /*out_dimming_stage*/) {
+  DEBUG_FUNC();
+
+  uint32_t num_types = 0;
+  uint32_t num_requests = 0;
+  const HWC2::Error hwc2_error = display.ValidateDisplay(&num_types,
+                                                         &num_requests);
+
+  /* Check if display has pending changes and no errors */
+  if (hwc2_error != HWC2::Error::None &&
+      hwc2_error != HWC2::Error::HasChanges) {
+    return Hwc2toHwc3Error(hwc2_error);
+  }
+
+  std::vector<hwc2_layer_t> hwc_changed_layers(num_types);
+  std::vector<int32_t> hwc_composition_types(num_types);
+  hwc3::Error error = Hwc2toHwc3Error(
+      display.GetChangedCompositionTypes(&num_types, hwc_changed_layers.data(),
+                                         hwc_composition_types.data()));
+  if (error != hwc3::Error::kNone) {
+    return error;
+  }
+
+  int32_t display_reqs = 0;
+  out_request_masks->resize(num_requests);
+  std::vector<hwc2_layer_t> hwc_requested_layers(num_requests);
+  error = Hwc2toHwc3Error(
+      display.GetDisplayRequests(&display_reqs, &num_requests,
+                                 hwc_requested_layers.data(),
+                                 out_request_masks->data()));
+  if (error != hwc3::Error::kNone) {
+    return error;
+  }
+
+  for (const auto& layer : hwc_changed_layers) {
+    out_changed_layers->emplace_back(Hwc2LayerToHwc3(layer));
+  }
+  for (const auto& type : hwc_composition_types) {
+    out_composition_types->emplace_back(Hwc2CompositionTypeToHwc3(type));
+  }
+  for (const auto& layer : hwc_requested_layers) {
+    out_requested_layers->emplace_back(Hwc2LayerToHwc3(layer));
+  }
+  *out_display_request_mask = display_reqs;
+
+  /* Client target property/dimming stage unsupported */
+  return hwc3::Error::kNone;
+}
+
+hwc3::Error ComposerClient::PresentDisplayInternal(
+    uint64_t display_id, ::android::base::unique_fd& out_display_fence,
+    std::unordered_map<int64_t, ::android::base::unique_fd>&
+        out_release_fences) {
+  DEBUG_FUNC();
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return hwc3::Error::kBadDisplay;
+  }
+
+  if (composer_resources_->MustValidateDisplay(display_id)) {
+    return hwc3::Error::kNotValidated;
+  }
+
+  int32_t present_fence = -1;
+  auto error = Hwc2toHwc3Error(display->PresentDisplay(&present_fence));
+  if (error != hwc3::Error::kNone) {
+    return error;
+  }
+  out_display_fence.reset(present_fence);
+
+  uint32_t release_fence_count = 0;
+  error = Hwc2toHwc3Error(
+      display->GetReleaseFences(&release_fence_count, nullptr, nullptr));
+  if (error != hwc3::Error::kNone) {
+    return error;
+  }
+
+  std::vector<hwc2_layer_t> hwc_layers(release_fence_count);
+  std::vector<int32_t> hwc_fences(release_fence_count);
+  error = Hwc2toHwc3Error(display->GetReleaseFences(&release_fence_count,
+                                                    hwc_layers.data(),
+                                                    hwc_fences.data()));
+  if (error != hwc3::Error::kNone) {
+    return error;
+  }
+
+  for (size_t i = 0; i < hwc_layers.size(); i++) {
+    auto layer = Hwc2LayerToHwc3(hwc_layers[i]);
+    out_release_fences[layer] = ::android::base::unique_fd{hwc_fences[i]};
+  }
+
+  return hwc3::Error::kNone;
+}
+
+::android::HwcDisplay* ComposerClient::GetDisplay(uint64_t display_id) {
+  return hwc_->GetDisplay(display_id);
+}
+
+void ComposerClient::DispatchLayerCommand(int64_t display_id,
+                                          const LayerCommand& command) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  auto* layer = display->get_layer(command.layer);
+  if (layer == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadLayer);
+    return;
+  }
+
+  HwcLayerWrapper layer_wrapper{command.layer, layer};
+  if (command.buffer) {
+    ExecuteSetLayerBuffer(display_id, layer_wrapper, *command.buffer);
+  }
+  if (command.blendMode) {
+    ExecuteSetLayerBlendMode(display_id, layer_wrapper, *command.blendMode);
+  }
+  if (command.composition) {
+    ExecuteSetLayerComposition(display_id, layer_wrapper, *command.composition);
+  }
+  if (command.dataspace) {
+    ExecuteSetLayerDataspace(display_id, layer_wrapper, *command.dataspace);
+  }
+  if (command.displayFrame) {
+    ExecuteSetLayerDisplayFrame(display_id, layer_wrapper,
+                                *command.displayFrame);
+  }
+  if (command.planeAlpha) {
+    ExecuteSetLayerPlaneAlpha(display_id, layer_wrapper, *command.planeAlpha);
+  }
+  if (command.sourceCrop) {
+    ExecuteSetLayerSourceCrop(display_id, layer_wrapper, *command.sourceCrop);
+  }
+  if (command.transform) {
+    ExecuteSetLayerTransform(display_id, layer_wrapper, *command.transform);
+  }
+  if (command.z) {
+    ExecuteSetLayerZOrder(display_id, layer_wrapper, *command.z);
+  }
+  if (command.brightness) {
+    ExecuteSetLayerBrightness(display_id, layer_wrapper, *command.brightness);
+  }
+
+  // Some unsupported functionality returns kUnsupported, and others
+  // are just a no-op.
+  // TODO: Audit whether some of these should actually return kUnsupported
+  // instead.
+  if (command.sidebandStream) {
+    cmd_result_writer_->AddError(hwc3::Error::kUnsupported);
+  }
+  // TODO: Blocking region handling missing.
+  // TODO: Layer surface damage.
+  // TODO: Layer visible region.
+  // TODO: Per-frame metadata.
+  // TODO: Layer color transform.
+  // TODO: Layer cursor position.
+  // TODO: Layer color.
+}
+
+void ComposerClient::ExecuteDisplayCommand(const DisplayCommand& command) {
+  const int64_t display_id = command.display;
+  if (hwc_->GetDisplay(display_id) == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  for (const auto& layer_cmd : command.layers) {
+    DispatchLayerCommand(command.display, layer_cmd);
+  }
+
+  if (command.brightness) {
+    ExecuteSetDisplayBrightness(command.display, *command.brightness);
+  }
+  if (command.colorTransformMatrix) {
+    ExecuteSetDisplayColorTransform(command.display,
+                                    *command.colorTransformMatrix);
+  }
+  if (command.clientTarget) {
+    ExecuteSetDisplayClientTarget(command.display, *command.clientTarget);
+  }
+  if (command.virtualDisplayOutputBuffer) {
+    ExecuteSetDisplayOutputBuffer(command.display,
+                                  *command.virtualDisplayOutputBuffer);
+  }
+  if (command.validateDisplay) {
+    ExecuteValidateDisplay(command.display, command.expectedPresentTime);
+  }
+  if (command.acceptDisplayChanges) {
+    ExecuteAcceptDisplayChanges(command.display);
+  }
+  if (command.presentDisplay) {
+    ExecutePresentDisplay(command.display);
+  }
+  if (command.presentOrValidateDisplay) {
+    ExecutePresentOrValidateDisplay(command.display,
+                                    command.expectedPresentTime);
+  }
 }
 
 ndk::ScopedAStatus ComposerClient::executeCommands(
-    const std::vector<DisplayCommand>& /*commands*/,
-    std::vector<CommandResultPayload>* /*results*/) {
-  DEBUG_FUNC();
+    const std::vector<DisplayCommand>& commands,
+    std::vector<CommandResultPayload>* results) {
+  cmd_result_writer_ = std::make_unique<CommandResultWriter>(results);
+  for (const auto& cmd : commands) {
+    ExecuteDisplayCommand(cmd);
+    cmd_result_writer_->IncrementCommand();
+  }
+  cmd_result_writer_.reset();
+
   return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t /*display*/,
-                                                   int32_t* /*config*/) {
+ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t display_id,
+                                                   int32_t* config) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  uint32_t hwc2_config = 0;
+  const hwc3::Error error = Hwc2toHwc3Error(
+      display->GetActiveConfig(&hwc2_config));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+  *config = Hwc2ConfigIdToHwc3(hwc2_config);
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getColorModes(
-    int64_t /*display*/, std::vector<ColorMode>* /*colorModes*/) {
+    int64_t display_id, std::vector<ColorMode>* color_modes) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  uint32_t num_modes = 0;
+  auto error = Hwc2toHwc3Error(display->GetColorModes(&num_modes, nullptr));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  std::vector<int32_t> hwc2_color_modes(num_modes);
+  error = Hwc2toHwc3Error(
+      display->GetColorModes(&num_modes, hwc2_color_modes.data()));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  for (const auto& mode : hwc2_color_modes) {
+    color_modes->push_back(Hwc2ColorModeToHwc3(mode));
+  }
+
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getDataspaceSaturationMatrix(
-    common::Dataspace /*dataspace*/, std::vector<float>* /*matrix*/) {
+    common::Dataspace dataspace, std::vector<float>* matrix) {
   DEBUG_FUNC();
+  if (dataspace != common::Dataspace::SRGB_LINEAR) {
+    return ToBinderStatus(hwc3::Error::kBadParameter);
+  }
+
+  matrix->clear();
+  matrix->insert(matrix->begin(), kIdentityMatrix.begin(),
+                 kIdentityMatrix.end());
+
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayAttribute(
-    int64_t /*display*/, int32_t /*config*/, DisplayAttribute /*attribute*/,
-    int32_t* /*value*/) {
+    int64_t display_id, int32_t config, DisplayAttribute attribute,
+    int32_t* value) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  const hwc3::Error error = Hwc2toHwc3Error(
+      display->GetDisplayAttribute(Hwc3ConfigIdToHwc2(config),
+                                   Hwc3DisplayAttributeToHwc2(attribute),
+                                   value));
+  return ToBinderStatus(error);
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(
-    int64_t /*display*/, std::vector<DisplayCapability>* /*caps*/) {
+    int64_t display_id, std::vector<DisplayCapability>* caps) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
 
+  uint32_t num_capabilities = 0;
+  hwc3::Error error = Hwc2toHwc3Error(
+      display->GetDisplayCapabilities(&num_capabilities, nullptr));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  std::vector<uint32_t> out_caps(num_capabilities);
+  error = Hwc2toHwc3Error(
+      display->GetDisplayCapabilities(&num_capabilities, out_caps.data()));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  caps->reserve(num_capabilities);
+  for (const auto cap : out_caps) {
+    caps->emplace_back(Hwc2DisplayCapabilityToHwc3(cap));
+  }
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayConfigs(
-    int64_t /*display*/, std::vector<int32_t>* /*configs*/) {
+    int64_t display_id, std::vector<int32_t>* configs) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  uint32_t num_configs = 0;
+  hwc3::Error error = Hwc2toHwc3Error(
+      display->GetDisplayConfigs(&num_configs, nullptr));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  std::vector<hwc2_config_t> out_configs(num_configs);
+  error = Hwc2toHwc3Error(
+      display->GetDisplayConfigs(&num_configs, out_configs.data()));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  configs->reserve(num_configs);
+  for (const auto config : out_configs) {
+    configs->emplace_back(Hwc2ConfigIdToHwc3(config));
+  }
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayConnectionType(
-    int64_t /*display*/, DisplayConnectionType* /*type*/) {
+    int64_t display_id, DisplayConnectionType* type) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  uint32_t out_type = 0;
+  const hwc3::Error error = Hwc2toHwc3Error(
+      display->GetDisplayConnectionType(&out_type));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  *type = Hwc2DisplayConnectionTypeToHwc3(out_type);
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayIdentificationData(
-    int64_t /*display*/, DisplayIdentification* /*id*/) {
+    int64_t display_id, DisplayIdentification* id) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  uint8_t port = 0;
+  uint32_t data_size = 0;
+  hwc3::Error error = Hwc2toHwc3Error(
+      display->GetDisplayIdentificationData(&port, &data_size, nullptr));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  id->data.resize(data_size);
+  error = Hwc2toHwc3Error(
+      display->GetDisplayIdentificationData(&port, &data_size,
+                                            id->data.data()));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  id->port = static_cast<int8_t>(port);
   return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t /*display*/,
-                                                  std::string* /*name*/) {
+ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t display_id,
+                                                  std::string* name) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  uint32_t size = 0;
+  auto error = Hwc2toHwc3Error(display->GetDisplayName(&size, nullptr));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  name->resize(size);
+  error = Hwc2toHwc3Error(display->GetDisplayName(&size, name->data()));
+  return ToBinderStatus(error);
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(
-    int64_t /*display*/, int32_t* /*vsyncPeriod*/) {
+    int64_t display_id, int32_t* vsync_period) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  uint32_t hwc2_vsync_period = 0;
+  auto error = Hwc2toHwc3Error(
+      display->GetDisplayVsyncPeriod(&hwc2_vsync_period));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  *vsync_period = static_cast<int32_t>(hwc2_vsync_period);
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayedContentSample(
-    int64_t /*display*/, int64_t /*maxFrames*/, int64_t /*timestamp*/,
+    int64_t /*display_id*/, int64_t /*max_frames*/, int64_t /*timestamp*/,
     DisplayContentSample* /*samples*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayedContentSamplingAttributes(
-    int64_t /*display*/, DisplayContentSamplingAttributes* /*attrs*/) {
+    int64_t /*display_id*/, DisplayContentSamplingAttributes* /*attrs*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayPhysicalOrientation(
-    int64_t /*display*/, common::Transform* /*orientation*/) {
+    int64_t display_id, common::Transform* orientation) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  *orientation = common::Transform::NONE;
   return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus ComposerClient::getHdrCapabilities(
-    int64_t /*display*/, HdrCapabilities* /*caps*/) {
+ndk::ScopedAStatus ComposerClient::getHdrCapabilities(int64_t display_id,
+                                                      HdrCapabilities* caps) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  /* No HDR capabilities */
+  caps->types.clear();
   return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(
-    int32_t* /*count*/) {
+ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(int32_t* count) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  *count = static_cast<int32_t>(hwc_->GetMaxVirtualDisplayCount());
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getPerFrameMetadataKeys(
-    int64_t /*display*/, std::vector<PerFrameMetadataKey>* /*keys*/) {
+    int64_t /*display_id*/, std::vector<PerFrameMetadataKey>* /*keys*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
 ndk::ScopedAStatus ComposerClient::getReadbackBufferAttributes(
-    int64_t /*display*/, ReadbackBufferAttributes* /*attrs*/) {
+    int64_t /*display_id*/, ReadbackBufferAttributes* /*attrs*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
 ndk::ScopedAStatus ComposerClient::getReadbackBufferFence(
-    int64_t /*display*/, ndk::ScopedFileDescriptor* /*acquireFence*/) {
+    int64_t /*display_id*/, ndk::ScopedFileDescriptor* /*acquireFence*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
 ndk::ScopedAStatus ComposerClient::getRenderIntents(
-    int64_t /*display*/, ColorMode /*mode*/,
-    std::vector<RenderIntent>* /*intents*/) {
+    int64_t display_id, ColorMode mode, std::vector<RenderIntent>* intents) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  const int32_t hwc2_color_mode = Hwc3ColorModeToHwc2(mode);
+  uint32_t out_num_intents = 0;
+  auto error = Hwc2toHwc3Error(
+      display->GetRenderIntents(hwc2_color_mode, &out_num_intents, nullptr));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  std::vector<int32_t> out_intents(out_num_intents);
+  error = Hwc2toHwc3Error(display->GetRenderIntents(hwc2_color_mode,
+                                                    &out_num_intents,
+                                                    out_intents.data()));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  intents->reserve(out_num_intents);
+  for (const auto intent : out_intents) {
+    intents->emplace_back(Hwc2RenderIntentToHwc3(intent));
+  }
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getSupportedContentTypes(
-    int64_t /*display*/, std::vector<ContentType>* /*types*/) {
+    int64_t display_id, std::vector<ContentType>* types) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  uint32_t out_num_supported_types = 0;
+  auto error = Hwc2toHwc3Error(
+      display->GetSupportedContentTypes(&out_num_supported_types, nullptr));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  std::vector<uint32_t> out_supported_types(out_num_supported_types);
+  error = Hwc2toHwc3Error(
+      display->GetSupportedContentTypes(&out_num_supported_types,
+                                        out_supported_types.data()));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  for (const auto type : out_supported_types) {
+    types->push_back(Hwc2ContentTypeToHwc3(type));
+  }
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus ComposerClient::getDisplayDecorationSupport(
-    int64_t /*display*/,
-    std::optional<common::DisplayDecorationSupport>* /*supportStruct*/) {
+    int64_t /*display_id*/,
+    std::optional<common::DisplayDecorationSupport>* /*support_struct*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
 ndk::ScopedAStatus ComposerClient::registerCallback(
-    const std::shared_ptr<IComposerCallback>& /*callback*/) {
+    const std::shared_ptr<IComposerCallback>& callback) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  // This function is specified to be called exactly once.
+  hwc_->Init(callback);
   return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t /*display*/,
-                                                   int32_t /*config*/) {
+ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t display_id,
+                                                   int32_t config) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  return ToBinderStatus(Hwc2toHwc3Error(display->SetActiveConfig(config)));
 }
 
 ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints(
-    int64_t /*display*/, int32_t /*config*/,
-    const VsyncPeriodChangeConstraints& /*constraints*/,
-    VsyncPeriodChangeTimeline* /*timeline*/) {
+    int64_t display_id, int32_t config,
+    const VsyncPeriodChangeConstraints& constraints,
+    VsyncPeriodChangeTimeline* timeline) {
   DEBUG_FUNC();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  hwc_vsync_period_change_constraints_t hwc2_constraints;
+  hwc2_constraints.desiredTimeNanos = constraints.desiredTimeNanos;
+  hwc2_constraints.seamlessRequired = static_cast<uint8_t>(
+      constraints.seamlessRequired);
+
+  hwc_vsync_period_change_timeline_t hwc2_timeline{};
+  auto error = Hwc2toHwc3Error(
+      display->SetActiveConfigWithConstraints(config, &hwc2_constraints,
+                                              &hwc2_timeline));
+  if (error != hwc3::Error::kNone) {
+    return ToBinderStatus(error);
+  }
+
+  timeline->refreshTimeNanos = hwc2_timeline.refreshTimeNanos;
+  timeline->newVsyncAppliedTimeNanos = hwc2_timeline.newVsyncAppliedTimeNanos;
+  timeline->refreshRequired = static_cast<bool>(hwc2_timeline.refreshRequired);
   return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t /*display*/,
+ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t /*display_id*/,
                                                         int32_t /*config*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
-ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(int64_t /*display*/) {
+ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(
+    int64_t /*display_id*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
 ndk::ScopedAStatus ComposerClient::getPreferredBootDisplayConfig(
-    int64_t /*display*/, int32_t* /*config*/) {
+    int64_t /*display_id*/, int32_t* /*config*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
-ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t /*display*/,
-                                                         bool /*on*/) {
+ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t display_id,
+                                                         bool on) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  auto error = Hwc2toHwc3Error(display->SetAutoLowLatencyMode(on));
+  return ToBinderStatus(error);
 }
 
-ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t /*display*/,
-                                                            int32_t /*count*/) {
+ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t display_id,
+                                                            int32_t count) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(
+      composer_resources_->SetDisplayClientTargetCacheSize(display_id, count));
 }
 
-ndk::ScopedAStatus ComposerClient::setColorMode(int64_t /*display*/,
-                                                ColorMode /*mode*/,
-                                                RenderIntent /*intent*/) {
+ndk::ScopedAStatus ComposerClient::setColorMode(int64_t display_id,
+                                                ColorMode mode,
+                                                RenderIntent intent) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  auto error = display->SetColorModeWithIntent(Hwc3ColorModeToHwc2(mode),
+                                               Hwc3RenderIntentToHwc2(intent));
+  return ToBinderStatus(Hwc2toHwc3Error(error));
 }
 
-ndk::ScopedAStatus ComposerClient::setContentType(int64_t /*display*/,
-                                                  ContentType /*type*/) {
+ndk::ScopedAStatus ComposerClient::setContentType(int64_t display_id,
+                                                  ContentType type) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  auto error = display->SetContentType(Hwc3ContentTypeToHwc2(type));
+  return ToBinderStatus(Hwc2toHwc3Error(error));
 }
 
 ndk::ScopedAStatus ComposerClient::setDisplayedContentSamplingEnabled(
-    int64_t /*display*/, bool /*enable*/,
+    int64_t /*display_id*/, bool /*enable*/,
     FormatColorComponent /*componentMask*/, int64_t /*maxFrames*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
-ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t /*display*/,
-                                                PowerMode /*mode*/) {
+ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display_id,
+                                                PowerMode mode) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  auto error = display->SetPowerMode(Hwc3PowerModeToHwc2(mode));
+  return ToBinderStatus(Hwc2toHwc3Error(error));
 }
 
 ndk::ScopedAStatus ComposerClient::setReadbackBuffer(
-    int64_t /*display*/, const AidlNativeHandle& /*aidlBuffer*/,
+    int64_t /*display_id*/, const AidlNativeHandle& /*aidlBuffer*/,
     const ndk::ScopedFileDescriptor& /*releaseFence*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
-ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t /*display*/,
-                                                   bool /*enabled*/) {
+ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t display_id,
+                                                   bool enabled) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
+  HwcDisplay* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
+  auto error = display->SetVsyncEnabled(static_cast<int32_t>(enabled));
+  return ToBinderStatus(Hwc2toHwc3Error(error));
 }
 
-ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t /*display*/,
+ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t /*display_id*/,
                                                        int32_t /*timeout*/) {
   DEBUG_FUNC();
-  return ndk::ScopedAStatus::ok();
+  return ToBinderStatus(hwc3::Error::kUnsupported);
+}
+
+std::string ComposerClient::Dump() {
+  uint32_t size = 0;
+  hwc_->Dump(&size, nullptr);
+
+  std::string buffer(size, '\0');
+  hwc_->Dump(&size, &buffer.front());
+  return buffer;
 }
 
 ::ndk::SpAIBinder ComposerClient::createBinder() {
@@ -299,4 +926,335 @@
   return binder;
 }
 
+void ComposerClient::ExecuteSetLayerBuffer(int64_t display_id,
+                                           HwcLayerWrapper& layer,
+                                           const Buffer& buffer) {
+  buffer_handle_t imported_buffer = nullptr;
+
+  auto releaser = composer_resources_->CreateResourceReleaser(true);
+  auto err = composer_resources_->GetLayerBuffer(display_id, layer.layer_id,
+                                                 buffer, &imported_buffer,
+                                                 releaser.get());
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+    return;
+  }
+
+  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+  auto fence_fd = const_cast<ndk::ScopedFileDescriptor&>(buffer.fence)
+                      .release();
+  err = Hwc2toHwc3Error(layer.layer->SetLayerBuffer(imported_buffer, fence_fd));
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+  }
+}
+
+void ComposerClient::ExecuteSetLayerBlendMode(
+    int64_t /*display_id*/, HwcLayerWrapper& layer,
+    const ParcelableBlendMode& blend_mode) {
+  auto err = Hwc2toHwc3Error(layer.layer->SetLayerBlendMode(
+      Hwc3BlendModeToHwc2(blend_mode.blendMode)));
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+  }
+}
+
+void ComposerClient::ExecuteSetLayerComposition(
+    int64_t /*display_id*/, HwcLayerWrapper& layer,
+    const ParcelableComposition& composition) {
+  hwc3::Error error = hwc3::Error::kNone;
+  switch (composition.composition) {
+      // Unsupported composition types should set an error for the current
+      // DisplayCommand.
+    case Composition::DISPLAY_DECORATION:
+    case Composition::SIDEBAND:
+      error = hwc3::Error::kUnsupported;
+      break;
+    default:
+      error = Hwc2toHwc3Error(layer.layer->SetLayerCompositionType(
+          Hwc3CompositionToHwc2(composition.composition)));
+  }
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+  }
+}
+
+void ComposerClient::ExecuteSetLayerDataspace(
+    int64_t /*display_id*/, HwcLayerWrapper& layer,
+    const ParcelableDataspace& dataspace) {
+  auto err = Hwc2toHwc3Error(
+      layer.layer->SetLayerDataspace(Hwc3DataspaceToHwc2(dataspace.dataspace)));
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+  }
+}
+
+void ComposerClient::ExecuteSetLayerDisplayFrame(int64_t /*display_id*/,
+                                                 HwcLayerWrapper& layer,
+                                                 const common::Rect& rect) {
+  const hwc_rect_t hwc2_rect{rect.left, rect.top, rect.right, rect.bottom};
+  auto err = Hwc2toHwc3Error(layer.layer->SetLayerDisplayFrame(hwc2_rect));
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+  }
+}
+void ComposerClient::ExecuteSetLayerPlaneAlpha(int64_t /*display_id*/,
+                                               HwcLayerWrapper& layer,
+                                               const PlaneAlpha& plane_alpha) {
+  auto err = Hwc2toHwc3Error(
+      layer.layer->SetLayerPlaneAlpha(plane_alpha.alpha));
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+  }
+}
+
+void ComposerClient::ExecuteSetLayerSourceCrop(
+    int64_t /*display_id*/, HwcLayerWrapper& layer,
+    const common::FRect& source_crop) {
+  const hwc_frect_t rect{source_crop.left, source_crop.top, source_crop.right,
+                         source_crop.bottom};
+  auto err = Hwc2toHwc3Error(layer.layer->SetLayerSourceCrop(rect));
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+  }
+}
+void ComposerClient::ExecuteSetLayerTransform(
+    int64_t /*display_id*/, HwcLayerWrapper& layer,
+    const ParcelableTransform& transform) {
+  auto err = Hwc2toHwc3Error(
+      layer.layer->SetLayerTransform(Hwc3TransformToHwc2(transform.transform)));
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+  }
+}
+void ComposerClient::ExecuteSetLayerZOrder(int64_t /*display_id*/,
+                                           HwcLayerWrapper& layer,
+                                           const ZOrder& z_order) {
+  auto err = Hwc2toHwc3Error(layer.layer->SetLayerZOrder(z_order.z));
+  if (err != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(err);
+  }
+}
+
+void ComposerClient::ExecuteSetLayerBrightness(
+    int64_t /*display_id*/, HwcLayerWrapper& /*layer*/,
+    const LayerBrightness& brightness) {
+  if (std::signbit(brightness.brightness) ||
+      std::isnan(brightness.brightness)) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadParameter);
+  }
+}
+
+void ComposerClient::ExecuteSetDisplayBrightness(
+    uint64_t display_id, const DisplayBrightness& command) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  auto error = Hwc2toHwc3Error(
+      display->SetDisplayBrightness(command.brightness));
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+  }
+}
+void ComposerClient::ExecuteSetDisplayColorTransform(
+    uint64_t display_id, const std::vector<float>& matrix) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  auto almost_equal = [](auto a, auto b) {
+    const float epsilon = 0.001F;
+    return std::abs(a - b) < epsilon;
+  };
+  const bool is_identity = std::equal(matrix.begin(), matrix.end(),
+                                      kIdentityMatrix.begin(), almost_equal);
+
+  const int32_t hint = is_identity ? HAL_COLOR_TRANSFORM_IDENTITY
+                                   : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
+
+  auto error = Hwc2toHwc3Error(display->SetColorTransform(matrix.data(), hint));
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+  }
+}
+void ComposerClient::ExecuteSetDisplayClientTarget(
+    uint64_t display_id, const ClientTarget& command) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  hwc_region_t damage_regions;
+  damage_regions.numRects = command.damage.size();
+
+  std::vector<hwc_rect_t> regions(command.damage.size());
+  for (const auto& region : command.damage) {
+    regions.push_back({region.left, region.top, region.right, region.bottom});
+  }
+  damage_regions.rects = regions.data();
+
+  buffer_handle_t imported_buffer = nullptr;
+  auto buf_releaser = composer_resources_->CreateResourceReleaser(true);
+
+  auto error = composer_resources_->GetDisplayClientTarget(display_id,
+                                                           command.buffer,
+                                                           &imported_buffer,
+                                                           buf_releaser.get());
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+    return;
+  }
+
+  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+  auto fence = const_cast<::ndk::ScopedFileDescriptor&>(command.buffer.fence)
+                   .release();
+  error = Hwc2toHwc3Error(
+      display->SetClientTarget(imported_buffer, fence,
+                               Hwc3DataspaceToHwc2(command.dataspace),
+                               damage_regions));
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+  }
+}
+
+void ComposerClient::ExecuteSetDisplayOutputBuffer(uint64_t display_id,
+                                                   const Buffer& buffer) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  buffer_handle_t imported_buffer = nullptr;
+  auto buf_releaser = composer_resources_->CreateResourceReleaser(true);
+
+  auto error = composer_resources_->GetDisplayOutputBuffer(display_id, buffer,
+                                                           &imported_buffer,
+                                                           buf_releaser.get());
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+    return;
+  }
+
+  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+  auto fence = const_cast<::ndk::ScopedFileDescriptor&>(buffer.fence).release();
+  error = Hwc2toHwc3Error(display->SetOutputBuffer(imported_buffer, fence));
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+    return;
+  }
+}
+void ComposerClient::ExecuteValidateDisplay(
+    int64_t display_id,
+    std::optional<ClockMonotonicTimestamp> /*expected_present_time*/
+) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  /* TODO: Handle expectedPresentTime */
+
+  std::vector<int64_t> changed_layers;
+  std::vector<Composition> composition_types;
+  int32_t display_request_mask = 0;
+  std::vector<int64_t> requested_layers;
+  std::vector<int32_t> request_masks;
+
+  const hwc3::Error error = ValidateDisplayInternal(*display, &changed_layers,
+                                                    &composition_types,
+                                                    &display_request_mask,
+                                                    &requested_layers,
+                                                    &request_masks, nullptr,
+                                                    nullptr);
+
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+  }
+
+  // If a CommandError has been been set for the current DisplayCommand, then
+  // no other results should be returned besides the error.
+  if (cmd_result_writer_->HasError()) {
+    return;
+  }
+
+  DisplayChanges changes{};
+  for (size_t i = 0; i < composition_types.size(); i++) {
+    changes.AddLayerCompositionChange(display_id, changed_layers[i],
+                                      composition_types[i]);
+  }
+
+  std::vector<DisplayRequest::LayerRequest> layer_requests;
+  for (size_t i = 0; i < requested_layers.size(); i++) {
+    layer_requests.push_back({requested_layers[i], request_masks[i]});
+  }
+
+  const DisplayRequest request_changes{display_id, display_request_mask,
+                                       layer_requests};
+  changes.display_request_changes = request_changes;
+
+  cmd_result_writer_->AddChanges(changes);
+  composer_resources_->SetDisplayMustValidateState(display_id, false);
+}
+
+void ComposerClient::ExecuteAcceptDisplayChanges(int64_t display_id) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  auto error = Hwc2toHwc3Error(display->AcceptDisplayChanges());
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+    return;
+  }
+}
+
+void ComposerClient::ExecutePresentDisplay(int64_t display_id) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  ::android::base::unique_fd display_fence;
+  std::unordered_map<int64_t, ::android::base::unique_fd> release_fences;
+  auto error = PresentDisplayInternal(display_id, display_fence,
+                                      release_fences);
+  if (error != hwc3::Error::kNone) {
+    cmd_result_writer_->AddError(error);
+  }
+  if (cmd_result_writer_->HasError()) {
+    return;
+  }
+
+  cmd_result_writer_->AddPresentFence(display_id, std::move(display_fence));
+  cmd_result_writer_->AddReleaseFence(display_id, release_fences);
+}
+
+void ComposerClient::ExecutePresentOrValidateDisplay(
+    int64_t display_id,
+    std::optional<ClockMonotonicTimestamp> expected_present_time) {
+  auto* display = GetDisplay(display_id);
+  if (display == nullptr) {
+    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
+    return;
+  }
+
+  /* TODO: Handle expectedPresentTime */
+  /* TODO: Add check if it's possible to skip display validation */
+  ExecuteValidateDisplay(display_id, expected_present_time);
+  cmd_result_writer_
+      ->AddPresentOrValidateResult(display_id,
+                                   PresentOrValidate::Result::Validated);
+}
+
 }  // namespace aidl::android::hardware::graphics::composer3::impl