/*
 * Copyright (C) 2018 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2-types"
#include <log/log.h>

#include <codec2/hidl/1.0/types.h>

#include <C2AllocatorIon.h>
#include <C2AllocatorGralloc.h>
#include <C2BlockInternal.h>
#include <C2Buffer.h>
#include <C2Component.h>
#include <C2Param.h>
#include <C2ParamInternal.h>
#include <C2PlatformSupport.h>
#include <C2Work.h>
#include <util/C2ParamUtils.h>

#include <unordered_map>
#include <algorithm>

#include <media/stagefright/foundation/AUtils.h>

namespace hardware {
namespace google {
namespace media {
namespace c2 {
namespace V1_0 {
namespace utils {

using namespace ::android;
using ::android::hardware::Return;
using ::android::hardware::media::bufferpool::BufferPoolData;
using ::android::hardware::media::bufferpool::V1_0::BufferStatusMessage;
using ::android::hardware::media::bufferpool::V1_0::ResultStatus;
using ::android::hardware::media::bufferpool::V1_0::implementation::
        ClientManager;
using ::android::hardware::media::bufferpool::V1_0::implementation::
        TransactionId;

namespace /* unnamed */ {

template <typename Common, typename DstVector, typename SrcVector>
void copyVector(DstVector* d, const SrcVector& s) {
    static_assert(sizeof(Common) == sizeof(decltype((*d)[0])),
            "DstVector's component size does not match Common");
    static_assert(sizeof(Common) == sizeof(decltype(s[0])),
            "SrcVector's component size does not match Common");
    d->resize(s.size());
    std::copy(
            reinterpret_cast<const Common*>(&s[0]),
            reinterpret_cast<const Common*>(&s[0] + s.size()),
            reinterpret_cast<Common*>(&(*d)[0]));
}

// C2ParamField -> ParamField
void objcpy(ParamField *d, const C2ParamField &s) {
    d->index = static_cast<ParamIndex>(_C2ParamInspector::GetIndex(s));
    d->fieldId.offset = static_cast<uint32_t>(_C2ParamInspector::GetOffset(s));
    d->fieldId.size = static_cast<uint32_t>(_C2ParamInspector::GetSize(s));
}

struct C2ParamFieldBuilder : public C2ParamField {
    C2ParamFieldBuilder() : C2ParamField(
            static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) {
    }
    // ParamField -> C2ParamField
    C2ParamFieldBuilder(const ParamField& s) : C2ParamField(
            static_cast<C2Param::Index>(static_cast<uint32_t>(s.index)),
            static_cast<uint32_t>(s.fieldId.offset),
            static_cast<uint32_t>(s.fieldId.size)) {
    }
};

// C2WorkOrdinalStruct -> WorkOrdinal
void objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
    d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku());
    d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku());
    d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku());
}

// WorkOrdinal -> C2WorkOrdinalStruct
void objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) {
    d->frameIndex = c2_cntr64_t(s.frameIndex);
    d->timestamp = c2_cntr64_t(s.timestampUs);
    d->customOrdinal = c2_cntr64_t(s.customOrdinal);
}

// C2FieldSupportedValues::range's type -> FieldSupportedValues::Range
void objcpy(
        FieldSupportedValues::Range* d,
        const decltype(C2FieldSupportedValues::range)& s) {
    d->min = static_cast<PrimitiveValue>(s.min.u64);
    d->max = static_cast<PrimitiveValue>(s.max.u64);
    d->step = static_cast<PrimitiveValue>(s.step.u64);
    d->num = static_cast<PrimitiveValue>(s.num.u64);
    d->denom = static_cast<PrimitiveValue>(s.denom.u64);
}

// C2FieldSupportedValues -> FieldSupportedValues
Status objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
    d->typeOther = static_cast<int32_t>(s.type);
    switch (s.type) {
    case C2FieldSupportedValues::EMPTY:
        d->type = FieldSupportedValues::Type::EMPTY;
        d->values.resize(0);
        return Status::OK;
    case C2FieldSupportedValues::RANGE:
        d->type = FieldSupportedValues::Type::RANGE;
        objcpy(&d->range, s.range);
        d->values.resize(0);
        return Status::OK;
    default:
        switch (s.type) {
        case C2FieldSupportedValues::VALUES:
            d->type = FieldSupportedValues::Type::VALUES;
            break;
        case C2FieldSupportedValues::FLAGS:
            d->type = FieldSupportedValues::Type::FLAGS;
            break;
        default:
            d->type = FieldSupportedValues::Type::OTHER;
            // Copy all fields in this case
            objcpy(&d->range, s.range);
        }
        d->values.resize(s.values.size());
        copyVector<uint64_t>(&d->values, s.values);
        return Status::OK;
    }
}

// FieldSupportedValues::Range -> C2FieldSupportedValues::range's type
void objcpy(
        decltype(C2FieldSupportedValues::range)* d,
        const FieldSupportedValues::Range& s) {
    d->min.u64 = static_cast<uint64_t>(s.min);
    d->max.u64 = static_cast<uint64_t>(s.max);
    d->step.u64 = static_cast<uint64_t>(s.step);
    d->num.u64 = static_cast<uint64_t>(s.num);
    d->denom.u64 = static_cast<uint64_t>(s.denom);
}

// FieldSupportedValues -> C2FieldSupportedValues
c2_status_t objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
    switch (s.type) {
    case FieldSupportedValues::Type::EMPTY:
        d->type = C2FieldSupportedValues::EMPTY;
        return C2_OK;
    case FieldSupportedValues::Type::RANGE:
        d->type = C2FieldSupportedValues::RANGE;
        objcpy(&d->range, s.range);
        d->values.resize(0);
        return C2_OK;
    default:
        switch (s.type) {
        case FieldSupportedValues::Type::VALUES:
            d->type = C2FieldSupportedValues::VALUES;
            break;
        case FieldSupportedValues::Type::FLAGS:
            d->type = C2FieldSupportedValues::FLAGS;
            break;
        default:
            d->type = static_cast<C2FieldSupportedValues::type_t>(s.typeOther);
            // Copy all fields in this case
            objcpy(&d->range, s.range);
        }
        copyVector<uint64_t>(&d->values, s.values);
        return C2_OK;
    }
}

} // unnamed namespace

// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
Status objcpy(
        FieldSupportedValuesQuery* d,
        const C2FieldSupportedValuesQuery& s) {
    objcpy(&d->field, s.field());
    switch (s.type()) {
    case C2FieldSupportedValuesQuery::POSSIBLE:
        d->type = FieldSupportedValuesQuery::Type::POSSIBLE;
        break;
    case C2FieldSupportedValuesQuery::CURRENT:
        d->type = FieldSupportedValuesQuery::Type::CURRENT;
        break;
    default:
        ALOGE("Unknown type of C2FieldSupportedValuesQuery: %u",
                static_cast<unsigned>(s.type()));
        return Status::BAD_VALUE;
    }
    return Status::OK;
}

// FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
c2_status_t objcpy(
        C2FieldSupportedValuesQuery* d,
        const FieldSupportedValuesQuery& s) {
    C2FieldSupportedValuesQuery::type_t dType;
    switch (s.type) {
    case FieldSupportedValuesQuery::Type::POSSIBLE:
        dType = C2FieldSupportedValuesQuery::POSSIBLE;
        break;
    case FieldSupportedValuesQuery::Type::CURRENT:
        dType = C2FieldSupportedValuesQuery::CURRENT;
        break;
    default:
        ALOGE("Unknown type of FieldSupportedValuesQuery: %u",
                static_cast<unsigned>(s.type));
        return C2_BAD_VALUE;
    }
    *d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType);
    return C2_OK;
}

// C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
Status objcpy(
        FieldSupportedValuesQueryResult* d,
        const C2FieldSupportedValuesQuery& s) {
    d->status = static_cast<Status>(s.status);
    return objcpy(&d->values, s.values);
}

// FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
// C2FieldSupportedValuesQuery
c2_status_t objcpy(
        C2FieldSupportedValuesQuery* d,
        const FieldSupportedValuesQuery& sq,
        const FieldSupportedValuesQueryResult& sr) {
    c2_status_t status = objcpy(d, sq);
    if (status != C2_OK) {
        return status;
    }
    d->status = static_cast<c2_status_t>(sr.status);
    return objcpy(&d->values, sr.values);
}

// C2Component::Traits -> IComponentStore::ComponentTraits
Status objcpy(
        IComponentStore::ComponentTraits *d,
        const C2Component::Traits &s) {
    d->name = s.name;

    switch (s.domain) {
    case C2Component::DOMAIN_VIDEO:
        d->domain = IComponentStore::ComponentTraits::Domain::VIDEO;
        break;
    case C2Component::DOMAIN_AUDIO:
        d->domain = IComponentStore::ComponentTraits::Domain::AUDIO;
        break;
    default:
        d->domain = IComponentStore::ComponentTraits::Domain::OTHER;
    }
    d->domainOther = static_cast<uint32_t>(s.domain);

    switch (s.kind) {
    case C2Component::KIND_DECODER:
        d->kind = IComponentStore::ComponentTraits::Kind::DECODER;
        break;
    case C2Component::KIND_ENCODER:
        d->kind = IComponentStore::ComponentTraits::Kind::ENCODER;
        break;
    default:
        d->kind = IComponentStore::ComponentTraits::Kind::OTHER;
    }
    d->kindOther = static_cast<uint32_t>(s.kind);

    d->rank = static_cast<uint32_t>(s.rank);

    d->mediaType = s.mediaType;

    d->aliases.resize(s.aliases.size());
    for (size_t ix = s.aliases.size(); ix > 0; ) {
        --ix;
        d->aliases[ix] = s.aliases[ix];
    }
    return Status::OK;
}

// ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
c2_status_t objcpy(
        C2Component::Traits* d,
        std::unique_ptr<std::vector<std::string>>* aliasesBuffer,
        const IComponentStore::ComponentTraits& s) {
    d->name = s.name.c_str();

    switch (s.domain) {
    case IComponentStore::ComponentTraits::Domain::VIDEO:
        d->domain = C2Component::DOMAIN_VIDEO;
        break;
    case IComponentStore::ComponentTraits::Domain::AUDIO:
        d->domain = C2Component::DOMAIN_AUDIO;
        break;
    default:
        d->domain = static_cast<C2Component::domain_t>(s.domainOther);
    }

    switch (s.kind) {
    case IComponentStore::ComponentTraits::Kind::DECODER:
        d->kind = C2Component::KIND_DECODER;
        break;
    case IComponentStore::ComponentTraits::Kind::ENCODER:
        d->kind = C2Component::KIND_ENCODER;
        break;
    default:
        d->kind = static_cast<C2Component::kind_t>(s.kindOther);
    }

    d->rank = static_cast<C2Component::rank_t>(s.rank);
    d->mediaType = s.mediaType.c_str();

    // aliasesBuffer must not be resized after this.
    *aliasesBuffer = std::make_unique<std::vector<std::string>>(
            s.aliases.size());
    (*aliasesBuffer)->resize(s.aliases.size());
    std::vector<C2StringLiteral> dAliases(s.aliases.size());
    for (size_t i = 0; i < s.aliases.size(); ++i) {
        (**aliasesBuffer)[i] = s.aliases[i].c_str();
        d->aliases[i] = (**aliasesBuffer)[i].c_str();
    }
    return C2_OK;
}

namespace /* unnamed */ {

// C2ParamFieldValues -> ParamFieldValues
Status objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) {
    objcpy(&d->paramOrField, s.paramOrField);
    if (s.values) {
        d->values.resize(1);
        return objcpy(&d->values[0], *s.values);
    }
    d->values.resize(0);
    return Status::OK;
}

// ParamFieldValues -> C2ParamFieldValues
c2_status_t objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) {
    d->paramOrField = C2ParamFieldBuilder(s.paramOrField);
    if (s.values.size() == 1) {
        d->values = std::make_unique<C2FieldSupportedValues>();
        return objcpy(d->values.get(), s.values[0]);
    } else if (s.values.size() == 0) {
        d->values.reset();
        return C2_OK;
    }
    ALOGE("Multiple FieldSupportedValues objects. "
            "(Only one is allowed.)");
    return C2_BAD_VALUE;
}

} // unnamed namespace

