/*
 * Copyright (c) 2019-2020, 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 __QTIQMAACOMPOSERCOMMANDBUFFER_H__
#define __QTIQMAACOMPOSERCOMMANDBUFFER_H__

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

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

namespace vendor {
namespace qti {
namespace hardware {
namespace display {
namespace composer {
namespace V3_0 {

using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_vec;
using ::android::hardware::MessageQueue;
using ::android::hardware::MQDescriptorSync;
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::Display;
using ::android::hardware::graphics::composer::V2_1::Error;
using ::android::hardware::graphics::composer::V2_1::Layer;
using ::android::hardware::graphics::composer::V2_4::IComposerClient;

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

using std::shared_ptr;
using std::string;

// 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();
  }

  IComposerClient::Command getCommand(uint32_t offset) {
    uint32_t val = (offset < mDataWritten) ? mData[offset] : 0;
    return static_cast<IComposerClient::Command>(
        val & static_cast<uint32_t>(IComposerClient::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(IComposerClient::Command::SELECT_DISPLAY, kSelectDisplayLength);
    write64(display);
    endCommand();
  }

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

  static constexpr uint16_t kSetErrorLength = 2;
  void setError(uint32_t location, Error error) {
    beginCommand(IComposerClient::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(IComposerClient::Command::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT,
                 kPresentOrValidateDisplayResultLength);
    write(state);
    endCommand();
  }

  void setChangedCompositionTypes(const std::vector<Layer> &layers,
                                  const std::vector<IComposerClient::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(IComposerClient::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(IComposerClient::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 kSetColorTransformLength = 17;
  void setColorTransform(const float *matrix, ColorTransform hint) {
    beginCommand(IComposerClient::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<int32_t> &acquireFence, Dataspace dataspace,
                       const std::vector<IComposerClient::Rect> &damage) {
    bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
    size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);

    beginCommand(IComposerClient::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 kSetOutputBufferLength = 3;
  void setOutputBuffer(uint32_t slot, const native_handle_t *buffer,
                       const shared_ptr<int32_t> &releaseFence) {
    beginCommand(IComposerClient::Command::SET_OUTPUT_BUFFER, kSetOutputBufferLength);
    write(slot);
    writeHandle(buffer, true);
    writeFence(releaseFence);
    endCommand();
  }

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

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

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

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

  static constexpr uint16_t kSetLayerCursorPositionLength = 2;
  void setLayerCursorPosition(int32_t x, int32_t y) {
    beginCommand(IComposerClient::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<int32_t> &acquireFence) {
    beginCommand(IComposerClient::Command::SET_LAYER_BUFFER, kSetLayerBufferLength);
    write(slot);
    writeHandle(buffer, true);
    writeFence(acquireFence);
    endCommand();
  }

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

    beginCommand(IComposerClient::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(IComposerClient::BlendMode mode) {
    beginCommand(IComposerClient::Command::SET_LAYER_BLEND_MODE, kSetLayerBlendModeLength);
    writeSigned(static_cast<int32_t>(mode));
    endCommand();
  }

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

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

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

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

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

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

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

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

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

    beginCommand(IComposerClient::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(IComposerClient::Command::SET_LAYER_Z_ORDER, kSetLayerZOrderLength);
    write(z);
    endCommand();
  }

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

  void setLayerPerFrameMetadata(const hidl_vec<IComposerClient::PerFrameMetadata> &metadataVec) {
    beginCommand(IComposerClient::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(IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM,
                 kSetLayerColorTransformLength);
    for (int i = 0; i < 16; i++) {
      writeFloat(matrix[i]);
    }
    endCommand();
  }

  void setLayerPerFrameMetadataBlobs(
      const hidl_vec<IComposerClient::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(IComposerClient::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();
  }

 protected:
  // Commands from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
  void beginCommand(IComposerClient::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 IComposerClient::Rect &rect) {
    writeSigned(rect.left);
    writeSigned(rect.top);
    writeSigned(rect.right);
    writeSigned(rect.bottom);
  }

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

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

  void writeColor(const IComposerClient::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) ? IComposerClient::HandleIndex::CACHED
                                                  : IComposerClient::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<int32_t> &fence) {
    native_handle_t *handle = nullptr;
    if (fence) {
      handle = getTemporaryHandle(1, 0);
    }

    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 IComposerClient::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 <= 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(IComposerClient::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>(IComposerClient::Command::OPCODE_MASK);
    constexpr uint32_t length_mask = static_cast<uint32_t>(IComposerClient::Command::LENGTH_MASK);

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

    if (mDataRead + length > mDataSize) {
      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;
  }

  IComposerClient::Color readColor() {
    uint32_t val = read();
    return IComposerClient::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>(IComposerClient::HandleIndex::EMPTY):
        useCache = false;
        break;
      case static_cast<int32_t>(IComposerClient::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<int32_t> *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;
    }

    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_0
}  // namespace composer
}  // namespace display
}  // namespace hardware
}  // namespace qti
}  // namespace vendor

#endif  // __QTIQMAACOMPOSERCOMMANDBUFFER_H__