/*
 * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 2017 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 <vector>
#include <string>

#include "QtiComposerClient.h"

namespace vendor {
namespace qti {
namespace hardware {
namespace display {
namespace composer {
namespace V3_1 {
namespace implementation {

ComposerHandleImporter mHandleImporter;

BufferCacheEntry::BufferCacheEntry() : mHandle(nullptr) {}

BufferCacheEntry::BufferCacheEntry(BufferCacheEntry&& other) {
  mHandle = other.mHandle;
  other.mHandle = nullptr;
}

BufferCacheEntry& BufferCacheEntry::operator=(buffer_handle_t handle) {
  clear();
  mHandle = handle;
  return *this;
}

BufferCacheEntry::~BufferCacheEntry() {
  clear();
}

void BufferCacheEntry::clear() {
  if (mHandle) {
    mHandleImporter.freeBuffer(mHandle);
  }
}

QtiComposerClient::QtiComposerClient() : mWriter(kWriterInitialSize), mReader(*this) {
  hwc_session_ = HWCSession::GetInstance();
  mHandleImporter.initialize();
}

QtiComposerClient::~QtiComposerClient() {
  // We want to call hwc2_close here (and move hwc2_open to the
  // constructor), with the assumption that hwc2_close would
  //
  //  - clean up all resources owned by the client
  //  - make sure all displays are blank (since there is no layer)
  //
  // But since SF used to crash at this point, different hwcomposer2
  // implementations behave differently on hwc2_close.  Our only portable
  // choice really is to abort().  But that is not an option anymore
  // because we might also have VTS or VR as clients that can come and go.
  //
  // Below we manually clean all resources (layers and virtual
  // displays), and perform a presentDisplay afterwards.
  ALOGW("destroying composer client");

  enableCallback(false);

  // no need to grab the mutex as any in-flight hwbinder call would have
  // kept the client alive
  for (const auto& dpy : mDisplayData) {
    ALOGW("destroying client resources for display %" PRIu64, dpy.first);

    for (const auto& ly : dpy.second.Layers) {
      hwc_session_->DestroyLayer(dpy.first, ly.first);
    }

    if (dpy.second.IsVirtual) {
      destroyVirtualDisplay(dpy.first);
    } else {
      ALOGW("performing a final presentDisplay");

      mReader.validateDisplay();

      hwc_session_->AcceptDisplayChanges(dpy.first);

      shared_ptr<Fence> presentFence = nullptr;
      std::vector<Layer> releasedLayers;
      std::vector<shared_ptr<Fence>> releaseFences;
      mReader.presentDisplay(dpy.first, &presentFence, releasedLayers, releaseFences);
    }
  }

  mDisplayData.clear();

  mHandleImporter.cleanup();

  ALOGW("removed composer client");
}

void QtiComposerClient::onHotplug(hwc2_callback_data_t callbackData, hwc2_display_t display,
                                    int32_t connected) {
  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
  auto connect = static_cast<composer_V2_4::IComposerCallback::Connection>(connected);
  if (connect == composer_V2_4::IComposerCallback::Connection::CONNECTED) {
    std::lock_guard<std::mutex> lock_d(client->mDisplayDataMutex);
    client->mDisplayData.emplace(display, DisplayData(false));
  }

  auto ret = client->callback_->onHotplug(display, connect);
  ALOGW_IF(!ret.isOk(), "failed to send onHotplug: %s. SF likely unavailable.",
           ret.description().c_str());

  if (connect == composer_V2_4::IComposerCallback::Connection::DISCONNECTED) {
    // Trigger refresh to make sure disconnect event received/updated properly by SurfaceFlinger.
    client->hwc_session_->Refresh(HWC_DISPLAY_PRIMARY);
    // Wait for sufficient time to ensure sufficient resources are available to process connection.
    uint32_t vsync_period;
    client->hwc_session_->GetVsyncPeriod(HWC_DISPLAY_PRIMARY, &vsync_period);
    usleep(vsync_period * 2 / 1000);

    // Wait for the input command message queue to process before destroying the local display data.
    std::lock_guard<std::mutex> lock(client->mCommandMutex);
    std::lock_guard<std::mutex> lock_d(client->mDisplayDataMutex);
    client->mDisplayData.erase(display);
  }
}

void QtiComposerClient::onRefresh(hwc2_callback_data_t callbackData, hwc2_display_t display) {
  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
  auto ret = client->callback_->onRefresh(display);
  ALOGW_IF(!ret.isOk(), "failed to send onRefresh: %s. SF likely unavailable.",
           ret.description().c_str());
}

void QtiComposerClient::onVsync(hwc2_callback_data_t callbackData, hwc2_display_t display,
                                int64_t timestamp) {
  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
  auto ret = client->callback_->onVsync(display, timestamp);
  ALOGW_IF(!ret.isOk(), "failed to send onVsync: %s. SF likely unavailable.",
           ret.description().c_str());
}

void QtiComposerClient::onVsync_2_4(hwc2_callback_data_t callbackData, hwc2_display_t display,
                                    int64_t timestamp, VsyncPeriodNanos vsyncPeriodNanos) {
  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
  auto ret = client->callback24_->onVsync_2_4(display, timestamp, vsyncPeriodNanos);
  ALOGW_IF(!ret.isOk(), "failed to send onVsync_2_4: %s. SF likely unavailable.",
           ret.description().c_str());
}

void QtiComposerClient::onVsyncPeriodTimingChanged(hwc2_callback_data_t callbackData,
      hwc2_display_t display, hwc_vsync_period_change_timeline_t *updatedTimeline) {
   VsyncPeriodChangeTimeline timeline =
                                   {updatedTimeline->newVsyncAppliedTimeNanos,
                                    static_cast<bool>(updatedTimeline->refreshRequired),
                                    updatedTimeline->refreshTimeNanos};

  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
  auto ret = client->callback24_->onVsyncPeriodTimingChanged(display, timeline);
  ALOGW_IF(!ret.isOk(), "failed to send onVsyncPeriodTimingChanged: %s. SF likely unavailable.",
          ret.description().c_str());
}

void QtiComposerClient::onSeamlessPossible(hwc2_callback_data_t callbackData,
                                           hwc2_display_t display) {
  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
  auto ret = client->callback24_->onSeamlessPossible(display);
  ALOGW_IF(!ret.isOk(), "failed to send onSeamlessPossible: %s. SF likely unavailable.",
           ret.description().c_str());
}

// convert fenceFd to or from hidl_handle
// Handle would still own original fence. Hence create a Fence object on duped fd.
Error QtiComposerClient::getFence(const hidl_handle& fenceHandle, shared_ptr<Fence>* outFence,
                                  const string& name) {
  auto handle = fenceHandle.getNativeHandle();
  if (handle && handle->numFds > 1) {
    QTI_LOGE("Invalid fence handle with %d fds", handle->numFds);
    return Error::BAD_PARAMETER;
  }

  int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
  *outFence = Fence::Create(dup(fenceFd), name);

  return Error::NONE;
}

// Handle would own fence hereafter. Hence provide a dupped fd.
hidl_handle QtiComposerClient::getFenceHandle(const shared_ptr<Fence>& fence,
                                              char* handleStorage) {
  native_handle_t* handle = nullptr;
  if (fence) {
    handle = native_handle_init(handleStorage, 1, 0);
    if (handle) {
      handle->data[0] = Fence::Dup(fence);
    }
  }

  return hidl_handle(handle);
}

Error QtiComposerClient::getDisplayReadbackBuffer(Display display,
                                                  const native_handle_t* rawHandle,
                                                  const native_handle_t** outHandle) {
  // TODO(user): revisit for caching and freeBuffer in success case.
  if (!mHandleImporter.importBuffer(rawHandle)) {
    QTI_LOGE("ImportBuffer failed: ");
    return Error::NO_RESOURCES;
  }

  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
  auto iter = mDisplayData.find(display);
  if (iter == mDisplayData.end()) {
    mHandleImporter.freeBuffer(rawHandle);
    return Error::BAD_DISPLAY;
  }

  *outHandle = rawHandle;
  return Error::NONE;
}

void QtiComposerClient::getCapabilities() {
  uint32_t count = 0;
  hwc_session_->GetCapabilities(&count, nullptr);

  std::vector<int32_t> composer_caps(count);
  hwc_session_->GetCapabilities(&count, composer_caps.data());
  composer_caps.resize(count);

  mCapabilities.reserve(count);
  for (auto cap : composer_caps) {
    mCapabilities.insert(static_cast<hwc2_capability_t>(cap));
  }
}

void QtiComposerClient::enableCallback(bool enable) {
  if (enable) {
    hwc_session_->RegisterCallback(HWC2_CALLBACK_HOTPLUG, this,
                                   reinterpret_cast<hwc2_function_pointer_t>(onHotplug));
    hwc_session_->RegisterCallback(HWC2_CALLBACK_REFRESH, this,
                                   reinterpret_cast<hwc2_function_pointer_t>(onRefresh));
    if (!mUseCallback24_) {
      hwc_session_->RegisterCallback(HWC2_CALLBACK_VSYNC, this,
                                     reinterpret_cast<hwc2_function_pointer_t>(onVsync));
    } else {
      hwc_session_->RegisterCallback(HWC2_CALLBACK_VSYNC_2_4, this,
                                     reinterpret_cast<hwc2_function_pointer_t>(onVsync_2_4));
      hwc_session_->RegisterCallback(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, this,
                             reinterpret_cast<hwc2_function_pointer_t>(onVsyncPeriodTimingChanged));
      hwc_session_->RegisterCallback(HWC2_CALLBACK_SEAMLESS_POSSIBLE, this,
                                     reinterpret_cast<hwc2_function_pointer_t>(onSeamlessPossible));
    }
  } else {
    hwc_session_->RegisterCallback(HWC2_CALLBACK_HOTPLUG, this, nullptr);
    hwc_session_->RegisterCallback(HWC2_CALLBACK_REFRESH, this, nullptr);
    if (!mUseCallback24_) {
      hwc_session_->RegisterCallback(HWC2_CALLBACK_VSYNC, this, nullptr);
    } else {
      hwc_session_->RegisterCallback(HWC2_CALLBACK_VSYNC_2_4, this, nullptr);
      hwc_session_->RegisterCallback(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, this, nullptr);
      hwc_session_->RegisterCallback(HWC2_CALLBACK_SEAMLESS_POSSIBLE, this, nullptr);
    }
  }
}

// Methods from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
Return<void> QtiComposerClient::registerCallback(
                                            const sp<composer_V2_1::IComposerCallback>& callback) {
  callback_ = callback;
  enableCallback(callback != nullptr);
  return Void();
}

Return<uint32_t> QtiComposerClient::getMaxVirtualDisplayCount() {
  return hwc_session_->GetMaxVirtualDisplayCount();
}

Return<void> QtiComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
                                                     common_V1_0::PixelFormat formatHint,
                                                     uint32_t outputBufferSlotCount,
                                                     createVirtualDisplay_cb _hidl_cb) {
  // TODO(user): Implement combinedly w.r.t createVirtualDisplay_2_2
  int32_t format = static_cast<int32_t>(formatHint);
  uint64_t display;
  auto error = hwc_session_->CreateVirtualDisplay(width, height, &format, &display);

  if (static_cast<Error>(error) == Error::NONE) {
    std::lock_guard<std::mutex> lock(mDisplayDataMutex);

    auto dpy = mDisplayData.emplace(static_cast<Display>(display), DisplayData(true)).first;
    dpy->second.OutputBuffers.resize(outputBufferSlotCount);
  }

  _hidl_cb(static_cast<Error>(error), display, static_cast<common_V1_0::PixelFormat>(format));
  return Void();
}

Return<composer_V2_1::Error> QtiComposerClient::destroyVirtualDisplay(uint64_t display) {
  auto error = hwc_session_->DestroyVirtualDisplay(display);
  if (static_cast<Error>(error) == Error::NONE) {
    std::lock_guard<std::mutex> lock(mDisplayDataMutex);

    mDisplayData.erase(display);
  }

  return static_cast<Error>(error);
}

Return<void> QtiComposerClient::createLayer(uint64_t display, uint32_t bufferSlotCount,
                                            createLayer_cb _hidl_cb) {
  composer_V2_1::Layer layer = 0;
  auto error = hwc_session_->CreateLayer(display, &layer);
  Error err = static_cast<Error>(error);
  if (err == Error::NONE) {
    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
    auto dpy = mDisplayData.find(display);
    // The display entry may have already been removed by onHotplug.
    if (dpy != mDisplayData.end()) {
      auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
      ly->second.Buffers.resize(bufferSlotCount);
    } else {
      err = Error::BAD_DISPLAY;
      // Note: We do not destroy the layer on this error as the hotplug
      // disconnect invalidates the display id. The implementation should
      // ensure all layers for the display are destroyed.
    }
  }

  _hidl_cb(err, layer);
  return Void();
}

Return<Error> QtiComposerClient::destroyLayer(uint64_t display, uint64_t layer) {
  auto error = hwc_session_->DestroyLayer(display, layer);
  Error err = static_cast<Error>(error);
  if (err == Error::NONE) {
    std::lock_guard<std::mutex> lock(mDisplayDataMutex);

    auto dpy = mDisplayData.find(display);
    // The display entry may have already been removed by onHotplug.
    if (dpy != mDisplayData.end()) {
      dpy->second.Layers.erase(layer);
    }
  }

  return static_cast<Error>(error);
}

Return<void> QtiComposerClient::getActiveConfig(uint64_t display, getActiveConfig_cb _hidl_cb) {
  uint32_t config = 0;
  auto error = hwc_session_->GetActiveConfig(display, &config);

  _hidl_cb(static_cast<Error>(error), config);

  return Void();
}

Return<Error> QtiComposerClient::getClientTargetSupport(uint64_t display, uint32_t width,
                                                        uint32_t height,
                                                        common_V1_0::PixelFormat format,
                                                        common_V1_0::Dataspace dataspace) {
  auto error = hwc_session_->GetClientTargetSupport(display, width, height,
                                                    static_cast<int32_t>(format),
                                                    static_cast<int32_t>(dataspace));

  return static_cast<Error>(error);
}

Return<void> QtiComposerClient::getColorModes(uint64_t display, getColorModes_cb _hidl_cb) {
  // TODO(user): Implement combinedly w.r.t getColorModes_2_3
  hidl_vec<common_V1_0::ColorMode> modes;
  uint32_t count = 0;

  auto error = hwc_session_->GetColorModes(display, &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), modes);
    return Void();
  }

  modes.resize(count);
  error = hwc_session_->GetColorModes(display, &count,
              reinterpret_cast<std::underlying_type<common_V1_0::ColorMode>::type*>(modes.data()));

  _hidl_cb(static_cast<Error>(error), modes);
  return Void();
}

Return<void> QtiComposerClient::getDisplayAttribute(uint64_t display, uint32_t config,
                                               composer_V2_1::IComposerClient::Attribute attribute,
                                               getDisplayAttribute_cb _hidl_cb) {
  int32_t value = 0;
  auto error = hwc_session_->GetDisplayAttribute(
      display, config, static_cast<composer_V2_4::IComposerClient::Attribute>(attribute), &value);

  _hidl_cb(static_cast<Error>(error), value);
  return Void();
}

Return<void> QtiComposerClient::getDisplayConfigs(uint64_t display,
                                                  getDisplayConfigs_cb _hidl_cb) {
  hidl_vec<uint32_t> configs;
  uint32_t count = 0;

  auto error = hwc_session_->GetDisplayConfigs(display, &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), configs);
    return Void();
  }

  configs.resize(count);
  error = hwc_session_->GetDisplayConfigs(display, &count, configs.data());

  _hidl_cb(static_cast<Error>(error), configs);
  return Void();
}

Return<void> QtiComposerClient::getDisplayName(uint64_t display, getDisplayName_cb _hidl_cb) {
  uint32_t count = 0;
  hidl_string name_reply;
  std::vector<char> name;

  auto error = hwc_session_->GetDisplayName(display, &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), name_reply);
    return Void();
  }

  name.resize(count + 1);
  error = hwc_session_->GetDisplayName(display, &count, name.data());
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), name_reply);
    return Void();
  }

  name.resize(count + 1);
  name[count] = '\0';
  name_reply.setToExternal(name.data(), count);

  _hidl_cb(static_cast<Error>(error), name_reply);
  return Void();
}

Return<void> QtiComposerClient::getDisplayType(uint64_t display, getDisplayType_cb _hidl_cb) {
  int32_t hwc_type;
  auto error = hwc_session_->GetDisplayType(display, &hwc_type);

  _hidl_cb(static_cast<Error>(error), static_cast<IComposerClient::DisplayType>(hwc_type));
  return Void();
}

Return<void> QtiComposerClient::getDozeSupport(uint64_t display, getDozeSupport_cb _hidl_cb) {
  int32_t hwc_support = 0;

  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
  if (mDisplayData.find(display) == mDisplayData.end()) {
    _hidl_cb(Error::BAD_DISPLAY, hwc_support);
    return Void();
  }

  auto error = hwc_session_->GetDozeSupport(display, &hwc_support);

  _hidl_cb(static_cast<Error>(error), hwc_support);
  return Void();
}

Return<void> QtiComposerClient::getHdrCapabilities(uint64_t display,
                                                   getHdrCapabilities_cb _hidl_cb) {
  // TODO(user): Implement combinedly w.r.t getHdrCapabilities_2_3
  uint32_t count = 0;
  hidl_vec<common_V1_0::Hdr> types;
  float max_lumi = 0.0f;
  float max_avg_lumi = 0.0f;
  float min_lumi = 0.0f;

  auto error = hwc_session_->GetHdrCapabilities(display, &count, nullptr, &max_lumi,
                                                &max_avg_lumi, &min_lumi);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), types, max_lumi, max_avg_lumi, min_lumi);
    return Void();
  }

  types.resize(count);
  error = hwc_session_->GetHdrCapabilities(display, &count,
           reinterpret_cast<std::underlying_type<common_V1_2::Hdr>::type*>(types.data()),
           &max_lumi, &max_avg_lumi, &min_lumi);

  _hidl_cb(static_cast<Error>(error), types, max_lumi, max_avg_lumi, min_lumi);
  return Void();
}

Return<Error> QtiComposerClient::setClientTargetSlotCount(uint64_t display,
                                                          uint32_t clientTargetSlotCount) {
  std::lock_guard<std::mutex> lock(mDisplayDataMutex);

  auto dpy = mDisplayData.find(display);
  if (dpy == mDisplayData.end()) {
    return Error::BAD_DISPLAY;
  }
  dpy->second.ClientTargets.resize(clientTargetSlotCount);

  return Error::NONE;
}

Return<Error> QtiComposerClient::setActiveConfig(uint64_t display, uint32_t config) {
  auto error = hwc_session_->SetActiveConfig(display, config);

  return static_cast<Error>(error);
}

Return<Error> QtiComposerClient::setColorMode(uint64_t display, common_V1_0::ColorMode mode) {
  auto error = hwc_session_->SetColorMode(display, static_cast<int32_t>(mode));

  return static_cast<Error>(error);
}

Return<Error> QtiComposerClient::setPowerMode(uint64_t display,
                                              composer_V2_1::IComposerClient::PowerMode mode) {
  // TODO(user): Implement combinedly w.r.t setPowerMode_2_2
  auto error = hwc_session_->SetPowerMode(display, static_cast<int32_t>(mode));

  return static_cast<Error>(error);
}

Return<Error> QtiComposerClient::setVsyncEnabled(uint64_t display,
                                                 composer_V2_1::IComposerClient::Vsync enabled) {
  auto error = hwc_session_->SetVsyncEnabled(display, static_cast<int32_t>(enabled));

  return static_cast<Error>(error);
}

Return<Error> QtiComposerClient::setInputCommandQueue(
                                                    const MQDescriptorSync<uint32_t>& descriptor) {
  std::lock_guard<std::mutex> lock(mCommandMutex);
  return mReader.setMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES;
}

Return<void> QtiComposerClient::getOutputCommandQueue(getOutputCommandQueue_cb _hidl_cb) {
  // no locking as we require this function to be called inside
  // executeCommands_cb

  auto outDescriptor = mWriter.getMQDescriptor();
  if (outDescriptor) {
    _hidl_cb(Error::NONE, *outDescriptor);
  } else {
    _hidl_cb(Error::NO_RESOURCES, MQDescriptorSync<uint32_t>());
  }

  return Void();
}

Return<void> QtiComposerClient::executeCommands(uint32_t inLength,
                                                const hidl_vec<hidl_handle>& inHandles,
                                                executeCommands_cb _hidl_cb) {
  std::lock_guard<std::mutex> lock(mCommandMutex);

  std::lock_guard<std::mutex> hwc_lock(hwc_session_->command_seq_mutex_);

  bool outChanged = false;
  uint32_t outLength = 0;
  hidl_vec<hidl_handle> outHandles;

  if (!mReader.readQueue(inLength, inHandles)) {
    _hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
    return Void();
  }

  Error err = mReader.parse();
  if (err == Error::NONE &&
      !mWriter.writeQueue(outChanged, outLength, outHandles)) {
    err = Error::NO_RESOURCES;
  }

  _hidl_cb(Error::NONE, outChanged, outLength, outHandles);

  mReader.reset();
  mWriter.reset();

  return Void();
}


// Methods from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
Return<void> QtiComposerClient::getPerFrameMetadataKeys(uint64_t display,
                                                        getPerFrameMetadataKeys_cb _hidl_cb) {
  // TODO(user): Implement combinedly w.r.t getPerFrameMetadataKeys_2_3
  std::vector<PerFrameMetadataKey_V2> keys;
  uint32_t count = 0;

  auto error = hwc_session_->GetPerFrameMetadataKeys(display, &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), keys);
    return Void();
  }

  keys.resize(count);
  error = hwc_session_->GetPerFrameMetadataKeys(display, &count,
               reinterpret_cast<std::underlying_type<PerFrameMetadataKey_V2>::type*>(keys.data()));

  _hidl_cb(static_cast<Error>(error), keys);
  return Void();
}

Return<void> QtiComposerClient::getReadbackBufferAttributes(uint64_t display,
                                                         getReadbackBufferAttributes_cb _hidl_cb) {
  // TODO(user): Implement combinedly w.r.t getReadbackBufferAttributes_2_3
  int32_t format = 0;
  int32_t dataspace = 0;

  auto error = hwc_session_->GetReadbackBufferAttributes(display, &format, &dataspace);

  if (error != HWC2_ERROR_NONE) {
    format = 0;
    dataspace = 0;
  }

  _hidl_cb(static_cast<Error>(error), static_cast<common_V1_1::PixelFormat>(format),
           static_cast<common_V1_1::Dataspace>(dataspace));
  return Void();
}

Return<void> QtiComposerClient::getReadbackBufferFence(uint64_t display,
                                                       getReadbackBufferFence_cb _hidl_cb) {
  shared_ptr<Fence> fence = nullptr;
  auto error = hwc_session_->GetReadbackBufferFence(display, &fence);
  if (static_cast<Error>(error) != Error::NONE) {
    _hidl_cb(static_cast<Error>(error), nullptr);
    return Void();
  }

  NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);

  _hidl_cb(static_cast<Error>(error), getFenceHandle(fence, fenceStorage));
  return Void();
}

Return<Error> QtiComposerClient::setReadbackBuffer(uint64_t display, const hidl_handle& buffer,
                                                   const hidl_handle& releaseFence) {
  shared_ptr<Fence> fence = nullptr;
  Error error = getFence(releaseFence, &fence, "read_back");
  if (error != Error::NONE) {
    return error;
  }

  {
    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
    if (mDisplayData.find(display) == mDisplayData.end()) {
      return Error::BAD_DISPLAY;
    }
  }

  const native_handle_t* readbackBuffer;
  getDisplayReadbackBuffer(display, buffer.getNativeHandle(), &readbackBuffer);
  if (error != Error::NONE) {
    return error;
  }

  auto err = hwc_session_->SetReadbackBuffer(display, readbackBuffer, fence);
  return static_cast<Error>(err);
}

Return<void> QtiComposerClient::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
                                                         common_V1_1::PixelFormat formatHint,
                                                         uint32_t outputBufferSlotCount,
                                                         createVirtualDisplay_2_2_cb _hidl_cb) {
  int32_t format = static_cast<int32_t>(formatHint);
  uint64_t display;
  auto error = hwc_session_->CreateVirtualDisplay(width, height, &format, &display);

  if (static_cast<Error>(error) == Error::NONE) {
    std::lock_guard<std::mutex> lock(mDisplayDataMutex);

    auto dpy = mDisplayData.emplace(static_cast<Display>(display), DisplayData(true)).first;
    dpy->second.OutputBuffers.resize(outputBufferSlotCount);
  }

  _hidl_cb(static_cast<Error>(error), display, static_cast<common_V1_1::PixelFormat>(format));
  return Void();
}

Return<Error> QtiComposerClient::getClientTargetSupport_2_2(uint64_t display, uint32_t width,
                                                            uint32_t height,
                                                            common_V1_1::PixelFormat format,
                                                            common_V1_1::Dataspace dataspace) {
  auto error = hwc_session_->GetClientTargetSupport(display, width, height,
                                                    static_cast<int32_t>(format),
                                                    static_cast<int32_t>(dataspace));

  return static_cast<Error>(error);
}

Return<Error> QtiComposerClient::setPowerMode_2_2(uint64_t display,
                                                  composer_V2_2::IComposerClient::PowerMode mode) {
  if (mode == IComposerClient::PowerMode::ON_SUSPEND) {
    return Error::UNSUPPORTED;
  }
  auto error = hwc_session_->SetPowerMode(display, static_cast<int32_t>(mode));

  return static_cast<Error>(error);
}

Return<void> QtiComposerClient::getColorModes_2_2(uint64_t display,
                                                  getColorModes_2_2_cb _hidl_cb) {
  // TODO(user): Implement combinedly w.r.t getColorModes_2_3
  hidl_vec<common_V1_1::ColorMode> modes;
  uint32_t count = 0;

  auto error = hwc_session_->GetColorModes(display, &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), modes);
    return Void();
  }

  modes.resize(count);
  error = hwc_session_->GetColorModes(display, &count,
              reinterpret_cast<std::underlying_type<common_V1_1::ColorMode>::type*>(modes.data()));

  _hidl_cb(static_cast<Error>(error), modes);
  return Void();
}

Return<void> QtiComposerClient::getRenderIntents(uint64_t display, common_V1_1::ColorMode mode,
                                                 getRenderIntents_cb _hidl_cb) {
  // TODO(user): Implement combinedly w.r.t getRenderIntents_2_3
  uint32_t count = 0;
  std::vector<RenderIntent> intents;

  auto error = hwc_session_->GetRenderIntents(display, int32_t(mode), &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), intents);
    return Void();
  }

  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
  if (mDisplayData.find(display) == mDisplayData.end()) {
    _hidl_cb(Error::BAD_DISPLAY, intents);
    return Void();
  }

  intents.resize(count);
  error = hwc_session_->GetRenderIntents(display, int32_t(mode), &count,
  reinterpret_cast<std::underlying_type<RenderIntent>::type*>(intents.data()));

  _hidl_cb(static_cast<Error>(error), intents);
  return Void();
}

Return<Error> QtiComposerClient::setColorMode_2_2(uint64_t display, common_V1_1::ColorMode mode,
                                                  common_V1_1::RenderIntent intent) {
  auto error = hwc_session_->SetColorModeWithRenderIntent(display, static_cast<int32_t>(mode),
                                                          static_cast<int32_t>(intent));

  return static_cast<Error>(error);
}

Return<void> QtiComposerClient::getDataspaceSaturationMatrix(common_V1_1::Dataspace dataspace,
                                                        getDataspaceSaturationMatrix_cb _hidl_cb) {
  if (dataspace != common_V1_1::Dataspace::SRGB_LINEAR) {
    _hidl_cb(Error::BAD_PARAMETER, std::array<float, 16>{0.0f}.data());
    return Void();
  }

  std::array<float, 16> matrix;
  int32_t error = HWC2_ERROR_UNSUPPORTED;
  error = hwc_session_->GetDataspaceSaturationMatrix(static_cast<int32_t>(dataspace),
                                                     matrix.data());
  if (error != HWC2_ERROR_NONE) {
    matrix = {
      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,
    };
  }
  _hidl_cb(Error::NONE, matrix.data());
  return Void();
}

Return<void> QtiComposerClient::executeCommands_2_2(uint32_t inLength,
                                                    const hidl_vec<hidl_handle>& inHandles,
                                                    executeCommands_2_2_cb _hidl_cb) {
  std::lock_guard<std::mutex> lock(mCommandMutex);

  // This lock ensures that Client gets exclusive access to hwc display.
  // Failing which return to SF will be blocked leading to fence timeouts.
  std::lock_guard<std::mutex> hwc_lock(hwc_session_->command_seq_mutex_);
  bool outChanged = false;
  uint32_t outLength = 0;
  hidl_vec<hidl_handle> outHandles;

  if (!mReader.readQueue(inLength, inHandles)) {
    _hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
    return Void();
  }

  Error err = mReader.parse();
  if (err == Error::NONE &&
      !mWriter.writeQueue(outChanged, outLength, outHandles)) {
      err = Error::NO_RESOURCES;
  }

  _hidl_cb(Error::NONE, outChanged, outLength, outHandles);

  mReader.reset();
  mWriter.reset();

  return Void();
}


// Methods from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
Return<void> QtiComposerClient::getDisplayIdentificationData(uint64_t display,
                                                        getDisplayIdentificationData_cb _hidl_cb) {
  uint8_t port = 0;
  uint32_t size = 0;
  std::vector<uint8_t> data(size);

  auto error = hwc_session_->GetDisplayIdentificationData(display, &port, &size, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), port, data);
    return Void();
  }

  data.resize(size);
  error = hwc_session_->GetDisplayIdentificationData(display, &port, &size, data.data());

  _hidl_cb(static_cast<Error>(error), port, data);
  return Void();
}

Return<void> QtiComposerClient::getReadbackBufferAttributes_2_3(uint64_t display,
                                                     getReadbackBufferAttributes_2_3_cb _hidl_cb) {
  int32_t format = 0;
  int32_t dataspace = 0;

  auto error = hwc_session_->GetReadbackBufferAttributes(display, &format, &dataspace);

  if (error != HWC2_ERROR_NONE) {
    format = 0;
    dataspace = 0;
  }

  _hidl_cb(static_cast<Error>(error), static_cast<common_V1_2::PixelFormat>(format),
           static_cast<common_V1_2::Dataspace>(dataspace));
  return Void();
}

Return<Error> QtiComposerClient::getClientTargetSupport_2_3(uint64_t display, uint32_t width,
                                                            uint32_t height,
                                                            common_V1_2::PixelFormat format,
                                                            common_V1_2::Dataspace dataspace) {
  auto error = hwc_session_->GetClientTargetSupport(display, width, height,
                                                    static_cast<int32_t>(format),
                                                    static_cast<int32_t>(dataspace));

  return static_cast<Error>(error);
}

Return<void> QtiComposerClient::getDisplayedContentSamplingAttributes(uint64_t display,
                                               getDisplayedContentSamplingAttributes_cb _hidl_cb) {
  // getDisplayedContentSamplingAttributes is not supported
  int constexpr invalid = -1;
  auto error = Error::UNSUPPORTED;
  common_V1_2::PixelFormat format = static_cast<common_V1_2::PixelFormat>(invalid);
  common_V1_2::Dataspace dataspace = static_cast<common_V1_2::Dataspace>(invalid);
  hidl_bitfield<IComposerClient::FormatColorComponent> componentMask =
    static_cast<hidl_bitfield<IComposerClient::FormatColorComponent>>(invalid);

  _hidl_cb(error, format, dataspace, componentMask);
  return Void();
}

Return<Error> QtiComposerClient::setDisplayedContentSamplingEnabled(uint64_t display,
                                   composer_V2_3::IComposerClient::DisplayedContentSampling enable,
                                   hidl_bitfield<FormatColorComponent> componentMask,
                                   uint64_t maxFrames) {
  // setDisplayedContentSamplingEnabled is not supported
  return Error::UNSUPPORTED;
}

Return<void> QtiComposerClient::getDisplayedContentSample(uint64_t display, uint64_t maxFrames,
                                                          uint64_t timestamp,
                                                          getDisplayedContentSample_cb _hidl_cb) {
  // getDisplayedContentSample is not supported
  auto error = Error::UNSUPPORTED;
  uint64_t frameCount = 0;
  hidl_vec<uint64_t> sampleComponent0 = 0;
  hidl_vec<uint64_t> sampleComponent1 = 0;
  hidl_vec<uint64_t> sampleComponent2 = 0;
  hidl_vec<uint64_t> sampleComponent3 = 0;

  _hidl_cb(error, frameCount, sampleComponent0, sampleComponent1, sampleComponent2,
           sampleComponent3);
  return Void();
}

Return<void> QtiComposerClient::executeCommands_2_3(uint32_t inLength,
                                                    const hidl_vec<hidl_handle>& inHandles,
                                                    executeCommands_2_3_cb _hidl_cb) {
  // TODO(user): Implement combinedly w.r.t executeCommands_2_2
  std::lock_guard<std::mutex> lock(mCommandMutex);

  std::lock_guard<std::mutex> hwc_lock(hwc_session_->command_seq_mutex_);
  bool outChanged = false;
  uint32_t outLength = 0;
  hidl_vec<hidl_handle> outHandles;

  if (!mReader.readQueue(inLength, inHandles)) {
    _hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
    return Void();
  }

  Error err = mReader.parse();
  if (err == Error::NONE &&
      !mWriter.writeQueue(outChanged, outLength, outHandles)) {
      err = Error::NO_RESOURCES;
  }

  _hidl_cb(Error::NONE, outChanged, outLength, outHandles);

  mReader.reset();
  mWriter.reset();

  return Void();
}

Return<void> QtiComposerClient::getRenderIntents_2_3(uint64_t display, common_V1_2::ColorMode mode,
                                                     getRenderIntents_2_3_cb _hidl_cb) {
  uint32_t count = 0;
  std::vector<RenderIntent> intents;

  auto error = hwc_session_->GetRenderIntents(display, int32_t(mode), &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), intents);
    return Void();
  }

  intents.resize(count);
  error = hwc_session_->GetRenderIntents(display, int32_t(mode), &count,
  reinterpret_cast<std::underlying_type<RenderIntent>::type*>(intents.data()));

  _hidl_cb(static_cast<Error>(error), intents);
  return Void();
}

Return<void> QtiComposerClient::getColorModes_2_3(uint64_t display,
                                                  getColorModes_2_3_cb _hidl_cb) {
  hidl_vec<common_V1_2::ColorMode> modes;
  uint32_t count = 0;

  auto error = hwc_session_->GetColorModes(display, &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), modes);
    return Void();
  }

  modes.resize(count);
  error = hwc_session_->GetColorModes(display, &count,
              reinterpret_cast<std::underlying_type<common_V1_2::ColorMode>::type*>(modes.data()));

  _hidl_cb(static_cast<Error>(error), modes);
  return Void();
}

Return<Error> QtiComposerClient::setColorMode_2_3(uint64_t display, common_V1_2::ColorMode mode,
                                                  common_V1_1::RenderIntent intent) {
  auto error = hwc_session_->SetColorModeWithRenderIntent(display, static_cast<int32_t>(mode),
                                                          static_cast<int32_t>(intent));

  return static_cast<Error>(error);
}

Return<void> QtiComposerClient::getDisplayCapabilities(uint64_t display,
                                                       getDisplayCapabilities_cb _hidl_cb) {
  // Report optional capabilities that we do support to pass VTS.

  hidl_vec<composer_V2_3::IComposerClient::DisplayCapability> capabilities;

  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
  if (mDisplayData.find(display) == mDisplayData.end()) {
     _hidl_cb(Error::BAD_DISPLAY, capabilities);
    return Void();
  }

  HwcDisplayConnectionType display_conn_type = HwcDisplayConnectionType::INTERNAL;
  int32_t ret = hwc_session_->GetDisplayConnectionType(display, &display_conn_type);

  if (HWC2_ERROR_NONE != ret) {
     _hidl_cb(static_cast<Error>(ret), capabilities);
    return Void();
  }

  if (HwcDisplayConnectionType::INTERNAL == display_conn_type) {
    int32_t has_doze_support = 0;
    hwc_session_->GetDozeSupport(display, &has_doze_support);
    if (has_doze_support) {
      capabilities = { composer_V2_3::IComposerClient::DisplayCapability::DOZE,
                       composer_V2_3::IComposerClient::DisplayCapability::BRIGHTNESS };
    } else {
      capabilities = { composer_V2_3::IComposerClient::DisplayCapability::BRIGHTNESS };
    }
  }

  _hidl_cb(Error::NONE, capabilities);
  return Void();
}

Return<void> QtiComposerClient::getPerFrameMetadataKeys_2_3(uint64_t display,
                                                         getPerFrameMetadataKeys_2_3_cb _hidl_cb) {
  std::vector<PerFrameMetadataKey> keys;
  uint32_t count = 0;

  auto error = hwc_session_->GetPerFrameMetadataKeys(display, &count, nullptr);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), keys);
    return Void();
  }

  keys.resize(count);
  error = hwc_session_->GetPerFrameMetadataKeys(display, &count,
                  reinterpret_cast<std::underlying_type<PerFrameMetadataKey>::type*>(keys.data()));

  _hidl_cb(static_cast<Error>(error), keys);
  return Void();
}

Return<void> QtiComposerClient::getHdrCapabilities_2_3(uint64_t display,
                                                       getHdrCapabilities_2_3_cb _hidl_cb) {
  uint32_t count = 0;
  hidl_vec<common_V1_2::Hdr> types;
  float max_lumi = 0.0f;
  float max_avg_lumi = 0.0f;
  float min_lumi = 0.0f;

  auto error = hwc_session_->GetHdrCapabilities(display, &count, nullptr, &max_lumi,
                                                &max_avg_lumi, &min_lumi);
  if (error != HWC2_ERROR_NONE) {
    _hidl_cb(static_cast<Error>(error), types, max_lumi, max_avg_lumi, min_lumi);
    return Void();
  }

  types.resize(count);
  error = hwc_session_->GetHdrCapabilities(display, &count,
           reinterpret_cast<std::underlying_type<common_V1_2::Hdr>::type*>(types.data()),
           &max_lumi, &max_avg_lumi, &min_lumi);

  _hidl_cb(static_cast<Error>(error), types, max_lumi, max_avg_lumi, min_lumi);
  return Void();
}

Return<void> QtiComposerClient::getDisplayBrightnessSupport(uint64_t display,
                                                         getDisplayBrightnessSupport_cb _hidl_cb) {
  bool support = false;

  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
  if (mDisplayData.find(display) == mDisplayData.end()) {
    _hidl_cb(Error::BAD_DISPLAY, support);
    return Void();
  }

  auto error = hwc_session_->GetDisplayBrightnessSupport(display, &support);

  _hidl_cb(static_cast<Error>(error), support);
  return Void();
}

Return<Error> QtiComposerClient::setDisplayBrightness(uint64_t display, float brightness) {
  if (std::isnan(brightness) || brightness > 1.0f || (brightness < 0.0f && brightness != -1.0f)) {
    return Error::BAD_PARAMETER;
  }

  auto error = hwc_session_->SetDisplayBrightness(display, brightness);
  return static_cast<Error>(error);
}

// Methods from ::android::hardware::graphics::composer::V2_4::IComposerClient follow.
Return<void> QtiComposerClient::registerCallback_2_4(
    const sp<composer_V2_4::IComposerCallback> &callback) {
  callback_ = sp<composer_V2_1::IComposerCallback>(callback.get());
  callback24_ = callback;
  mUseCallback24_ = true;
  enableCallback(callback != nullptr);
  return Void();
}

Return<void> QtiComposerClient::getDisplayCapabilities_2_4(uint64_t display,
                                                           getDisplayCapabilities_2_4_cb _hidl_cb) {
  hidl_vec<HwcDisplayCapability> capabilities;
  auto error = hwc_session_->GetDisplayCapabilities(display, &capabilities);
  _hidl_cb(static_cast<composer_V2_4::Error>(error), capabilities);
  return Void();
}

Return<void> QtiComposerClient::getDisplayConnectionType(uint64_t display,
                                                         getDisplayConnectionType_cb _hidl_cb) {
  HwcDisplayConnectionType type;
  auto error = hwc_session_->GetDisplayConnectionType(display, &type);
  _hidl_cb(static_cast<composer_V2_4::Error>(error), type);
  return Void();
}

Return<void> QtiComposerClient::getDisplayAttribute_2_4(
    uint64_t display, uint32_t config, composer_V2_4::IComposerClient::Attribute attribute,
    getDisplayAttribute_2_4_cb _hidl_cb) {
  int32_t value = 0;
  auto error = hwc_session_->GetDisplayAttribute(display, config, attribute, &value);
  _hidl_cb(static_cast<composer_V2_4::Error>(error), value);
  return Void();
}

Return<void> QtiComposerClient::getDisplayVsyncPeriod(uint64_t display,
                                                      getDisplayVsyncPeriod_cb _hidl_cb) {
  VsyncPeriodNanos vsync_period;
  auto error = hwc_session_->GetDisplayVsyncPeriod(display, &vsync_period);
  _hidl_cb(static_cast<composer_V2_4::Error>(error), vsync_period);
  return Void();
}

Return<void> QtiComposerClient::setActiveConfigWithConstraints(
    uint64_t display, uint32_t config,
    const VsyncPeriodChangeConstraints &vsyncPeriodChangeConstraints,
    setActiveConfigWithConstraints_cb _hidl_cb) {
  VsyncPeriodChangeTimeline timeline;
  timeline.newVsyncAppliedTimeNanos = systemTime();
  timeline.refreshRequired = false;
  timeline.refreshTimeNanos = 0;

  auto error = hwc_session_->SetActiveConfigWithConstraints(
      display, config, &vsyncPeriodChangeConstraints, &timeline);
  _hidl_cb(static_cast<composer_V2_4::Error>(error), timeline);
  return Void();
}

Return<composer_V2_4::Error> QtiComposerClient::setAutoLowLatencyMode(uint64_t display, bool on) {
  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
  if (mDisplayData.find(display) == mDisplayData.end()) {
    return composer_V2_4::Error::BAD_DISPLAY;
  }
  return composer_V2_4::Error::UNSUPPORTED;
}

Return<void> QtiComposerClient::getSupportedContentTypes(uint64_t display,
                                                         getSupportedContentTypes_cb _hidl_cb) {
  hidl_vec<composer_V2_4::IComposerClient::ContentType> types = {};
  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
  if (mDisplayData.find(display) == mDisplayData.end()) {
    _hidl_cb(composer_V2_4::Error::BAD_DISPLAY, types);
    return Void();
  }
  _hidl_cb(composer_V2_4::Error::NONE, types);
  return Void();
}

Return<composer_V2_4::Error> QtiComposerClient::setContentType(
    uint64_t display, composer_V2_4::IComposerClient::ContentType type) {
  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
  if (mDisplayData.find(display) == mDisplayData.end()) {
    return composer_V2_4::Error::BAD_DISPLAY;
  }
  if (type == composer_V2_4::IComposerClient::ContentType::NONE) {
    return composer_V2_4::Error::NONE;
  }
  return composer_V2_4::Error::UNSUPPORTED;
}

Return<void> QtiComposerClient::getLayerGenericMetadataKeys(
    getLayerGenericMetadataKeys_cb _hidl_cb) {
  hidl_vec<composer_V2_4::IComposerClient::LayerGenericMetadataKey> keys = {};
  _hidl_cb(composer_V2_4::Error::NONE, keys);
  return Void();
}

Return<Error> QtiComposerClient::tryDrawMethod(uint64_t display,
    IQtiComposerClient::DrawMethod drawMethod) {
  auto error = hwc_session_->TryDrawMethod(display, drawMethod);
  return static_cast<Error>(error);
}

QtiComposerClient::CommandReader::CommandReader(QtiComposerClient& client)
  : mClient(client), mWriter(client.mWriter) {
}

bool QtiComposerClient::CommandReader::parseCommonCmd(
    IComposerClient::Command command, uint16_t length) {
  bool parsed = false;

  switch (command) {
  // Commands from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
  case IComposerClient::Command::SELECT_DISPLAY: {
    parsed = parseSelectDisplay(length);
    std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
    // Displays will not be removed while processing the command queue.
    if (parsed && mClient.mDisplayData.find(mDisplay) == mClient.mDisplayData.end()) {
      ALOGW("Command::SELECT_DISPLAY: Display %" PRId64 "not found. Dropping commands.", mDisplay);
      mDisplay = sdm::HWCCallbacks::kNumDisplays;
    }
    break;
  }
  case IComposerClient::Command::SELECT_LAYER:
    parsed = parseSelectLayer(length);
    break;
  case IComposerClient::Command::SET_COLOR_TRANSFORM:
    parsed = parseSetColorTransform(length);
    break;
  case IComposerClient::Command::SET_CLIENT_TARGET:
    parsed = parseSetClientTarget(length);
    break;
  case IComposerClient::Command::SET_OUTPUT_BUFFER:
    parsed = parseSetOutputBuffer(length);
    break;
  case IComposerClient::Command::VALIDATE_DISPLAY:
    parsed = parseValidateDisplay(length);
    break;
  case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
    parsed = parseAcceptDisplayChanges(length);
    break;
  case IComposerClient::Command::PRESENT_DISPLAY:
    parsed = parsePresentDisplay(length);
    break;
  case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
    parsed = parsePresentOrValidateDisplay(length);
    break;
  case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
    parsed = parseSetLayerCursorPosition(length);
    break;
  case IComposerClient::Command::SET_LAYER_BUFFER:
    parsed = parseSetLayerBuffer(length);
    break;
  case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
    parsed = parseSetLayerSurfaceDamage(length);
    break;
  case IComposerClient::Command::SET_LAYER_BLEND_MODE:
    parsed = parseSetLayerBlendMode(length);
    break;
  case IComposerClient::Command::SET_LAYER_COLOR:
    parsed = parseSetLayerColor(length);
    break;
  case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
    parsed = parseSetLayerCompositionType(length);
    break;
  case IComposerClient::Command::SET_LAYER_DATASPACE:
    parsed = parseSetLayerDataspace(length);
    break;
  case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
    parsed = parseSetLayerDisplayFrame(length);
    break;
  case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
    parsed = parseSetLayerPlaneAlpha(length);
    break;
  case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
    parsed = parseSetLayerSidebandStream(length);
    break;
  case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
    parsed = parseSetLayerSourceCrop(length);
    break;
  case IComposerClient::Command::SET_LAYER_TRANSFORM:
    parsed = parseSetLayerTransform(length);
    break;
  case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
    parsed = parseSetLayerVisibleRegion(length);
    break;
  case IComposerClient::Command::SET_LAYER_Z_ORDER:
    parsed = parseSetLayerZOrder(length);
    break;
  // Commands from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
  case IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA:
    parsed = parseSetLayerPerFrameMetadata(length);
    break;
  case IComposerClient::Command::SET_LAYER_FLOAT_COLOR:
    parsed = parseSetLayerFloatColor(length);
    break;
  // Commands from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
  case IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM:
    parsed = parseSetLayerColorTransform(length);
    break;
  case IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA_BLOBS:
    parsed = parseSetLayerPerFrameMetadataBlobs(length);
    break;
  default:
    parsed = false;
    break;
  }

  return parsed;
}

Error QtiComposerClient::CommandReader::parse() {
  IQtiComposerClient::Command qticommand;
  uint16_t length;

  while (!isEmpty()) {
    if (!beginCommand(qticommand, length)) {
      break;
    }

    bool parsed = false;
    switch (qticommand) {
      case IQtiComposerClient::Command::SET_LAYER_TYPE:
        parsed = parseSetLayerType(length);
        break;
      case IQtiComposerClient::Command::SET_DISPLAY_ELAPSE_TIME:
        parsed = parseSetDisplayElapseTime(length);
        break;
      case IQtiComposerClient::Command::SET_CLIENT_TARGET_3_1:
        parsed = parseSetClientTarget_3_1(length);
        break;
      case IQtiComposerClient::Command::SET_LAYER_FLAG_3_1:
        parsed = parseSetLayerFlag(length);
        break;
      default:
        parsed = parseCommonCmd(static_cast<IComposerClient::Command>(qticommand), length);
        break;
    }

    endCommand();

    if (!parsed) {
      ALOGE("failed to parse command 0x%x, length %" PRIu16,
          qticommand, length);
      break;
    }
  }

  return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER;
}

bool QtiComposerClient::CommandReader::parseSelectDisplay(uint16_t length) {
  if (length != CommandWriter::kSelectDisplayLength) {
    return false;
  }

  mDisplay = read64();
  mWriter.selectDisplay(mDisplay);

  return true;
}

bool QtiComposerClient::CommandReader::parseSelectLayer(uint16_t length) {
  if (length != CommandWriter::kSelectLayerLength) {
    return false;
  }

  mLayer = read64();

  return true;
}

bool QtiComposerClient::CommandReader::parseSetColorTransform(uint16_t length) {
  if (length != CommandWriter::kSetColorTransformLength) {
    return false;
  }

  float matrix[16];
  for (int i = 0; i < 16; i++) {
    matrix[i] = readFloat();
  }
  auto transform = readSigned();

  auto err = mClient.hwc_session_->SetColorTransform(mDisplay, matrix, transform);
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetClientTarget(uint16_t length) {
  // 4 parameters followed by N rectangles
  if ((length - 4) % 4 != 0) {
    return false;
  }

  bool useCache = false;
  auto slot = read();
  auto clientTarget = readHandle(useCache);
  shared_ptr<Fence> fence = nullptr;
  readFence(&fence, "fbt");
  auto dataspace = readSigned();
  auto damage = readRegion((length - 4) / 4);
  hwc_region region = {damage.size(), damage.data()};
  auto err = lookupBuffer(BufferCache::CLIENT_TARGETS, slot, useCache, clientTarget, &clientTarget);
  if (err == Error::NONE) {
    auto error = mClient.hwc_session_->SetClientTarget(mDisplay, clientTarget, fence,
        dataspace, region);
    err = static_cast<Error>(error);
    auto updateBufErr = updateBuffer(BufferCache::CLIENT_TARGETS, slot,
        useCache, clientTarget);
    if (err == Error::NONE) {
      err = updateBufErr;
    }
  }
  if (err != Error::NONE) {
    mWriter.setError(getCommandLoc(), err);
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetClientTarget_3_1(uint16_t length) {
  bool useCache = true;
  auto slot = read();
  buffer_handle_t clientTarget = nullptr;
  shared_ptr<Fence> fence = nullptr;
  readFence(&fence, "fbt");
  auto dataspace = readSigned();
  hwc_region region = {};
  auto err = lookupBuffer(BufferCache::CLIENT_TARGETS, slot, useCache, clientTarget, &clientTarget);
  if (err == Error::NONE) {
    auto error = mClient.hwc_session_->SetClientTarget_3_1(mDisplay, clientTarget, fence,
        dataspace, region);
    err = static_cast<Error>(error);
    auto updateBufErr = updateBuffer(BufferCache::CLIENT_TARGETS, slot,
        useCache, clientTarget);
    if (err == Error::NONE) {
      err = updateBufErr;
    }
  }
  if (err != Error::NONE) {
    mWriter.setError(getCommandLoc(), err);
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length) {
  if (length != CommandWriter::kSetOutputBufferLength) {
    return false;
  }

  bool useCache;
  auto slot = read();
  auto outputBuffer = readHandle(useCache);
  shared_ptr<Fence> fence = nullptr;
  readFence(&fence, "outbuf");
  auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS, slot, useCache, outputBuffer, &outputBuffer);
  if (err == Error::NONE) {
    auto error = mClient.hwc_session_->SetOutputBuffer(mDisplay, outputBuffer, fence);
    err = static_cast<Error>(error);
    auto updateBufErr = updateBuffer(BufferCache::OUTPUT_BUFFERS, slot, useCache, outputBuffer);
    if (err == Error::NONE) {
      err = updateBufErr;
    }
  }

  if (err != Error::NONE) {
    mWriter.setError(getCommandLoc(), err);
  }

  return true;
}

Error QtiComposerClient::CommandReader::validateDisplay() {
  bool validate_only = true;
  bool needsCommit = false;
  uint32_t types_count = 0;
  uint32_t reqs_count = 0;
  shared_ptr<Fence> presentFence = nullptr;

  auto err = mClient.hwc_session_->CommitOrPrepare(mDisplay, validate_only, &presentFence,
                                                   &types_count, &reqs_count, &needsCommit);
  auto status = INT32(err);
  if (status != HWC2_ERROR_NONE && status != HWC2_ERROR_HAS_CHANGES) {
    return static_cast<Error>(err);
  }

  return postValidateDisplay(types_count, reqs_count);
}

bool QtiComposerClient::CommandReader::parseValidateDisplay(uint16_t length) {
  if (length != CommandWriter::kValidateDisplayLength) {
    return false;
  }

  std::vector<Layer> changedLayers;
  std::vector<IComposerClient::Composition> compositionTypes;
  std::vector<Layer> requestedLayers;
  std::vector<uint32_t> requestMasks;

  auto err = validateDisplay();

  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseAcceptDisplayChanges(uint16_t length) {
  if (length != CommandWriter::kAcceptDisplayChangesLength) {
    return false;
  }

  auto err = mClient.hwc_session_->AcceptDisplayChanges(mDisplay);
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

Error QtiComposerClient::CommandReader::presentDisplay(Display display,
                                                  shared_ptr<Fence>* presentFence,
                                                  std::vector<Layer>& layers,
                                                  std::vector<shared_ptr<Fence>>& releaseFences) {
  int32_t err = mClient.hwc_session_->PresentDisplay(display, presentFence);
  if (err != HWC2_ERROR_NONE) {
    return static_cast<Error>(err);
  }

  return postPresentDisplay(presentFence);
}

bool QtiComposerClient::CommandReader::parsePresentDisplay(uint16_t length) {
  if (length != CommandWriter::kPresentDisplayLength) {
    return false;
  }

  shared_ptr<Fence> presentFence = nullptr;
  std::vector<Layer> layers;
  std::vector<shared_ptr<Fence>> fences;

  auto err = presentDisplay(mDisplay, &presentFence, layers, fences);
  if (err != Error::NONE) {
    mWriter.setError(getCommandLoc(), err);
  }

  return true;
}

Error QtiComposerClient::CommandReader::postPresentDisplay(shared_ptr<Fence>* presentFence) {
  uint32_t count = 0;
  auto err = mClient.hwc_session_->GetReleaseFences(mDisplay, &count, nullptr, nullptr);
  if (err != HWC2_ERROR_NONE) {
    ALOGW("failed to get release fences");
    return Error::NONE;
  }

  std::vector<Layer> layers;
  std::vector<shared_ptr<Fence>> releaseFences;
  layers.resize(count);
  releaseFences.resize(count);
  err = mClient.hwc_session_->GetReleaseFences(mDisplay, &count, layers.data(), &releaseFences);
  if (err != HWC2_ERROR_NONE) {
    ALOGW("failed to get release fences");
    layers.clear();
    releaseFences.clear();
    return Error::NONE;
  }
  mWriter.setPresentFence(*presentFence);
  mWriter.setReleaseFences(layers, releaseFences);

  return Error::NONE;
}

Error QtiComposerClient::CommandReader::postValidateDisplay(uint32_t& types_count,
                                                            uint32_t& reqs_count) {
  std::vector<Layer> changedLayers;
  std::vector<IComposerClient::Composition> compositionTypes;
  std::vector<Layer> requestedLayers;
  std::vector<uint32_t> requestMasks;
  IComposerClient::ClientTargetProperty clientTargetProperty;
  changedLayers.resize(types_count);
  compositionTypes.resize(types_count);
  auto err = mClient.hwc_session_->GetChangedCompositionTypes(mDisplay, &types_count,
                                                              nullptr, nullptr);
  if (err != HWC2_ERROR_NONE) {
    return static_cast<Error>(err);
  }

  err = mClient.hwc_session_->GetChangedCompositionTypes(mDisplay, &types_count,
                        changedLayers.data(),
                        reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
                        compositionTypes.data()));

  if (err != HWC2_ERROR_NONE) {
    changedLayers.clear();
    compositionTypes.clear();
    return static_cast<Error>(err);
  }

  int32_t display_reqs = 0;
  err = mClient.hwc_session_->GetDisplayRequests(mDisplay, &display_reqs, &reqs_count, nullptr,
                                                 nullptr);
  if (err != HWC2_ERROR_NONE) {
    changedLayers.clear();
    compositionTypes.clear();
    return static_cast<Error>(err);
  }

  requestedLayers.resize(reqs_count);
  requestMasks.resize(reqs_count);
  err = mClient.hwc_session_->GetDisplayRequests(mDisplay, &display_reqs, &reqs_count,
                                                 requestedLayers.data(),
                                                 reinterpret_cast<int32_t*>(requestMasks.data()));
  if (err != HWC2_ERROR_NONE) {
    changedLayers.clear();
    compositionTypes.clear();

    requestedLayers.clear();
    requestMasks.clear();
  }

  err = mClient.hwc_session_->GetClientTargetProperty(mDisplay, &clientTargetProperty);
  if (err != HWC2_ERROR_NONE) {
    // todo: reset to default values
    return static_cast<Error>(err);
  }

  mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
  mWriter.setDisplayRequests(display_reqs, requestedLayers, requestMasks);
  if (mClient.mUseCallback24_) {
    mWriter.setClientTargetProperty(clientTargetProperty);
  }

  return static_cast<Error>(err);
}

bool QtiComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length) {
  if (length != CommandWriter::kPresentOrValidateDisplayLength) {
     return false;
  }

  // Handle unified commit.
  bool needsCommit = false;
  shared_ptr<Fence> presentFence = nullptr;
  uint32_t typesCount = 0;
  uint32_t reqsCount = 0;
  bool validate_only = false;
  auto status = mClient.hwc_session_->CommitOrPrepare(mDisplay, validate_only, &presentFence,
                                                      &typesCount, &reqsCount, &needsCommit);
  if (needsCommit) {
    if (status != HWC2::Error::None && status != HWC2::Error::HasChanges) {
      ALOGE("CommitOrPrepare failed %d", status);
    }
    // Implement post validation. Getcomptypes etc;
    postValidateDisplay(typesCount, reqsCount);
    mWriter.setPresentOrValidateResult(0);
  } else {
    if (status == HWC2::Error::HasChanges) {
      // Perform post validate.
      auto error = postValidateDisplay(typesCount, reqsCount);
      if (error == Error::NONE) {
        mClient.hwc_session_->AcceptDisplayChanges(mDisplay);
      }
      // Set result to 2.
      mWriter.setPresentOrValidateResult(2);
    } else {
      // Set result to 1.
      mWriter.setPresentOrValidateResult(1);
    }
    // perform post present display.
    postPresentDisplay(&presentFence);
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerCursorPosition(uint16_t length) {
  if (length != CommandWriter::kSetLayerCursorPositionLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetCursorPosition(mDisplay, mLayer, readSigned(), readSigned());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length) {
  if (length != CommandWriter::kSetLayerBufferLength) {
    return false;
  }

  bool useCache;
  auto slot = read();
  auto buffer = readHandle(useCache);
  shared_ptr<Fence> fence = nullptr;
  readFence(&fence, "layer");
  auto error = lookupBuffer(BufferCache::LAYER_BUFFERS, slot, useCache, buffer, &buffer);
  if (error == Error::NONE) {
    auto err = mClient.hwc_session_->SetLayerBuffer(mDisplay, mLayer, buffer, fence);
    error = static_cast<Error>(err);
    auto updateBufErr = updateBuffer(BufferCache::LAYER_BUFFERS, slot, useCache, buffer);
    if (static_cast<Error>(error) == Error::NONE) {
      error = updateBufErr;
    }
  }
  if (static_cast<Error>(error) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(error));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length) {
  // N rectangles
  if (length % 4 != 0) {
    return false;
  }

  auto damage = readRegion(length / 4);
  hwc_region region = {damage.size(), damage.data()};
  auto err = mClient.hwc_session_->SetLayerSurfaceDamage(mDisplay, mLayer, region);
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerBlendMode(uint16_t length) {
  if (length != CommandWriter::kSetLayerBlendModeLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerBlendMode(mDisplay, mLayer, readSigned());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerColor(uint16_t length) {
  if (length != CommandWriter::kSetLayerColorLength) {
    return false;
  }
  auto color = readColor();
  hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
  auto err = mClient.hwc_session_->SetLayerColor(mDisplay, mLayer, hwc_color);
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerCompositionType(uint16_t length) {
  if (length != CommandWriter::kSetLayerCompositionTypeLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerCompositionType(mDisplay, mLayer, readSigned());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerDataspace(uint16_t length) {
  if (length != CommandWriter::kSetLayerDataspaceLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerDataspace(mDisplay, mLayer, readSigned());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length) {
  if (length != CommandWriter::kSetLayerDisplayFrameLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerDisplayFrame(mDisplay, mLayer, readRect());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length) {
  if (length != CommandWriter::kSetLayerPlaneAlphaLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerPlaneAlpha(mDisplay, mLayer, readFloat());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length) {
  if (length != CommandWriter::kSetLayerSidebandStreamLength) {
    return false;
  }

  // Sideband stream is not supported
  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerSourceCrop(uint16_t length) {
  if (length != CommandWriter::kSetLayerSourceCropLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerSourceCrop(mDisplay, mLayer, readFRect());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerTransform(uint16_t length) {
  if (length != CommandWriter::kSetLayerTransformLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerTransform(mDisplay, mLayer, readSigned());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length) {
  // N rectangles
  if (length % 4 != 0) {
    return false;
  }

  auto region = readRegion(length / 4);
  hwc_region visibleRegion = {region.size(), region.data()};
  auto err = mClient.hwc_session_->SetLayerVisibleRegion(mDisplay, mLayer, visibleRegion);
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerZOrder(uint16_t length) {
  if (length != CommandWriter::kSetLayerZOrderLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerZOrder(mDisplay, mLayer, read());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerType(uint16_t length) {
  if (length != CommandWriter::kSetLayerTypeLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerType(mDisplay, mLayer,
            static_cast<IQtiComposerClient::LayerType>(read()));
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerFlag(uint16_t length) {
  if (length != CommandWriter::kSetLayerFlagLength) {
    return false;
  }

  auto err = mClient.hwc_session_->SetLayerFlag(mDisplay, mLayer,
                                                static_cast<IQtiComposerClient::LayerFlag>(read()));
  if (static_cast<Error>(err) != Error::NONE) {
     mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerPerFrameMetadata(uint16_t length) {
  // (key, value) pairs
  if (length % 2 != 0) {
    return false;
  }

  std::vector<IComposerClient::PerFrameMetadata> metadata;
  metadata.reserve(length / 2);
  while (length > 0) {
    metadata.emplace_back(IComposerClient::PerFrameMetadata{
                          static_cast<IComposerClient::PerFrameMetadataKey>(readSigned()),
                          readFloat()});
    length -= 2;
  }

  std::vector<int32_t> keys;
  std::vector<float> values;
  keys.reserve(metadata.size());
  values.reserve(metadata.size());
  for (const auto& m : metadata) {
    keys.push_back(static_cast<int32_t>(m.key));
    values.push_back(m.value);
  }

  auto err = mClient.hwc_session_->SetLayerPerFrameMetadata(mDisplay, mLayer, metadata.size(),
                                                            keys.data(), values.data());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerFloatColor(uint16_t length) {
  if (length != CommandWriter::kSetLayerFloatColorLength) {
    return false;
  }

  // setLayerFloatColor is not supported
  auto err = Error::UNSUPPORTED;
  mWriter.setError(getCommandLoc(), static_cast<Error>(err));

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerColorTransform(uint16_t length) {
  if (length != CommandWriter::kSetLayerColorTransformLength) {
    return false;
  }

  float matrix[16];
  for (int i = 0; i < 16; i++) {
    matrix[i] = readFloat();
  }

  auto error = mClient.hwc_session_->SetLayerColorTransform(mDisplay, mLayer, matrix);
  if (static_cast<Error>(error) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(error));
  }

  return true;
}

bool QtiComposerClient::CommandReader::parseSetLayerPerFrameMetadataBlobs(uint16_t length) {
  // must have at least one metadata blob
  // of at least size 1 in queue (i.e {/*numBlobs=*/1, key, size, blob})
  if (length < 4) {
    return false;
  }

  uint32_t numBlobs = read();
  length--;
  std::vector<IComposerClient::PerFrameMetadataBlob> metadata;

  for (size_t i = 0; i < numBlobs; i++) {
    IComposerClient::PerFrameMetadataKey key =
      static_cast<IComposerClient::PerFrameMetadataKey>(readSigned());
    uint32_t blobSize = read();
    length -= 2;

    if (length * sizeof(uint32_t) < blobSize) {
      return false;
    }

    metadata.push_back({key, std::vector<uint8_t>()});
    IComposerClient::PerFrameMetadataBlob& metadataBlob = metadata.back();
    metadataBlob.blob.resize(blobSize);
    readBlob(blobSize, metadataBlob.blob.data());
  }

  std::vector<int32_t> keys;
  std::vector<uint32_t> sizes_of_metablob_;
  std::vector<uint8_t> blob_of_data_;
  keys.reserve(metadata.size());
  sizes_of_metablob_.reserve(metadata.size());
  for (const auto& m : metadata) {
    keys.push_back(static_cast<int32_t>(m.key));
    sizes_of_metablob_.push_back(m.blob.size());
    for (uint8_t i = 0; i < m.blob.size(); i++) {
      blob_of_data_.push_back(m.blob[i]);
    }
  }
  auto err = mClient.hwc_session_->SetLayerPerFrameMetadataBlobs(mDisplay, mLayer, metadata.size(),
                                                                 keys.data(),
                                                                 sizes_of_metablob_.data(),
                                                                 blob_of_data_.data());
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }
  return true;
}