// C2SettingResult -> SettingResult
Status objcpy(SettingResult *d, const C2SettingResult &s) {
    d->failureOther = static_cast<uint32_t>(s.failure);
    switch (s.failure) {
    case C2SettingResult::READ_ONLY:
        d->failure = SettingResult::Failure::READ_ONLY;
        break;
    case C2SettingResult::MISMATCH:
        d->failure = SettingResult::Failure::MISMATCH;
        break;
    case C2SettingResult::BAD_VALUE:
        d->failure = SettingResult::Failure::BAD_VALUE;
        break;
    case C2SettingResult::BAD_TYPE:
        d->failure = SettingResult::Failure::BAD_TYPE;
        break;
    case C2SettingResult::BAD_PORT:
        d->failure = SettingResult::Failure::BAD_PORT;
        break;
    case C2SettingResult::BAD_INDEX:
        d->failure = SettingResult::Failure::BAD_INDEX;
        break;
    case C2SettingResult::CONFLICT:
        d->failure = SettingResult::Failure::CONFLICT;
        break;
    case C2SettingResult::UNSUPPORTED:
        d->failure = SettingResult::Failure::UNSUPPORTED;
        break;
    case C2SettingResult::INFO_CONFLICT:
        d->failure = SettingResult::Failure::INFO_CONFLICT;
        break;
    default:
        d->failure = SettingResult::Failure::OTHER;
    }
    Status status = objcpy(&d->field, s.field);
    if (status != Status::OK) {
        return status;
    }
    d->conflicts.resize(s.conflicts.size());
    size_t i = 0;
    for (const C2ParamFieldValues& sConflict : s.conflicts) {
        ParamFieldValues &dConflict = d->conflicts[i++];
        status = objcpy(&dConflict, sConflict);
        if (status != Status::OK) {
            return status;
        }
    }
    return Status::OK;
}

// SettingResult -> std::unique_ptr<C2SettingResult>
c2_status_t objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
    *d = std::unique_ptr<C2SettingResult>(new C2SettingResult {
            .field = C2ParamFieldValues(C2ParamFieldBuilder()) });
    if (!*d) {
        return C2_NO_MEMORY;
    }

    // failure
    switch (s.failure) {
    case SettingResult::Failure::READ_ONLY:
        (*d)->failure = C2SettingResult::READ_ONLY;
        break;
    case SettingResult::Failure::MISMATCH:
        (*d)->failure = C2SettingResult::MISMATCH;
        break;
    case SettingResult::Failure::BAD_VALUE:
        (*d)->failure = C2SettingResult::BAD_VALUE;
        break;
    case SettingResult::Failure::BAD_TYPE:
        (*d)->failure = C2SettingResult::BAD_TYPE;
        break;
    case SettingResult::Failure::BAD_PORT:
        (*d)->failure = C2SettingResult::BAD_PORT;
        break;
    case SettingResult::Failure::BAD_INDEX:
        (*d)->failure = C2SettingResult::BAD_INDEX;
        break;
    case SettingResult::Failure::CONFLICT:
        (*d)->failure = C2SettingResult::CONFLICT;
        break;
    case SettingResult::Failure::UNSUPPORTED:
        (*d)->failure = C2SettingResult::UNSUPPORTED;
        break;
    case SettingResult::Failure::INFO_CONFLICT:
        (*d)->failure = C2SettingResult::INFO_CONFLICT;
        break;
    default:
        (*d)->failure = static_cast<C2SettingResult::Failure>(s.failureOther);
    }

    // field
    c2_status_t status = objcpy(&(*d)->field, s.field);
    if (status != C2_OK) {
        return status;
    }

    // conflicts
    (*d)->conflicts.clear();
    (*d)->conflicts.reserve(s.conflicts.size());
    for (const ParamFieldValues& sConflict : s.conflicts) {
        (*d)->conflicts.emplace_back(
                C2ParamFieldValues{ C2ParamFieldBuilder(), nullptr });
        status = objcpy(&(*d)->conflicts.back(), sConflict);
        if (status != C2_OK) {
            return status;
        }
    }
    return C2_OK;
}

// C2ParamDescriptor -> ParamDescriptor
Status objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
    d->index = static_cast<ParamIndex>(s.index());
    d->attrib = static_cast<hidl_bitfield<ParamDescriptor::Attrib>>(
            _C2ParamInspector::GetAttrib(s));
    d->name = s.name();
    copyVector<uint32_t>(&d->dependencies, s.dependencies());
    return Status::OK;
}

// ParamDescriptor -> C2ParamDescriptor
c2_status_t objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
    std::vector<C2Param::Index> dDependencies;
    dDependencies.reserve(s.dependencies.size());
    for (const ParamIndex& sDependency : s.dependencies) {
        dDependencies.emplace_back(static_cast<uint32_t>(sDependency));
    }
    *d = std::make_shared<C2ParamDescriptor>(
            C2Param::Index(static_cast<uint32_t>(s.index)),
            static_cast<C2ParamDescriptor::attrib_t>(s.attrib),
            C2String(s.name.c_str()),
            std::move(dDependencies));
    return C2_OK;
}

// C2StructDescriptor -> StructDescriptor
Status objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
    d->type = static_cast<ParamIndex>(s.coreIndex().coreIndex());
    d->fields.resize(s.numFields());
    size_t i = 0;
    for (const auto& sField : s) {
        FieldDescriptor& dField = d->fields[i++];
        dField.fieldId.offset = static_cast<uint32_t>(
                _C2ParamInspector::GetOffset(sField));
        dField.fieldId.size = static_cast<uint32_t>(
                _C2ParamInspector::GetSize(sField));
        dField.type = static_cast<hidl_bitfield<FieldDescriptor::Type>>(
                sField.type());
        dField.length = static_cast<uint32_t>(sField.extent());
        dField.name = static_cast<hidl_string>(sField.name());
        const auto& sNamedValues = sField.namedValues();
        dField.namedValues.resize(sNamedValues.size());
        size_t j = 0;
        for (const auto& sNamedValue : sNamedValues) {
            FieldDescriptor::NamedValue& dNamedValue = dField.namedValues[j++];
            dNamedValue.name = static_cast<hidl_string>(sNamedValue.first);
            dNamedValue.value = static_cast<PrimitiveValue>(
                    sNamedValue.second.u64);
        }
    }
    return Status::OK;
}

// StructDescriptor -> C2StructDescriptor
c2_status_t objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
    C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type));
    std::vector<C2FieldDescriptor> dFields;
    dFields.reserve(s.fields.size());
    for (const auto &sField : s.fields) {
        C2FieldDescriptor dField = {
            static_cast<uint32_t>(sField.type),
            sField.length,
            sField.name,
            sField.fieldId.offset,
            sField.fieldId.size };
        C2FieldDescriptor::NamedValuesType namedValues;
        namedValues.reserve(sField.namedValues.size());
        for (const auto& sNamedValue : sField.namedValues) {
            namedValues.emplace_back(
                sNamedValue.name,
                C2Value::Primitive(static_cast<uint64_t>(sNamedValue.value)));
        }
        _C2ParamInspector::AddNamedValues(dField, std::move(namedValues));
        dFields.emplace_back(dField);
    }
    *d = std::make_unique<C2StructDescriptor>(
            _C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields)));
    return C2_OK;
}

