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, ×tampUs);
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(¶ms, 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(¶ms, 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 ¶ms) {
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(¶mPointers, 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*> ¶ms) {
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*> ¶ms) {
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>> ¶ms) {
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>> ¶ms) {
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>> ¶ms) {
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(¶mPointers, 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