bool QtiComposerClient::CommandReader::parseSetDisplayElapseTime(uint16_t length) {
  if (length < CommandWriter::kSetDisplayElapseTime) {
    return false;
  }
  uint64_t time = read64();

  auto err = mClient.hwc_session_->SetDisplayElapseTime(mDisplay, time);
  if (static_cast<Error>(err) != Error::NONE) {
    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
  }

  return true;
}

hwc_rect_t QtiComposerClient::CommandReader::readRect() {
  return hwc_rect_t{
    readSigned(),
    readSigned(),
    readSigned(),
    readSigned(),
  };
}

std::vector<hwc_rect_t> QtiComposerClient::CommandReader::readRegion(size_t count) {
  std::vector<hwc_rect_t> region;
  region.reserve(count);
  while (count > 0) {
    region.emplace_back(readRect());
    count--;
  }

  return region;
}

hwc_frect_t QtiComposerClient::CommandReader::readFRect() {
  return hwc_frect_t{
    readFloat(),
    readFloat(),
    readFloat(),
    readFloat(),
  };
}

Error QtiComposerClient::CommandReader::lookupBufferCacheEntryLocked(BufferCache cache,
                                                                     uint32_t slot,
                                                                     BufferCacheEntry** outEntry) {
  auto dpy = mClient.mDisplayData.find(mDisplay);
  if (dpy == mClient.mDisplayData.end()) {
    return Error::BAD_DISPLAY;
  }

  BufferCacheEntry* entry = nullptr;
  switch (cache) {
  case BufferCache::CLIENT_TARGETS:
    if (slot < dpy->second.ClientTargets.size()) {
      entry = &dpy->second.ClientTargets[slot];
    }
    break;
  case BufferCache::OUTPUT_BUFFERS:
    if (slot < dpy->second.OutputBuffers.size()) {
      entry = &dpy->second.OutputBuffers[slot];
    }
    break;
  case BufferCache::LAYER_BUFFERS:
    {
      auto ly = dpy->second.Layers.find(mLayer);
      if (ly == dpy->second.Layers.end()) {
        return Error::BAD_LAYER;
      }
      if (slot < ly->second.Buffers.size()) {
        entry = &ly->second.Buffers[slot];
      }
    }
    break;
  case BufferCache::LAYER_SIDEBAND_STREAMS:
    {
      auto ly = dpy->second.Layers.find(mLayer);
      if (ly == dpy->second.Layers.end()) {
        return Error::BAD_LAYER;
      }
      if (slot == 0) {
        entry = &ly->second.SidebandStream;
      }
    }
    break;
  default:
    break;
  }

  if (!entry) {
    ALOGW("invalid buffer slot %" PRIu32, slot);
    return Error::BAD_PARAMETER;
  }

  *outEntry = entry;

  return Error::NONE;
}