namespace /* unnamed */ {

// Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
// associated map.
// Note: The handle is not cloned.
Status _addBaseBlock(
        uint32_t* index,
        const C2Handle* handle,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    if (!handle) {
        ALOGE("addBaseBlock called on a null C2Handle.");
        return Status::BAD_VALUE;
    }
    auto it = baseBlockIndices->find(handle);
    if (it != baseBlockIndices->end()) {
        *index = it->second;
    } else {
        *index = baseBlocks->size();
        baseBlockIndices->emplace(handle, *index);
        baseBlocks->emplace_back();

        BaseBlock &dBaseBlock = baseBlocks->back();
        dBaseBlock.type = BaseBlock::Type::NATIVE;
        // This does not clone the handle.
        dBaseBlock.nativeBlock =
                reinterpret_cast<const native_handle_t*>(handle);

    }
    return Status::OK;
}

// Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
// an associated map.
Status _addBaseBlock(
        uint32_t* index,
        const std::shared_ptr<BufferPoolData> bpData,
        BufferPoolSender* bufferPoolSender,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    if (!bpData) {
        ALOGE("addBaseBlock called on a null BufferPoolData.");
        return Status::BAD_VALUE;
    }
    auto it = baseBlockIndices->find(bpData.get());
    if (it != baseBlockIndices->end()) {
        *index = it->second;
    } else if (!bufferPoolSender) {
        ALOGE("No access to the receiver's BufferPool.");
        return Status::BAD_VALUE;
    } else {
        *index = baseBlocks->size();
        baseBlockIndices->emplace(bpData.get(), *index);
        baseBlocks->emplace_back();

        BaseBlock &dBaseBlock = baseBlocks->back();
        dBaseBlock.type = BaseBlock::Type::POOLED;
        ResultStatus bpStatus = bufferPoolSender->send(
                bpData,
                &dBaseBlock.pooledBlock);

        if (bpStatus != ResultStatus::OK) {
            ALOGE("Failed to send buffer with BufferPool. Error: %d.",
                    static_cast<int>(bpStatus));
            return Status::BAD_VALUE;
        }

    }
    return Status::OK;
}

Status addBaseBlock(
        uint32_t* index,
        const C2Handle* handle,
        const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
        BufferPoolSender* bufferPoolSender,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    if (!blockPoolData) {
        // No BufferPoolData ==> NATIVE block.
        return _addBaseBlock(
                index, handle,
                baseBlocks, baseBlockIndices);
    }
    switch (blockPoolData->getType()) {
    case _C2BlockPoolData::TYPE_BUFFERPOOL: {
            // BufferPoolData
            std::shared_ptr<BufferPoolData> bpData;
            if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
                    || !bpData) {
                ALOGE("BufferPoolData unavailable in a block.");
                return Status::BAD_VALUE;
            }
            return _addBaseBlock(
                    index, bpData,
                    bufferPoolSender, baseBlocks, baseBlockIndices);
        }
    case _C2BlockPoolData::TYPE_BUFFERQUEUE:
        // Do the same thing as a NATIVE block.
        return _addBaseBlock(
                index, handle,
                baseBlocks, baseBlockIndices);
    default:
        ALOGE("Unknown C2BlockPoolData type.");
        return Status::BAD_VALUE;
    }
}

// C2Fence -> hidl_handle
// Note: File descriptors are not duplicated. The original file descriptor must
// not be closed before the transaction is complete.
Status objcpy(hidl_handle* d, const C2Fence& s) {
    (void)s; // TODO: implement s.fd()
    int fenceFd = -1;
    d->setTo(nullptr);
    if (fenceFd >= 0) {
        native_handle_t *handle = native_handle_create(1, 0);
        if (!handle) {
            return Status::NO_MEMORY;
        }
        handle->data[0] = fenceFd;
        d->setTo(handle, true /* owns */);
    }
    return Status::OK;
}

// C2ConstLinearBlock -> Block
// Note: Native handles are not duplicated. The original handles must not be
// closed before the transaction is complete.
Status objcpy(Block* d, const C2ConstLinearBlock& s,
        BufferPoolSender* bufferPoolSender,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    std::shared_ptr<const _C2BlockPoolData> bpData =
            _C2BlockFactory::GetLinearBlockPoolData(s);
    Status status = addBaseBlock(&d->index, s.handle(), bpData,
            bufferPoolSender, baseBlocks, baseBlockIndices);
    if (status != Status::OK) {
        return status;
    }

    // Create the metadata.
    C2Hidl_RangeInfo dRangeInfo;
    dRangeInfo.offset = static_cast<uint32_t>(s.offset());
    dRangeInfo.length = static_cast<uint32_t>(s.size());
    status = createParamsBlob(&d->meta,
            std::vector<C2Param*>{ &dRangeInfo });
    if (status != Status::OK) {
        return Status::BAD_VALUE;
    }

    // Copy the fence
    return objcpy(&d->fence, s.fence());
}

// C2ConstGraphicBlock -> Block
// Note: Native handles are not duplicated. The original handles must not be
// closed before the transaction is complete.
Status objcpy(Block* d, const C2ConstGraphicBlock& s,
        BufferPoolSender* bufferPoolSender,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    std::shared_ptr<const _C2BlockPoolData> bpData =
            _C2BlockFactory::GetGraphicBlockPoolData(s);
    Status status = addBaseBlock(&d->index, s.handle(), bpData,
            bufferPoolSender, baseBlocks, baseBlockIndices);

    // Create the metadata.
    C2Hidl_RectInfo dRectInfo;
    C2Rect sRect = s.crop();
    dRectInfo.left = static_cast<uint32_t>(sRect.left);
    dRectInfo.top = static_cast<uint32_t>(sRect.top);
    dRectInfo.width = static_cast<uint32_t>(sRect.width);
    dRectInfo.height = static_cast<uint32_t>(sRect.height);
    status = createParamsBlob(&d->meta,
            std::vector<C2Param*>{ &dRectInfo });
    if (status != Status::OK) {
        return Status::BAD_VALUE;
    }

    // Copy the fence
    return objcpy(&d->fence, s.fence());
}

// C2BufferData -> Buffer
// This function only fills in d->blocks.
Status objcpy(Buffer* d, const C2BufferData& s,
        BufferPoolSender* bufferPoolSender,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    Status status;
    d->blocks.resize(
            s.linearBlocks().size() +
            s.graphicBlocks().size());
    size_t i = 0;
    for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
        Block& dBlock = d->blocks[i++];
        status = objcpy(
                &dBlock, linearBlock,
                bufferPoolSender, baseBlocks, baseBlockIndices);
        if (status != Status::OK) {
            return status;
        }
    }
    for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
        Block& dBlock = d->blocks[i++];
        status = objcpy(
                &dBlock, graphicBlock,
                bufferPoolSender, baseBlocks, baseBlockIndices);
        if (status != Status::OK) {
            return status;
        }
    }
    return Status::OK;
}

