/*
 * 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.
 */

#include "ComposerClient.h"

#include <aidlcommonsupport/NativeHandle.h>
#include <android/binder_ibinder_platform.h>

#include "Common.h"
#include "Device.h"
#include "GuestFrameComposer.h"
#include "HostFrameComposer.h"

namespace aidl::android::hardware::graphics::composer3::impl {
namespace {

#define GET_DISPLAY_OR_RETURN_ERROR()                                    \
  Display* display = getDisplay(displayId);                              \
  if (display == nullptr) {                                              \
    ALOGE("%s failed to get display:%" PRIu64, __FUNCTION__, displayId); \
    return ToBinderStatus(HWC3::Error::BadDisplay);                      \
  }

}  // namespace

using ::aidl::android::hardware::graphics::common::PixelFormat;

class ComposerClient::CommandResultWriter {
 public:
  CommandResultWriter(std::vector<CommandResultPayload>* results)
      : mIndex(0), mResults(results) {}

  void nextCommand() { ++mIndex; }

  void addError(HWC3::Error error) {
    CommandError commandErrorResult;
    commandErrorResult.commandIndex = mIndex;
    commandErrorResult.errorCode = static_cast<int32_t>(error);
    mResults->emplace_back(std::move(commandErrorResult));
  }

  void addPresentFence(int64_t displayId, ::android::base::unique_fd fence) {
    if (fence >= 0) {
      PresentFence presentFenceResult;
      presentFenceResult.display = displayId;
      presentFenceResult.fence = ndk::ScopedFileDescriptor(fence.release());
      mResults->emplace_back(std::move(presentFenceResult));
    }
  }

  void addReleaseFences(
      int64_t displayId,
      std::unordered_map<int64_t, ::android::base::unique_fd> layerFences) {
    ReleaseFences releaseFencesResult;
    releaseFencesResult.display = displayId;
    for (auto& [layer, layerFence] : layerFences) {
      if (layerFence >= 0) {
        ReleaseFences::Layer releaseFencesLayerResult;
        releaseFencesLayerResult.layer = layer;
        releaseFencesLayerResult.fence =
            ndk::ScopedFileDescriptor(layerFence.release());
        releaseFencesResult.layers.emplace_back(
            std::move(releaseFencesLayerResult));
      }
    }
    mResults->emplace_back(std::move(releaseFencesResult));
  }

  void addChanges(const DisplayChanges& changes) {
    if (changes.compositionChanges) {
      mResults->emplace_back(*changes.compositionChanges);
    }
    if (changes.displayRequestChanges) {
      mResults->emplace_back(*changes.displayRequestChanges);
    }
  }

  void addPresentOrValidateResult(int64_t displayId,
                                  PresentOrValidate::Result pov) {
    PresentOrValidate result;
    result.display = displayId;
    result.result = pov;
    mResults->emplace_back(std::move(result));
  }

