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