// C2Buffer -> Buffer
Status objcpy(Buffer* d, const C2Buffer& s,
        BufferPoolSender* bufferPoolSender,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    Status status = createParamsBlob(&d->info, s.info());
    if (status != Status::OK) {
        return status;
    }
    return objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices);
}

// C2InfoBuffer -> InfoBuffer
Status objcpy(InfoBuffer* d, const C2InfoBuffer& s,
        BufferPoolSender* bufferPoolSender,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    // TODO: C2InfoBuffer is not implemented.
    (void)d;
    (void)s;
    (void)bufferPoolSender;
    (void)baseBlocks;
    (void)baseBlockIndices;
    return Status::OK;
    /*
    // Stub implementation that may work in the future.
    d->index = static_cast<uint32_t>(s.index());
    d->buffer.info.resize(0);
    return objcpy(&d->buffer, s.data(), baseBlocks, baseBlockIndices);
    */
}

// C2FrameData -> FrameData
Status objcpy(FrameData* d, const C2FrameData& s,
        BufferPoolSender* bufferPoolSender,
        std::list<BaseBlock>* baseBlocks,
        std::map<const void*, uint32_t>* baseBlockIndices) {
    d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
    objcpy(&d->ordinal, s.ordinal);

    Status status;
    d->buffers.resize(s.buffers.size());
    size_t i = 0;
    for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
        Buffer& dBuffer = d->buffers[i++];
        if (!sBuffer) {
            // A null (pointer to) C2Buffer corresponds to a Buffer with empty
            // info and blocks.
            dBuffer.info.resize(0);
            dBuffer.blocks.resize(0);
            continue;
        }
        status = objcpy(
                &dBuffer, *sBuffer,
                bufferPoolSender, baseBlocks, baseBlockIndices);
        if (status != Status::OK) {
            return status;
        }
    }

    status = createParamsBlob(&d->configUpdate, s.configUpdate);
    if (status != Status::OK) {
        return status;
    }

    d->infoBuffers.resize(s.infoBuffers.size());
    i = 0;
    for (const std::shared_ptr<C2InfoBuffer>& sInfoBuffer : s.infoBuffers) {
        InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
        if (!sInfoBuffer) {
            ALOGE("Null C2InfoBuffer");
            return Status::BAD_VALUE;
        }
        status = objcpy(&dInfoBuffer, *sInfoBuffer,
                bufferPoolSender, baseBlocks, baseBlockIndices);
        if (status != Status::OK) {
            return status;
        }
    }

    return status;
}

} // unnamed namespace

// DefaultBufferPoolSender's implementation

DefaultBufferPoolSender::DefaultBufferPoolSender(
        const sp<IClientManager>& receiverManager) :
    mReceiverManager(receiverManager), mSourceConnectionId(0) {
}

void DefaultBufferPoolSender::setReceiver(const sp<IClientManager>& receiverManager) {
    std::lock_guard<std::mutex> lock(mMutex);
    if (mReceiverManager != receiverManager) {
        mReceiverManager = receiverManager;
    }
}

ResultStatus DefaultBufferPoolSender::send(
        const std::shared_ptr<BufferPoolData>& bpData,
        BufferStatusMessage* bpMessage) {
    if (!mReceiverManager) {
        ALOGE("No access to receiver's BufferPool.");
        return ResultStatus::NOT_FOUND;
    }
    ResultStatus rs;
    std::lock_guard<std::mutex> lock(mMutex);
    if (!mSenderManager) {
        mSenderManager = ClientManager::getInstance();
        if (!mSenderManager) {
            ALOGE("Failed to retrieve local BufferPool ClientManager.");
            return ResultStatus::CRITICAL_ERROR;
        }
    }
    int64_t connectionId = bpData->mConnectionId;
    if (mSourceConnectionId == 0 || mSourceConnectionId != connectionId) {
        // Initialize the bufferpool connection.
        mSourceConnectionId = connectionId;
        if (mSourceConnectionId == 0) {
            return ResultStatus::CRITICAL_ERROR;
        }
        int64_t receiverConnectionId;
        rs = mSenderManager->registerSender(mReceiverManager, connectionId, &receiverConnectionId);
        if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
            ALOGW("registerSender -- returned error: %d.",
                    static_cast<int>(rs));
            return rs;
        } else {
            mReceiverConnectionId = receiverConnectionId;
        }
    }

    uint64_t transactionId;
    int64_t timestampUs;
    rs = mSenderManager->postSend(
            mReceiverConnectionId, bpData, &transactionId, &timestampUs);
    if (rs != ResultStatus::OK) {
        ALOGE("ClientManager::postSend -- returned error: %d.",
                static_cast<int>(rs));
        return rs;
    }
    if (!bpMessage) {
        ALOGE("Null output parameter for BufferStatusMessage.");
        return ResultStatus::CRITICAL_ERROR;
    }
    bpMessage->connectionId = mReceiverConnectionId;
    bpMessage->bufferId = bpData->mId;
    bpMessage->transactionId = transactionId;
    bpMessage->timestampUs = timestampUs;
    return rs;
}

