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

#ifndef __QTICOMPOSERCOMMANDBUFFER_H__
#define __QTICOMPOSERCOMMANDBUFFER_H__

#include <log/log.h>
#include <sync/sync.h>
#include <fmq/MessageQueue.h>
#include <hidl/MQDescriptor.h>
#include <utils/fence.h>

#include <limits>
#include <algorithm>
#include <vector>
#include <string>

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

using ::android::hardware::graphics::common::V1_0::ColorTransform;
using ::android::hardware::graphics::common::V1_0::Dataspace;
using ::android::hardware::graphics::common::V1_0::Transform;
using ::android::hardware::graphics::composer::V2_1::Error;
using ::android::hardware::graphics::composer::V2_1::Display;
using ::android::hardware::graphics::composer::V2_1::Layer;
using ::android::hardware::MessageQueue;
using ::android::hardware::MQDescriptorSync;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_handle;

using CommandQueueType = MessageQueue<uint32_t, ::android::hardware::kSynchronizedReadWrite>;

using std::shared_ptr;
using std::string;
using sdm::Fence;

// This class helps build a command queue.  Note that all sizes/lengths are in units of uint32_t's.
class CommandWriter {
 public:
  explicit CommandWriter(uint32_t initialMaxSize) : mDataMaxSize(initialMaxSize) {
    mData = std::make_unique<uint32_t[]>(mDataMaxSize);
    reset();
  }

  ~CommandWriter() { reset(); }

  void reset() {
    mDataWritten = 0;
    mCommandEnd = 0;

    // handles in mDataHandles are owned by the caller
    mDataHandles.clear();

    // handles in mTemporaryHandles are owned by the writer
    for (auto handle : mTemporaryHandles) {
      native_handle_close(handle);
      native_handle_delete(handle);
    }
    mTemporaryHandles.clear();
  }

  IQtiComposerClient::Command getCommand(uint32_t offset) {
    uint32_t val = (offset < mDataWritten) ? mData[offset] : 0;
    return static_cast<IQtiComposerClient::Command>(val &
      static_cast<uint32_t>(IQtiComposerClient::Command::OPCODE_MASK));
  }

  bool writeQueue(bool& queueChanged, uint32_t& commandLength,
                  hidl_vec<hidl_handle>& commandHandles) {
    if (mDataWritten == 0) {
      queueChanged = false;
      commandLength = 0;
      commandHandles.setToExternal(nullptr, 0);
      return true;
    }

    // After data are written to the queue, it may not be read by the
    // remote reader when
    //
    //  - the writer does not send them (because of other errors)
    //  - the hwbinder transaction fails
    //  - the reader does not read them (because of other errors)
    //
    // Discard the stale data here.
    size_t staleDataSize = mQueue ? mQueue->availableToRead() : 0;
    if (staleDataSize > 0) {
      ALOGW("discarding stale data from message queue");
      CommandQueueType::MemTransaction tx;
      if (mQueue->beginRead(staleDataSize, &tx)) {
        mQueue->commitRead(staleDataSize);
      }
    }
    // write data to queue, optionally resizing it
    if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) {
      if (!mQueue->write(mData.get(), mDataWritten)) {
        ALOGE("failed to write commands to message queue");
        return false;
      }

      queueChanged = false;
    } else {
      auto newQueue = std::make_unique<CommandQueueType>(mDataMaxSize);
      if (!newQueue->isValid() || !newQueue->write(mData.get(), mDataWritten)) {
        ALOGE("failed to prepare a new message queue ");
        return false;
      }

      mQueue = std::move(newQueue);
      queueChanged = true;
    }

    commandLength = mDataWritten;
    commandHandles.setToExternal(const_cast<hidl_handle*>(mDataHandles.data()),
                                 mDataHandles.size());