 private:
  int32_t mIndex = 0;
  std::vector<CommandResultPayload>* mResults = nullptr;
};

ComposerClient::ComposerClient() { DEBUG_LOG("%s", __FUNCTION__); }

ComposerClient::~ComposerClient() {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  destroyDisplaysLocked();

  if (mOnClientDestroyed) {
    mOnClientDestroyed();
  }
}

HWC3::Error ComposerClient::init() {
  DEBUG_LOG("%s", __FUNCTION__);

  HWC3::Error error = HWC3::Error::None;

  std::unique_lock<std::mutex> lock(mStateMutex);

  mResources = std::make_unique<ComposerResources>();
  if (!mResources) {
    ALOGE("%s failed to allocate ComposerResources", __FUNCTION__);
    return HWC3::Error::NoResources;
  }

  error = mResources->init();
  if (error != HWC3::Error::None) {
    ALOGE("%s failed to initialize ComposerResources", __FUNCTION__);
    return error;
  }

  error = Device::getInstance().getComposer(&mComposer);
  if (error != HWC3::Error::None) {
    ALOGE("%s failed to get FrameComposer", __FUNCTION__);
    return error;
  }

  const auto HotplugCallback = [this](bool connected,   //
                                      int32_t id,       //
                                      uint32_t width,   //
                                      uint32_t height,  //
                                      uint32_t dpiX,    //
                                      uint32_t dpiY,    //
                                      uint32_t refreshRate) {
    handleHotplug(connected, id, width, height, dpiX, dpiY, refreshRate);
  };
  error = mComposer->registerOnHotplugCallback(HotplugCallback);
  if (error != HWC3::Error::None) {
    ALOGE("%s failed to register hotplug callback", __FUNCTION__);
    return error;
  }

  error = createDisplaysLocked();
  if (error != HWC3::Error::None) {
    ALOGE("%s failed to create displays.", __FUNCTION__);
    return error;
  }

  DEBUG_LOG("%s initialized!", __FUNCTION__);
  return HWC3::Error::None;
}

ndk::ScopedAStatus ComposerClient::createLayer(int64_t displayId,
                                               int32_t bufferSlotCount,
                                               int64_t* layerId) {
  DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  HWC3::Error error = display->createLayer(layerId);
  if (error != HWC3::Error::None) {
    ALOGE("%s: display:%" PRIu64 " failed to create layer", __FUNCTION__,
          displayId);
    return ToBinderStatus(error);
  }

  error = mResources->addLayer(displayId, *layerId, bufferSlotCount);
  if (error != HWC3::Error::None) {
    ALOGE("%s: display:%" PRIu64 " resources failed to create layer",
          __FUNCTION__, displayId);
    return ToBinderStatus(error);
  }

  return ToBinderStatus(HWC3::Error::None);
}

ndk::ScopedAStatus ComposerClient::createVirtualDisplay(
    int32_t /*width*/, int32_t /*height*/, PixelFormat /*formatHint*/,
    int32_t /*outputBufferSlotCount*/, VirtualDisplay* /*display*/) {
  DEBUG_LOG("%s", __FUNCTION__);

  return ToBinderStatus(HWC3::Error::Unsupported);
}

ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t displayId,
                                                int64_t layerId) {
  DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  HWC3::Error error = display->destroyLayer(layerId);
  if (error != HWC3::Error::None) {
    ALOGE("%s: display:%" PRIu64 " failed to destroy layer:%" PRIu64,
          __FUNCTION__, displayId, layerId);
    return ToBinderStatus(error);
  }

  error = mResources->removeLayer(displayId, layerId);
  if (error != HWC3::Error::None) {
    ALOGE("%s: display:%" PRIu64 " resources failed to destroy layer:%" PRIu64,
          __FUNCTION__, displayId, layerId);
    return ToBinderStatus(error);
  }

  return ToBinderStatus(HWC3::Error::None);
}

ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(
    int64_t /*displayId*/) {
  DEBUG_LOG("%s", __FUNCTION__);

  return ToBinderStatus(HWC3::Error::Unsupported);
}

ndk::ScopedAStatus ComposerClient::executeCommands(
    const std::vector<DisplayCommand>& commands,
    std::vector<CommandResultPayload>* commandResultPayloads) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  mCommandResults =
      std::make_unique<CommandResultWriter>(commandResultPayloads);

  for (const DisplayCommand& command : commands) {
    executeDisplayCommand(command);
    mCommandResults->nextCommand();
  }

  mCommandResults.reset();

  return ToBinderStatus(HWC3::Error::None);
}

ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t displayId,
                                                   int32_t* config) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getActiveConfig(config));
}

ndk::ScopedAStatus ComposerClient::getColorModes(
    int64_t displayId, std::vector<ColorMode>* colorModes) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getColorModes(colorModes));
}

ndk::ScopedAStatus ComposerClient::getDataspaceSaturationMatrix(
    common::Dataspace dataspace, std::vector<float>* matrix) {
  DEBUG_LOG("%s", __FUNCTION__);

  if (dataspace != common::Dataspace::SRGB_LINEAR) {
    return ToBinderStatus(HWC3::Error::BadParameter);
  }

  // clang-format off
  constexpr std::array<float, 16> kUnit {
    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
  matrix->clear();
  matrix->insert(matrix->begin(), kUnit.begin(), kUnit.end());

  return ToBinderStatus(HWC3::Error::None);
}

ndk::ScopedAStatus ComposerClient::getDisplayAttribute(
    int64_t displayId, int32_t config, DisplayAttribute attribute,
    int32_t* value) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getDisplayAttribute(config, attribute, value));
}

ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(
    int64_t displayId, std::vector<DisplayCapability>* outCaps) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getDisplayCapabilities(outCaps));
}

