Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "Codec2-types"
     19 #include <log/log.h>
     20 
     21 #include <codec2/hidl/1.0/types.h>
     22 
     23 #include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
     24 
     25 #include <C2AllocatorIon.h>
     26 #include <C2AllocatorGralloc.h>
     27 #include <C2BlockInternal.h>
     28 #include <C2Buffer.h>
     29 #include <C2Component.h>
     30 #include <C2Param.h>
     31 #include <C2ParamInternal.h>
     32 #include <C2PlatformSupport.h>
     33 #include <C2Work.h>
     34 #include <util/C2ParamUtils.h>
     35 
     36 #include <algorithm>
     37 #include <functional>
     38 #include <unordered_map>
     39 
     40 #include <media/stagefright/foundation/AUtils.h>
     41 
     42 namespace hardware {
     43 namespace google {
     44 namespace media {
     45 namespace c2 {
     46 namespace V1_0 {
     47 namespace utils {
     48 
     49 using namespace ::android;
     50 using ::android::hardware::Return;
     51 using ::android::hardware::media::bufferpool::BufferPoolData;
     52 using ::android::hardware::media::bufferpool::V1_0::BufferStatusMessage;
     53 using ::android::hardware::media::bufferpool::V1_0::ResultStatus;
     54 using ::android::hardware::media::bufferpool::V1_0::implementation::
     55         ClientManager;
     56 using ::android::hardware::media::bufferpool::V1_0::implementation::
     57         TransactionId;
     58 using ::android::TWGraphicBufferProducer;
     59 
     60 namespace /* unnamed */ {
     61 
     62 template <typename Common, typename DstVector, typename SrcVector>
     63 void copyVector(DstVector* d, const SrcVector& s) {
     64     static_assert(sizeof(Common) == sizeof(decltype((*d)[0])),
     65             "DstVector's component size does not match Common");
     66     static_assert(sizeof(Common) == sizeof(decltype(s[0])),
     67             "SrcVector's component size does not match Common");
     68     d->resize(s.size());
     69     std::copy(
     70             reinterpret_cast<const Common*>(&s[0]),
     71             reinterpret_cast<const Common*>(&s[0] + s.size()),
     72             reinterpret_cast<Common*>(&(*d)[0]));
     73 }
     74 
     75 // C2ParamField -> ParamField
     76 void objcpy(ParamField *d, const C2ParamField &s) {
     77     d->index = static_cast<ParamIndex>(_C2ParamInspector::GetIndex(s));
     78     d->fieldId.offset = static_cast<uint32_t>(_C2ParamInspector::GetOffset(s));
     79     d->fieldId.size = static_cast<uint32_t>(_C2ParamInspector::GetSize(s));
     80 }
     81 
     82 struct C2ParamFieldBuilder : public C2ParamField {
     83     C2ParamFieldBuilder() : C2ParamField(
     84             static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) {
     85     }
     86     // ParamField -> C2ParamField
     87     C2ParamFieldBuilder(const ParamField& s) : C2ParamField(
     88             static_cast<C2Param::Index>(static_cast<uint32_t>(s.index)),
     89             static_cast<uint32_t>(s.fieldId.offset),
     90             static_cast<uint32_t>(s.fieldId.size)) {
     91     }
     92 };
     93 
     94 // C2WorkOrdinalStruct -> WorkOrdinal
     95 void objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
     96     d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku());
     97     d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku());
     98     d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku());
     99 }
    100 
    101 // WorkOrdinal -> C2WorkOrdinalStruct
    102 void objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) {
    103     d->frameIndex = c2_cntr64_t(s.frameIndex);
    104     d->timestamp = c2_cntr64_t(s.timestampUs);
    105     d->customOrdinal = c2_cntr64_t(s.customOrdinal);
    106 }
    107 
    108 // C2FieldSupportedValues::range's type -> FieldSupportedValues::Range
    109 void objcpy(
    110         FieldSupportedValues::Range* d,
    111         const decltype(C2FieldSupportedValues::range)& s) {
    112     d->min = static_cast<PrimitiveValue>(s.min.u64);
    113     d->max = static_cast<PrimitiveValue>(s.max.u64);
    114     d->step = static_cast<PrimitiveValue>(s.step.u64);
    115     d->num = static_cast<PrimitiveValue>(s.num.u64);
    116     d->denom = static_cast<PrimitiveValue>(s.denom.u64);
    117 }
    118 
    119 // C2FieldSupportedValues -> FieldSupportedValues
    120 Status objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
    121     d->typeOther = static_cast<int32_t>(s.type);
    122     switch (s.type) {
    123     case C2FieldSupportedValues::EMPTY:
    124         d->type = FieldSupportedValues::Type::EMPTY;
    125         d->values.resize(0);
    126         return Status::OK;
    127     case C2FieldSupportedValues::RANGE:
    128         d->type = FieldSupportedValues::Type::RANGE;
    129         objcpy(&d->range, s.range);
    130         d->values.resize(0);
    131         return Status::OK;
    132     default:
    133         switch (s.type) {
    134         case C2FieldSupportedValues::VALUES:
    135             d->type = FieldSupportedValues::Type::VALUES;
    136             break;
    137         case C2FieldSupportedValues::FLAGS:
    138             d->type = FieldSupportedValues::Type::FLAGS;
    139             break;
    140         default:
    141             d->type = FieldSupportedValues::Type::OTHER;
    142             // Copy all fields in this case
    143             objcpy(&d->range, s.range);
    144         }
    145         d->values.resize(s.values.size());
    146         copyVector<uint64_t>(&d->values, s.values);
    147         return Status::OK;
    148     }
    149 }
    150 
    151 // FieldSupportedValues::Range -> C2FieldSupportedValues::range's type
    152 void objcpy(
    153         decltype(C2FieldSupportedValues::range)* d,
    154         const FieldSupportedValues::Range& s) {
    155     d->min.u64 = static_cast<uint64_t>(s.min);
    156     d->max.u64 = static_cast<uint64_t>(s.max);
    157     d->step.u64 = static_cast<uint64_t>(s.step);
    158     d->num.u64 = static_cast<uint64_t>(s.num);
    159     d->denom.u64 = static_cast<uint64_t>(s.denom);
    160 }
    161 
    162 // FieldSupportedValues -> C2FieldSupportedValues
    163 c2_status_t objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
    164     switch (s.type) {
    165     case FieldSupportedValues::Type::EMPTY:
    166         d->type = C2FieldSupportedValues::EMPTY;
    167         return C2_OK;
    168     case FieldSupportedValues::Type::RANGE:
    169         d->type = C2FieldSupportedValues::RANGE;
    170         objcpy(&d->range, s.range);
    171         d->values.resize(0);
    172         return C2_OK;
    173     default:
    174         switch (s.type) {
    175         case FieldSupportedValues::Type::VALUES:
    176             d->type = C2FieldSupportedValues::VALUES;
    177             break;
    178         case FieldSupportedValues::Type::FLAGS:
    179             d->type = C2FieldSupportedValues::FLAGS;
    180             break;
    181         default:
    182             d->type = static_cast<C2FieldSupportedValues::type_t>(s.typeOther);
    183             // Copy all fields in this case
    184             objcpy(&d->range, s.range);
    185         }
    186         copyVector<uint64_t>(&d->values, s.values);
    187         return C2_OK;
    188     }
    189 }
    190 
    191 } // unnamed namespace
    192 
    193 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
    194 Status objcpy(
    195         FieldSupportedValuesQuery* d,
    196         const C2FieldSupportedValuesQuery& s) {
    197     objcpy(&d->field, s.field());
    198     switch (s.type()) {
    199     case C2FieldSupportedValuesQuery::POSSIBLE:
    200         d->type = FieldSupportedValuesQuery::Type::POSSIBLE;
    201         break;
    202     case C2FieldSupportedValuesQuery::CURRENT:
    203         d->type = FieldSupportedValuesQuery::Type::CURRENT;
    204         break;
    205     default:
    206         ALOGE("Unknown type of C2FieldSupportedValuesQuery: %u",
    207                 static_cast<unsigned>(s.type()));
    208         return Status::BAD_VALUE;
    209     }
    210     return Status::OK;
    211 }
    212 
    213 // FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
    214 c2_status_t objcpy(
    215         C2FieldSupportedValuesQuery* d,
    216         const FieldSupportedValuesQuery& s) {
    217     C2FieldSupportedValuesQuery::type_t dType;
    218     switch (s.type) {
    219     case FieldSupportedValuesQuery::Type::POSSIBLE:
    220         dType = C2FieldSupportedValuesQuery::POSSIBLE;
    221         break;
    222     case FieldSupportedValuesQuery::Type::CURRENT:
    223         dType = C2FieldSupportedValuesQuery::CURRENT;
    224         break;
    225     default:
    226         ALOGE("Unknown type of FieldSupportedValuesQuery: %u",
    227                 static_cast<unsigned>(s.type));
    228         return C2_BAD_VALUE;
    229     }
    230     *d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType);
    231     return C2_OK;
    232 }
    233 
    234 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
    235 Status objcpy(
    236         FieldSupportedValuesQueryResult* d,
    237         const C2FieldSupportedValuesQuery& s) {
    238     d->status = static_cast<Status>(s.status);
    239     return objcpy(&d->values, s.values);
    240 }
    241 
    242 // FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
    243 // C2FieldSupportedValuesQuery
    244 c2_status_t objcpy(
    245         C2FieldSupportedValuesQuery* d,
    246         const FieldSupportedValuesQuery& sq,
    247         const FieldSupportedValuesQueryResult& sr) {
    248     c2_status_t status = objcpy(d, sq);
    249     if (status != C2_OK) {
    250         return status;
    251     }
    252     d->status = static_cast<c2_status_t>(sr.status);
    253     return objcpy(&d->values, sr.values);
    254 }
    255 
    256 // C2Component::Traits -> IComponentStore::ComponentTraits
    257 Status objcpy(
    258         IComponentStore::ComponentTraits *d,
    259         const C2Component::Traits &s) {
    260     d->name = s.name;
    261 
    262     switch (s.domain) {
    263     case C2Component::DOMAIN_VIDEO:
    264         d->domain = IComponentStore::ComponentTraits::Domain::VIDEO;
    265         break;
    266     case C2Component::DOMAIN_AUDIO:
    267         d->domain = IComponentStore::ComponentTraits::Domain::AUDIO;
    268         break;
    269     default:
    270         d->domain = IComponentStore::ComponentTraits::Domain::OTHER;
    271     }
    272     d->domainOther = static_cast<uint32_t>(s.domain);
    273 
    274     switch (s.kind) {
    275     case C2Component::KIND_DECODER:
    276         d->kind = IComponentStore::ComponentTraits::Kind::DECODER;
    277         break;
    278     case C2Component::KIND_ENCODER:
    279         d->kind = IComponentStore::ComponentTraits::Kind::ENCODER;
    280         break;
    281     default:
    282         d->kind = IComponentStore::ComponentTraits::Kind::OTHER;
    283     }
    284     d->kindOther = static_cast<uint32_t>(s.kind);
    285 
    286     d->rank = static_cast<uint32_t>(s.rank);
    287 
    288     d->mediaType = s.mediaType;
    289 
    290     d->aliases.resize(s.aliases.size());
    291     for (size_t ix = s.aliases.size(); ix > 0; ) {
    292         --ix;
    293         d->aliases[ix] = s.aliases[ix];
    294     }
    295     return Status::OK;
    296 }
    297 
    298 // ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
    299 c2_status_t objcpy(
    300         C2Component::Traits* d,
    301         std::unique_ptr<std::vector<std::string>>* aliasesBuffer,
    302         const IComponentStore::ComponentTraits& s) {
    303     d->name = s.name.c_str();
    304 
    305     switch (s.domain) {
    306     case IComponentStore::ComponentTraits::Domain::VIDEO:
    307         d->domain = C2Component::DOMAIN_VIDEO;
    308         break;
    309     case IComponentStore::ComponentTraits::Domain::AUDIO:
    310         d->domain = C2Component::DOMAIN_AUDIO;
    311         break;
    312     default:
    313         d->domain = static_cast<C2Component::domain_t>(s.domainOther);
    314     }
    315 
    316     switch (s.kind) {
    317     case IComponentStore::ComponentTraits::Kind::DECODER:
    318         d->kind = C2Component::KIND_DECODER;
    319         break;
    320     case IComponentStore::ComponentTraits::Kind::ENCODER:
    321         d->kind = C2Component::KIND_ENCODER;
    322         break;
    323     default:
    324         d->kind = static_cast<C2Component::kind_t>(s.kindOther);
    325     }
    326 
    327     d->rank = static_cast<C2Component::rank_t>(s.rank);
    328     d->mediaType = s.mediaType.c_str();
    329 
    330     // aliasesBuffer must not be resized after this.
    331     *aliasesBuffer = std::make_unique<std::vector<std::string>>(
    332             s.aliases.size());
    333     (*aliasesBuffer)->resize(s.aliases.size());
    334     std::vector<C2StringLiteral> dAliases(s.aliases.size());
    335     for (size_t i = 0; i < s.aliases.size(); ++i) {
    336         (**aliasesBuffer)[i] = s.aliases[i].c_str();
    337         d->aliases[i] = (**aliasesBuffer)[i].c_str();
    338     }
    339     return C2_OK;
    340 }
    341 
    342 namespace /* unnamed */ {
    343 
    344 // C2ParamFieldValues -> ParamFieldValues
    345 Status objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) {
    346     objcpy(&d->paramOrField, s.paramOrField);
    347     if (s.values) {
    348         d->values.resize(1);
    349         return objcpy(&d->values[0], *s.values);
    350     }
    351     d->values.resize(0);
    352     return Status::OK;
    353 }
    354 
    355 // ParamFieldValues -> C2ParamFieldValues
    356 c2_status_t objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) {
    357     d->paramOrField = C2ParamFieldBuilder(s.paramOrField);
    358     if (s.values.size() == 1) {
    359         d->values = std::make_unique<C2FieldSupportedValues>();
    360         return objcpy(d->values.get(), s.values[0]);
    361     } else if (s.values.size() == 0) {
    362         d->values.reset();
    363         return C2_OK;
    364     }
    365     ALOGE("Multiple FieldSupportedValues objects. "
    366             "(Only one is allowed.)");
    367     return C2_BAD_VALUE;
    368 }
    369 
    370 } // unnamed namespace
    371 
    372 // C2SettingResult -> SettingResult
    373 Status objcpy(SettingResult *d, const C2SettingResult &s) {
    374     d->failureOther = static_cast<uint32_t>(s.failure);
    375     switch (s.failure) {
    376     case C2SettingResult::READ_ONLY:
    377         d->failure = SettingResult::Failure::READ_ONLY;
    378         break;
    379     case C2SettingResult::MISMATCH:
    380         d->failure = SettingResult::Failure::MISMATCH;
    381         break;
    382     case C2SettingResult::BAD_VALUE:
    383         d->failure = SettingResult::Failure::BAD_VALUE;
    384         break;
    385     case C2SettingResult::BAD_TYPE:
    386         d->failure = SettingResult::Failure::BAD_TYPE;
    387         break;
    388     case C2SettingResult::BAD_PORT:
    389         d->failure = SettingResult::Failure::BAD_PORT;
    390         break;
    391     case C2SettingResult::BAD_INDEX:
    392         d->failure = SettingResult::Failure::BAD_INDEX;
    393         break;
    394     case C2SettingResult::CONFLICT:
    395         d->failure = SettingResult::Failure::CONFLICT;
    396         break;
    397     case C2SettingResult::UNSUPPORTED:
    398         d->failure = SettingResult::Failure::UNSUPPORTED;
    399         break;
    400     case C2SettingResult::INFO_CONFLICT:
    401         d->failure = SettingResult::Failure::INFO_CONFLICT;
    402         break;
    403     default:
    404         d->failure = SettingResult::Failure::OTHER;
    405     }
    406     Status status = objcpy(&d->field, s.field);
    407     if (status != Status::OK) {
    408         return status;
    409     }
    410     d->conflicts.resize(s.conflicts.size());
    411     size_t i = 0;
    412     for (const C2ParamFieldValues& sConflict : s.conflicts) {
    413         ParamFieldValues &dConflict = d->conflicts[i++];
    414         status = objcpy(&dConflict, sConflict);
    415         if (status != Status::OK) {
    416             return status;
    417         }
    418     }
    419     return Status::OK;
    420 }
    421 
    422 // SettingResult -> std::unique_ptr<C2SettingResult>
    423 c2_status_t objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
    424     *d = std::unique_ptr<C2SettingResult>(new C2SettingResult {
    425             .field = C2ParamFieldValues(C2ParamFieldBuilder()) });
    426     if (!*d) {
    427         return C2_NO_MEMORY;
    428     }
    429 
    430     // failure
    431     switch (s.failure) {
    432     case SettingResult::Failure::READ_ONLY:
    433         (*d)->failure = C2SettingResult::READ_ONLY;
    434         break;
    435     case SettingResult::Failure::MISMATCH:
    436         (*d)->failure = C2SettingResult::MISMATCH;
    437         break;
    438     case SettingResult::Failure::BAD_VALUE:
    439         (*d)->failure = C2SettingResult::BAD_VALUE;
    440         break;
    441     case SettingResult::Failure::BAD_TYPE:
    442         (*d)->failure = C2SettingResult::BAD_TYPE;
    443         break;
    444     case SettingResult::Failure::BAD_PORT:
    445         (*d)->failure = C2SettingResult::BAD_PORT;
    446         break;
    447     case SettingResult::Failure::BAD_INDEX:
    448         (*d)->failure = C2SettingResult::BAD_INDEX;
    449         break;
    450     case SettingResult::Failure::CONFLICT:
    451         (*d)->failure = C2SettingResult::CONFLICT;
    452         break;
    453     case SettingResult::Failure::UNSUPPORTED:
    454         (*d)->failure = C2SettingResult::UNSUPPORTED;
    455         break;
    456     case SettingResult::Failure::INFO_CONFLICT:
    457         (*d)->failure = C2SettingResult::INFO_CONFLICT;
    458         break;
    459     default:
    460         (*d)->failure = static_cast<C2SettingResult::Failure>(s.failureOther);
    461     }
    462 
    463     // field
    464     c2_status_t status = objcpy(&(*d)->field, s.field);
    465     if (status != C2_OK) {
    466         return status;
    467     }
    468 
    469     // conflicts
    470     (*d)->conflicts.clear();
    471     (*d)->conflicts.reserve(s.conflicts.size());
    472     for (const ParamFieldValues& sConflict : s.conflicts) {
    473         (*d)->conflicts.emplace_back(
    474                 C2ParamFieldValues{ C2ParamFieldBuilder(), nullptr });
    475         status = objcpy(&(*d)->conflicts.back(), sConflict);
    476         if (status != C2_OK) {
    477             return status;
    478         }
    479     }
    480     return C2_OK;
    481 }
    482 
    483 // C2ParamDescriptor -> ParamDescriptor
    484 Status objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
    485     d->index = static_cast<ParamIndex>(s.index());
    486     d->attrib = static_cast<hidl_bitfield<ParamDescriptor::Attrib>>(
    487             _C2ParamInspector::GetAttrib(s));
    488     d->name = s.name();
    489     copyVector<uint32_t>(&d->dependencies, s.dependencies());
    490     return Status::OK;
    491 }
    492 
    493 // ParamDescriptor -> C2ParamDescriptor
    494 c2_status_t objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
    495     std::vector<C2Param::Index> dDependencies;
    496     dDependencies.reserve(s.dependencies.size());
    497     for (const ParamIndex& sDependency : s.dependencies) {
    498         dDependencies.emplace_back(static_cast<uint32_t>(sDependency));
    499     }
    500     *d = std::make_shared<C2ParamDescriptor>(
    501             C2Param::Index(static_cast<uint32_t>(s.index)),
    502             static_cast<C2ParamDescriptor::attrib_t>(s.attrib),
    503             C2String(s.name.c_str()),
    504             std::move(dDependencies));
    505     return C2_OK;
    506 }
    507 
    508 // C2StructDescriptor -> StructDescriptor
    509 Status objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
    510     d->type = static_cast<ParamIndex>(s.coreIndex().coreIndex());
    511     d->fields.resize(s.numFields());
    512     size_t i = 0;
    513     for (const auto& sField : s) {
    514         FieldDescriptor& dField = d->fields[i++];
    515         dField.fieldId.offset = static_cast<uint32_t>(
    516                 _C2ParamInspector::GetOffset(sField));
    517         dField.fieldId.size = static_cast<uint32_t>(
    518                 _C2ParamInspector::GetSize(sField));
    519         dField.type = static_cast<hidl_bitfield<FieldDescriptor::Type>>(
    520                 sField.type());
    521         dField.length = static_cast<uint32_t>(sField.extent());
    522         dField.name = static_cast<hidl_string>(sField.name());
    523         const auto& sNamedValues = sField.namedValues();
    524         dField.namedValues.resize(sNamedValues.size());
    525         size_t j = 0;
    526         for (const auto& sNamedValue : sNamedValues) {
    527             FieldDescriptor::NamedValue& dNamedValue = dField.namedValues[j++];
    528             dNamedValue.name = static_cast<hidl_string>(sNamedValue.first);
    529             dNamedValue.value = static_cast<PrimitiveValue>(
    530                     sNamedValue.second.u64);
    531         }
    532     }
    533     return Status::OK;
    534 }
    535 
    536 // StructDescriptor -> C2StructDescriptor
    537 c2_status_t objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
    538     C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type));
    539     std::vector<C2FieldDescriptor> dFields;
    540     dFields.reserve(s.fields.size());
    541     for (const auto &sField : s.fields) {
    542         C2FieldDescriptor dField = {
    543             static_cast<uint32_t>(sField.type),
    544             sField.length,
    545             sField.name,
    546             sField.fieldId.offset,
    547             sField.fieldId.size };
    548         C2FieldDescriptor::NamedValuesType namedValues;
    549         namedValues.reserve(sField.namedValues.size());
    550         for (const auto& sNamedValue : sField.namedValues) {
    551             namedValues.emplace_back(
    552                 sNamedValue.name,
    553                 C2Value::Primitive(static_cast<uint64_t>(sNamedValue.value)));
    554         }
    555         _C2ParamInspector::AddNamedValues(dField, std::move(namedValues));
    556         dFields.emplace_back(dField);
    557     }
    558     *d = std::make_unique<C2StructDescriptor>(
    559             _C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields)));
    560     return C2_OK;
    561 }
    562 
    563 namespace /* unnamed */ {
    564 
    565 // Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
    566 // associated map.
    567 // Note: The handle is not cloned.
    568 Status _addBaseBlock(
    569         uint32_t* index,
    570         const C2Handle* handle,
    571         std::list<BaseBlock>* baseBlocks,
    572         std::map<const void*, uint32_t>* baseBlockIndices) {
    573     if (!handle) {
    574         ALOGE("addBaseBlock called on a null C2Handle.");
    575         return Status::BAD_VALUE;
    576     }
    577     auto it = baseBlockIndices->find(handle);
    578     if (it != baseBlockIndices->end()) {
    579         *index = it->second;
    580     } else {
    581         *index = baseBlocks->size();
    582         baseBlockIndices->emplace(handle, *index);
    583         baseBlocks->emplace_back();
    584 
    585         BaseBlock &dBaseBlock = baseBlocks->back();
    586         dBaseBlock.type = BaseBlock::Type::NATIVE;
    587         // This does not clone the handle.
    588         dBaseBlock.nativeBlock =
    589                 reinterpret_cast<const native_handle_t*>(handle);
    590 
    591     }
    592     return Status::OK;
    593 }
    594 
    595 // Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
    596 // an associated map.
    597 Status _addBaseBlock(
    598         uint32_t* index,
    599         const std::shared_ptr<BufferPoolData> bpData,
    600         BufferPoolSender* bufferPoolSender,
    601         std::list<BaseBlock>* baseBlocks,
    602         std::map<const void*, uint32_t>* baseBlockIndices) {
    603     if (!bpData) {
    604         ALOGE("addBaseBlock called on a null BufferPoolData.");
    605         return Status::BAD_VALUE;
    606     }
    607     auto it = baseBlockIndices->find(bpData.get());
    608     if (it != baseBlockIndices->end()) {
    609         *index = it->second;
    610     } else if (!bufferPoolSender) {
    611         ALOGE("No access to the receiver's BufferPool.");
    612         return Status::BAD_VALUE;
    613     } else {
    614         *index = baseBlocks->size();
    615         baseBlockIndices->emplace(bpData.get(), *index);
    616         baseBlocks->emplace_back();
    617 
    618         BaseBlock &dBaseBlock = baseBlocks->back();
    619         dBaseBlock.type = BaseBlock::Type::POOLED;
    620         ResultStatus bpStatus = bufferPoolSender->send(
    621                 bpData,
    622                 &dBaseBlock.pooledBlock);
    623 
    624         if (bpStatus != ResultStatus::OK) {
    625             ALOGE("Failed to send buffer with BufferPool. Error: %d.",
    626                     static_cast<int>(bpStatus));
    627             return Status::BAD_VALUE;
    628         }
    629 
    630     }
    631     return Status::OK;
    632 }
    633 
    634 Status addBaseBlock(
    635         uint32_t* index,
    636         const C2Handle* handle,
    637         const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
    638         BufferPoolSender* bufferPoolSender,
    639         std::list<BaseBlock>* baseBlocks,
    640         std::map<const void*, uint32_t>* baseBlockIndices) {
    641     if (!blockPoolData) {
    642         // No BufferPoolData ==> NATIVE block.
    643         return _addBaseBlock(
    644                 index, handle,
    645                 baseBlocks, baseBlockIndices);
    646     }
    647     switch (blockPoolData->getType()) {
    648     case _C2BlockPoolData::TYPE_BUFFERPOOL: {
    649             // BufferPoolData
    650             std::shared_ptr<BufferPoolData> bpData;
    651             if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
    652                     || !bpData) {
    653                 ALOGE("BufferPoolData unavailable in a block.");
    654                 return Status::BAD_VALUE;
    655             }
    656             return _addBaseBlock(
    657                     index, bpData,
    658                     bufferPoolSender, baseBlocks, baseBlockIndices);
    659         }
    660     case _C2BlockPoolData::TYPE_BUFFERQUEUE:
    661         // Do the same thing as a NATIVE block.
    662         return _addBaseBlock(
    663                 index, handle,
    664                 baseBlocks, baseBlockIndices);
    665     default:
    666         ALOGE("Unknown C2BlockPoolData type.");
    667         return Status::BAD_VALUE;
    668     }
    669 }
    670 
    671 // C2Fence -> hidl_handle
    672 // Note: File descriptors are not duplicated. The original file descriptor must
    673 // not be closed before the transaction is complete.
    674 Status objcpy(hidl_handle* d, const C2Fence& s) {
    675     (void)s; // TODO: implement s.fd()
    676     int fenceFd = -1;
    677     d->setTo(nullptr);
    678     if (fenceFd >= 0) {
    679         native_handle_t *handle = native_handle_create(1, 0);
    680         if (!handle) {
    681             return Status::NO_MEMORY;
    682         }
    683         handle->data[0] = fenceFd;
    684         d->setTo(handle, true /* owns */);
    685     }
    686     return Status::OK;
    687 }
    688 
    689 // C2ConstLinearBlock -> Block
    690 // Note: Native handles are not duplicated. The original handles must not be
    691 // closed before the transaction is complete.
    692 Status objcpy(Block* d, const C2ConstLinearBlock& s,
    693         BufferPoolSender* bufferPoolSender,
    694         std::list<BaseBlock>* baseBlocks,
    695         std::map<const void*, uint32_t>* baseBlockIndices) {
    696     std::shared_ptr<const _C2BlockPoolData> bpData =
    697             _C2BlockFactory::GetLinearBlockPoolData(s);
    698     Status status = addBaseBlock(&d->index, s.handle(), bpData,
    699             bufferPoolSender, baseBlocks, baseBlockIndices);
    700     if (status != Status::OK) {
    701         return status;
    702     }
    703 
    704     // Create the metadata.
    705     C2Hidl_RangeInfo dRangeInfo;
    706     dRangeInfo.offset = static_cast<uint32_t>(s.offset());
    707     dRangeInfo.length = static_cast<uint32_t>(s.size());
    708     status = createParamsBlob(&d->meta,
    709             std::vector<C2Param*>{ &dRangeInfo });
    710     if (status != Status::OK) {
    711         return Status::BAD_VALUE;
    712     }
    713 
    714     // Copy the fence
    715     return objcpy(&d->fence, s.fence());
    716 }
    717 
    718 // C2ConstGraphicBlock -> Block
    719 // Note: Native handles are not duplicated. The original handles must not be
    720 // closed before the transaction is complete.
    721 Status objcpy(Block* d, const C2ConstGraphicBlock& s,
    722         BufferPoolSender* bufferPoolSender,
    723         std::list<BaseBlock>* baseBlocks,
    724         std::map<const void*, uint32_t>* baseBlockIndices) {
    725     std::shared_ptr<const _C2BlockPoolData> bpData =
    726             _C2BlockFactory::GetGraphicBlockPoolData(s);
    727     Status status = addBaseBlock(&d->index, s.handle(), bpData,
    728             bufferPoolSender, baseBlocks, baseBlockIndices);
    729 
    730     // Create the metadata.
    731     C2Hidl_RectInfo dRectInfo;
    732     C2Rect sRect = s.crop();
    733     dRectInfo.left = static_cast<uint32_t>(sRect.left);
    734     dRectInfo.top = static_cast<uint32_t>(sRect.top);
    735     dRectInfo.width = static_cast<uint32_t>(sRect.width);
    736     dRectInfo.height = static_cast<uint32_t>(sRect.height);
    737     status = createParamsBlob(&d->meta,
    738             std::vector<C2Param*>{ &dRectInfo });
    739     if (status != Status::OK) {
    740         return Status::BAD_VALUE;
    741     }
    742 
    743     // Copy the fence
    744     return objcpy(&d->fence, s.fence());
    745 }
    746 
    747 // C2BufferData -> Buffer
    748 // This function only fills in d->blocks.
    749 Status objcpy(Buffer* d, const C2BufferData& s,
    750         BufferPoolSender* bufferPoolSender,
    751         std::list<BaseBlock>* baseBlocks,
    752         std::map<const void*, uint32_t>* baseBlockIndices) {
    753     Status status;
    754     d->blocks.resize(
    755             s.linearBlocks().size() +
    756             s.graphicBlocks().size());
    757     size_t i = 0;
    758     for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
    759         Block& dBlock = d->blocks[i++];
    760         status = objcpy(
    761                 &dBlock, linearBlock,
    762                 bufferPoolSender, baseBlocks, baseBlockIndices);
    763         if (status != Status::OK) {
    764             return status;
    765         }
    766     }
    767     for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
    768         Block& dBlock = d->blocks[i++];
    769         status = objcpy(
    770                 &dBlock, graphicBlock,
    771                 bufferPoolSender, baseBlocks, baseBlockIndices);
    772         if (status != Status::OK) {
    773             return status;
    774         }
    775     }
    776     return Status::OK;
    777 }
    778 
    779 // C2Buffer -> Buffer
    780 Status objcpy(Buffer* d, const C2Buffer& s,
    781         BufferPoolSender* bufferPoolSender,
    782         std::list<BaseBlock>* baseBlocks,
    783         std::map<const void*, uint32_t>* baseBlockIndices) {
    784     Status status = createParamsBlob(&d->info, s.info());
    785     if (status != Status::OK) {
    786         return status;
    787     }
    788     return objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices);
    789 }
    790 
    791 // C2InfoBuffer -> InfoBuffer
    792 Status objcpy(InfoBuffer* d, const C2InfoBuffer& s,
    793         BufferPoolSender* bufferPoolSender,
    794         std::list<BaseBlock>* baseBlocks,
    795         std::map<const void*, uint32_t>* baseBlockIndices) {
    796     // TODO: C2InfoBuffer is not implemented.
    797     (void)d;
    798     (void)s;
    799     (void)bufferPoolSender;
    800     (void)baseBlocks;
    801     (void)baseBlockIndices;
    802     return Status::OK;
    803     /*
    804     // Stub implementation that may work in the future.
    805     d->index = static_cast<uint32_t>(s.index());
    806     d->buffer.info.resize(0);
    807     return objcpy(&d->buffer, s.data(), baseBlocks, baseBlockIndices);
    808     */
    809 }
    810 
    811 // C2FrameData -> FrameData
    812 Status objcpy(FrameData* d, const C2FrameData& s,
    813         BufferPoolSender* bufferPoolSender,
    814         std::list<BaseBlock>* baseBlocks,
    815         std::map<const void*, uint32_t>* baseBlockIndices) {
    816     d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
    817     objcpy(&d->ordinal, s.ordinal);
    818 
    819     Status status;
    820     d->buffers.resize(s.buffers.size());
    821     size_t i = 0;
    822     for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
    823         Buffer& dBuffer = d->buffers[i++];
    824         if (!sBuffer) {
    825             // A null (pointer to) C2Buffer corresponds to a Buffer with empty
    826             // info and blocks.
    827             dBuffer.info.resize(0);
    828             dBuffer.blocks.resize(0);
    829             continue;
    830         }
    831         status = objcpy(
    832                 &dBuffer, *sBuffer,
    833                 bufferPoolSender, baseBlocks, baseBlockIndices);
    834         if (status != Status::OK) {
    835             return status;
    836         }
    837     }
    838 
    839     status = createParamsBlob(&d->configUpdate, s.configUpdate);
    840     if (status != Status::OK) {
    841         return status;
    842     }
    843 
    844     d->infoBuffers.resize(s.infoBuffers.size());
    845     i = 0;
    846     for (const std::shared_ptr<C2InfoBuffer>& sInfoBuffer : s.infoBuffers) {
    847         InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
    848         if (!sInfoBuffer) {
    849             ALOGE("Null C2InfoBuffer");
    850             return Status::BAD_VALUE;
    851         }
    852         status = objcpy(&dInfoBuffer, *sInfoBuffer,
    853                 bufferPoolSender, baseBlocks, baseBlockIndices);
    854         if (status != Status::OK) {
    855             return status;
    856         }
    857     }
    858 
    859     return status;
    860 }
    861 
    862 } // unnamed namespace
    863 
    864 // DefaultBufferPoolSender's implementation
    865 
    866 DefaultBufferPoolSender::DefaultBufferPoolSender(
    867         const sp<IClientManager>& receiverManager) :
    868     mReceiverManager(receiverManager), mSourceConnectionId(0) {
    869 }
    870 
    871 void DefaultBufferPoolSender::setReceiver(const sp<IClientManager>& receiverManager) {
    872     std::lock_guard<std::mutex> lock(mMutex);
    873     if (mReceiverManager != receiverManager) {
    874         mReceiverManager = receiverManager;
    875     }
    876 }
    877 
    878 ResultStatus DefaultBufferPoolSender::send(
    879         const std::shared_ptr<BufferPoolData>& bpData,
    880         BufferStatusMessage* bpMessage) {
    881     if (!mReceiverManager) {
    882         ALOGE("No access to receiver's BufferPool.");
    883         return ResultStatus::NOT_FOUND;
    884     }
    885     ResultStatus rs;
    886     std::lock_guard<std::mutex> lock(mMutex);
    887     if (!mSenderManager) {
    888         mSenderManager = ClientManager::getInstance();
    889         if (!mSenderManager) {
    890             ALOGE("Failed to retrieve local BufferPool ClientManager.");
    891             return ResultStatus::CRITICAL_ERROR;
    892         }
    893     }
    894     int64_t connectionId = bpData->mConnectionId;
    895     if (mSourceConnectionId == 0 || mSourceConnectionId != connectionId) {
    896         // Initialize the bufferpool connection.
    897         mSourceConnectionId = connectionId;
    898         if (mSourceConnectionId == 0) {
    899             return ResultStatus::CRITICAL_ERROR;
    900         }
    901         int64_t receiverConnectionId;
    902         rs = mSenderManager->registerSender(mReceiverManager, connectionId, &receiverConnectionId);
    903         if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
    904             ALOGW("registerSender -- returned error: %d.",
    905                     static_cast<int>(rs));
    906             return rs;
    907         } else {
    908             mReceiverConnectionId = receiverConnectionId;
    909         }
    910     }
    911 
    912     uint64_t transactionId;
    913     int64_t timestampUs;
    914     rs = mSenderManager->postSend(
    915             mReceiverConnectionId, bpData, &transactionId, &timestampUs);
    916     if (rs != ResultStatus::OK) {
    917         ALOGE("ClientManager::postSend -- returned error: %d.",
    918                 static_cast<int>(rs));
    919         return rs;
    920     }
    921     if (!bpMessage) {
    922         ALOGE("Null output parameter for BufferStatusMessage.");
    923         return ResultStatus::CRITICAL_ERROR;
    924     }
    925     bpMessage->connectionId = mReceiverConnectionId;
    926     bpMessage->bufferId = bpData->mId;
    927     bpMessage->transactionId = transactionId;
    928     bpMessage->timestampUs = timestampUs;
    929     return rs;
    930 }
    931 
    932 // std::list<std::unique_ptr<C2Work>> -> WorkBundle
    933 Status objcpy(
    934         WorkBundle* d,
    935         const std::list<std::unique_ptr<C2Work>>& s,
    936         BufferPoolSender* bufferPoolSender) {
    937     Status status = Status::OK;
    938 
    939     // baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
    940     std::list<BaseBlock> baseBlocks;
    941 
    942     // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
    943     // inside baseBlocks to the corresponding index into baseBlocks. The keys
    944     // (pointers) are used to identify blocks that have the same "base block" in
    945     // s, a list of C2Work objects. Because baseBlocks will be copied into a
    946     // hidl_vec eventually, the values of baseBlockIndices are zero-based
    947     // integer indices instead of list iterators.
    948     //
    949     // Note that the pointers can be raw because baseBlockIndices has a shorter
    950     // lifespan than all of base blocks.
    951     std::map<const void*, uint32_t> baseBlockIndices;
    952 
    953     d->works.resize(s.size());
    954     size_t i = 0;
    955     for (const std::unique_ptr<C2Work>& sWork : s) {
    956         Work &dWork = d->works[i++];
    957         if (!sWork) {
    958             ALOGW("Null C2Work encountered.");
    959             continue;
    960         }
    961         status = objcpy(&dWork.input, sWork->input,
    962                 bufferPoolSender, &baseBlocks, &baseBlockIndices);
    963         if (status != Status::OK) {
    964             return status;
    965         }
    966         if (sWork->worklets.size() == 0) {
    967             ALOGW("Work with no worklets.");
    968         } else {
    969             if (sWork->worklets.size() > 1) {
    970                 ALOGW("Work with multiple worklets. "
    971                         "Only the first worklet will be marshalled.");
    972             }
    973             if (!sWork->worklets.front()) {
    974                 ALOGE("Null worklet encountered.");
    975                 return Status::BAD_VALUE;
    976             }
    977 
    978             // Parcel the first worklet.
    979             const C2Worklet &sWorklet = *sWork->worklets.front();
    980             Worklet &dWorklet = dWork.worklet;
    981 
    982             dWorklet.tunings.resize(sWorklet.tunings.size());
    983             size_t j = 0;
    984             for (const std::unique_ptr<C2Tuning>& sTuning : sWorklet.tunings) {
    985                 status = createParamsBlob(
    986                         &dWorklet.tunings[j++],
    987                         std::vector<C2Param*>
    988                         { reinterpret_cast<C2Param*>(sTuning.get()) });
    989                 if (status != Status::OK) {
    990                     return status;
    991                 }
    992             }
    993 
    994             dWorklet.failures.resize(sWorklet.failures.size());
    995             j = 0;
    996             for (const std::unique_ptr<C2SettingResult>& sFailure :
    997                     sWorklet.failures) {
    998                 if (!sFailure) {
    999                     ALOGE("Null C2SettingResult");
   1000                     return Status::BAD_VALUE;
   1001                 }
   1002                 status = objcpy(&dWorklet.failures[j++], *sFailure);
   1003                 if (status != Status::OK) {
   1004                     return status;
   1005                 }
   1006             }
   1007 
   1008             status = objcpy(&dWorklet.output, sWorklet.output,
   1009                     bufferPoolSender, &baseBlocks, &baseBlockIndices);
   1010             if (status != Status::OK) {
   1011                 return status;
   1012             }
   1013         }
   1014         dWork.workletProcessed = sWork->workletsProcessed > 0;
   1015         dWork.result = static_cast<Status>(sWork->result);
   1016     }
   1017 
   1018     // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
   1019     {
   1020         d->baseBlocks.resize(baseBlocks.size());
   1021         size_t i = 0;
   1022         for (const BaseBlock& baseBlock : baseBlocks) {
   1023             d->baseBlocks[i++] = baseBlock;
   1024         }
   1025     }
   1026 
   1027     return Status::OK;
   1028 }
   1029 
   1030 namespace /* unnamed */ {
   1031 
   1032 struct C2BaseBlock {
   1033     enum type_t {
   1034         LINEAR,
   1035         GRAPHIC,
   1036     };
   1037     type_t type;
   1038     std::shared_ptr<C2LinearBlock> linear;
   1039     std::shared_ptr<C2GraphicBlock> graphic;
   1040 };
   1041 
   1042 // hidl_handle -> C2Fence
   1043 // Note: File descriptors are not duplicated. The original file descriptor must
   1044 // not be closed before the transaction is complete.
   1045 c2_status_t objcpy(C2Fence* d, const hidl_handle& s) {
   1046     // TODO: Implement.
   1047     (void)s;
   1048     *d = C2Fence();
   1049     return C2_OK;
   1050 }
   1051 
   1052 // C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
   1053 c2_status_t createLinearBuffer(
   1054         std::shared_ptr<C2Buffer>* buffer,
   1055         const std::shared_ptr<C2LinearBlock>& block,
   1056         const std::vector<C2Param*>& meta,
   1057         const C2Fence& fence) {
   1058     // Check the block meta. It should have exactly 1 C2Info:
   1059     // C2Hidl_RangeInfo.
   1060     if ((meta.size() != 1) || !meta[0]) {
   1061         ALOGE("Invalid block metadata for ion block.");
   1062         return C2_BAD_VALUE;
   1063     }
   1064     if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
   1065         ALOGE("Invalid block metadata for ion block: range.");
   1066         return C2_BAD_VALUE;
   1067     }
   1068     C2Hidl_RangeInfo *rangeInfo =
   1069             reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
   1070 
   1071     // Create C2Buffer from C2LinearBlock.
   1072     *buffer = C2Buffer::CreateLinearBuffer(block->share(
   1073             rangeInfo->offset, rangeInfo->length,
   1074             fence));
   1075     if (!(*buffer)) {
   1076         ALOGE("Cannot create a linear buffer.");
   1077         return C2_BAD_VALUE;
   1078     }
   1079     return C2_OK;
   1080 }
   1081 
   1082 // C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
   1083 c2_status_t createGraphicBuffer(
   1084         std::shared_ptr<C2Buffer>* buffer,
   1085         const std::shared_ptr<C2GraphicBlock>& block,
   1086         const std::vector<C2Param*>& meta,
   1087         const C2Fence& fence) {
   1088     // Check the block meta. It should have exactly 1 C2Info:
   1089     // C2Hidl_RectInfo.
   1090     if ((meta.size() != 1) || !meta[0]) {
   1091         ALOGE("Invalid block metadata for graphic block.");
   1092         return C2_BAD_VALUE;
   1093     }
   1094     if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
   1095         ALOGE("Invalid block metadata for graphic block: crop rect.");
   1096         return C2_BAD_VALUE;
   1097     }
   1098     C2Hidl_RectInfo *rectInfo =
   1099             reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
   1100 
   1101     // Create C2Buffer from C2GraphicBlock.
   1102     *buffer = C2Buffer::CreateGraphicBuffer(block->share(
   1103             C2Rect(rectInfo->width, rectInfo->height).
   1104             at(rectInfo->left, rectInfo->top),
   1105             fence));
   1106     if (!(*buffer)) {
   1107         ALOGE("Cannot create a graphic buffer.");
   1108         return C2_BAD_VALUE;
   1109     }
   1110     return C2_OK;
   1111 }
   1112 
   1113 // Buffer -> C2Buffer
   1114 // Note: The native handles will be cloned.
   1115 c2_status_t objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
   1116         const std::vector<C2BaseBlock>& baseBlocks) {
   1117     c2_status_t status;
   1118     *d = nullptr;
   1119 
   1120     // Currently, a non-null C2Buffer must contain exactly 1 block.
   1121     if (s.blocks.size() == 0) {
   1122         return C2_OK;
   1123     } else if (s.blocks.size() != 1) {
   1124         ALOGE("Currently, a C2Buffer must contain exactly 1 block.");
   1125         return C2_BAD_VALUE;
   1126     }
   1127 
   1128     const Block &sBlock = s.blocks[0];
   1129     if (sBlock.index >= baseBlocks.size()) {
   1130         ALOGE("Index into baseBlocks is out of range.");
   1131         return C2_BAD_VALUE;
   1132     }
   1133     const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
   1134 
   1135     // Parse meta.
   1136     std::vector<C2Param*> sBlockMeta;
   1137     status = parseParamsBlob(&sBlockMeta, sBlock.meta);
   1138     if (status != C2_OK) {
   1139         ALOGE("Invalid block params blob.");
   1140         return C2_BAD_VALUE;
   1141     }
   1142 
   1143     // Copy fence.
   1144     C2Fence dFence;
   1145     status = objcpy(&dFence, sBlock.fence);
   1146 
   1147     // Construct a block.
   1148     switch (baseBlock.type) {
   1149     case C2BaseBlock::LINEAR:
   1150         status = createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence);
   1151         break;
   1152     case C2BaseBlock::GRAPHIC:
   1153         status = createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence);
   1154         break;
   1155     default:
   1156         ALOGE("Invalid BaseBlock type.");
   1157         return C2_BAD_VALUE;
   1158     }
   1159     if (status != C2_OK) {
   1160         return status;
   1161     }
   1162 
   1163     // Parse info
   1164     std::vector<C2Param*> params;
   1165     status = parseParamsBlob(&params, s.info);
   1166     if (status != C2_OK) {
   1167         ALOGE("Invalid buffer params blob.");
   1168         return status;
   1169     }
   1170     for (C2Param* param : params) {
   1171         if (param == nullptr) {
   1172             ALOGE("Null buffer param encountered.");
   1173             return C2_BAD_VALUE;
   1174         }
   1175         std::shared_ptr<C2Param> c2param(
   1176                 C2Param::Copy(*param).release());
   1177         if (!c2param) {
   1178             ALOGE("Invalid buffer param inside a blob.");
   1179             return C2_BAD_VALUE;
   1180         }
   1181         status = (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
   1182         if (status != C2_OK) {
   1183             ALOGE("C2Buffer::setInfo failed().");
   1184             return C2_BAD_VALUE;
   1185         }
   1186     }
   1187 
   1188     return C2_OK;
   1189 }
   1190 
   1191 // FrameData -> C2FrameData
   1192 c2_status_t objcpy(C2FrameData* d, const FrameData& s,
   1193         const std::vector<C2BaseBlock>& baseBlocks) {
   1194     c2_status_t status;
   1195     d->flags = static_cast<C2FrameData::flags_t>(s.flags);
   1196     objcpy(&d->ordinal, s.ordinal);
   1197     d->buffers.clear();
   1198     d->buffers.reserve(s.buffers.size());
   1199     for (const Buffer& sBuffer : s.buffers) {
   1200         std::shared_ptr<C2Buffer> dBuffer;
   1201         status = objcpy(&dBuffer, sBuffer, baseBlocks);
   1202         if (status != C2_OK) {
   1203             return status;
   1204         }
   1205         d->buffers.emplace_back(dBuffer);
   1206     }
   1207 
   1208     std::vector<C2Param*> params;
   1209     status = parseParamsBlob(&params, s.configUpdate);
   1210     if (status != C2_OK) {
   1211         ALOGE("Failed to parse frame data params.");
   1212         return status;
   1213     }
   1214     d->configUpdate.clear();
   1215     for (C2Param* param : params) {
   1216         d->configUpdate.emplace_back(C2Param::Copy(*param));
   1217         if (!d->configUpdate.back()) {
   1218             ALOGE("Unexpected error while parsing frame data params.");
   1219             return C2_BAD_VALUE;
   1220         }
   1221     }
   1222 
   1223     // TODO: Implement this once C2InfoBuffer has constructors.
   1224     d->infoBuffers.clear();
   1225     return C2_OK;
   1226 }
   1227 
   1228 // BaseBlock -> C2BaseBlock
   1229 c2_status_t objcpy(C2BaseBlock* d, const BaseBlock& s) {
   1230     switch (s.type) {
   1231     case BaseBlock::Type::NATIVE: {
   1232             native_handle_t* sHandle =
   1233                     native_handle_clone(s.nativeBlock);
   1234             if (sHandle == nullptr) {
   1235                 ALOGE("Null native handle in a block.");
   1236                 return C2_BAD_VALUE;
   1237             }
   1238             const C2Handle *sC2Handle =
   1239                     reinterpret_cast<const C2Handle*>(sHandle);
   1240 
   1241             d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
   1242             if (d->linear) {
   1243                 d->type = C2BaseBlock::LINEAR;
   1244                 return C2_OK;
   1245             }
   1246 
   1247             d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
   1248             if (d->graphic) {
   1249                 d->type = C2BaseBlock::GRAPHIC;
   1250                 return C2_OK;
   1251             }
   1252 
   1253             ALOGE("Unknown handle type in native BaseBlock.");
   1254             if (sHandle) {
   1255                 native_handle_close(sHandle);
   1256                 native_handle_delete(sHandle);
   1257             }
   1258             return C2_BAD_VALUE;
   1259         }
   1260     case BaseBlock::Type::POOLED: {
   1261             const BufferStatusMessage &bpMessage =
   1262                     s.pooledBlock;
   1263             sp<ClientManager> bp = ClientManager::getInstance();
   1264             std::shared_ptr<BufferPoolData> bpData;
   1265             native_handle_t *cHandle;
   1266             ResultStatus bpStatus = bp->receive(
   1267                     bpMessage.connectionId,
   1268                     bpMessage.transactionId,
   1269                     bpMessage.bufferId,
   1270                     bpMessage.timestampUs,
   1271                     &cHandle,
   1272                     &bpData);
   1273             if (bpStatus != ResultStatus::OK) {
   1274                 ALOGE("Failed to receive buffer from bufferpool -- "
   1275                         "resultStatus = %d",
   1276                         static_cast<int>(bpStatus));
   1277                 return toC2Status(bpStatus);
   1278             } else if (!bpData) {
   1279                 ALOGE("No data in bufferpool transaction.");
   1280                 return C2_BAD_VALUE;
   1281             }
   1282 
   1283             d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
   1284             if (d->linear) {
   1285                 d->type = C2BaseBlock::LINEAR;
   1286                 return C2_OK;
   1287             }
   1288 
   1289             d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
   1290             if (d->graphic) {
   1291                 d->type = C2BaseBlock::GRAPHIC;
   1292                 return C2_OK;
   1293             }
   1294 
   1295             ALOGE("Unknown handle type in pooled BaseBlock.");
   1296             return C2_BAD_VALUE;
   1297         }
   1298     default:
   1299         ALOGE("Corrupted BaseBlock type: %d", static_cast<int>(s.type));
   1300         return C2_BAD_VALUE;
   1301     }
   1302 }
   1303 
   1304 } // unnamed namespace
   1305 
   1306 // WorkBundle -> std::list<std::unique_ptr<C2Work>>
   1307 c2_status_t objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
   1308     c2_status_t status;
   1309 
   1310     // Convert BaseBlocks to C2BaseBlocks.
   1311     std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
   1312     for (size_t i = 0; i < s.baseBlocks.size(); ++i) {
   1313         status = objcpy(&dBaseBlocks[i], s.baseBlocks[i]);
   1314         if (status != C2_OK) {
   1315             return status;
   1316         }
   1317     }
   1318 
   1319     d->clear();
   1320     for (const Work& sWork : s.works) {
   1321         d->emplace_back(std::make_unique<C2Work>());
   1322         C2Work& dWork = *d->back();
   1323 
   1324         // input
   1325         status = objcpy(&dWork.input, sWork.input, dBaseBlocks);
   1326         if (status != C2_OK) {
   1327             ALOGE("Error constructing C2Work's input.");
   1328             return C2_BAD_VALUE;
   1329         }
   1330 
   1331         // worklet(s)
   1332         dWork.worklets.clear();
   1333         // TODO: Currently, tunneling is not supported.
   1334         if (sWork.workletProcessed) {
   1335             dWork.workletsProcessed = 1;
   1336 
   1337             const Worklet &sWorklet = sWork.worklet;
   1338             std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
   1339 
   1340             // tunings
   1341             dWorklet->tunings.clear();
   1342             dWorklet->tunings.reserve(sWorklet.tunings.size());
   1343             for (const Params& sTuning : sWorklet.tunings) {
   1344                 std::vector<C2Param*> dParams;
   1345                 status = parseParamsBlob(&dParams, sTuning);
   1346                 if (status != C2_OK) {
   1347                     ALOGE("Failed to parse C2Tuning in C2Worklet.");
   1348                     return C2_BAD_VALUE;
   1349                 }
   1350                 for (C2Param* param : dParams) {
   1351                     std::unique_ptr<C2Param> dParam = C2Param::Copy(*param);
   1352                     if (!dParam) {
   1353                         ALOGE("Null C2Tuning encountered while "
   1354                                 "parsing C2Worklet.");
   1355                         return C2_BAD_VALUE;
   1356                     }
   1357                     dWorklet->tunings.emplace_back(
   1358                             std::unique_ptr<C2Tuning>(
   1359                             reinterpret_cast<C2Tuning*>(
   1360                             dParam.release())));
   1361                 }
   1362             }
   1363             // failures
   1364             dWorklet->failures.clear();
   1365             dWorklet->failures.reserve(sWorklet.failures.size());
   1366             for (const SettingResult& sFailure : sWorklet.failures) {
   1367                 std::unique_ptr<C2SettingResult> dFailure;
   1368                 status = objcpy(&dFailure, sFailure);
   1369                 if (status != C2_OK) {
   1370                     ALOGE("Failed to create C2SettingResult in C2Worklet.");
   1371                     return C2_BAD_VALUE;
   1372                 }
   1373                 dWorklet->failures.emplace_back(std::move(dFailure));
   1374             }
   1375             // output
   1376             status = objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks);
   1377             if (status != C2_OK) {
   1378                 ALOGE("Failed to create output C2FrameData.");
   1379                 return C2_BAD_VALUE;
   1380             }
   1381             dWork.worklets.emplace_back(std::move(dWorklet));
   1382         } else {
   1383             dWork.worklets.emplace_back(std::make_unique<C2Worklet>());
   1384             dWork.workletsProcessed = 0;
   1385         }
   1386 
   1387         // result
   1388         dWork.result = static_cast<c2_status_t>(sWork.result);
   1389     }
   1390 
   1391     return C2_OK;
   1392 }
   1393 
   1394 constexpr size_t PARAMS_ALIGNMENT = 8;  // 64-bit alignment
   1395 static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch");
   1396 static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch");
   1397 static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");
   1398 
   1399 // Params -> std::vector<C2Param*>
   1400 c2_status_t parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
   1401     // assuming blob is const here
   1402     size_t size = blob.size();
   1403     size_t ix = 0;
   1404     const uint8_t *data = blob.data();
   1405     C2Param *p = nullptr;
   1406 
   1407     do {
   1408         p = C2ParamUtils::ParseFirst(data + ix, size - ix);
   1409         if (p) {
   1410             params->emplace_back(p);
   1411             ix += p->size();
   1412             ix = align(ix, PARAMS_ALIGNMENT);
   1413         }
   1414     } while (p);
   1415 
   1416     return ix == size ? C2_OK : C2_BAD_VALUE;
   1417 }
   1418 
   1419 namespace /* unnamed */ {
   1420 
   1421 /**
   1422  * Concatenates a list of C2Params into a params blob.
   1423  * \param[out] blob target blob
   1424  * \param[in] params parameters to concatenate
   1425  * \retval C2_OK if the blob was successfully created
   1426  * \retval C2_BAD_VALUE if the blob was not successful (this only happens if the parameters were
   1427  *         not const)
   1428  */
   1429 template<typename T>
   1430 Status _createParamsBlob(hidl_vec<uint8_t> *blob, const T &params) {
   1431     // assuming the parameter values are const
   1432     size_t size = 0;
   1433     for (const auto &p : params) {
   1434         if (!p) {
   1435             continue;
   1436         }
   1437         size += p->size();
   1438         size = align(size, PARAMS_ALIGNMENT);
   1439     }
   1440     blob->resize(size);
   1441     size_t ix = 0;
   1442     for (const auto &p : params) {
   1443         if (!p) {
   1444             continue;
   1445         }
   1446         // NEVER overwrite even if param values (e.g. size) changed
   1447         size_t paramSize = std::min(p->size(), size - ix);
   1448         std::copy(
   1449                 reinterpret_cast<const uint8_t*>(&*p),
   1450                 reinterpret_cast<const uint8_t*>(&*p) + paramSize,
   1451                 &(*blob)[ix]);
   1452         ix += paramSize;
   1453         ix = align(ix, PARAMS_ALIGNMENT);
   1454     }
   1455     blob->resize(ix);
   1456     return ix == size ? Status::OK : Status::CORRUPTED;
   1457 }
   1458 
   1459 } // unnamed namespace
   1460 
   1461 // std::vector<const C2Param*> -> Params
   1462 Status createParamsBlob(
   1463         hidl_vec<uint8_t> *blob,
   1464         const std::vector<const C2Param*> &params) {
   1465     return _createParamsBlob(blob, params);
   1466 }
   1467 
   1468 // std::vector<C2Param*> -> Params
   1469 Status createParamsBlob(
   1470         hidl_vec<uint8_t> *blob,
   1471         const std::vector<C2Param*> &params) {
   1472     return _createParamsBlob(blob, params);
   1473 }
   1474 
   1475 // std::vector<std::unique_ptr<C2Param>> -> Params
   1476 Status createParamsBlob(
   1477         hidl_vec<uint8_t> *blob,
   1478         const std::vector<std::unique_ptr<C2Param>> &params) {
   1479     return _createParamsBlob(blob, params);
   1480 }
   1481 
   1482 // std::vector<std::unique_ptr<C2Tuning>> -> Params
   1483 Status createParamsBlob(
   1484         hidl_vec<uint8_t> *blob,
   1485         const std::vector<std::unique_ptr<C2Tuning>> &params) {
   1486     return _createParamsBlob(blob, params);
   1487 }
   1488 
   1489 // std::vector<std::shared_ptr<const C2Info>> -> Params
   1490 Status createParamsBlob(
   1491         hidl_vec<uint8_t> *blob,
   1492         const std::vector<std::shared_ptr<const C2Info>> &params) {
   1493     return _createParamsBlob(blob, params);
   1494 }
   1495 
   1496 // Params -> std::vector<std::unique_ptr<C2Param>>
   1497 c2_status_t copyParamsFromBlob(
   1498         std::vector<std::unique_ptr<C2Param>>* params,
   1499         Params blob) {
   1500     std::vector<C2Param*> paramPointers;
   1501     c2_status_t status = parseParamsBlob(&paramPointers, blob);
   1502     if (status != C2_OK) {
   1503         ALOGE("copyParamsFromBlob -- blob parsing failed.");
   1504         return status;
   1505     }
   1506     params->resize(paramPointers.size());
   1507     size_t i = 0;
   1508     for (C2Param* const& paramPointer : paramPointers) {
   1509         if (!paramPointer) {
   1510             ALOGE("copyParamsFromBlob -- corrupted params blob.");
   1511             return C2_BAD_VALUE;
   1512         }
   1513         (*params)[i++] = C2Param::Copy(*paramPointer);
   1514     }
   1515     return C2_OK;
   1516 }
   1517 
   1518 // Params -> update std::vector<std::unique_ptr<C2Param>>
   1519 c2_status_t updateParamsFromBlob(
   1520         const std::vector<C2Param*>& params,
   1521         const Params& blob) {
   1522     std::unordered_map<uint32_t, C2Param*> index2param;
   1523     for (C2Param* const& param : params) {
   1524         if (!param) {
   1525             ALOGE("updateParamsFromBlob -- corrupted input params.");
   1526             return C2_BAD_VALUE;
   1527         }
   1528         if (index2param.find(param->index()) == index2param.end()) {
   1529             index2param.emplace(param->index(), param);
   1530         }
   1531     }
   1532 
   1533     std::vector<C2Param*> paramPointers;
   1534     c2_status_t status = parseParamsBlob(&paramPointers, blob);
   1535     if (status != C2_OK) {
   1536         ALOGE("updateParamsFromBlob -- blob parsing failed.");
   1537         return status;
   1538     }
   1539 
   1540     for (C2Param* const& paramPointer : paramPointers) {
   1541         if (!paramPointer) {
   1542             ALOGE("updateParamsFromBlob -- corrupted param in blob.");
   1543             return C2_BAD_VALUE;
   1544         }
   1545         decltype(index2param)::iterator i = index2param.find(
   1546                 paramPointer->index());
   1547         if (i == index2param.end()) {
   1548             ALOGW("updateParamsFromBlob -- unseen param index.");
   1549             continue;
   1550         }
   1551         if (!i->second->updateFrom(*paramPointer)) {
   1552             ALOGE("updateParamsFromBlob -- mismatching sizes: "
   1553                     "%u vs %u (index = %u).",
   1554                     static_cast<unsigned>(params.size()),
   1555                     static_cast<unsigned>(paramPointer->size()),
   1556                     static_cast<unsigned>(i->first));
   1557             return C2_BAD_VALUE;
   1558         }
   1559     }
   1560     return C2_OK;
   1561 }
   1562 
   1563 // Convert BufferPool ResultStatus to c2_status_t.
   1564 c2_status_t toC2Status(ResultStatus rs) {
   1565     switch (rs) {
   1566     case ResultStatus::OK:
   1567         return C2_OK;
   1568     case ResultStatus::NO_MEMORY:
   1569         return C2_NO_MEMORY;
   1570     case ResultStatus::ALREADY_EXISTS:
   1571         return C2_DUPLICATE;
   1572     case ResultStatus::NOT_FOUND:
   1573         return C2_NOT_FOUND;
   1574     case ResultStatus::CRITICAL_ERROR:
   1575         return C2_CORRUPTED;
   1576     default:
   1577         ALOGW("Unrecognized BufferPool ResultStatus: %d", static_cast<int>(rs));
   1578         return C2_CORRUPTED;
   1579     }
   1580 }
   1581 
   1582 namespace /* unnamed */ {
   1583 
   1584 // Create a GraphicBuffer object from a graphic block.
   1585 sp<GraphicBuffer> createGraphicBuffer(const C2ConstGraphicBlock& block) {
   1586     uint32_t width;
   1587     uint32_t height;
   1588     uint32_t format;
   1589     uint64_t usage;
   1590     uint32_t stride;
   1591     uint64_t bqId;
   1592     int32_t bqSlot;
   1593     _UnwrapNativeCodec2GrallocMetadata(
   1594             block.handle(), &width, &height, &format, &usage,
   1595             &stride, &bqId, reinterpret_cast<uint32_t*>(&bqSlot));
   1596     native_handle_t *grallocHandle =
   1597             UnwrapNativeCodec2GrallocHandle(block.handle());
   1598     sp<GraphicBuffer> graphicBuffer =
   1599             new GraphicBuffer(grallocHandle,
   1600                               GraphicBuffer::CLONE_HANDLE,
   1601                               width, height, format,
   1602                               1, usage, stride);
   1603     native_handle_delete(grallocHandle);
   1604     return graphicBuffer;
   1605 }
   1606 
   1607 template <typename BlockProcessor>
   1608 void forEachBlock(C2FrameData& frameData,
   1609                   BlockProcessor process) {
   1610     for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
   1611         if (buffer) {
   1612             for (const C2ConstGraphicBlock& block :
   1613                     buffer->data().graphicBlocks()) {
   1614                 process(block);
   1615             }
   1616         }
   1617     }
   1618 }
   1619 
   1620 template <typename BlockProcessor>
   1621 void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
   1622                   BlockProcessor process,
   1623                   bool processInput, bool processOutput) {
   1624     for (const std::unique_ptr<C2Work>& work : workList) {
   1625         if (!work) {
   1626             continue;
   1627         }
   1628         if (processInput) {
   1629             forEachBlock(work->input, process);
   1630         }
   1631         if (processOutput) {
   1632             for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
   1633                 if (worklet) {
   1634                     forEachBlock(worklet->output,
   1635                                  process);
   1636                 }
   1637             }
   1638         }
   1639     }
   1640 }
   1641 
   1642 sp<HGraphicBufferProducer> getHgbp(const sp<IGraphicBufferProducer>& igbp) {
   1643     sp<HGraphicBufferProducer> hgbp = igbp->getHalInterface();
   1644     return hgbp ? hgbp :
   1645             new TWGraphicBufferProducer<HGraphicBufferProducer>(igbp);
   1646 }
   1647 
   1648 } // unnamed namespace
   1649 
   1650 status_t attachToBufferQueue(const C2ConstGraphicBlock& block,
   1651                              const sp<IGraphicBufferProducer>& igbp,
   1652                              uint32_t generation,
   1653                              int32_t* bqSlot) {
   1654     if (!igbp) {
   1655         ALOGW("attachToBufferQueue -- null producer.");
   1656         return NO_INIT;
   1657     }
   1658 
   1659     sp<GraphicBuffer> graphicBuffer = createGraphicBuffer(block);
   1660     graphicBuffer->setGenerationNumber(generation);
   1661 
   1662     ALOGV("attachToBufferQueue -- attaching buffer: "
   1663             "block dimension %ux%u, "
   1664             "graphicBuffer dimension %ux%u, "
   1665             "format %#x, usage %#llx, stride %u, generation %u.",
   1666             static_cast<unsigned>(block.width()),
   1667             static_cast<unsigned>(block.height()),
   1668             static_cast<unsigned>(graphicBuffer->getWidth()),
   1669             static_cast<unsigned>(graphicBuffer->getHeight()),
   1670             static_cast<unsigned>(graphicBuffer->getPixelFormat()),
   1671             static_cast<unsigned long long>(graphicBuffer->getUsage()),
   1672             static_cast<unsigned>(graphicBuffer->getStride()),
   1673             static_cast<unsigned>(graphicBuffer->getGenerationNumber()));
   1674 
   1675     status_t result = igbp->attachBuffer(bqSlot, graphicBuffer);
   1676     if (result != OK) {
   1677         ALOGW("attachToBufferQueue -- attachBuffer failed. Error code = %d",
   1678                 static_cast<int>(result));
   1679         return false;
   1680     }
   1681     ALOGV("attachToBufferQueue -- attachBuffer returned slot %d",
   1682             static_cast<int>(*bqSlot));
   1683     return true;
   1684 }
   1685 
   1686 bool getBufferQueueAssignment(const C2ConstGraphicBlock& block,
   1687                               uint64_t* bqId,
   1688                               int32_t* bqSlot) {
   1689     return _C2BlockFactory::GetBufferQueueData(
   1690             _C2BlockFactory::GetGraphicBlockPoolData(block),
   1691             bqId, bqSlot);
   1692 }
   1693 
   1694 bool yieldBufferQueueBlock(const C2ConstGraphicBlock& block) {
   1695     std::shared_ptr<_C2BlockPoolData> data =
   1696             _C2BlockFactory::GetGraphicBlockPoolData(block);
   1697     if (data && _C2BlockFactory::GetBufferQueueData(data)) {
   1698         _C2BlockFactory::YieldBlockToBufferQueue(data);
   1699         return true;
   1700     }
   1701     return false;
   1702 }
   1703 
   1704 void yieldBufferQueueBlocks(
   1705         const std::list<std::unique_ptr<C2Work>>& workList,
   1706         bool processInput, bool processOutput) {
   1707     forEachBlock(workList, yieldBufferQueueBlock, processInput, processOutput);
   1708 }
   1709 
   1710 bool holdBufferQueueBlock(const C2ConstGraphicBlock& block,
   1711                             const sp<IGraphicBufferProducer>& igbp,
   1712                             uint64_t bqId,
   1713                             uint32_t generation) {
   1714     std::shared_ptr<_C2BlockPoolData> data =
   1715             _C2BlockFactory::GetGraphicBlockPoolData(block);
   1716     if (!data) {
   1717         return false;
   1718     }
   1719 
   1720     uint64_t oldId;
   1721     int32_t oldSlot;
   1722     // If the block is not bufferqueue-based, do nothing.
   1723     if (!_C2BlockFactory::GetBufferQueueData(data, &oldId, &oldSlot) ||
   1724             (oldId == 0)) {
   1725         return false;
   1726     }
   1727 
   1728     // If the block's bqId is the same as the desired bqId, just hold.
   1729     if (oldId == bqId) {
   1730         ALOGV("holdBufferQueueBlock -- import without attaching: "
   1731                 "bqId %llu, bqSlot %d, generation %u.",
   1732                 static_cast<long long unsigned>(oldId),
   1733                 static_cast<int>(oldSlot),
   1734                 static_cast<unsigned>(generation));
   1735         _C2BlockFactory::HoldBlockFromBufferQueue(data, getHgbp(igbp));
   1736         return true;
   1737     }
   1738 
   1739     // Otherwise, attach to the given igbp, which must not be null.
   1740     if (!igbp) {
   1741         return false;
   1742     }
   1743 
   1744     int32_t bqSlot;
   1745     status_t result = attachToBufferQueue(block, igbp, generation, &bqSlot);
   1746 
   1747     if (result != OK) {
   1748         ALOGE("holdBufferQueueBlock -- fail to attach: "
   1749                 "target bqId %llu, generation %u.",
   1750                 static_cast<long long unsigned>(bqId),
   1751                 static_cast<unsigned>(generation));
   1752 
   1753         return false;
   1754     }
   1755 
   1756     ALOGV("holdBufferQueueBlock -- attached: "
   1757             "bqId %llu, bqSlot %d, generation %u.",
   1758             static_cast<long long unsigned>(bqId),
   1759             static_cast<int>(bqSlot),
   1760             static_cast<unsigned>(generation));
   1761     _C2BlockFactory::AssignBlockToBufferQueue(
   1762             data, getHgbp(igbp), bqId, bqSlot, true);
   1763     return true;
   1764 }
   1765 
   1766 void holdBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>>& workList,
   1767                            const sp<IGraphicBufferProducer>& igbp,
   1768                            uint64_t bqId,
   1769                            uint32_t generation,
   1770                            bool forInput) {
   1771     forEachBlock(workList,
   1772                  std::bind(holdBufferQueueBlock,
   1773                            std::placeholders::_1, igbp, bqId, generation),
   1774                  forInput, !forInput);
   1775 }
   1776 
   1777 }  // namespace utils
   1778 }  // namespace V1_0
   1779 }  // namespace c2
   1780 }  // namespace media
   1781 }  // namespace google
   1782 }  // namespace hardware
   1783 
   1784