    return true;
  }

  const MQDescriptorSync<uint32_t>* getMQDescriptor() const {
    return (mQueue) ? mQueue->getDesc() : nullptr;
  }

  // Commands from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
  static constexpr uint16_t kSelectDisplayLength = 2;
  void selectDisplay(Display display) {
    beginCommand(IQtiComposerClient::Command::SELECT_DISPLAY, kSelectDisplayLength);
    write64(display);
    endCommand();
  }

  static constexpr uint16_t kSelectLayerLength = 2;
  void selectLayer(Layer layer) {
    beginCommand(IQtiComposerClient::Command::SELECT_LAYER, kSelectLayerLength);
    write64(layer);
    endCommand();
  }

  static constexpr uint16_t kSetErrorLength = 2;
  void setError(uint32_t location, Error error) {
    beginCommand(IQtiComposerClient::Command::SET_ERROR, kSetErrorLength);
    write(location);
    writeSigned(static_cast<int32_t>(error));
    endCommand();
  }

  static constexpr uint32_t kPresentOrValidateDisplayResultLength = 1;
  void setPresentOrValidateResult(uint32_t state) {
    beginCommand(IQtiComposerClient::Command::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT,
                 kPresentOrValidateDisplayResultLength);
    write(state);
    endCommand();
  }

  void setChangedCompositionTypes(const std::vector<Layer>& layers,
                                  const std::vector<IQtiComposerClient::Composition>& types) {
    size_t totalLayers = std::min(layers.size(), types.size());
    size_t currentLayer = 0;

    while (currentLayer < totalLayers) {
      size_t count = std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength) / 3);

      beginCommand(IQtiComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES, count * 3);
      for (size_t i = 0; i < count; i++) {
        write64(layers[currentLayer + i]);
        writeSigned(static_cast<int32_t>(types[currentLayer + i]));
      }
      endCommand();

      currentLayer += count;
    }
  }

  void setDisplayRequests(uint32_t displayRequestMask, const std::vector<Layer>& layers,
                          const std::vector<uint32_t>& layerRequestMasks) {
    size_t totalLayers = std::min(layers.size(), layerRequestMasks.size());
    size_t currentLayer = 0;

    while (currentLayer < totalLayers) {
      size_t count = std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength - 1) / 3);

      beginCommand(IQtiComposerClient::Command::SET_DISPLAY_REQUESTS, 1 + count * 3);
      write(displayRequestMask);
      for (size_t i = 0; i < count; i++) {
        write64(layers[currentLayer + i]);
        write(static_cast<int32_t>(layerRequestMasks[currentLayer + i]));
      }
      endCommand();

      currentLayer += count;
    }
  }

  static constexpr uint16_t kSetPresentFenceLength = 1;
  void setPresentFence(const shared_ptr<Fence> &presentFence) {
    beginCommand(IQtiComposerClient::Command::SET_PRESENT_FENCE, kSetPresentFenceLength);
    writeFence(presentFence);
    endCommand();
  }

  void setReleaseFences(const std::vector<Layer>& layers,
                        const std::vector<shared_ptr<Fence>>& releaseFences) {
    size_t totalLayers = std::min(layers.size(), releaseFences.size());
    size_t currentLayer = 0;

    while (currentLayer < totalLayers) {
      size_t count = std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength) / 3);

      beginCommand(IQtiComposerClient::Command::SET_RELEASE_FENCES, count * 3);
      for (size_t i = 0; i < count; i++) {
        write64(layers[currentLayer + i]);
        writeFence(releaseFences[currentLayer + i]);
      }
      endCommand();

      currentLayer += count;
    }
  }

  static constexpr uint16_t kSetColorTransformLength = 17;
  void setColorTransform(const float* matrix, ColorTransform hint) {
    beginCommand(IQtiComposerClient::Command::SET_COLOR_TRANSFORM, kSetColorTransformLength);
    for (int i = 0; i < 16; i++) {
      writeFloat(matrix[i]);
    }
    writeSigned(static_cast<int32_t>(hint));
    endCommand();
  }

  void setClientTarget(uint32_t slot, const native_handle_t* target,
                       const shared_ptr<Fence>& acquireFence, Dataspace dataspace,
                       const std::vector<IQtiComposerClient::Rect>& damage) {
    bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
    size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);

    beginCommand(IQtiComposerClient::Command::SET_CLIENT_TARGET, length);
    write(slot);
    writeHandle(target, true);
    writeFence(acquireFence);
    writeSigned(static_cast<int32_t>(dataspace));
    // When there are too many rectangles in the damage region and doWrite
    // is false, we write no rectangle at all which means the entire
    // client target is damaged.
    if (doWrite) {
      writeRegion(damage);
    }
    endCommand();
  }

  static constexpr uint16_t kSetClientTarget_3_1_Length = 3;
  void setClientTarget_3_1(uint32_t slot, const shared_ptr<Fence>& acquireFence, Dataspace dataspace) {
    beginCommand(IQtiComposerClient::Command::SET_CLIENT_TARGET_3_1, kSetClientTarget_3_1_Length);
    write(slot);
    writeFence(acquireFence);
    writeSigned(static_cast<int32_t>(dataspace));
    endCommand();
  }

  static constexpr uint16_t kSetOutputBufferLength = 3;
  void setOutputBuffer(uint32_t slot, const native_handle_t* buffer,
                       const shared_ptr<Fence>& releaseFence) {
    beginCommand(IQtiComposerClient::Command::SET_OUTPUT_BUFFER, kSetOutputBufferLength);
    write(slot);
    writeHandle(buffer, true);
    writeFence(releaseFence);
    endCommand();
  }

  static constexpr uint16_t kValidateDisplayLength = 0;
  void validateDisplay() {
    beginCommand(IQtiComposerClient::Command::VALIDATE_DISPLAY, kValidateDisplayLength);
    endCommand();
  }

  static constexpr uint16_t kPresentOrValidateDisplayLength = 0;
  void presentOrvalidateDisplay() {
    beginCommand(IQtiComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY,
                 kPresentOrValidateDisplayLength);
    endCommand();
  }

  static constexpr uint16_t kAcceptDisplayChangesLength = 0;
  void acceptDisplayChanges() {
    beginCommand(IQtiComposerClient::Command::ACCEPT_DISPLAY_CHANGES, kAcceptDisplayChangesLength);
    endCommand();
  }

  static constexpr uint16_t kPresentDisplayLength = 0;
  void presentDisplay() {
    beginCommand(IQtiComposerClient::Command::PRESENT_DISPLAY, kPresentDisplayLength);
    endCommand();
  }

  static constexpr uint16_t kSetLayerCursorPositionLength = 2;
  void setLayerCursorPosition(int32_t x, int32_t y) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_CURSOR_POSITION,
                 kSetLayerCursorPositionLength);
    writeSigned(x);
    writeSigned(y);
    endCommand();
  }

  static constexpr uint16_t kSetLayerBufferLength = 3;
  void setLayerBuffer(uint32_t slot, const native_handle_t* buffer,
                      const shared_ptr<Fence>& acquireFence) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_BUFFER, kSetLayerBufferLength);
    write(slot);
    writeHandle(buffer, true);
    writeFence(acquireFence);
    endCommand();
  }

  void setLayerSurfaceDamage(const std::vector<IQtiComposerClient::Rect>& damage) {
    bool doWrite = (damage.size() <= kMaxLength / 4);
    size_t length = (doWrite) ? damage.size() * 4 : 0;

    beginCommand(IQtiComposerClient::Command::SET_LAYER_SURFACE_DAMAGE, length);
    // When there are too many rectangles in the damage region and doWrite
    // is false, we write no rectangle at all which means the entire
    // layer is damaged.
    if (doWrite) {
      writeRegion(damage);
    }
    endCommand();
  }

  static constexpr uint16_t kSetLayerBlendModeLength = 1;
  void setLayerBlendMode(IQtiComposerClient::BlendMode mode) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_BLEND_MODE, kSetLayerBlendModeLength);
    writeSigned(static_cast<int32_t>(mode));
    endCommand();
  }

  static constexpr uint16_t kSetLayerColorLength = 1;
  void setLayerColor(IQtiComposerClient::Color color) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_COLOR, kSetLayerColorLength);
    writeColor(color);
    endCommand();
  }

  static constexpr uint16_t kSetLayerCompositionTypeLength = 1;
  void setLayerCompositionType(IQtiComposerClient::Composition type) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_COMPOSITION_TYPE,
                 kSetLayerCompositionTypeLength);
    writeSigned(static_cast<int32_t>(type));
    endCommand();
  }

  static constexpr uint16_t kSetLayerDataspaceLength = 1;
  void setLayerDataspace(Dataspace dataspace) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_DATASPACE, kSetLayerDataspaceLength);
    writeSigned(static_cast<int32_t>(dataspace));
    endCommand();
  }

  static constexpr uint16_t kSetLayerDisplayFrameLength = 4;
  void setLayerDisplayFrame(const IQtiComposerClient::Rect& frame) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_DISPLAY_FRAME, kSetLayerDisplayFrameLength);
    writeRect(frame);
    endCommand();
  }

  static constexpr uint16_t kSetLayerPlaneAlphaLength = 1;
  void setLayerPlaneAlpha(float alpha) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_PLANE_ALPHA, kSetLayerPlaneAlphaLength);
    writeFloat(alpha);
    endCommand();
  }

  static constexpr uint16_t kSetLayerSidebandStreamLength = 1;
  void setLayerSidebandStream(const native_handle_t* stream) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_SIDEBAND_STREAM,
                 kSetLayerSidebandStreamLength);
    writeHandle(stream);
    endCommand();
  }

  static constexpr uint16_t kSetLayerSourceCropLength = 4;
  void setLayerSourceCrop(const IQtiComposerClient::FRect& crop) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_SOURCE_CROP, kSetLayerSourceCropLength);
    writeFRect(crop);
    endCommand();
  }

  static constexpr uint16_t kSetLayerTransformLength = 1;
  void setLayerTransform(Transform transform) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_TRANSFORM, kSetLayerTransformLength);
    writeSigned(static_cast<int32_t>(transform));
    endCommand();
  }

  void setLayerVisibleRegion(const std::vector<IQtiComposerClient::Rect>& visible) {
    bool doWrite = (visible.size() <= kMaxLength / 4);
    size_t length = (doWrite) ? visible.size() * 4 : 0;

    beginCommand(IQtiComposerClient::Command::SET_LAYER_VISIBLE_REGION, length);
    // When there are too many rectangles in the visible region and
    // doWrite is false, we write no rectangle at all which means the
    // entire layer is visible.
    if (doWrite) {
      writeRegion(visible);
    }
    endCommand();
  }

  static constexpr uint16_t kSetLayerZOrderLength = 1;
  void setLayerZOrder(uint32_t z) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_Z_ORDER, kSetLayerZOrderLength);
    write(z);
    endCommand();
  }

  static constexpr uint16_t kSetLayerTypeLength = 1;
  void setLayerType(uint32_t z) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_TYPE, kSetLayerTypeLength);
    write(z);
    endCommand();
  }

  static constexpr uint16_t kSetLayerFlagLength = 1;
  void setLayerFlag(uint32_t type) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_FLAG_3_1, kSetLayerTypeLength);
    write(type);
    endCommand();
  }

  // Commands from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
  static constexpr uint16_t kSetLayerFloatColorLength = 4;
  void setLayerFloatColor(IQtiComposerClient::FloatColor color) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_FLOAT_COLOR, kSetLayerFloatColorLength);
    writeFloatColor(color);
    endCommand();
  }

  void setLayerPerFrameMetadata(const hidl_vec<IQtiComposerClient::PerFrameMetadata>& metadataVec) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_PER_FRAME_METADATA,
                 metadataVec.size() * 2);
    for (const auto& metadata : metadataVec) {
      writeSigned(static_cast<int32_t>(metadata.key));
      writeFloat(metadata.value);
    }
    endCommand();
  }

  // Commands from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
  static constexpr uint16_t kSetLayerColorTransformLength = 16;
  void setLayerColorTransform(const float* matrix) {
    beginCommand(IQtiComposerClient::Command::SET_LAYER_COLOR_TRANSFORM,
                 kSetLayerColorTransformLength);
    for (int i = 0; i < 16; i++) {
      writeFloat(matrix[i]);
    }
    endCommand();
  }

  void setLayerPerFrameMetadataBlobs(
    const hidl_vec<IQtiComposerClient::PerFrameMetadataBlob>& metadata) {
    size_t commandLength = 0;

    if (metadata.size() > std::numeric_limits<uint32_t>::max()) {
      LOG_FATAL("too many metadata blobs - dynamic metadata size is too large");
      return;
    }

    // number of blobs
    commandLength += metadata.size();

    for (auto metadataBlob : metadata) {
      commandLength += sizeof(int32_t);  // key of metadata blob
      commandLength += 1;                // size information of metadata blob

      // metadata content size
      size_t metadataSize = metadataBlob.blob.size() / sizeof(uint32_t);
      commandLength += metadataSize;
      commandLength += (metadataBlob.blob.size() - (metadataSize * sizeof(uint32_t)) > 0) ? 1 : 0;
    }

    if (commandLength > std::numeric_limits<uint16_t>::max()) {
      LOG_FATAL("dynamic metadata size is too large");
      return;
    }

    // Blobs are written as:
    // {numElements, key1, size1, blob1, key2, size2, blob2, key3, size3...}
    uint16_t length = static_cast<uint16_t>(commandLength);
    beginCommand(IQtiComposerClient::Command::SET_LAYER_PER_FRAME_METADATA_BLOBS, length);
    write(static_cast<uint32_t>(metadata.size()));
    for (auto metadataBlob : metadata) {
      writeSigned(static_cast<int32_t>(metadataBlob.key));
      write(static_cast<uint32_t>(metadataBlob.blob.size()));
      writeBlob(static_cast<uint32_t>(metadataBlob.blob.size()), metadataBlob.blob.data());
    }
    endCommand();
  }

  static constexpr uint16_t kSetDisplayElapseTime = 2;
  void setDisplayElapseTime(uint64_t time) {
    beginCommand(IQtiComposerClient::Command::SET_DISPLAY_ELAPSE_TIME, kSetDisplayElapseTime);
    write64(time);
    endCommand();
  }

  // Commands from ::android::hardware::graphics::composer::V2_4::IComposerClient follow.
  static constexpr uint16_t kSetClientTargetPropertyLength = 2;
  void setClientTargetProperty(
        const IQtiComposerClient::ClientTargetProperty& clientTargetProperty) {
    beginCommand(IQtiComposerClient::Command::SET_CLIENT_TARGET_PROPERTY,
                 kSetClientTargetPropertyLength);
    writeSigned(static_cast<int32_t>(clientTargetProperty.pixelFormat));
    writeSigned(static_cast<int32_t>(clientTargetProperty.dataspace));
    endCommand();
  }

 protected:
  // Commands from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
  void beginCommand(IQtiComposerClient::Command command, uint16_t length) {
    if (mCommandEnd) {
      LOG_FATAL("endCommand was not called before command 0x%x", command);
    }

    growData(1 + length);
    write(static_cast<uint32_t>(command) | length);

    mCommandEnd = mDataWritten + length;
  }

  void endCommand() {
    if (!mCommandEnd) {
      LOG_FATAL("beginCommand was not called");
    } else if (mDataWritten > mCommandEnd) {
      LOG_FATAL("too much data written");
      mDataWritten = mCommandEnd;
    } else if (mDataWritten < mCommandEnd) {
      LOG_FATAL("too little data written");
      while (mDataWritten < mCommandEnd) {
        write(0);
      }
    }

    mCommandEnd = 0;
  }

  void write(uint32_t val) { mData[mDataWritten++] = val; }

  void writeSigned(int32_t val) { memcpy(&mData[mDataWritten++], &val, sizeof(val)); }

  void writeFloat(float val) { memcpy(&mData[mDataWritten++], &val, sizeof(val)); }

  void write64(uint64_t val) {
    uint32_t lo = static_cast<uint32_t>(val & 0xffffffff);
    uint32_t hi = static_cast<uint32_t>(val >> 32);
    write(lo);
    write(hi);
  }

  void writeRect(const IQtiComposerClient::Rect& rect) {
    writeSigned(rect.left);
    writeSigned(rect.top);
    writeSigned(rect.right);
    writeSigned(rect.bottom);
  }

  void writeRegion(const std::vector<IQtiComposerClient::Rect>& region) {
    for (const auto& rect : region) {
      writeRect(rect);
    }
  }

  void writeFRect(const IQtiComposerClient::FRect& rect) {
    writeFloat(rect.left);
    writeFloat(rect.top);
    writeFloat(rect.right);
    writeFloat(rect.bottom);
  }

  void writeColor(const IQtiComposerClient::Color& color) {
    write((color.r <<  0) | (color.g <<  8) | (color.b << 16) | (color.a << 24));
  }

  // ownership of handle is not transferred
  void writeHandle(const native_handle_t* handle, bool useCache) {
    if (!handle) {
      writeSigned(static_cast<int32_t>((useCache) ?
                IQtiComposerClient::HandleIndex::CACHED : IQtiComposerClient::HandleIndex::EMPTY));
      return;
    }

    mDataHandles.push_back(handle);
    writeSigned(mDataHandles.size() - 1);
  }

  void writeHandle(const native_handle_t* handle) {
    writeHandle(handle, false);
  }

  // Handle would own fence hereafter. Hence provide a dupped fd.
  void writeFence(const shared_ptr<Fence>& fence) {
    native_handle_t* handle = nullptr;
    if (fence) {
      handle = getTemporaryHandle(1, 0);
      if (handle) {
        handle->data[0] = Fence::Dup(fence);
      } else {
        ALOGW("failed to get temporary handle for fence %s", Fence::GetStr(fence).c_str());
        Fence::Wait(fence);
      }
    }

    writeHandle(handle);
  }

  native_handle_t* getTemporaryHandle(int numFds, int numInts) {
    native_handle_t* handle = native_handle_create(numFds, numInts);
    if (handle) {
      mTemporaryHandles.push_back(handle);
    }
    return handle;
  }

  static constexpr uint16_t kMaxLength = std::numeric_limits<uint16_t>::max();

  // Commands from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
  void writeFloatColor(const IQtiComposerClient::FloatColor& color) {
    writeFloat(color.r);
    writeFloat(color.g);
    writeFloat(color.b);
    writeFloat(color.a);
  }

  // Commands from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
  void writeBlob(uint32_t length, const unsigned char* blob) {
    memcpy(&mData[mDataWritten], blob, length);
    uint32_t numElements = length / 4;
    mDataWritten += numElements;
    mDataWritten += (length - (numElements * 4) > 0) ? 1 : 0;
  }

 private:
  void growData(uint32_t grow) {
    uint32_t newWritten = mDataWritten + grow;
    if (newWritten < mDataWritten) {
      LOG_ALWAYS_FATAL("buffer overflowed; data written %" PRIu32
                       ", growing by %" PRIu32, mDataWritten, grow);
    }

    if (newWritten <= mDataMaxSize) {
      return;
    }

    uint32_t newMaxSize = mDataMaxSize << 1;
    if (newMaxSize < newWritten) {
      newMaxSize = newWritten;
    }

    auto newData = std::make_unique<uint32_t[]>(newMaxSize);
    std::copy_n(mData.get(), mDataWritten, newData.get());
    mDataMaxSize = newMaxSize;
    mData = std::move(newData);
  }

  uint32_t mDataMaxSize;
  std::unique_ptr<uint32_t[]> mData;

  uint32_t mDataWritten;
  // end offset of the current command
  uint32_t mCommandEnd;

  std::vector<hidl_handle> mDataHandles;
  std::vector<native_handle_t *> mTemporaryHandles;

  std::unique_ptr<CommandQueueType> mQueue;
};