ndk::ScopedAStatus ComposerClient::getDisplayConfigs(
    int64_t displayId, std::vector<int32_t>* outConfigs) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getDisplayConfigs(outConfigs));
}

ndk::ScopedAStatus ComposerClient::getDisplayConnectionType(
    int64_t displayId, DisplayConnectionType* outType) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getDisplayConnectionType(outType));
}

ndk::ScopedAStatus ComposerClient::getDisplayIdentificationData(
    int64_t displayId, DisplayIdentification* outIdentification) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(
      display->getDisplayIdentificationData(outIdentification));
}

ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t displayId,
                                                  std::string* outName) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getDisplayName(outName));
}

ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(
    int64_t displayId, int32_t* outVsyncPeriod) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getDisplayVsyncPeriod(outVsyncPeriod));
}

ndk::ScopedAStatus ComposerClient::getDisplayedContentSample(
    int64_t displayId, int64_t maxFrames, int64_t timestamp,
    DisplayContentSample* outSamples) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(
      display->getDisplayedContentSample(maxFrames, timestamp, outSamples));
}

ndk::ScopedAStatus ComposerClient::getDisplayedContentSamplingAttributes(
    int64_t displayId, DisplayContentSamplingAttributes* outAttributes) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(
      display->getDisplayedContentSamplingAttributes(outAttributes));
}

ndk::ScopedAStatus ComposerClient::getDisplayPhysicalOrientation(
    int64_t displayId, common::Transform* outOrientation) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getDisplayPhysicalOrientation(outOrientation));
}

ndk::ScopedAStatus ComposerClient::getHdrCapabilities(
    int64_t displayId, HdrCapabilities* outCapabilities) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getHdrCapabilities(outCapabilities));
}

ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(
    int32_t* outCount) {
  DEBUG_LOG("%s", __FUNCTION__);

  // Not supported.
  *outCount = 0;

  return ToBinderStatus(HWC3::Error::None);
}

ndk::ScopedAStatus ComposerClient::getPerFrameMetadataKeys(
    int64_t displayId, std::vector<PerFrameMetadataKey>* outKeys) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getPerFrameMetadataKeys(outKeys));
}

ndk::ScopedAStatus ComposerClient::getReadbackBufferAttributes(
    int64_t displayId, ReadbackBufferAttributes* outAttributes) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getReadbackBufferAttributes(outAttributes));
}

ndk::ScopedAStatus ComposerClient::getReadbackBufferFence(
    int64_t displayId, ndk::ScopedFileDescriptor* outAcquireFence) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getReadbackBufferFence(outAcquireFence));
}

ndk::ScopedAStatus ComposerClient::getRenderIntents(
    int64_t displayId, ColorMode mode, std::vector<RenderIntent>* outIntents) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getRenderIntents(mode, outIntents));
}

ndk::ScopedAStatus ComposerClient::getSupportedContentTypes(
    int64_t displayId, std::vector<ContentType>* outTypes) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getSupportedContentTypes(outTypes));
}

ndk::ScopedAStatus ComposerClient::getDisplayDecorationSupport(
    int64_t displayId,
    std::optional<common::DisplayDecorationSupport>* outSupport) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getDecorationSupport(outSupport));
}

