• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
asString(Status status,const char * def)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>
underlying_value(EnumClass x)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>
copyVector(DstVector * d,const SrcVector & s)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
objcpy(ParamField * d,const C2ParamField & s)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 {
C2ParamFieldBuilderandroid::hardware::media::c2::V1_0::utils::__anon652206de0111::C2ParamFieldBuilder90     C2ParamFieldBuilder() : C2ParamField(
91             static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) {
92     }
93     // ParamField -> C2ParamField
C2ParamFieldBuilderandroid::hardware::media::c2::V1_0::utils::__anon652206de0111::C2ParamFieldBuilder94     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
objcpy(WorkOrdinal * d,const C2WorkOrdinalStruct & s)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
objcpy(C2WorkOrdinalStruct * d,const WorkOrdinal & s)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
objcpy(ValueRange * d,const decltype(C2FieldSupportedValues::range) & s)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
objcpy(FieldSupportedValues * d,const C2FieldSupportedValues & s)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
objcpy(decltype(C2FieldSupportedValues::range) * d,const ValueRange & s)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
objcpy(C2FieldSupportedValues * d,const FieldSupportedValues & s)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
objcpy(FieldSupportedValuesQuery * d,const C2FieldSupportedValuesQuery & s)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
objcpy(C2FieldSupportedValuesQuery * d,const FieldSupportedValuesQuery & s)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
objcpy(FieldSupportedValuesQueryResult * d,const C2FieldSupportedValuesQuery & s)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
objcpy(C2FieldSupportedValuesQuery * d,const FieldSupportedValuesQuery & sq,const FieldSupportedValuesQueryResult & sr)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
objcpy(IComponentStore::ComponentTraits * d,const C2Component::Traits & s)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>>
objcpy(C2Component::Traits * d,const IComponentStore::ComponentTraits & s)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
objcpy(ParamFieldValues * d,const C2ParamFieldValues & s)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
objcpy(C2ParamFieldValues * d,const ParamFieldValues & s)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
objcpy(SettingResult * d,const C2SettingResult & s)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>
objcpy(std::unique_ptr<C2SettingResult> * d,const SettingResult & s)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
objcpy(ParamDescriptor * d,const C2ParamDescriptor & s)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
objcpy(std::shared_ptr<C2ParamDescriptor> * d,const ParamDescriptor & s)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
objcpy(StructDescriptor * d,const C2StructDescriptor & s)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
objcpy(std::unique_ptr<C2StructDescriptor> * d,const StructDescriptor & s)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.
_addBaseBlock(uint32_t * index,const C2Handle * handle,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)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.
_addBaseBlock(uint32_t * index,const std::shared_ptr<BufferPoolData> bpData,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)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 
addBaseBlock(uint32_t * index,const C2Handle * handle,const std::shared_ptr<const _C2BlockPoolData> & blockPoolData,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)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.
objcpy(hidl_handle * d,const C2Fence & s)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.
objcpy(Block * d,const C2ConstLinearBlock & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)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.
objcpy(Block * d,const C2ConstGraphicBlock & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)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.
objcpy(Buffer * d,const C2BufferData & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)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
objcpy(Buffer * d,const C2Buffer & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)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
objcpy(InfoBuffer * d,const C2InfoBuffer & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)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     d->index = static_cast<ParamIndex>(s.index());
899     Buffer& dBuffer = d->buffer;
900     if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
901         LOG(ERROR) << "Invalid C2InfoBuffer::data";
902         return false;
903     }
904     return true;
905 }
906 
907 // C2FrameData -> FrameData
objcpy(FrameData * d,const C2FrameData & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)908 bool objcpy(FrameData* d, const C2FrameData& s,
909         BufferPoolSender* bufferPoolSender,
910         std::list<BaseBlock>* baseBlocks,
911         std::map<const void*, uint32_t>* baseBlockIndices) {
912     d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
913     if (!objcpy(&d->ordinal, s.ordinal)) {
914         LOG(ERROR) << "Invalid C2FrameData::ordinal.";
915         return false;
916     }
917 
918     d->buffers.resize(s.buffers.size());
919     size_t i = 0;
920     for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
921         Buffer& dBuffer = d->buffers[i++];
922         if (!sBuffer) {
923             // A null (pointer to) C2Buffer corresponds to a Buffer with empty
924             // info and blocks.
925             dBuffer.info.resize(0);
926             dBuffer.blocks.resize(0);
927             continue;
928         }
929         if (!objcpy(
930                 &dBuffer, *sBuffer,
931                 bufferPoolSender, baseBlocks, baseBlockIndices)) {
932             LOG(ERROR) << "Invalid C2FrameData::buffers["
933                        << i - 1 << "].";
934             return false;
935         }
936     }
937 
938     if (!createParamsBlob(&d->configUpdate, s.configUpdate)) {
939         LOG(ERROR) << "Invalid C2FrameData::configUpdate.";
940         return false;
941     }
942 
943     d->infoBuffers.resize(s.infoBuffers.size());
944     i = 0;
945     for (const C2InfoBuffer& sInfoBuffer : s.infoBuffers) {
946         InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
947         if (!objcpy(&dInfoBuffer, sInfoBuffer,
948                 bufferPoolSender, baseBlocks, baseBlockIndices)) {
949             LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
950                        << i - 1 << "].";
951             return false;
952         }
953     }
954 
955     return true;
956 }
957 
958 } // unnamed namespace
959 
960 // DefaultBufferPoolSender's implementation
961 
DefaultBufferPoolSender(const sp<IClientManager> & receiverManager,std::chrono::steady_clock::duration refreshInterval)962 DefaultBufferPoolSender::DefaultBufferPoolSender(
963         const sp<IClientManager>& receiverManager,
964         std::chrono::steady_clock::duration refreshInterval)
965     : mReceiverManager(receiverManager),
966       mRefreshInterval(refreshInterval) {
967 }
968 
setReceiver(const sp<IClientManager> & receiverManager,std::chrono::steady_clock::duration refreshInterval)969 void DefaultBufferPoolSender::setReceiver(
970         const sp<IClientManager>& receiverManager,
971         std::chrono::steady_clock::duration refreshInterval) {
972     std::lock_guard<std::mutex> lock(mMutex);
973     if (mReceiverManager != receiverManager) {
974         mReceiverManager = receiverManager;
975         mConnections.clear();
976     }
977     mRefreshInterval = refreshInterval;
978 }
979 
send(const std::shared_ptr<BufferPoolData> & bpData,BufferStatusMessage * bpMessage)980 ResultStatus DefaultBufferPoolSender::send(
981         const std::shared_ptr<BufferPoolData>& bpData,
982         BufferStatusMessage* bpMessage) {
983     int64_t connectionId = bpData->mConnectionId;
984     if (connectionId == 0) {
985         LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
986         return ResultStatus::CRITICAL_ERROR;
987     }
988     std::lock_guard<std::mutex> lock(mMutex);
989     if (!mReceiverManager) {
990         LOG(ERROR) << "No access to receiver's BufferPool.";
991         return ResultStatus::NOT_FOUND;
992     }
993     if (!mSenderManager) {
994         mSenderManager = ClientManager::getInstance();
995         if (!mSenderManager) {
996             LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
997             return ResultStatus::CRITICAL_ERROR;
998         }
999     }
1000 
1001     int64_t receiverConnectionId{0};
1002     auto foundConnection = mConnections.find(connectionId);
1003     bool isNewConnection = foundConnection == mConnections.end();
1004     std::chrono::steady_clock::time_point now =
1005             std::chrono::steady_clock::now();
1006     if (isNewConnection ||
1007             (now - foundConnection->second.lastSent > mRefreshInterval)) {
1008         // Initialize the bufferpool connection.
1009         ResultStatus rs =
1010                 mSenderManager->registerSender(mReceiverManager,
1011                                                connectionId,
1012                                                &receiverConnectionId);
1013         if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
1014             LOG(WARNING) << "registerSender -- returned error: "
1015                          << static_cast<int32_t>(rs)
1016                          << ".";
1017             return rs;
1018         } else if (receiverConnectionId == 0) {
1019             LOG(WARNING) << "registerSender -- "
1020                             "invalid receiver connection id (0).";
1021             return ResultStatus::CRITICAL_ERROR;
1022         } else {
1023             if (isNewConnection) {
1024                 foundConnection = mConnections.try_emplace(
1025                         connectionId, receiverConnectionId, now).first;
1026             } else {
1027                 foundConnection->second.receiverConnectionId = receiverConnectionId;
1028             }
1029         }
1030     } else {
1031         receiverConnectionId = foundConnection->second.receiverConnectionId;
1032     }
1033 
1034     uint64_t transactionId;
1035     int64_t timestampUs;
1036     ResultStatus rs = mSenderManager->postSend(
1037             receiverConnectionId, bpData, &transactionId, &timestampUs);
1038     if (rs != ResultStatus::OK) {
1039         LOG(ERROR) << "ClientManager::postSend -- returned error: "
1040                    << static_cast<int32_t>(rs)
1041                    << ".";
1042         mConnections.erase(foundConnection);
1043         return rs;
1044     }
1045     if (!bpMessage) {
1046         LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
1047         mConnections.erase(foundConnection);
1048         return ResultStatus::CRITICAL_ERROR;
1049     }
1050     bpMessage->connectionId = receiverConnectionId;
1051     bpMessage->bufferId = bpData->mId;
1052     bpMessage->transactionId = transactionId;
1053     bpMessage->timestampUs = timestampUs;
1054     foundConnection->second.lastSent = now;
1055     return rs;
1056 }
1057 
1058 // std::list<std::unique_ptr<C2Work>> -> WorkBundle
objcpy(WorkBundle * d,const std::list<std::unique_ptr<C2Work>> & s,BufferPoolSender * bufferPoolSender)1059 bool objcpy(
1060         WorkBundle* d,
1061         const std::list<std::unique_ptr<C2Work>>& s,
1062         BufferPoolSender* bufferPoolSender) {
1063     // baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
1064     std::list<BaseBlock> baseBlocks;
1065 
1066     // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
1067     // inside baseBlocks to the corresponding index into baseBlocks. The keys
1068     // (pointers) are used to identify blocks that have the same "base block" in
1069     // s, a list of C2Work objects. Because baseBlocks will be copied into a
1070     // hidl_vec eventually, the values of baseBlockIndices are zero-based
1071     // integer indices instead of list iterators.
1072     //
1073     // Note that the pointers can be raw because baseBlockIndices has a shorter
1074     // lifespan than all of base blocks.
1075     std::map<const void*, uint32_t> baseBlockIndices;
1076 
1077     d->works.resize(s.size());
1078     size_t i = 0;
1079     for (const std::unique_ptr<C2Work>& sWork : s) {
1080         Work &dWork = d->works[i++];
1081         if (!sWork) {
1082             LOG(WARNING) << "Null C2Work encountered.";
1083             continue;
1084         }
1085 
1086         // chain info is not in use currently.
1087 
1088         // input
1089         if (!objcpy(&dWork.input, sWork->input,
1090                 bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
1091             LOG(ERROR) << "Invalid C2Work::input.";
1092             return false;
1093         }
1094 
1095         // worklets
1096         if (sWork->worklets.size() == 0) {
1097             LOG(DEBUG) << "Work with no worklets.";
1098         } else {
1099             // Parcel the worklets.
1100             hidl_vec<Worklet> &dWorklets = dWork.worklets;
1101             dWorklets.resize(sWork->worklets.size());
1102             size_t j = 0;
1103             for (const std::unique_ptr<C2Worklet>& sWorklet : sWork->worklets)
1104             {
1105                 if (!sWorklet) {
1106                     LOG(WARNING) << "Null C2Work::worklets["
1107                                  << j << "].";
1108                     continue;
1109                 }
1110                 Worklet &dWorklet = dWorklets[j++];
1111 
1112                 // component id
1113                 dWorklet.componentId = static_cast<uint32_t>(
1114                         sWorklet->component);
1115 
1116                 // tunings
1117                 if (!createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
1118                     LOG(ERROR) << "Invalid C2Work::worklets["
1119                                << j - 1 << "]->tunings.";
1120                     return false;
1121                 }
1122 
1123                 // failures
1124                 dWorklet.failures.resize(sWorklet->failures.size());
1125                 size_t k = 0;
1126                 for (const std::unique_ptr<C2SettingResult>& sFailure :
1127                         sWorklet->failures) {
1128                     if (!sFailure) {
1129                         LOG(WARNING) << "Null C2Work::worklets["
1130                                      << j - 1 << "]->failures["
1131                                      << k << "].";
1132                         continue;
1133                     }
1134                     if (!objcpy(&dWorklet.failures[k++], *sFailure)) {
1135                         LOG(ERROR) << "Invalid C2Work::worklets["
1136                                    << j - 1 << "]->failures["
1137                                    << k - 1 << "].";
1138                         return false;
1139                     }
1140                 }
1141 
1142                 // output
1143                 if (!objcpy(&dWorklet.output, sWorklet->output,
1144                         bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
1145                     LOG(ERROR) << "Invalid C2Work::worklets["
1146                                << j - 1 << "]->output.";
1147                     return false;
1148                 }
1149             }
1150         }
1151 
1152         // worklets processed
1153         dWork.workletsProcessed = sWork->workletsProcessed;
1154 
1155         // result
1156         dWork.result = static_cast<Status>(sWork->result);
1157     }
1158 
1159     // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
1160     {
1161         d->baseBlocks.resize(baseBlocks.size());
1162         size_t i = 0;
1163         for (const BaseBlock& baseBlock : baseBlocks) {
1164             d->baseBlocks[i++] = baseBlock;
1165         }
1166     }
1167 
1168     return true;
1169 }
1170 
1171 namespace /* unnamed */ {
1172 
1173 struct C2BaseBlock {
1174     enum type_t {
1175         LINEAR,
1176         GRAPHIC,
1177     };
1178     type_t type;
1179     std::shared_ptr<C2LinearBlock> linear;
1180     std::shared_ptr<C2GraphicBlock> graphic;
1181 };
1182 
1183 // hidl_handle -> C2Fence
1184 // Note: File descriptors are not duplicated. The original file descriptor must
1185 // not be closed before the transaction is complete.
objcpy(C2Fence * d,const hidl_handle & s)1186 bool objcpy(C2Fence* d, const hidl_handle& s) {
1187     // TODO: Implement.
1188     (void)s;
1189     *d = C2Fence();
1190     return true;
1191 }
1192 
1193 // C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
createLinearBuffer(std::shared_ptr<C2Buffer> * buffer,const std::shared_ptr<C2LinearBlock> & block,const std::vector<C2Param * > & meta,const C2Fence & fence)1194 bool createLinearBuffer(
1195         std::shared_ptr<C2Buffer>* buffer,
1196         const std::shared_ptr<C2LinearBlock>& block,
1197         const std::vector<C2Param*>& meta,
1198         const C2Fence& fence) {
1199     // Check the block meta. It should have exactly 1 C2Info:
1200     // C2Hidl_RangeInfo.
1201     if ((meta.size() != 1) || !meta[0]) {
1202         LOG(ERROR) << "Invalid C2LinearBlock::meta.";
1203         return false;
1204     }
1205     if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
1206         LOG(ERROR) << "Invalid range info in C2LinearBlock.";
1207         return false;
1208     }
1209     C2Hidl_RangeInfo *rangeInfo =
1210             reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
1211 
1212     // Create C2Buffer from C2LinearBlock.
1213     *buffer = C2Buffer::CreateLinearBuffer(block->share(
1214             rangeInfo->offset, rangeInfo->length,
1215             fence));
1216     if (!(*buffer)) {
1217         LOG(ERROR) << "CreateLinearBuffer failed.";
1218         return false;
1219     }
1220     return true;
1221 }
1222 
1223 // C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
createGraphicBuffer(std::shared_ptr<C2Buffer> * buffer,const std::shared_ptr<C2GraphicBlock> & block,const std::vector<C2Param * > & meta,const C2Fence & fence)1224 bool createGraphicBuffer(
1225         std::shared_ptr<C2Buffer>* buffer,
1226         const std::shared_ptr<C2GraphicBlock>& block,
1227         const std::vector<C2Param*>& meta,
1228         const C2Fence& fence) {
1229     // Check the block meta. It should have exactly 1 C2Info:
1230     // C2Hidl_RectInfo.
1231     if ((meta.size() != 1) || !meta[0]) {
1232         LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
1233         return false;
1234     }
1235     if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
1236         LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
1237         return false;
1238     }
1239     C2Hidl_RectInfo *rectInfo =
1240             reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
1241 
1242     // Create C2Buffer from C2GraphicBlock.
1243     *buffer = C2Buffer::CreateGraphicBuffer(block->share(
1244             C2Rect(rectInfo->width, rectInfo->height).
1245             at(rectInfo->left, rectInfo->top),
1246             fence));
1247     if (!(*buffer)) {
1248         LOG(ERROR) << "CreateGraphicBuffer failed.";
1249         return false;
1250     }
1251     return true;
1252 }
1253 
1254 // Buffer -> C2Buffer
1255 // Note: The native handles will be cloned.
objcpy(std::shared_ptr<C2Buffer> * d,const Buffer & s,const std::vector<C2BaseBlock> & baseBlocks)1256 bool objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
1257         const std::vector<C2BaseBlock>& baseBlocks) {
1258     *d = nullptr;
1259 
1260     // Currently, a non-null C2Buffer must contain exactly 1 block.
1261     if (s.blocks.size() == 0) {
1262         return true;
1263     } else if (s.blocks.size() != 1) {
1264         LOG(ERROR) << "Invalid Buffer: "
1265                       "Currently, a C2Buffer must contain exactly 1 block.";
1266         return false;
1267     }
1268 
1269     const Block &sBlock = s.blocks[0];
1270     if (sBlock.index >= baseBlocks.size()) {
1271         LOG(ERROR) << "Invalid Buffer::blocks[0].index: "
1272                       "Array index out of range.";
1273         return false;
1274     }
1275     const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
1276 
1277     // Parse meta.
1278     std::vector<C2Param*> sBlockMeta;
1279     if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
1280         LOG(ERROR) << "Invalid Buffer::blocks[0].meta.";
1281         return false;
1282     }
1283 
1284     // Copy fence.
1285     C2Fence dFence;
1286     if (!objcpy(&dFence, sBlock.fence)) {
1287         LOG(ERROR) << "Invalid Buffer::blocks[0].fence.";
1288         return false;
1289     }
1290 
1291     // Construct a block.
1292     switch (baseBlock.type) {
1293     case C2BaseBlock::LINEAR:
1294         if (!createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
1295             LOG(ERROR) << "Invalid C2BaseBlock::linear.";
1296             return false;
1297         }
1298         break;
1299     case C2BaseBlock::GRAPHIC:
1300         if (!createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
1301             LOG(ERROR) << "Invalid C2BaseBlock::graphic.";
1302             return false;
1303         }
1304         break;
1305     default:
1306         LOG(ERROR) << "Invalid C2BaseBlock::type.";
1307         return false;
1308     }
1309 
1310     // Parse info
1311     std::vector<C2Param*> params;
1312     if (!parseParamsBlob(&params, s.info)) {
1313         LOG(ERROR) << "Invalid Buffer::info.";
1314         return false;
1315     }
1316     for (C2Param* param : params) {
1317         if (param == nullptr) {
1318             LOG(ERROR) << "Null param in Buffer::info.";
1319             return false;
1320         }
1321         std::shared_ptr<C2Param> c2param{
1322                 C2Param::Copy(*param).release()};
1323         if (!c2param) {
1324             LOG(ERROR) << "Invalid param in Buffer::info.";
1325             return false;
1326         }
1327         c2_status_t status =
1328                 (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
1329         if (status != C2_OK) {
1330             LOG(ERROR) << "C2Buffer::setInfo failed.";
1331             return false;
1332         }
1333     }
1334 
1335     return true;
1336 }
1337 
1338 // InfoBuffer -> C2InfoBuffer
objcpy(std::vector<C2InfoBuffer> * d,const InfoBuffer & s,const std::vector<C2BaseBlock> & baseBlocks)1339 bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
1340         const std::vector<C2BaseBlock>& baseBlocks) {
1341 
1342     // Currently, a non-null C2InfoBufer must contain exactly 1 block.
1343     if (s.buffer.blocks.size() == 0) {
1344         return true;
1345     } else if (s.buffer.blocks.size() != 1) {
1346         LOG(ERROR) << "Invalid InfoBuffer::Buffer "
1347                       "Currently, a C2InfoBuffer must contain exactly 1 block.";
1348         return false;
1349     }
1350 
1351     const Block &sBlock = s.buffer.blocks[0];
1352     if (sBlock.index >= baseBlocks.size()) {
1353         LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
1354                       "Array index out of range.";
1355         return false;
1356     }
1357     const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
1358 
1359     // Parse meta.
1360     std::vector<C2Param*> sBlockMeta;
1361     if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
1362         LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].meta.";
1363         return false;
1364     }
1365 
1366     // Copy fence.
1367     C2Fence dFence;
1368     if (!objcpy(&dFence, sBlock.fence)) {
1369         LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].fence.";
1370         return false;
1371     }
1372 
1373     // Construct a block.
1374     switch (baseBlock.type) {
1375     case C2BaseBlock::LINEAR:
1376         if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
1377             sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
1378             C2Hidl_RangeInfo *rangeInfo =
1379                     reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
1380             d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
1381                     s.index,
1382                     baseBlock.linear->share(
1383                             rangeInfo->offset, rangeInfo->length, dFence)));
1384             return true;
1385         }
1386         LOG(ERROR) << "Invalid Meta for C2BaseBlock::Linear InfoBuffer.";
1387         break;
1388     case C2BaseBlock::GRAPHIC:
1389         // It's not used now
1390         LOG(ERROR) << "Non-Used C2BaseBlock::type for InfoBuffer.";
1391         break;
1392     default:
1393         LOG(ERROR) << "Invalid C2BaseBlock::type for InfoBuffer.";
1394         break;
1395     }
1396 
1397     return false;
1398 }
1399 
1400 // FrameData -> C2FrameData
objcpy(C2FrameData * d,const FrameData & s,const std::vector<C2BaseBlock> & baseBlocks)1401 bool objcpy(C2FrameData* d, const FrameData& s,
1402         const std::vector<C2BaseBlock>& baseBlocks) {
1403     d->flags = static_cast<C2FrameData::flags_t>(s.flags);
1404     if (!objcpy(&d->ordinal, s.ordinal)) {
1405         LOG(ERROR) << "Invalid FrameData::ordinal.";
1406         return false;
1407     }
1408     d->buffers.clear();
1409     d->buffers.reserve(s.buffers.size());
1410     for (const Buffer& sBuffer : s.buffers) {
1411         std::shared_ptr<C2Buffer> dBuffer;
1412         if (!objcpy(&dBuffer, sBuffer, baseBlocks)) {
1413             LOG(ERROR) << "Invalid FrameData::buffers.";
1414             return false;
1415         }
1416         d->buffers.emplace_back(dBuffer);
1417     }
1418 
1419     std::vector<C2Param*> params;
1420     if (!parseParamsBlob(&params, s.configUpdate)) {
1421         LOG(ERROR) << "Invalid FrameData::configUpdate.";
1422         return false;
1423     }
1424     d->configUpdate.clear();
1425     for (C2Param* param : params) {
1426         d->configUpdate.emplace_back(C2Param::Copy(*param));
1427         if (!d->configUpdate.back()) {
1428             LOG(ERROR) << "Unexpected error while parsing "
1429                           "FrameData::configUpdate.";
1430             return false;
1431         }
1432     }
1433 
1434     d->infoBuffers.clear();
1435     if (s.infoBuffers.size() == 0) {
1436         // InfoBuffer is optional
1437         return true;
1438     }
1439     d->infoBuffers.reserve(s.infoBuffers.size());
1440     for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
1441         if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
1442             LOG(ERROR) << "Invalid Framedata::infoBuffers.";
1443             return false;
1444         }
1445     }
1446     return true;
1447 }
1448 
1449 // BaseBlock -> C2BaseBlock
objcpy(C2BaseBlock * d,const BaseBlock & s)1450 bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
1451     switch (s.getDiscriminator()) {
1452     case BaseBlock::hidl_discriminator::nativeBlock: {
1453             native_handle_t* sHandle =
1454                     native_handle_clone(s.nativeBlock());
1455             if (sHandle == nullptr) {
1456                 LOG(ERROR) << "Null BaseBlock::nativeBlock.";
1457                 return false;
1458             }
1459             const C2Handle *sC2Handle =
1460                     reinterpret_cast<const C2Handle*>(sHandle);
1461 
1462             d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
1463             if (d->linear) {
1464                 d->type = C2BaseBlock::LINEAR;
1465                 return true;
1466             }
1467 
1468             d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
1469             if (d->graphic) {
1470                 d->type = C2BaseBlock::GRAPHIC;
1471                 return true;
1472             }
1473 
1474             LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
1475             if (sHandle) {
1476                 native_handle_close(sHandle);
1477                 native_handle_delete(sHandle);
1478             }
1479             return false;
1480         }
1481     case BaseBlock::hidl_discriminator::pooledBlock: {
1482             const BufferStatusMessage &bpMessage =
1483                     s.pooledBlock();
1484             sp<ClientManager> bp = ClientManager::getInstance();
1485             std::shared_ptr<BufferPoolData> bpData;
1486             native_handle_t *cHandle;
1487             ResultStatus bpStatus = bp->receive(
1488                     bpMessage.connectionId,
1489                     bpMessage.transactionId,
1490                     bpMessage.bufferId,
1491                     bpMessage.timestampUs,
1492                     &cHandle,
1493                     &bpData);
1494             if (bpStatus != ResultStatus::OK) {
1495                 LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
1496                            << "resultStatus = " << underlying_value(bpStatus)
1497                            << ".";
1498                 return false;
1499             } else if (!bpData) {
1500                 LOG(ERROR) << "No data in bufferpool transaction.";
1501                 return false;
1502             }
1503 
1504             d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
1505             if (d->linear) {
1506                 d->type = C2BaseBlock::LINEAR;
1507                 return true;
1508             }
1509 
1510             d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
1511             if (d->graphic) {
1512                 d->type = C2BaseBlock::GRAPHIC;
1513                 return true;
1514             }
1515             if (cHandle) {
1516                 // Though we got cloned handle, creating block failed.
1517                 native_handle_close(cHandle);
1518                 native_handle_delete(cHandle);
1519             }
1520 
1521             LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
1522             return false;
1523         }
1524     default:
1525         LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
1526                    << "underlying value "
1527                    << underlying_value(s.getDiscriminator()) << ".";
1528         return false;
1529     }
1530 }
1531 
1532 } // unnamed namespace
1533 
1534 // WorkBundle -> std::list<std::unique_ptr<C2Work>>
objcpy(std::list<std::unique_ptr<C2Work>> * d,const WorkBundle & s)1535 bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
1536     // Convert BaseBlocks to C2BaseBlocks.
1537     std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
1538     for (size_t i = 0; i < s.baseBlocks.size(); ++i) {
1539         if (!objcpy(&dBaseBlocks[i], s.baseBlocks[i])) {
1540             LOG(ERROR) << "Invalid WorkBundle::baseBlocks["
1541                        << i << "].";
1542             return false;
1543         }
1544     }
1545 
1546     d->clear();
1547     for (const Work& sWork : s.works) {
1548         d->emplace_back(std::make_unique<C2Work>());
1549         C2Work& dWork = *d->back();
1550 
1551         // chain info is not in use currently.
1552 
1553         // input
1554         if (!objcpy(&dWork.input, sWork.input, dBaseBlocks)) {
1555             LOG(ERROR) << "Invalid Work::input.";
1556             return false;
1557         }
1558 
1559         // worklet(s)
1560         dWork.worklets.clear();
1561         for (const Worklet& sWorklet : sWork.worklets) {
1562             std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
1563 
1564             // component id
1565             dWorklet->component = static_cast<c2_node_id_t>(
1566                     sWorklet.componentId);
1567 
1568             // tunings
1569             if (!copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
1570                 LOG(ERROR) << "Invalid Worklet::tunings";
1571                 return false;
1572             }
1573 
1574             // failures
1575             dWorklet->failures.clear();
1576             dWorklet->failures.reserve(sWorklet.failures.size());
1577             for (const SettingResult& sFailure : sWorklet.failures) {
1578                 std::unique_ptr<C2SettingResult> dFailure;
1579                 if (!objcpy(&dFailure, sFailure)) {
1580                     LOG(ERROR) << "Invalid Worklet::failures.";
1581                     return false;
1582                 }
1583                 dWorklet->failures.emplace_back(std::move(dFailure));
1584             }
1585 
1586             // output
1587             if (!objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks)) {
1588                 LOG(ERROR) << "Invalid Worklet::output.";
1589                 return false;
1590             }
1591 
1592             dWork.worklets.emplace_back(std::move(dWorklet));
1593         }
1594 
1595         // workletsProcessed
1596         dWork.workletsProcessed = sWork.workletsProcessed;
1597 
1598         // result
1599         dWork.result = static_cast<c2_status_t>(sWork.result);
1600     }
1601 
1602     return true;
1603 }
1604 
1605 constexpr size_t PARAMS_ALIGNMENT = 8;  // 64-bit alignment
1606 static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch");
1607 static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch");
1608 static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");
1609 
1610 // Params -> std::vector<C2Param*>
parseParamsBlob(std::vector<C2Param * > * params,const hidl_vec<uint8_t> & blob)1611 bool parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
1612     // assuming blob is const here
1613     size_t size = blob.size();
1614     size_t ix = 0;
1615     const uint8_t *data = blob.data();
1616     C2Param *p = nullptr;
1617 
1618     do {
1619         p = C2ParamUtils::ParseFirst(data + ix, size - ix);
1620         if (p) {
1621             params->emplace_back(p);
1622             ix += p->size();
1623             ix = align(ix, PARAMS_ALIGNMENT);
1624         }
1625     } while (p);
1626 
1627     if (ix != size) {
1628         LOG(ERROR) << "parseParamsBlob -- inconsistent sizes.";
1629         return false;
1630     }
1631     return true;
1632 }
1633 
1634 namespace /* unnamed */ {
1635 
1636 /**
1637  * Concatenates a list of C2Params into a params blob. T is a container type
1638  * whose member type is compatible with C2Param*.
1639  *
1640  * \param[out] blob target blob
1641  * \param[in] params parameters to concatenate
1642  * \retval C2_OK if the blob was successfully created
1643  * \retval C2_BAD_VALUE if the blob was not successful created (this only
1644  *         happens if the parameters were not const)
1645  */
1646 template <typename T>
_createParamsBlob(hidl_vec<uint8_t> * blob,const T & params)1647 bool _createParamsBlob(hidl_vec<uint8_t> *blob, const T &params) {
1648     // assuming the parameter values are const
1649     size_t size = 0;
1650     for (const auto &p : params) {
1651         if (!p) {
1652             continue;
1653         }
1654         size += p->size();
1655         size = align(size, PARAMS_ALIGNMENT);
1656     }
1657     blob->resize(size);
1658     size_t ix = 0;
1659     for (const auto &p : params) {
1660         if (!p) {
1661             continue;
1662         }
1663         // NEVER overwrite even if param values (e.g. size) changed
1664         size_t paramSize = std::min(p->size(), size - ix);
1665         std::copy(
1666                 reinterpret_cast<const uint8_t*>(&*p),
1667                 reinterpret_cast<const uint8_t*>(&*p) + paramSize,
1668                 &(*blob)[ix]);
1669         ix += paramSize;
1670         ix = align(ix, PARAMS_ALIGNMENT);
1671     }
1672     blob->resize(ix);
1673     if (ix != size) {
1674         LOG(ERROR) << "createParamsBlob -- inconsistent sizes.";
1675         return false;
1676     }
1677     return true;
1678 }
1679 
1680 /**
1681  * Parses a params blob and create a vector of new T objects that contain copies
1682  * of the params in the blob. T is C2Param or its compatible derived class.
1683  *
1684  * \param[out] params the resulting vector
1685  * \param[in] blob parameter blob to parse
1686  * \retval C2_OK if the full blob was parsed and params was constructed
1687  * \retval C2_BAD_VALUE otherwise
1688  */
1689 template <typename T>
_copyParamsFromBlob(std::vector<std::unique_ptr<T>> * params,Params blob)1690 bool _copyParamsFromBlob(
1691         std::vector<std::unique_ptr<T>>* params,
1692         Params blob) {
1693 
1694     std::vector<C2Param*> paramPointers;
1695     if (!parseParamsBlob(&paramPointers, blob)) {
1696         LOG(ERROR) << "copyParamsFromBlob -- failed to parse.";
1697         return false;
1698     }
1699 
1700     params->resize(paramPointers.size());
1701     size_t i = 0;
1702     for (C2Param* const& paramPointer : paramPointers) {
1703         if (!paramPointer) {
1704             LOG(ERROR) << "copyParamsFromBlob -- null paramPointer.";
1705             return false;
1706         }
1707         (*params)[i++].reset(reinterpret_cast<T*>(
1708                 C2Param::Copy(*paramPointer).release()));
1709     }
1710     return true;
1711 }
1712 
1713 } // unnamed namespace
1714 
1715 // std::vector<const C2Param*> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<const C2Param * > & params)1716 bool createParamsBlob(
1717         hidl_vec<uint8_t> *blob,
1718         const std::vector<const C2Param*> &params) {
1719     return _createParamsBlob(blob, params);
1720 }
1721 
1722 // std::vector<C2Param*> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<C2Param * > & params)1723 bool createParamsBlob(
1724         hidl_vec<uint8_t> *blob,
1725         const std::vector<C2Param*> &params) {
1726     return _createParamsBlob(blob, params);
1727 }
1728 
1729 // std::vector<std::unique_ptr<C2Param>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::unique_ptr<C2Param>> & params)1730 bool createParamsBlob(
1731         hidl_vec<uint8_t> *blob,
1732         const std::vector<std::unique_ptr<C2Param>> &params) {
1733     return _createParamsBlob(blob, params);
1734 }
1735 
1736 // std::vector<std::unique_ptr<C2Tuning>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::unique_ptr<C2Tuning>> & params)1737 bool createParamsBlob(
1738         hidl_vec<uint8_t> *blob,
1739         const std::vector<std::unique_ptr<C2Tuning>> &params) {
1740     return _createParamsBlob(blob, params);
1741 }
1742 
1743 // std::vector<std::shared_ptr<const C2Info>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::shared_ptr<const C2Info>> & params)1744 bool createParamsBlob(
1745         hidl_vec<uint8_t> *blob,
1746         const std::vector<std::shared_ptr<const C2Info>> &params) {
1747     return _createParamsBlob(blob, params);
1748 }
1749 
1750 // Params -> std::vector<std::unique_ptr<C2Param>>
copyParamsFromBlob(std::vector<std::unique_ptr<C2Param>> * params,Params blob)1751 bool copyParamsFromBlob(
1752         std::vector<std::unique_ptr<C2Param>>* params,
1753         Params blob) {
1754     return _copyParamsFromBlob(params, blob);
1755 }
1756 
1757 // Params -> std::vector<std::unique_ptr<C2Tuning>>
copyParamsFromBlob(std::vector<std::unique_ptr<C2Tuning>> * params,Params blob)1758 bool copyParamsFromBlob(
1759         std::vector<std::unique_ptr<C2Tuning>>* params,
1760         Params blob) {
1761     return _copyParamsFromBlob(params, blob);
1762 }
1763 
1764 // Params -> update std::vector<std::unique_ptr<C2Param>>
updateParamsFromBlob(const std::vector<C2Param * > & params,const Params & blob)1765 bool updateParamsFromBlob(
1766         const std::vector<C2Param*>& params,
1767         const Params& blob) {
1768     std::unordered_map<uint32_t, C2Param*> index2param;
1769     for (C2Param* const& param : params) {
1770         if (!param) {
1771             LOG(ERROR) << "updateParamsFromBlob -- null output param.";
1772             return false;
1773         }
1774         if (index2param.find(param->index()) == index2param.end()) {
1775             index2param.emplace(param->index(), param);
1776         }
1777     }
1778 
1779     std::vector<C2Param*> paramPointers;
1780     if (!parseParamsBlob(&paramPointers, blob)) {
1781         LOG(ERROR) << "updateParamsFromBlob -- failed to parse.";
1782         return false;
1783     }
1784 
1785     for (C2Param* const& paramPointer : paramPointers) {
1786         if (!paramPointer) {
1787             LOG(ERROR) << "updateParamsFromBlob -- null input param.";
1788             return false;
1789         }
1790         decltype(index2param)::iterator i = index2param.find(
1791                 paramPointer->index());
1792         if (i == index2param.end()) {
1793             LOG(DEBUG) << "updateParamsFromBlob -- index "
1794                        << paramPointer->index() << " not found. Skipping...";
1795             continue;
1796         }
1797         if (!i->second->updateFrom(*paramPointer)) {
1798             LOG(ERROR) << "updateParamsFromBlob -- size mismatch: "
1799                        << params.size() << " vs " << paramPointer->size()
1800                        << " (index = " << i->first << ").";
1801             return false;
1802         }
1803     }
1804     return true;
1805 }
1806 
1807 // Convert BufferPool ResultStatus to c2_status_t.
toC2Status(ResultStatus rs)1808 c2_status_t toC2Status(ResultStatus rs) {
1809     switch (rs) {
1810     case ResultStatus::OK:
1811         return C2_OK;
1812     case ResultStatus::NO_MEMORY:
1813         return C2_NO_MEMORY;
1814     case ResultStatus::ALREADY_EXISTS:
1815         return C2_DUPLICATE;
1816     case ResultStatus::NOT_FOUND:
1817         return C2_NOT_FOUND;
1818     case ResultStatus::CRITICAL_ERROR:
1819         return C2_CORRUPTED;
1820     default:
1821         LOG(WARNING) << "Unrecognized BufferPool ResultStatus: "
1822                      << static_cast<int32_t>(rs) << ".";
1823         return C2_CORRUPTED;
1824     }
1825 }
1826 
1827 namespace /* unnamed */ {
1828 
1829 template <typename BlockProcessor>
forEachBlock(C2FrameData & frameData,BlockProcessor process)1830 void forEachBlock(C2FrameData& frameData,
1831                   BlockProcessor process) {
1832     for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
1833         if (buffer) {
1834             for (const C2ConstGraphicBlock& block :
1835                     buffer->data().graphicBlocks()) {
1836                 process(block);
1837             }
1838         }
1839     }
1840 }
1841 
1842 template <typename BlockProcessor>
forEachBlock(const std::list<std::unique_ptr<C2Work>> & workList,BlockProcessor process,bool processInput,bool processOutput)1843 void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
1844                   BlockProcessor process,
1845                   bool processInput, bool processOutput) {
1846     for (const std::unique_ptr<C2Work>& work : workList) {
1847         if (!work) {
1848             continue;
1849         }
1850         if (processInput) {
1851             forEachBlock(work->input, process);
1852         }
1853         if (processOutput) {
1854             for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
1855                 if (worklet) {
1856                     forEachBlock(worklet->output,
1857                                  process);
1858                 }
1859             }
1860         }
1861     }
1862 }
1863 
1864 } // unnamed namespace
1865 
beginTransferBufferQueueBlock(const C2ConstGraphicBlock & block)1866 bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
1867     std::shared_ptr<_C2BlockPoolData> data =
1868             _C2BlockFactory::GetGraphicBlockPoolData(block);
1869     if (data && _C2BlockFactory::GetBufferQueueData(data)) {
1870         _C2BlockFactory::BeginTransferBlockToClient(data);
1871         return true;
1872     }
1873     return false;
1874 }
1875 
beginTransferBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>> & workList,bool processInput,bool processOutput)1876 void beginTransferBufferQueueBlocks(
1877         const std::list<std::unique_ptr<C2Work>>& workList,
1878         bool processInput, bool processOutput) {
1879     forEachBlock(workList, beginTransferBufferQueueBlock,
1880                  processInput, processOutput);
1881 }
1882 
endTransferBufferQueueBlock(const C2ConstGraphicBlock & block,bool transfer)1883 bool endTransferBufferQueueBlock(
1884         const C2ConstGraphicBlock& block,
1885         bool transfer) {
1886     std::shared_ptr<_C2BlockPoolData> data =
1887             _C2BlockFactory::GetGraphicBlockPoolData(block);
1888     if (data && _C2BlockFactory::GetBufferQueueData(data)) {
1889         _C2BlockFactory::EndTransferBlockToClient(data, transfer);
1890         return true;
1891     }
1892     return false;
1893 }
1894 
endTransferBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>> & workList,bool transfer,bool processInput,bool processOutput)1895 void endTransferBufferQueueBlocks(
1896         const std::list<std::unique_ptr<C2Work>>& workList,
1897         bool transfer,
1898         bool processInput, bool processOutput) {
1899     forEachBlock(workList,
1900                  std::bind(endTransferBufferQueueBlock,
1901                            std::placeholders::_1, transfer),
1902                  processInput, processOutput);
1903 }
1904 
displayBufferQueueBlock(const C2ConstGraphicBlock & block)1905 bool displayBufferQueueBlock(const C2ConstGraphicBlock& block) {
1906     std::shared_ptr<_C2BlockPoolData> data =
1907             _C2BlockFactory::GetGraphicBlockPoolData(block);
1908     if (data && _C2BlockFactory::GetBufferQueueData(data)) {
1909         _C2BlockFactory::DisplayBlockToBufferQueue(data);
1910         return true;
1911     }
1912     return false;
1913 }
1914 
1915 }  // namespace utils
1916 }  // namespace V1_0
1917 }  // namespace c2
1918 }  // namespace media
1919 }  // namespace hardware
1920 }  // namespace android
1921 
1922