// This class helps parse a command queue.  Note that all sizes/lengths are in units of uint32_t's.
class CommandReaderBase {
 public:
  CommandReaderBase() : mDataMaxSize(0) { reset(); }

  bool setMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) {
    mQueue = std::make_unique<CommandQueueType>(descriptor, false);
    if (mQueue->isValid()) {
      return true;
    } else {
      mQueue = nullptr;
      return false;
    }
  }

  bool readQueue(uint32_t commandLength, const hidl_vec<hidl_handle>& commandHandles) {
    if (!mQueue) {
      return false;
    }

    auto quantumCount = mQueue->getQuantumCount();
    if (mDataMaxSize < quantumCount) {
      mDataMaxSize = quantumCount;
      mData = std::make_unique<uint32_t[]>(mDataMaxSize);
    }

    if (commandLength > mDataMaxSize || !mQueue->read(mData.get(), commandLength)) {
      ALOGE("failed to read commands from message queue");
      return false;
    }

    mDataSize = commandLength;
    mDataRead = 0;
    mCommandBegin = 0;
    mCommandEnd = 0;
    mDataHandles.setToExternal(const_cast<hidl_handle*>(commandHandles.data()),
                               commandHandles.size());

    return true;
  }

  void reset() {
    mDataSize = 0;
    mDataRead = 0;
    mCommandBegin = 0;
    mCommandEnd = 0;
    mDataHandles.setToExternal(nullptr, 0);
  }

 protected:
  bool isEmpty() const { return (mDataRead >= mDataSize); }

  bool beginCommand(IQtiComposerClient::Command& command, uint16_t& length) {
    if (mCommandEnd) {
      LOG_FATAL("endCommand was not called before command 0x%x", command);
    }

    constexpr uint32_t opcode_mask =
      static_cast<uint32_t>(IQtiComposerClient::Command::OPCODE_MASK);
    constexpr uint32_t length_mask =
      static_cast<uint32_t>(IQtiComposerClient::Command::LENGTH_MASK);

    uint32_t val = read();
    command = static_cast<IQtiComposerClient::Command>(val & opcode_mask);
    length = static_cast<uint16_t>(val & length_mask);

    if (mDataRead + length > mDataSize) {
      ALOGE("command 0x%x has invalid command length %" PRIu16, command, length);
      // undo the read() above
      mDataRead--;
      return false;
    }

    mCommandEnd = mDataRead + length;

    return true;
  }

  void endCommand() {
    if (!mCommandEnd) {
      LOG_FATAL("beginCommand was not called");
    } else if (mDataRead > mCommandEnd) {
      LOG_FATAL("too much data read");
      mDataRead = mCommandEnd;
    } else if (mDataRead < mCommandEnd) {
      LOG_FATAL("too little data read");
      mDataRead = mCommandEnd;
    }

    mCommandBegin = mCommandEnd;
    mCommandEnd = 0;
  }

  uint32_t getCommandLoc() const { return mCommandBegin; }

  uint32_t read() { return mData[mDataRead++]; }

  int32_t readSigned() {
    int32_t val;
    memcpy(&val, &mData[mDataRead++], sizeof(val));
    return val;
  }

  float readFloat() {
    float val;
    memcpy(&val, &mData[mDataRead++], sizeof(val));
    return val;
  }

  uint64_t read64() {
    uint32_t lo = read();
    uint32_t hi = read();
    return (static_cast<uint64_t>(hi) << 32) | lo;
  }

  void readBlob(uint32_t size, void* blob) {
    memcpy(blob, &mData[mDataRead], size);
    uint32_t numElements = size / sizeof(uint32_t);
    mDataRead += numElements;
    mDataRead += (size - numElements * sizeof(uint32_t) != 0) ? 1 : 0;
  }

  IQtiComposerClient::Color readColor() {
    uint32_t val = read();
    return IQtiComposerClient::Color{
      static_cast<uint8_t>((val >>  0) & 0xff),
      static_cast<uint8_t>((val >>  8) & 0xff),
      static_cast<uint8_t>((val >> 16) & 0xff),
      static_cast<uint8_t>((val >> 24) & 0xff),
    };
  }

  // ownership of handle is not transferred
  const native_handle_t* readHandle(bool& useCache) {
    const native_handle_t* handle = nullptr;

    int32_t index = readSigned();
    switch (index) {
    case static_cast<int32_t>(IQtiComposerClient::HandleIndex::EMPTY):
      useCache = false;
      break;
    case static_cast<int32_t>(IQtiComposerClient::HandleIndex::CACHED):
      useCache = true;
      break;
    default:
      if (static_cast<size_t>(index) < mDataHandles.size()) {
        handle = mDataHandles[index].getNativeHandle();
      } else {
        ALOGE("invalid handle index %zu", static_cast<size_t>(index));
      }
      useCache = false;
      break;
    }

    return handle;
  }

  const native_handle_t* readHandle() {
    bool useCache;
    return readHandle(useCache);
  }

  // Handle would still own original fence. Hence create a Fence object on duped fd.
  void readFence(shared_ptr<Fence>* fence, const string &name) {
    auto handle = readHandle();
    if (!handle || handle->numFds == 0) {
      return;
    }

    if (handle->numFds != 1) {
      ALOGE("invalid fence handle with %d fds", handle->numFds);
      return;
    }

    *fence = Fence::Create(dup(handle->data[0]), name);
    if (*fence == nullptr) {
      ALOGW("failed to dup fence %d", handle->data[0]);
      sync_wait(handle->data[0], -1);
    }
  }

 private:
  std::unique_ptr<CommandQueueType> mQueue;
  uint32_t mDataMaxSize;
  std::unique_ptr<uint32_t[]> mData;

  uint32_t mDataSize;
  uint32_t mDataRead;

  // begin/end offsets of the current command
  uint32_t mCommandBegin;
  uint32_t mCommandEnd;

  hidl_vec<hidl_handle> mDataHandles;
};

}  // namespace V3_1
}  // namespace composer
}  // namespace display
}  // namespace hardware
}  // namespace qti
}  // namespace vendor

#endif  // __QTICOMPOSERCOMMANDBUFFER_H__