ndk::ScopedAStatus ComposerClient::registerCallback(
    const std::shared_ptr<IComposerCallback>& callback) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  const bool isFirstRegisterCallback = mCallbacks == nullptr;

  mCallbacks = callback;

  for (auto& [_, display] : mDisplays) {
    display->registerCallback(callback);
  }

  if (isFirstRegisterCallback) {
    lock.unlock();
    for (auto& [displayId, _] : mDisplays) {
      mCallbacks->onHotplug(displayId, /*connected=*/true);
    }
  }

  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t displayId,
                                                   int32_t configId) {
  DEBUG_LOG("%s display:%" PRIu64 " config:%" PRIu32, __FUNCTION__, displayId,
            configId);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setActiveConfig(configId));
}

ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints(
    int64_t displayId, int32_t configId,
    const VsyncPeriodChangeConstraints& constraints,
    VsyncPeriodChangeTimeline* outTimeline) {
  DEBUG_LOG("%s display:%" PRIu64 " config:%" PRIu32, __FUNCTION__, displayId,
            configId);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setActiveConfigWithConstraints(
      configId, constraints, outTimeline));
}

ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t displayId,
                                                        int32_t configId) {
  DEBUG_LOG("%s display:%" PRIu64 " config:%" PRIu32, __FUNCTION__, displayId,
            configId);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setBootConfig(configId));
}

ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(int64_t displayId) {
  DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->clearBootConfig());
}

ndk::ScopedAStatus ComposerClient::getPreferredBootDisplayConfig(
    int64_t displayId, int32_t* outConfigId) {
  DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->getPreferredBootConfig(outConfigId));
}

ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t displayId,
                                                         bool on) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setAutoLowLatencyMode(on));
}

ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t displayId,
                                                            int32_t count) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(
      mResources->setDisplayClientTargetCacheSize(displayId, count));
}

ndk::ScopedAStatus ComposerClient::setColorMode(int64_t displayId,
                                                ColorMode mode,
                                                RenderIntent intent) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setColorMode(mode, intent));
}

ndk::ScopedAStatus ComposerClient::setContentType(int64_t displayId,
                                                  ContentType type) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setContentType(type));
}

ndk::ScopedAStatus ComposerClient::setDisplayedContentSamplingEnabled(
    int64_t displayId, bool enable, FormatColorComponent componentMask,
    int64_t maxFrames) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setDisplayedContentSamplingEnabled(
      enable, componentMask, maxFrames));
}

ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t displayId,
                                                PowerMode mode) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setPowerMode(mode));
}

ndk::ScopedAStatus ComposerClient::setReadbackBuffer(
    int64_t displayId,
    const aidl::android::hardware::common::NativeHandle& buffer,
    const ndk::ScopedFileDescriptor& releaseFence) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  // Owned by mResources.
  buffer_handle_t importedBuffer = nullptr;

  auto releaser = mResources->createReleaser(true /* isBuffer */);
  auto error = mResources->getDisplayReadbackBuffer(
      displayId, buffer, &importedBuffer, releaser.get());
  if (error != HWC3::Error::None) {
    ALOGE("%s: failed to get readback buffer from resources.", __FUNCTION__);
    return ToBinderStatus(error);
  }

  error = display->setReadbackBuffer(importedBuffer, releaseFence);
  if (error != HWC3::Error::None) {
    ALOGE("%s: failed to set readback buffer to display.", __FUNCTION__);
    return ToBinderStatus(error);
  }

  return ToBinderStatus(HWC3::Error::None);
}

ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t displayId,
                                                   bool enabled) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setVsyncEnabled(enabled));
}

ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t displayId,
                                                       int32_t timeoutMs) {
  DEBUG_LOG("%s", __FUNCTION__);

  std::unique_lock<std::mutex> lock(mStateMutex);

  GET_DISPLAY_OR_RETURN_ERROR();

  return ToBinderStatus(display->setIdleTimerEnabled(timeoutMs));
}

ndk::SpAIBinder ComposerClient::createBinder() {
  auto binder = BnComposerClient::createBinder();
  AIBinder_setInheritRt(binder.get(), true);
  return binder;
}

namespace {

#define DISPATCH_LAYER_COMMAND(layerCmd, display, layer, field, funcName)     \
  do {                                                                        \
    if (layerCmd.field) {                                                     \
      ComposerClient::executeLayerCommandSetLayer##funcName(display, layer,   \
                                                            *layerCmd.field); \
    }                                                                         \
  } while (0)

#define DISPATCH_DISPLAY_COMMAND(displayCmd, display, field, funcName) \
  do {                                                                 \
    if (displayCmd.field) {                                            \
      executeDisplayCommand##funcName(display, *displayCmd.field);     \
    }                                                                  \
  } while (0)