Error QtiComposerClient::CommandReader::lookupBuffer(BufferCache cache, uint32_t slot,
                                                     bool useCache, buffer_handle_t handle,
                                                     buffer_handle_t* outHandle) {
  if (useCache) {
    std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);

    BufferCacheEntry* entry;
    Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
    if (error != Error::NONE) {
      return error;
    }

    // input handle is ignored
    *outHandle = entry->getHandle();
  } else if (cache == BufferCache::LAYER_SIDEBAND_STREAMS) {
    if (handle) {
      *outHandle = native_handle_clone(handle);
      if (*outHandle == nullptr) {
        return Error::NO_RESOURCES;
      }
    }
  } else {
    if (!mHandleImporter.importBuffer(handle)) {
      return Error::NO_RESOURCES;
    }

    *outHandle = handle;
  }

  return Error::NONE;
}

Error QtiComposerClient::CommandReader::updateBuffer(BufferCache cache, uint32_t slot,
                                                     bool useCache, buffer_handle_t handle) {
  // handle was looked up from cache
  if (useCache) {
    return Error::NONE;
  }

  std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);

  BufferCacheEntry* entry = nullptr;
  Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
  if (error != Error::NONE) {
    return error;
  }

  *entry = handle;
  return Error::NONE;
}
// Methods from ::android::hidl::base::V1_0::IBase follow.

IQtiComposerClient* HIDL_FETCH_IQtiComposerClient(const char* /* name */) {
  return QtiComposerClient::CreateQtiComposerClientInstance();
}

}  // namespace implementation
}  // namespace V3_0
}  // namespace composer
}  // namespace display
}  // namespace hardware
}  // namespace qti
}  // namespace vendor
