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