#define DISPATCH_DISPLAY_BOOL_COMMAND(displayCmd, display, field, funcName) \
  do {                                                                      \
    if (displayCmd.field) {                                                 \
      executeDisplayCommand##funcName(display);                             \
    }                                                                       \
  } while (0)

#define DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCmd, display, field, \
                                               data, funcName)             \
  do {                                                                     \
    if (displayCmd.field) {                                                \
      executeDisplayCommand##funcName(display, displayCmd.data);           \
    }                                                                      \
  } while (0)

#define LOG_DISPLAY_COMMAND_ERROR(display, error)                 \
  do {                                                            \
    const std::string errorString = toString(error);              \
    ALOGE("%s: display:%" PRId64 " failed with:%s", __FUNCTION__, \
          display->getId(), errorString.c_str());                 \
  } while (0)

#define LOG_LAYER_COMMAND_ERROR(display, layer, error)                \
  do {                                                                \
    const std::string errorString = toString(error);                  \
    ALOGE("%s: display:%" PRId64 " layer:%" PRId64 " failed with:%s", \
          __FUNCTION__, display->getId(), layer->getId(),             \
          errorString.c_str());                                       \
  } while (0)

}  // namespace

void ComposerClient::executeDisplayCommand(
    const DisplayCommand& displayCommand) {
  Display* display = getDisplay(displayCommand.display);
  if (display == nullptr) {
    mCommandResults->addError(HWC3::Error::BadDisplay);
    return;
  }

  for (const LayerCommand& layerCmd : displayCommand.layers) {
    executeLayerCommand(display, layerCmd);
  }

  DISPATCH_DISPLAY_COMMAND(displayCommand, display, colorTransformMatrix,
                           SetColorTransform);
  DISPATCH_DISPLAY_COMMAND(displayCommand, display, brightness, SetBrightness);
  DISPATCH_DISPLAY_COMMAND(displayCommand, display, clientTarget,
                           SetClientTarget);
  DISPATCH_DISPLAY_COMMAND(displayCommand, display, virtualDisplayOutputBuffer,
                           SetOutputBuffer);
  DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCommand, display,
                                         validateDisplay, expectedPresentTime,
                                         ValidateDisplay);
  DISPATCH_DISPLAY_BOOL_COMMAND(displayCommand, display, acceptDisplayChanges,
                                AcceptDisplayChanges);
  DISPATCH_DISPLAY_BOOL_COMMAND(displayCommand, display, presentDisplay,
                                PresentDisplay);
  DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(
      displayCommand, display, presentOrValidateDisplay, expectedPresentTime,
      PresentOrValidateDisplay);
}

void ComposerClient::executeLayerCommand(Display* display,
                                         const LayerCommand& layerCommand) {
  Layer* layer = display->getLayer(layerCommand.layer);
  if (layer == nullptr) {
    mCommandResults->addError(HWC3::Error::BadLayer);
    return;
  }

  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, cursorPosition,
                         CursorPosition);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, buffer, Buffer);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, damage, SurfaceDamage);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, blendMode, BlendMode);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, color, Color);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, composition,
                         Composition);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, dataspace, Dataspace);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, displayFrame,
                         DisplayFrame);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, planeAlpha, PlaneAlpha);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, sidebandStream,
                         SidebandStream);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, sourceCrop, SourceCrop);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, transform, Transform);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, visibleRegion,
                         VisibleRegion);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, z, ZOrder);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, colorTransform,
                         ColorTransform);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, brightness, Brightness);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, perFrameMetadata,
                         PerFrameMetadata);
  DISPATCH_LAYER_COMMAND(layerCommand, display, layer, perFrameMetadataBlob,
                         PerFrameMetadataBlobs);
}

void ComposerClient::executeDisplayCommandSetColorTransform(
    Display* display, const std::vector<float>& matrix) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = display->setColorTransform(matrix);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeDisplayCommandSetBrightness(
    Display* display, const DisplayBrightness& brightness) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = display->setBrightness(brightness.brightness);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeDisplayCommandSetClientTarget(
    Display* display, const ClientTarget& clientTarget) {
  DEBUG_LOG("%s", __FUNCTION__);

  // Owned by mResources.
  buffer_handle_t importedBuffer = nullptr;

  auto releaser = mResources->createReleaser(/*isBuffer=*/true);
  auto error = mResources->getDisplayClientTarget(
      display->getId(), clientTarget.buffer, &importedBuffer, releaser.get());
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
    return;
  }

  error = display->setClientTarget(importedBuffer, clientTarget.buffer.fence,
                                   clientTarget.dataspace, clientTarget.damage);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
    return;
  }
}