// std::list<std::unique_ptr<C2Work>> -> WorkBundle
Status objcpy(WorkBundle* d, const std::list<std::unique_ptr<C2Work>>& s,
        BufferPoolSender* bufferPoolSender) {
    Status status = Status::OK;

    // baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
    std::list<BaseBlock> baseBlocks;

    // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
    // inside baseBlocks to the corresponding index into baseBlocks. The keys
    // (pointers) are used to identify blocks that have the same "base block" in
    // s, a list of C2Work objects. Because baseBlocks will be copied into a
    // hidl_vec eventually, the values of baseBlockIndices are zero-based
    // integer indices instead of list iterators.
    //
    // Note that the pointers can be raw because baseBlockIndices has a shorter
    // lifespan than all of base blocks.
    std::map<const void*, uint32_t> baseBlockIndices;

    d->works.resize(s.size());
    size_t i = 0;
    for (const std::unique_ptr<C2Work>& sWork : s) {
        Work &dWork = d->works[i++];
        if (!sWork) {
            ALOGW("Null C2Work encountered.");
            continue;
        }
        status = objcpy(&dWork.input, sWork->input,
                bufferPoolSender, &baseBlocks, &baseBlockIndices);
        if (status != Status::OK) {
            return status;
        }
        if (sWork->worklets.size() == 0) {
            ALOGW("Work with no worklets.");
        } else {
            if (sWork->worklets.size() > 1) {
                ALOGW("Work with multiple worklets. "
                        "Only the first worklet will be marshalled.");
            }
            if (!sWork->worklets.front()) {
                ALOGE("Null worklet encountered.");
                return Status::BAD_VALUE;
            }

            // Parcel the first worklet.
            const C2Worklet &sWorklet = *sWork->worklets.front();
            Worklet &dWorklet = dWork.worklet;

            dWorklet.tunings.resize(sWorklet.tunings.size());
            size_t j = 0;
            for (const std::unique_ptr<C2Tuning>& sTuning : sWorklet.tunings) {
                status = createParamsBlob(
                        &dWorklet.tunings[j++],
                        std::vector<C2Param*>
                        { reinterpret_cast<C2Param*>(sTuning.get()) });
                if (status != Status::OK) {
                    return status;
                }
            }

            dWorklet.failures.resize(sWorklet.failures.size());
            j = 0;
            for (const std::unique_ptr<C2SettingResult>& sFailure :
                    sWorklet.failures) {
                if (!sFailure) {
                    ALOGE("Null C2SettingResult");
                    return Status::BAD_VALUE;
                }
                status = objcpy(&dWorklet.failures[j++], *sFailure);
                if (status != Status::OK) {
                    return status;
                }
            }

            status = objcpy(&dWorklet.output, sWorklet.output,
                    bufferPoolSender, &baseBlocks, &baseBlockIndices);
            if (status != Status::OK) {
                return status;
            }
        }
        dWork.workletProcessed = sWork->workletsProcessed > 0;
        dWork.result = static_cast<Status>(sWork->result);
    }

    // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
    {
        d->baseBlocks.resize(baseBlocks.size());
        size_t i = 0;
        for (const BaseBlock& baseBlock : baseBlocks) {
            d->baseBlocks[i++] = baseBlock;
        }
    }

    return Status::OK;
}

namespace /* unnamed */ {

struct C2BaseBlock {
    enum type_t {
        LINEAR,
        GRAPHIC,
    };
    type_t type;
    std::shared_ptr<C2LinearBlock> linear;
    std::shared_ptr<C2GraphicBlock> graphic;
};

// hidl_handle -> C2Fence
// Note: File descriptors are not duplicated. The original file descriptor must
// not be closed before the transaction is complete.
c2_status_t objcpy(C2Fence* d, const hidl_handle& s) {
    // TODO: Implement.
    (void)s;
    *d = C2Fence();
    return C2_OK;
}

// C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
c2_status_t createLinearBuffer(
        std::shared_ptr<C2Buffer>* buffer,
        const std::shared_ptr<C2LinearBlock>& block,
        const std::vector<C2Param*>& meta,
        const C2Fence& fence) {
    // Check the block meta. It should have exactly 1 C2Info:
    // C2Hidl_RangeInfo.
    if ((meta.size() != 1) || !meta[0]) {
        ALOGE("Invalid block metadata for ion block.");
        return C2_BAD_VALUE;
    }
    if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
        ALOGE("Invalid block metadata for ion block: range.");
        return C2_BAD_VALUE;
    }
    C2Hidl_RangeInfo *rangeInfo =
            reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);

    // Create C2Buffer from C2LinearBlock.
    *buffer = C2Buffer::CreateLinearBuffer(block->share(
            rangeInfo->offset, rangeInfo->length,
            fence));
    if (!(*buffer)) {
        ALOGE("Cannot create a linear buffer.");
        return C2_BAD_VALUE;
    }
    return C2_OK;
}

// C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
c2_status_t createGraphicBuffer(
        std::shared_ptr<C2Buffer>* buffer,
        const std::shared_ptr<C2GraphicBlock>& block,
        const std::vector<C2Param*>& meta,
        const C2Fence& fence) {
    // Check the block meta. It should have exactly 1 C2Info:
    // C2Hidl_RectInfo.
    if ((meta.size() != 1) || !meta[0]) {
        ALOGE("Invalid block metadata for graphic block.");
        return C2_BAD_VALUE;
    }
    if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
        ALOGE("Invalid block metadata for graphic block: crop rect.");
        return C2_BAD_VALUE;
    }
    C2Hidl_RectInfo *rectInfo =
            reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);

    // Create C2Buffer from C2GraphicBlock.
    *buffer = C2Buffer::CreateGraphicBuffer(block->share(
            C2Rect(rectInfo->width, rectInfo->height).
            at(rectInfo->left, rectInfo->top),
            fence));
    if (!(*buffer)) {
        ALOGE("Cannot create a graphic buffer.");
        return C2_BAD_VALUE;
    }
    return C2_OK;
}

// Buffer -> C2Buffer
// Note: The native handles will be cloned.
c2_status_t objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
        const std::vector<C2BaseBlock>& baseBlocks) {
    c2_status_t status;
    *d = nullptr;

    // Currently, a non-null C2Buffer must contain exactly 1 block.
    if (s.blocks.size() == 0) {
        return C2_OK;
    } else if (s.blocks.size() != 1) {
        ALOGE("Currently, a C2Buffer must contain exactly 1 block.");
        return C2_BAD_VALUE;
    }

    const Block &sBlock = s.blocks[0];
    if (sBlock.index >= baseBlocks.size()) {
        ALOGE("Index into baseBlocks is out of range.");
        return C2_BAD_VALUE;
    }
    const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];

    // Parse meta.
    std::vector<C2Param*> sBlockMeta;
    status = parseParamsBlob(&sBlockMeta, sBlock.meta);
    if (status != C2_OK) {
        ALOGE("Invalid block params blob.");
        return C2_BAD_VALUE;
    }

    // Copy fence.
    C2Fence dFence;
    status = objcpy(&dFence, sBlock.fence);

    // Construct a block.
    switch (baseBlock.type) {
    case C2BaseBlock::LINEAR:
        status = createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence);
        break;
    case C2BaseBlock::GRAPHIC:
        status = createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence);
        break;
    default:
        ALOGE("Invalid BaseBlock type.");
        return C2_BAD_VALUE;
    }
    if (status != C2_OK) {
        return status;
    }

    // Parse info
    std::vector<C2Param*> params;
    status = parseParamsBlob(&params, s.info);
    if (status != C2_OK) {
        ALOGE("Invalid buffer params blob.");
        return status;
    }
    for (C2Param* param : params) {
        if (param == nullptr) {
            ALOGE("Null buffer param encountered.");
            return C2_BAD_VALUE;
        }
        std::shared_ptr<C2Param> c2param(
                C2Param::Copy(*param).release());
        if (!c2param) {
            ALOGE("Invalid buffer param inside a blob.");
            return C2_BAD_VALUE;
        }
        status = (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
        if (status != C2_OK) {
            ALOGE("C2Buffer::setInfo failed().");
            return C2_BAD_VALUE;
        }
    }

    return C2_OK;
}

