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