void ComposerClient::executeDisplayCommandSetOutputBuffer(
    Display* display, const Buffer& buffer) {
  DEBUG_LOG("%s", __FUNCTION__);

  // Owned by mResources.
  buffer_handle_t importedBuffer = nullptr;

  auto releaser = mResources->createReleaser(/*isBuffer=*/true);
  auto error = mResources->getDisplayOutputBuffer(
      display->getId(), buffer, &importedBuffer, releaser.get());
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
    return;
  }

  error = display->setOutputBuffer(importedBuffer, buffer.fence);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
    return;
  }
}

void ComposerClient::executeDisplayCommandValidateDisplay(
    Display* display,
    const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = display->setExpectedPresentTime(expectedPresentTime);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
  }

  DisplayChanges changes;

  error = display->validate(&changes);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
  } else {
    mCommandResults->addChanges(changes);
  }

  mResources->setDisplayMustValidateState(display->getId(), false);
}

void ComposerClient::executeDisplayCommandAcceptDisplayChanges(
    Display* display) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = display->acceptChanges();
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeDisplayCommandPresentOrValidateDisplay(
    Display* display,
    const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
  DEBUG_LOG("%s", __FUNCTION__);

  // TODO: Support SKIP_VALIDATE.

  auto error = display->setExpectedPresentTime(expectedPresentTime);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
  }

  DisplayChanges changes;

  error = display->validate(&changes);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
  } else {
    const int64_t displayId = display->getId();
    mCommandResults->addChanges(changes);
    mCommandResults->addPresentOrValidateResult(
        displayId, PresentOrValidate::Result::Validated);
  }

  mResources->setDisplayMustValidateState(display->getId(), false);
}

void ComposerClient::executeDisplayCommandPresentDisplay(Display* display) {
  DEBUG_LOG("%s", __FUNCTION__);

  if (mResources->mustValidateDisplay(display->getId())) {
    ALOGE("%s: display:%" PRIu64 " not validated", __FUNCTION__,
          display->getId());
    mCommandResults->addError(HWC3::Error::NotValidated);
    return;
  }

  ::android::base::unique_fd displayFence;
  std::unordered_map<int64_t, ::android::base::unique_fd> layerFences;

  auto error = display->present(&displayFence, &layerFences);
  if (error != HWC3::Error::None) {
    LOG_DISPLAY_COMMAND_ERROR(display, error);
    mCommandResults->addError(error);
  } else {
    const int64_t displayId = display->getId();
    mCommandResults->addPresentFence(displayId, std::move(displayFence));
    mCommandResults->addReleaseFences(displayId, std::move(layerFences));
  }
}