// FrameData -> C2FrameData
c2_status_t objcpy(C2FrameData* d, const FrameData& s,
        const std::vector<C2BaseBlock>& baseBlocks) {
    c2_status_t status;
    d->flags = static_cast<C2FrameData::flags_t>(s.flags);
    objcpy(&d->ordinal, s.ordinal);
    d->buffers.clear();
    d->buffers.reserve(s.buffers.size());
    for (const Buffer& sBuffer : s.buffers) {
        std::shared_ptr<C2Buffer> dBuffer;
        status = objcpy(&dBuffer, sBuffer, baseBlocks);
        if (status != C2_OK) {
            return status;
        }
        d->buffers.emplace_back(dBuffer);
    }

    std::vector<C2Param*> params;
    status = parseParamsBlob(&params, s.configUpdate);
    if (status != C2_OK) {
        ALOGE("Failed to parse frame data params.");
        return status;
    }
    d->configUpdate.clear();
    for (C2Param* param : params) {
        d->configUpdate.emplace_back(C2Param::Copy(*param));
        if (!d->configUpdate.back()) {
            ALOGE("Unexpected error while parsing frame data params.");
            return C2_BAD_VALUE;
        }
    }

    // TODO: Implement this once C2InfoBuffer has constructors.
    d->infoBuffers.clear();
    return C2_OK;
}

// BaseBlock -> C2BaseBlock
c2_status_t objcpy(C2BaseBlock* d, const BaseBlock& s) {
    switch (s.type) {
    case BaseBlock::Type::NATIVE: {
            native_handle_t* sHandle =
                    native_handle_clone(s.nativeBlock);
            if (sHandle == nullptr) {
                ALOGE("Null native handle in a block.");
                return C2_BAD_VALUE;
            }
            const C2Handle *sC2Handle =
                    reinterpret_cast<const C2Handle*>(sHandle);

            d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
            if (d->linear) {
                d->type = C2BaseBlock::LINEAR;
                return C2_OK;
            }

            d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
            if (d->graphic) {
                d->type = C2BaseBlock::GRAPHIC;
                return C2_OK;
            }

            ALOGE("Unknown handle type in native BaseBlock.");
            if (sHandle) {
                native_handle_close(sHandle);
                native_handle_delete(sHandle);
            }
            return C2_BAD_VALUE;
        }
    case BaseBlock::Type::POOLED: {
            const BufferStatusMessage &bpMessage =
                    s.pooledBlock;
            sp<ClientManager> bp = ClientManager::getInstance();
            std::shared_ptr<BufferPoolData> bpData;
            native_handle_t *cHandle;
            ResultStatus bpStatus = bp->receive(
                    bpMessage.connectionId,
                    bpMessage.transactionId,
                    bpMessage.bufferId,
                    bpMessage.timestampUs,
                    &cHandle,
                    &bpData);
            if (bpStatus != ResultStatus::OK) {
                ALOGE("Failed to receive buffer from bufferpool -- "
                        "resultStatus = %d",
                        static_cast<int>(bpStatus));
                return toC2Status(bpStatus);
            } else if (!bpData) {
                ALOGE("No data in bufferpool transaction.");
                return C2_BAD_VALUE;
            }

            d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
            if (d->linear) {
                d->type = C2BaseBlock::LINEAR;
                return C2_OK;
            }

            d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
            if (d->graphic) {
                d->type = C2BaseBlock::GRAPHIC;
                return C2_OK;
            }

            ALOGE("Unknown handle type in pooled BaseBlock.");
            return C2_BAD_VALUE;
        }
    default:
        ALOGE("Corrupted BaseBlock type: %d", static_cast<int>(s.type));
        return C2_BAD_VALUE;
    }
}

} // unnamed namespace

// WorkBundle -> std::list<std::unique_ptr<C2Work>>
c2_status_t objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
    c2_status_t status;

    // Convert BaseBlocks to C2BaseBlocks.
    std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
    for (size_t i = 0; i < s.baseBlocks.size(); ++i) {
        status = objcpy(&dBaseBlocks[i], s.baseBlocks[i]);
        if (status != C2_OK) {
            return status;
        }
    }

    d->clear();
    for (const Work& sWork : s.works) {
        d->emplace_back(std::make_unique<C2Work>());
        C2Work& dWork = *d->back();

        // input
        status = objcpy(&dWork.input, sWork.input, dBaseBlocks);
        if (status != C2_OK) {
            ALOGE("Error constructing C2Work's input.");
            return C2_BAD_VALUE;
        }

        // worklet(s)
        dWork.worklets.clear();
        // TODO: Currently, tunneling is not supported.
        if (sWork.workletProcessed) {
            dWork.workletsProcessed = 1;

            const Worklet &sWorklet = sWork.worklet;
            std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();

            // tunings
            dWorklet->tunings.clear();
            dWorklet->tunings.reserve(sWorklet.tunings.size());
            for (const Params& sTuning : sWorklet.tunings) {
                std::vector<C2Param*> dParams;
                status = parseParamsBlob(&dParams, sTuning);
                if (status != C2_OK) {
                    ALOGE("Failed to parse C2Tuning in C2Worklet.");
                    return C2_BAD_VALUE;
                }
                for (C2Param* param : dParams) {
                    std::unique_ptr<C2Param> dParam = C2Param::Copy(*param);
                    if (!dParam) {
                        ALOGE("Null C2Tuning encountered while "
                                "parsing C2Worklet.");
                        return C2_BAD_VALUE;
                    }
                    dWorklet->tunings.emplace_back(
                            std::unique_ptr<C2Tuning>(
                            reinterpret_cast<C2Tuning*>(
                            dParam.release())));
                }
            }
            // failures
            dWorklet->failures.clear();
            dWorklet->failures.reserve(sWorklet.failures.size());
            for (const SettingResult& sFailure : sWorklet.failures) {
                std::unique_ptr<C2SettingResult> dFailure;
                status = objcpy(&dFailure, sFailure);
                if (status != C2_OK) {
                    ALOGE("Failed to create C2SettingResult in C2Worklet.");
                    return C2_BAD_VALUE;
                }
                dWorklet->failures.emplace_back(std::move(dFailure));
            }
            // output
            status = objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks);
            if (status != C2_OK) {
                ALOGE("Failed to create output C2FrameData.");
                return C2_BAD_VALUE;
            }
            dWork.worklets.emplace_back(std::move(dWorklet));
        } else {
            dWork.worklets.emplace_back(std::make_unique<C2Worklet>());
            dWork.workletsProcessed = 0;
        }

        // result
        dWork.result = static_cast<c2_status_t>(sWork.result);
    }

    return C2_OK;
}