void ComposerClient::executeLayerCommandSetLayerCursorPosition(
    Display* display, Layer* layer, const common::Point& cursorPosition) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setCursorPosition(cursorPosition);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerBuffer(Display* display,
                                                       Layer* layer,
                                                       const Buffer& buffer) {
  DEBUG_LOG("%s", __FUNCTION__);

  // Owned by mResources.
  buffer_handle_t importedBuffer = nullptr;

  auto releaser = mResources->createReleaser(/*isBuffer=*/true);
  auto error =
      mResources->getLayerBuffer(display->getId(), layer->getId(), buffer,
                                 &importedBuffer, releaser.get());
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
    return;
  }

  error = layer->setBuffer(importedBuffer, buffer.fence);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerSurfaceDamage(
    Display* display, Layer* layer,
    const std::vector<std::optional<common::Rect>>& damage) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setSurfaceDamage(damage);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerBlendMode(
    Display* display, Layer* layer, const ParcelableBlendMode& blendMode) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setBlendMode(blendMode.blendMode);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerColor(Display* display,
                                                      Layer* layer,
                                                      const Color& color) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setColor(color);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerComposition(
    Display* display, Layer* layer, const ParcelableComposition& composition) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setCompositionType(composition.composition);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerDataspace(
    Display* display, Layer* layer, const ParcelableDataspace& dataspace) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setDataspace(dataspace.dataspace);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerDisplayFrame(
    Display* display, Layer* layer, const common::Rect& rect) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setDisplayFrame(rect);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerPlaneAlpha(
    Display* display, Layer* layer, const PlaneAlpha& planeAlpha) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setPlaneAlpha(planeAlpha.alpha);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerSidebandStream(
    Display* display, Layer* layer,
    const aidl::android::hardware::common::NativeHandle& handle) {
  DEBUG_LOG("%s", __FUNCTION__);

  // Owned by mResources.
  buffer_handle_t importedStream = nullptr;

  auto releaser = mResources->createReleaser(/*isBuffer=*/false);
  auto error = mResources->getLayerSidebandStream(
      display->getId(), layer->getId(), handle, &importedStream,
      releaser.get());
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
    return;
  }

  error = layer->setSidebandStream(importedStream);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerSourceCrop(
    Display* display, Layer* layer, const common::FRect& sourceCrop) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setSourceCrop(sourceCrop);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerTransform(
    Display* display, Layer* layer, const ParcelableTransform& transform) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setTransform(transform.transform);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerVisibleRegion(
    Display* display, Layer* layer,
    const std::vector<std::optional<common::Rect>>& visibleRegion) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setVisibleRegion(visibleRegion);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerZOrder(Display* display,
                                                       Layer* layer,
                                                       const ZOrder& zOrder) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setZOrder(zOrder.z);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerPerFrameMetadata(
    Display* display, Layer* layer,
    const std::vector<std::optional<PerFrameMetadata>>& perFrameMetadata) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setPerFrameMetadata(perFrameMetadata);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerColorTransform(
    Display* display, Layer* layer, const std::vector<float>& colorTransform) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setColorTransform(colorTransform);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerBrightness(
    Display* display, Layer* layer, const LayerBrightness& brightness) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setBrightness(brightness.brightness);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

void ComposerClient::executeLayerCommandSetLayerPerFrameMetadataBlobs(
    Display* display, Layer* layer,
    const std::vector<std::optional<PerFrameMetadataBlob>>&
        perFrameMetadataBlob) {
  DEBUG_LOG("%s", __FUNCTION__);

  auto error = layer->setPerFrameMetadataBlobs(perFrameMetadataBlob);
  if (error != HWC3::Error::None) {
    LOG_LAYER_COMMAND_ERROR(display, layer, error);
    mCommandResults->addError(error);
  }
}

Display* ComposerClient::getDisplay(int64_t displayId) {
  auto it = mDisplays.find(displayId);
  if (it == mDisplays.end()) {
    ALOGE("%s: no display:%" PRIu64, __FUNCTION__, displayId);
    return nullptr;
  }
  return it->second.get();
}

HWC3::Error ComposerClient::createDisplaysLocked() {
  DEBUG_LOG("%s", __FUNCTION__);

  if (!mComposer) {
    ALOGE("%s composer not initialized!", __FUNCTION__);
    return HWC3::Error::NoResources;
  }

  std::vector<DisplayMultiConfigs> displays;

  HWC3::Error error = findDisplays(mComposer->getDrmPresenter(), &displays);
  if (error != HWC3::Error::None) {
    ALOGE("%s failed to find display configs", __FUNCTION__);
    return error;
  }

  for (const auto& iter : displays) {
    error =
        createDisplayLocked(iter.displayId, iter.activeConfigId, iter.configs);
    if (error != HWC3::Error::None) {
      ALOGE("%s failed to create display from config", __FUNCTION__);
      return error;
    }
  }

  return HWC3::Error::None;
}