constexpr size_t PARAMS_ALIGNMENT = 8;  // 64-bit alignment
static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch");
static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch");
static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");

// Params -> std::vector<C2Param*>
c2_status_t parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
    // assuming blob is const here
    size_t size = blob.size();
    size_t ix = 0;
    const uint8_t *data = blob.data();
    C2Param *p = nullptr;

    do {
        p = C2ParamUtils::ParseFirst(data + ix, size - ix);
        if (p) {
            params->emplace_back(p);
            ix += p->size();
            ix = align(ix, PARAMS_ALIGNMENT);
        }
    } while (p);

    return ix == size ? C2_OK : C2_BAD_VALUE;
}

namespace /* unnamed */ {

/**
 * Concatenates a list of C2Params into a params blob.
 * \param[out] blob target blob
 * \param[in] params parameters to concatenate
 * \retval C2_OK if the blob was successfully created
 * \retval C2_BAD_VALUE if the blob was not successful (this only happens if the parameters were
 *         not const)
 */
template<typename T>
Status _createParamsBlob(hidl_vec<uint8_t> *blob, const T &params) {
    // assuming the parameter values are const
    size_t size = 0;
    for (const auto &p : params) {
        if (!p) {
            continue;
        }
        size += p->size();
        size = align(size, PARAMS_ALIGNMENT);
    }
    blob->resize(size);
    size_t ix = 0;
    for (const auto &p : params) {
        if (!p) {
            continue;
        }
        // NEVER overwrite even if param values (e.g. size) changed
        size_t paramSize = std::min(p->size(), size - ix);
        std::copy(
                reinterpret_cast<const uint8_t*>(&*p),
                reinterpret_cast<const uint8_t*>(&*p) + paramSize,
                &(*blob)[ix]);
        ix += paramSize;
        ix = align(ix, PARAMS_ALIGNMENT);
    }
    blob->resize(ix);
    return ix == size ? Status::OK : Status::CORRUPTED;
}

} // unnamed namespace

// std::vector<const C2Param*> -> Params
Status createParamsBlob(
        hidl_vec<uint8_t> *blob,
        const std::vector<const C2Param*> &params) {
    return _createParamsBlob(blob, params);
}

// std::vector<C2Param*> -> Params
Status createParamsBlob(
        hidl_vec<uint8_t> *blob,
        const std::vector<C2Param*> &params) {
    return _createParamsBlob(blob, params);
}

// std::vector<std::unique_ptr<C2Param>> -> Params
Status createParamsBlob(
        hidl_vec<uint8_t> *blob,
        const std::vector<std::unique_ptr<C2Param>> &params) {
    return _createParamsBlob(blob, params);
}

// std::vector<std::unique_ptr<C2Tuning>> -> Params
Status createParamsBlob(
        hidl_vec<uint8_t> *blob,
        const std::vector<std::unique_ptr<C2Tuning>> &params) {
    return _createParamsBlob(blob, params);
}

// std::vector<std::shared_ptr<const C2Info>> -> Params
Status createParamsBlob(
        hidl_vec<uint8_t> *blob,
        const std::vector<std::shared_ptr<const C2Info>> &params) {
    return _createParamsBlob(blob, params);
}

// Params -> std::vector<std::unique_ptr<C2Param>>
c2_status_t copyParamsFromBlob(
        std::vector<std::unique_ptr<C2Param>>* params,
        Params blob) {
    std::vector<C2Param*> paramPointers;
    c2_status_t status = parseParamsBlob(&paramPointers, blob);
    if (status != C2_OK) {
        ALOGE("copyParamsFromBlob -- blob parsing failed.");
        return status;
    }
    params->resize(paramPointers.size());
    size_t i = 0;
    for (C2Param* const& paramPointer : paramPointers) {
        if (!paramPointer) {
            ALOGE("copyParamsFromBlob -- corrupted params blob.");
            return C2_BAD_VALUE;
        }
        (*params)[i++] = C2Param::Copy(*paramPointer);
    }
    return C2_OK;
}

// Params -> update std::vector<std::unique_ptr<C2Param>>
c2_status_t updateParamsFromBlob(
        const std::vector<C2Param*>& params,
        const Params& blob) {
    std::unordered_map<uint32_t, C2Param*> index2param;
    for (C2Param* const& param : params) {
        if (!param) {
            ALOGE("updateParamsFromBlob -- corrupted input params.");
            return C2_BAD_VALUE;
        }
        if (index2param.find(param->index()) == index2param.end()) {
            index2param.emplace(param->index(), param);
        }
    }

    std::vector<C2Param*> paramPointers;
    c2_status_t status = parseParamsBlob(&paramPointers, blob);
    if (status != C2_OK) {
        ALOGE("updateParamsFromBlob -- blob parsing failed.");
        return status;
    }

    for (C2Param* const& paramPointer : paramPointers) {
        if (!paramPointer) {
            ALOGE("updateParamsFromBlob -- corrupted param in blob.");
            return C2_BAD_VALUE;
        }
        decltype(index2param)::iterator i = index2param.find(
                paramPointer->index());
        if (i == index2param.end()) {
            ALOGW("updateParamsFromBlob -- unseen param index.");
            continue;
        }
        if (!i->second->updateFrom(*paramPointer)) {
            ALOGE("updateParamsFromBlob -- mismatching sizes: "
                    "%u vs %u (index = %u).",
                    static_cast<unsigned>(params.size()),
                    static_cast<unsigned>(paramPointer->size()),
                    static_cast<unsigned>(i->first));
            return C2_BAD_VALUE;
        }
    }
    return C2_OK;
}

// Convert BufferPool ResultStatus to c2_status_t.
c2_status_t toC2Status(ResultStatus rs) {
    switch (rs) {
    case ResultStatus::OK:
        return C2_OK;
    case ResultStatus::NO_MEMORY:
        return C2_NO_MEMORY;
    case ResultStatus::ALREADY_EXISTS:
        return C2_DUPLICATE;
    case ResultStatus::NOT_FOUND:
        return C2_NOT_FOUND;
    case ResultStatus::CRITICAL_ERROR:
        return C2_CORRUPTED;
    default:
        ALOGW("Unrecognized BufferPool ResultStatus: %d", static_cast<int>(rs));
        return C2_CORRUPTED;
    }
}

}  // namespace utils
}  // namespace V1_0
}  // namespace c2
}  // namespace media
}  // namespace google
}  // namespace hardware