HWC3::Error ComposerClient::createDisplayLocked(
    int64_t displayId, int32_t activeConfigId,
    const std::vector<DisplayConfig>& configs) {
  DEBUG_LOG("%s", __FUNCTION__);

  if (!mComposer) {
    ALOGE("%s composer not initialized!", __FUNCTION__);
    return HWC3::Error::NoResources;
  }

  auto display = std::make_unique<Display>(mComposer, displayId);
  if (display == nullptr) {
    ALOGE("%s failed to allocate display", __FUNCTION__);
    return HWC3::Error::NoResources;
  }

  HWC3::Error error = display->init(configs, activeConfigId);
  if (error != HWC3::Error::None) {
    ALOGE("%s failed to initialize display:%" PRIu64, __FUNCTION__, displayId);
    return error;
  }

  error = mComposer->onDisplayCreate(display.get());
  if (error != HWC3::Error::None) {
    ALOGE("%s failed to register display:%" PRIu64 " with composer",
          __FUNCTION__, displayId);
    return error;
  }

  display->setPowerMode(PowerMode::ON);

  DEBUG_LOG("%s: adding display:%" PRIu64, __FUNCTION__, displayId);
  mDisplays.emplace(displayId, std::move(display));

  error = mResources->addPhysicalDisplay(displayId);
  if (error != HWC3::Error::None) {
    ALOGE("%s failed to initialize display:%" PRIu64 " resources", __FUNCTION__,
          displayId);
    return error;
  }

  return HWC3::Error::None;
}

HWC3::Error ComposerClient::destroyDisplaysLocked() {
  DEBUG_LOG("%s", __FUNCTION__);

  std::vector<int64_t> displayIds;
  for (const auto& [displayId, _] : mDisplays) {
    displayIds.push_back(displayId);
  }
  for (const int64_t displayId : displayIds) {
    destroyDisplayLocked(displayId);
  }

  return HWC3::Error::None;
}

HWC3::Error ComposerClient::destroyDisplayLocked(int64_t displayId) {
  DEBUG_LOG("%s display:%" PRId64, __FUNCTION__, displayId);

  auto it = mDisplays.find(displayId);
  if (it == mDisplays.end()) {
    ALOGE("%s: display:%" PRId64 " no such display?", __FUNCTION__, displayId);
    return HWC3::Error::BadDisplay;
  }

  Display* display = it->second.get();

  display->setPowerMode(PowerMode::OFF);

  HWC3::Error error = mComposer->onDisplayDestroy(it->second.get());
  if (error != HWC3::Error::None) {
    ALOGE("%s: display:%" PRId64 " failed to destroy with frame composer",
          __FUNCTION__, displayId);
  }

  error = mResources->removeDisplay(displayId);
  if (error != HWC3::Error::None) {
    ALOGE("%s: display:%" PRId64 " failed to destroy with resources",
          __FUNCTION__, displayId);
  }

  mDisplays.erase(it);

  return HWC3::Error::None;
}

HWC3::Error ComposerClient::handleHotplug(bool connected, uint32_t id,
                                          uint32_t width, uint32_t height,
                                          uint32_t dpiX, uint32_t dpiY,
                                          uint32_t refreshRate) {
  if (!mCallbacks) {
    return HWC3::Error::None;
  }

  const int64_t displayId = static_cast<int64_t>(id);

  if (connected) {
    const int32_t configId = static_cast<int32_t>(id);
    const std::vector<DisplayConfig> configs = {
        DisplayConfig(configId, static_cast<int>(width),
                      static_cast<int>(height), static_cast<int>(dpiX),
                      static_cast<int>(dpiY), static_cast<int>(refreshRate))};
    {
      std::unique_lock<std::mutex> lock(mStateMutex);
      createDisplayLocked(displayId, configId, configs);
    }

    ALOGI("Connecting display:%" PRIu32 " w:%" PRIu32 " h:%" PRIu32
          " dpiX:%" PRIu32 " dpiY %" PRIu32 "fps %" PRIu32,
          id, width, height, dpiX, dpiY, refreshRate);
    mCallbacks->onHotplug(displayId, /*connected=*/true);
  } else {
    ALOGI("Disconnecting display:%" PRIu64, displayId);
    mCallbacks->onHotplug(displayId, /*connected=*/false);

    Display* display = getDisplay(displayId);
    if (display != nullptr) {
      std::unique_lock<std::mutex> lock(mStateMutex);
      destroyDisplayLocked(displayId);
    }
  }

  return HWC3::Error::None;
}

}  // namespace aidl::android::hardware::graphics::composer3::impl