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 "Codec2Client"
19 #define ATRACE_TAG ATRACE_TAG_VIDEO
20 #include <android-base/logging.h>
21 #include <utils/Trace.h>
22
23 #include <codec2/aidl/GraphicBufferAllocator.h>
24 #include <codec2/hidl/client.h>
25 #include <C2Debug.h>
26 #include <C2BufferPriv.h>
27 #include <C2Config.h> // for C2StreamUsageTuning
28 #include <C2PlatformSupport.h>
29
30 #include <android/hardware/media/bufferpool/2.0/IClientManager.h>
31 #include <android/hardware/media/c2/1.0/IComponent.h>
32 #include <android/hardware/media/c2/1.0/IComponentInterface.h>
33 #include <android/hardware/media/c2/1.0/IComponentListener.h>
34 #include <android/hardware/media/c2/1.0/IComponentStore.h>
35 #include <android/hardware/media/c2/1.0/IConfigurable.h>
36 #include <android/hidl/manager/1.2/IServiceManager.h>
37
38 #include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
39 #include <aidl/android/hardware/media/c2/BnComponentListener.h>
40 #include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
41 #include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
42 #include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
43 #include <aidl/android/hardware/media/c2/IComponent.h>
44 #include <aidl/android/hardware/media/c2/IComponentInterface.h>
45 #include <aidl/android/hardware/media/c2/IComponentStore.h>
46 #include <aidl/android/hardware/media/c2/IConfigurable.h>
47 #include <aidl/android/hardware/media/c2/ParamDescriptor.h>
48 #include <aidl/android/hardware/media/c2/StructDescriptor.h>
49
50 #include <aidlcommonsupport/NativeHandle.h>
51 #include <android/api-level.h>
52 #include <android/binder_auto_utils.h>
53 #include <android/binder_ibinder.h>
54 #include <android/binder_manager.h>
55 #include <android-base/properties.h>
56 #include <android-base/stringprintf.h>
57 #include <bufferpool/ClientManager.h>
58 #include <bufferpool2/ClientManager.h>
59 #include <codec2/aidl/BufferTypes.h>
60 #include <codec2/aidl/ParamTypes.h>
61 #include <codec2/hidl/1.0/types.h>
62 #include <codec2/hidl/1.1/types.h>
63 #include <codec2/hidl/1.2/types.h>
64 #include <codec2/hidl/output.h>
65
66 #include <cutils/native_handle.h>
67 #include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
68 #include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
69 #include <hardware/gralloc.h> // for GRALLOC_USAGE_*
70 #include <hidl/HidlSupport.h>
71 #include <system/window.h> // for NATIVE_WINDOW_QUERY_*
72 #include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
73
74 #include <deque>
75 #include <iterator>
76 #include <limits>
77 #include <map>
78 #include <mutex>
79 #include <optional>
80 #include <sstream>
81 #include <thread>
82 #include <type_traits>
83 #include <vector>
84
85 namespace android {
86
87 using ::android::hardware::hidl_vec;
88 using ::android::hardware::hidl_string;
89 using ::android::hardware::Return;
90 using ::android::hardware::Void;
91
92 using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
93 V1_0::IGraphicBufferProducer;
94 using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
95 V2_0::IGraphicBufferProducer;
96 using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
97 V2_0::utils::B2HGraphicBufferProducer;
98 using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
99 V2_0::utils::H2BGraphicBufferProducer;
100 using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
101
102 using AidlGraphicBufferAllocator = ::aidl::android::hardware::media::c2::
103 implementation::GraphicBufferAllocator;
104
105 namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
106 namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
107 namespace c2_aidl = ::aidl::android::hardware::media::c2;
108 namespace c2_hidl_base = ::android::hardware::media::c2;
109 namespace c2_hidl = ::android::hardware::media::c2::V1_2;
110
111 using c2_hidl::utils::operator<<;
112
113 namespace /* unnamed */ {
114
115 // c2_status_t value that corresponds to hwbinder transaction failure.
116 constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
117
118 // By default prepare buffer to be displayed on any of the common surfaces
119 constexpr uint64_t kDefaultConsumerUsage =
120 (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
121
122 // Searches for a name in GetServiceNames() and returns the index found. If the
123 // name is not found, the returned index will be equal to
124 // GetServiceNames().size().
getServiceIndex(char const * name)125 size_t getServiceIndex(char const* name) {
126 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
127 size_t i = 0;
128 for (; i < names.size(); ++i) {
129 if (name == names[i]) {
130 break;
131 }
132 }
133 return i;
134 }
135
136 class Client2Store : public C2ComponentStore {
137 std::shared_ptr<Codec2Client> mClient;
138
139 public:
Client2Store(std::shared_ptr<Codec2Client> const & client)140 Client2Store(std::shared_ptr<Codec2Client> const& client)
141 : mClient(client) { }
142
143 virtual ~Client2Store() = default;
144
config_sm(std::vector<C2Param * > const & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)145 virtual c2_status_t config_sm(
146 std::vector<C2Param*> const ¶ms,
147 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
148 return mClient->config(params, C2_MAY_BLOCK, failures);
149 };
150
copyBuffer(std::shared_ptr<C2GraphicBuffer>,std::shared_ptr<C2GraphicBuffer>)151 virtual c2_status_t copyBuffer(
152 std::shared_ptr<C2GraphicBuffer>,
153 std::shared_ptr<C2GraphicBuffer>) {
154 return C2_OMITTED;
155 }
156
createComponent(C2String,std::shared_ptr<C2Component> * const component)157 virtual c2_status_t createComponent(
158 C2String, std::shared_ptr<C2Component>* const component) {
159 component->reset();
160 return C2_OMITTED;
161 }
162
createInterface(C2String,std::shared_ptr<C2ComponentInterface> * const interface)163 virtual c2_status_t createInterface(
164 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
165 interface->reset();
166 return C2_OMITTED;
167 }
168
query_sm(std::vector<C2Param * > const & stackParams,std::vector<C2Param::Index> const & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const169 virtual c2_status_t query_sm(
170 std::vector<C2Param*> const& stackParams,
171 std::vector<C2Param::Index> const& heapParamIndices,
172 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
173 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
174 }
175
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const176 virtual c2_status_t querySupportedParams_nb(
177 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
178 return mClient->querySupportedParams(params);
179 }
180
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const181 virtual c2_status_t querySupportedValues_sm(
182 std::vector<C2FieldSupportedValuesQuery>& fields) const {
183 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
184 }
185
getName() const186 virtual C2String getName() const {
187 return mClient->getName();
188 }
189
getParamReflector() const190 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
191 return mClient->getParamReflector();
192 }
193
listComponents()194 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
195 return std::vector<std::shared_ptr<C2Component::Traits const>>();
196 }
197 };
198
GetC2Status(const::ndk::ScopedAStatus & transStatus,const char * method)199 c2_status_t GetC2Status(const ::ndk::ScopedAStatus &transStatus, const char *method) {
200 if (!transStatus.isOk()) {
201 if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
202 c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
203 LOG(DEBUG) << method << " -- call failed: " << status << ".";
204 return status;
205 } else {
206 LOG(ERROR) << method << " -- transaction failed.";
207 return C2_TRANSACTION_FAILED;
208 }
209 }
210 return C2_OK;
211 }
212
213 } // unnamed namespace
214
215 // This class caches a Codec2Client object and its component traits. The client
216 // will be created the first time it is needed, and it can be refreshed if the
217 // service dies (by calling invalidate()). The first time listComponents() is
218 // called from the client, the result will be cached.
219 class Codec2Client::Cache {
220 // Cached client
221 std::shared_ptr<Codec2Client> mClient;
222 mutable std::mutex mClientMutex;
223
224 // Cached component traits
225 std::vector<C2Component::Traits> mTraits;
226 std::once_flag mTraitsInitializationFlag;
227
228 // The index of the service. This is based on GetServiceNames().
229 size_t mIndex;
230 // Called by s() exactly once to initialize the cache. The index must be a
231 // valid index into the vector returned by GetServiceNames(). Calling
232 // init(index) will associate the cache to the service with name
233 // GetServiceNames()[index].
init(size_t index)234 void init(size_t index) {
235 mIndex = index;
236 }
237
238 public:
239 Cache() = default;
240
241 // Initializes mClient if needed, then returns mClient.
242 // If the service is unavailable but listed in the manifest, this function
243 // will block indefinitely.
getClient()244 std::shared_ptr<Codec2Client> getClient() {
245 std::scoped_lock lock{mClientMutex};
246 if (!mClient) {
247 mClient = Codec2Client::_CreateFromIndex(mIndex);
248 }
249 CHECK(mClient) << "Failed to create Codec2Client to service \""
250 << GetServiceNames()[mIndex] << "\". (Index = "
251 << mIndex << ").";
252 return mClient;
253 }
254
255 // Causes a subsequent call to getClient() to create a new client. This
256 // function should be called after the service dies.
257 //
258 // Note: This function is called only by ForAllServices().
invalidate()259 void invalidate() {
260 std::scoped_lock lock{mClientMutex};
261 mClient = nullptr;
262 }
263
264 // Returns a list of traits for components supported by the service. This
265 // list is cached.
getTraits()266 std::vector<C2Component::Traits> const& getTraits() {
267 std::call_once(mTraitsInitializationFlag, [this]() {
268 bool success{false};
269 // Spin until _listComponents() is successful.
270 while (true) {
271 std::shared_ptr<Codec2Client> client = getClient();
272 mTraits = client->_listComponents(&success);
273 if (success) {
274 break;
275 }
276 invalidate();
277 using namespace std::chrono_literals;
278 static constexpr auto kServiceRetryPeriod = 5s;
279 LOG(INFO) << "Failed to retrieve component traits from service "
280 "\"" << GetServiceNames()[mIndex] << "\". "
281 "Retrying...";
282 std::this_thread::sleep_for(kServiceRetryPeriod);
283 }
284 });
285 return mTraits;
286 }
287
288 // List() returns the list of all caches.
List()289 static std::vector<Cache>& List() {
290 static std::vector<Cache> sCaches{[]() {
291 size_t numServices = GetServiceNames().size();
292 std::vector<Cache> caches(numServices);
293 for (size_t i = 0; i < numServices; ++i) {
294 caches[i].init(i);
295 }
296 return caches;
297 }()};
298 return sCaches;
299 }
300 };
301 // Codec2ConfigurableClient::HidlImpl
302
303 struct Codec2ConfigurableClient::HidlImpl : public Codec2ConfigurableClient::ImplBase {
304 typedef c2_hidl::IConfigurable Base;
305
306 // base cannot be null.
307 explicit HidlImpl(const sp<Base>& base);
308
getNameandroid::Codec2ConfigurableClient::HidlImpl309 const C2String& getName() const override {
310 return mName;
311 }
312
313 c2_status_t query(
314 const std::vector<C2Param*>& stackParams,
315 const std::vector<C2Param::Index> &heapParamIndices,
316 c2_blocking_t mayBlock,
317 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
318
319 c2_status_t config(
320 const std::vector<C2Param*> ¶ms,
321 c2_blocking_t mayBlock,
322 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
323
324 c2_status_t querySupportedParams(
325 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
326 ) const override;
327
328 c2_status_t querySupportedValues(
329 std::vector<C2FieldSupportedValuesQuery>& fields,
330 c2_blocking_t mayBlock) const override;
331
332 private:
333 sp<Base> mBase;
334 const C2String mName;
335 };
336
HidlImpl(const sp<Base> & base)337 Codec2ConfigurableClient::HidlImpl::HidlImpl(const sp<Base>& base)
338 : mBase{base},
__anonfa4150790402() 339 mName{[base]() -> C2String {
340 C2String outName;
341 Return<void> transStatus = base->getName(
342 [&outName](const hidl_string& name) {
343 outName = name.c_str();
344 });
345 return transStatus.isOk() ? outName : "";
346 }()} {
347 }
348
query(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const heapParams) const349 c2_status_t Codec2ConfigurableClient::HidlImpl::query(
350 const std::vector<C2Param*> &stackParams,
351 const std::vector<C2Param::Index> &heapParamIndices,
352 c2_blocking_t mayBlock,
353 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
354 hidl_vec<c2_hidl::ParamIndex> indices(
355 stackParams.size() + heapParamIndices.size());
356 size_t numIndices = 0;
357 for (C2Param* const& stackParam : stackParams) {
358 if (!stackParam) {
359 LOG(WARNING) << "query -- null stack param encountered.";
360 continue;
361 }
362 indices[numIndices++] = static_cast<c2_hidl::ParamIndex>(stackParam->index());
363 }
364 size_t numStackIndices = numIndices;
365 for (const C2Param::Index& index : heapParamIndices) {
366 indices[numIndices++] =
367 static_cast<c2_hidl::ParamIndex>(static_cast<uint32_t>(index));
368 }
369 indices.resize(numIndices);
370 if (heapParams) {
371 heapParams->reserve(heapParams->size() + numIndices);
372 }
373 c2_status_t status;
374 Return<void> transStatus = mBase->query(
375 indices,
376 mayBlock == C2_MAY_BLOCK,
377 [&status, &numStackIndices, &stackParams, heapParams](
378 c2_hidl::Status s, const c2_hidl::Params& p) {
379 status = static_cast<c2_status_t>(s);
380 if (status != C2_OK && status != C2_BAD_INDEX) {
381 LOG(DEBUG) << "query -- call failed: "
382 << status << ".";
383 return;
384 }
385 std::vector<C2Param*> paramPointers;
386 if (!c2_hidl::utils::parseParamsBlob(¶mPointers, p)) {
387 LOG(ERROR) << "query -- error while parsing params.";
388 status = C2_CORRUPTED;
389 return;
390 }
391 size_t i = 0;
392 for (auto it = paramPointers.begin();
393 it != paramPointers.end(); ) {
394 C2Param* paramPointer = *it;
395 if (numStackIndices > 0) {
396 --numStackIndices;
397 if (!paramPointer) {
398 LOG(WARNING) << "query -- null stack param.";
399 ++it;
400 continue;
401 }
402 for (; i < stackParams.size() && !stackParams[i]; ) {
403 ++i;
404 }
405 if (i >= stackParams.size()) {
406 LOG(ERROR) << "query -- unexpected error.";
407 status = C2_CORRUPTED;
408 return;
409 }
410 if (stackParams[i]->index() != paramPointer->index()) {
411 LOG(WARNING) << "query -- param skipped: "
412 "index = "
413 << stackParams[i]->index() << ".";
414 stackParams[i++]->invalidate();
415 continue;
416 }
417 if (!stackParams[i++]->updateFrom(*paramPointer)) {
418 LOG(WARNING) << "query -- param update failed: "
419 "index = "
420 << paramPointer->index() << ".";
421 }
422 } else {
423 if (!paramPointer) {
424 LOG(WARNING) << "query -- null heap param.";
425 ++it;
426 continue;
427 }
428 if (!heapParams) {
429 LOG(WARNING) << "query -- "
430 "unexpected extra stack param.";
431 } else {
432 heapParams->emplace_back(
433 C2Param::Copy(*paramPointer));
434 }
435 }
436 ++it;
437 }
438 });
439 if (!transStatus.isOk()) {
440 LOG(ERROR) << "query -- transaction failed.";
441 return C2_TRANSACTION_FAILED;
442 }
443 return status;
444 }
445
config(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)446 c2_status_t Codec2ConfigurableClient::HidlImpl::config(
447 const std::vector<C2Param*> ¶ms,
448 c2_blocking_t mayBlock,
449 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
450 c2_hidl::Params hidlParams;
451 if (!c2_hidl::utils::createParamsBlob(&hidlParams, params)) {
452 LOG(ERROR) << "config -- bad input.";
453 return C2_TRANSACTION_FAILED;
454 }
455 c2_status_t status;
456 Return<void> transStatus = mBase->config(
457 hidlParams,
458 mayBlock == C2_MAY_BLOCK,
459 [&status, ¶ms, failures](
460 c2_hidl::Status s,
461 const hidl_vec<c2_hidl::SettingResult> f,
462 const c2_hidl::Params& o) {
463 status = static_cast<c2_status_t>(s);
464 if (status != C2_OK && status != C2_BAD_INDEX) {
465 LOG(DEBUG) << "config -- call failed: "
466 << status << ".";
467 }
468 size_t i = failures->size();
469 failures->resize(i + f.size());
470 for (const c2_hidl::SettingResult& sf : f) {
471 if (!c2_hidl::utils::objcpy(&(*failures)[i++], sf)) {
472 LOG(ERROR) << "config -- "
473 << "invalid SettingResult returned.";
474 return;
475 }
476 }
477 if (!c2_hidl::utils::updateParamsFromBlob(params, o)) {
478 LOG(ERROR) << "config -- "
479 << "failed to parse returned params.";
480 status = C2_CORRUPTED;
481 }
482 });
483 if (!transStatus.isOk()) {
484 LOG(ERROR) << "config -- transaction failed.";
485 return C2_TRANSACTION_FAILED;
486 }
487 return status;
488 }
489
querySupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const490 c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedParams(
491 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
492 // TODO: Cache and query properly!
493 c2_status_t status;
494 Return<void> transStatus = mBase->querySupportedParams(
495 std::numeric_limits<uint32_t>::min(),
496 std::numeric_limits<uint32_t>::max(),
497 [&status, params](
498 c2_hidl::Status s,
499 const hidl_vec<c2_hidl::ParamDescriptor>& p) {
500 status = static_cast<c2_status_t>(s);
501 if (status != C2_OK) {
502 LOG(DEBUG) << "querySupportedParams -- call failed: "
503 << status << ".";
504 return;
505 }
506 size_t i = params->size();
507 params->resize(i + p.size());
508 for (const c2_hidl::ParamDescriptor& sp : p) {
509 if (!c2_hidl::utils::objcpy(&(*params)[i++], sp)) {
510 LOG(ERROR) << "querySupportedParams -- "
511 << "invalid returned ParamDescriptor.";
512 return;
513 }
514 }
515 });
516 if (!transStatus.isOk()) {
517 LOG(ERROR) << "querySupportedParams -- transaction failed.";
518 return C2_TRANSACTION_FAILED;
519 }
520 return status;
521 }
522
querySupportedValues(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const523 c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedValues(
524 std::vector<C2FieldSupportedValuesQuery>& fields,
525 c2_blocking_t mayBlock) const {
526 hidl_vec<c2_hidl::FieldSupportedValuesQuery> inFields(fields.size());
527 for (size_t i = 0; i < fields.size(); ++i) {
528 if (!c2_hidl::utils::objcpy(&inFields[i], fields[i])) {
529 LOG(ERROR) << "querySupportedValues -- bad input";
530 return C2_TRANSACTION_FAILED;
531 }
532 }
533
534 c2_status_t status;
535 Return<void> transStatus = mBase->querySupportedValues(
536 inFields,
537 mayBlock == C2_MAY_BLOCK,
538 [&status, &inFields, &fields](
539 c2_hidl::Status s,
540 const hidl_vec<c2_hidl::FieldSupportedValuesQueryResult>& r) {
541 status = static_cast<c2_status_t>(s);
542 if (status != C2_OK) {
543 LOG(DEBUG) << "querySupportedValues -- call failed: "
544 << status << ".";
545 return;
546 }
547 if (r.size() != fields.size()) {
548 LOG(ERROR) << "querySupportedValues -- "
549 "input and output lists "
550 "have different sizes.";
551 status = C2_CORRUPTED;
552 return;
553 }
554 for (size_t i = 0; i < fields.size(); ++i) {
555 if (!c2_hidl::utils::objcpy(&fields[i], inFields[i], r[i])) {
556 LOG(ERROR) << "querySupportedValues -- "
557 "invalid returned value.";
558 status = C2_CORRUPTED;
559 return;
560 }
561 }
562 });
563 if (!transStatus.isOk()) {
564 LOG(ERROR) << "querySupportedValues -- transaction failed.";
565 return C2_TRANSACTION_FAILED;
566 }
567 return status;
568 }
569
570 // Codec2ConfigurableClient::AidlImpl
571
572 struct Codec2ConfigurableClient::AidlImpl : public Codec2ConfigurableClient::ImplBase {
573 typedef c2_aidl::IConfigurable Base;
574
575 // base cannot be null.
576 explicit AidlImpl(const std::shared_ptr<Base>& base);
577
getNameandroid::Codec2ConfigurableClient::AidlImpl578 const C2String& getName() const override {
579 return mName;
580 }
581
582 c2_status_t query(
583 const std::vector<C2Param*>& stackParams,
584 const std::vector<C2Param::Index> &heapParamIndices,
585 c2_blocking_t mayBlock,
586 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
587
588 c2_status_t config(
589 const std::vector<C2Param*> ¶ms,
590 c2_blocking_t mayBlock,
591 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
592
593 c2_status_t querySupportedParams(
594 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
595 ) const override;
596
597 c2_status_t querySupportedValues(
598 std::vector<C2FieldSupportedValuesQuery>& fields,
599 c2_blocking_t mayBlock) const override;
600
601 private:
602 std::shared_ptr<Base> mBase;
603 const C2String mName;
604 };
605
AidlImpl(const std::shared_ptr<Base> & base)606 Codec2ConfigurableClient::AidlImpl::AidlImpl(const std::shared_ptr<Base>& base)
607 : mBase{base},
__anonfa4150790a02() 608 mName{[base]() -> C2String {
609 std::string outName;
610 ndk::ScopedAStatus status = base->getName(&outName);
611 return status.isOk() ? outName : "";
612 }()} {
613 }
614
query(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const heapParams) const615 c2_status_t Codec2ConfigurableClient::AidlImpl::query(
616 const std::vector<C2Param*> &stackParams,
617 const std::vector<C2Param::Index> &heapParamIndices,
618 c2_blocking_t mayBlock,
619 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
620 std::vector<int> indices(
621 stackParams.size() + heapParamIndices.size());
622 size_t numIndices = 0;
623 for (C2Param* const& stackParam : stackParams) {
624 if (!stackParam) {
625 LOG(WARNING) << "query -- null stack param encountered.";
626 continue;
627 }
628 indices[numIndices++] = int(stackParam->index());
629 }
630 size_t numStackIndices = numIndices;
631 for (const C2Param::Index& index : heapParamIndices) {
632 indices[numIndices++] = int(static_cast<uint32_t>(index));
633 }
634 indices.resize(numIndices);
635 if (heapParams) {
636 heapParams->reserve(heapParams->size() + numIndices);
637 }
638 c2_aidl::IConfigurable::QueryResult result;
639 ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
640 c2_status_t status = GetC2Status(transStatus, "query");
641 if (status != C2_OK) {
642 return status;
643 }
644 status = static_cast<c2_status_t>(result.status.status);
645
646 std::vector<C2Param*> paramPointers;
647 if (!c2_aidl::utils::ParseParamsBlob(¶mPointers, result.params)) {
648 LOG(ERROR) << "query -- error while parsing params.";
649 return C2_CORRUPTED;
650 }
651 size_t i = 0;
652 size_t numQueried = 0;
653 for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
654 C2Param* paramPointer = *it;
655 if (numStackIndices > 0) {
656 --numStackIndices;
657 if (!paramPointer) {
658 LOG(DEBUG) << "query -- null stack param.";
659 ++it;
660 continue;
661 }
662 for (; i < stackParams.size() && !stackParams[i]; ) {
663 ++i;
664 }
665 if (i >= stackParams.size()) {
666 LOG(ERROR) << "query -- unexpected error.";
667 status = C2_CORRUPTED;
668 break;
669 }
670 if (stackParams[i]->index() != paramPointer->index()) {
671 LOG(DEBUG) << "query -- param skipped: "
672 "index = "
673 << stackParams[i]->index() << ".";
674 stackParams[i++]->invalidate();
675 // this means that the param could not be queried.
676 // signalling C2_BAD_INDEX to the client.
677 status = C2_BAD_INDEX;
678 continue;
679 }
680 if (stackParams[i++]->updateFrom(*paramPointer)) {
681 ++numQueried;
682 } else {
683 LOG(WARNING) << "query -- param update failed: "
684 "index = "
685 << paramPointer->index() << ".";
686 }
687 } else {
688 if (!paramPointer) {
689 LOG(DEBUG) << "query -- null heap param.";
690 ++it;
691 continue;
692 }
693 if (!heapParams) {
694 LOG(WARNING) << "query -- "
695 "unexpected extra stack param.";
696 } else {
697 heapParams->emplace_back(C2Param::Copy(*paramPointer));
698 ++numQueried;
699 }
700 }
701 ++it;
702 }
703 if (status == C2_OK && indices.size() != numQueried) {
704 status = C2_BAD_INDEX;
705 }
706 return status;
707 }
708
config(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)709 c2_status_t Codec2ConfigurableClient::AidlImpl::config(
710 const std::vector<C2Param*> ¶ms,
711 c2_blocking_t mayBlock,
712 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
713 c2_aidl::Params aidlParams;
714 if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
715 LOG(ERROR) << "config -- bad input.";
716 return C2_TRANSACTION_FAILED;
717 }
718 c2_aidl::IConfigurable::ConfigResult result;
719 ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
720 c2_status_t status = GetC2Status(transStatus, "config");
721 if (status != C2_OK) {
722 return status;
723 }
724 status = static_cast<c2_status_t>(result.status.status);
725 size_t i = failures->size();
726 failures->resize(i + result.failures.size());
727 for (const c2_aidl::SettingResult& sf : result.failures) {
728 if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
729 LOG(ERROR) << "config -- invalid SettingResult returned.";
730 return C2_CORRUPTED;
731 }
732 }
733 if (!c2_aidl::utils::UpdateParamsFromBlob(params, result.params)) {
734 LOG(ERROR) << "config -- "
735 << "failed to parse returned params.";
736 status = C2_CORRUPTED;
737 }
738 return status;
739 }
740
querySupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const741 c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
742 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
743 // TODO: Cache and query properly!
744 std::vector<c2_aidl::ParamDescriptor> result;
745 ndk::ScopedAStatus transStatus = mBase->querySupportedParams(
746 std::numeric_limits<uint32_t>::min(),
747 std::numeric_limits<uint32_t>::max(),
748 &result);
749 c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
750 if (status != C2_OK) {
751 return status;
752 }
753 size_t i = params->size();
754 params->resize(i + result.size());
755 for (const c2_aidl::ParamDescriptor& sp : result) {
756 if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
757 LOG(ERROR) << "querySupportedParams -- invalid returned ParamDescriptor.";
758 return C2_CORRUPTED;
759 }
760 }
761 return status;
762 }
763
querySupportedValues(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const764 c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
765 std::vector<C2FieldSupportedValuesQuery>& fields,
766 c2_blocking_t mayBlock) const {
767 std::vector<c2_aidl::FieldSupportedValuesQuery> inFields(fields.size());
768 for (size_t i = 0; i < fields.size(); ++i) {
769 if (!c2_aidl::utils::ToAidl(&inFields[i], fields[i])) {
770 LOG(ERROR) << "querySupportedValues -- bad input";
771 return C2_TRANSACTION_FAILED;
772 }
773 }
774
775 c2_aidl::IConfigurable::QuerySupportedValuesResult result;
776
777 ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
778 inFields, (mayBlock == C2_MAY_BLOCK), &result);
779 c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
780 if (status != C2_OK) {
781 return status;
782 }
783 status = static_cast<c2_status_t>(result.status.status);
784 if (result.values.size() != fields.size()) {
785 LOG(ERROR) << "querySupportedValues -- "
786 "input and output lists "
787 "have different sizes.";
788 return C2_CORRUPTED;
789 }
790 for (size_t i = 0; i < fields.size(); ++i) {
791 if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result.values[i])) {
792 LOG(ERROR) << "querySupportedValues -- "
793 "invalid returned value.";
794 return C2_CORRUPTED;
795 }
796 }
797 return status;
798 }
799
800 // Codec2ConfigurableClient
801
Codec2ConfigurableClient(const sp<HidlBase> & hidlBase)802 Codec2ConfigurableClient::Codec2ConfigurableClient(const sp<HidlBase> &hidlBase)
803 : mImpl(new Codec2ConfigurableClient::HidlImpl(hidlBase)) {
804 }
805
Codec2ConfigurableClient(const std::shared_ptr<AidlBase> & aidlBase)806 Codec2ConfigurableClient::Codec2ConfigurableClient(
807 const std::shared_ptr<AidlBase> &aidlBase)
808 : mImpl(new Codec2ConfigurableClient::AidlImpl(aidlBase)) {
809 }
810
getName() const811 const C2String& Codec2ConfigurableClient::getName() const {
812 return mImpl->getName();
813 }
814
query(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const heapParams) const815 c2_status_t Codec2ConfigurableClient::query(
816 const std::vector<C2Param*>& stackParams,
817 const std::vector<C2Param::Index> &heapParamIndices,
818 c2_blocking_t mayBlock,
819 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
820 return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams);
821 }
822
config(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)823 c2_status_t Codec2ConfigurableClient::config(
824 const std::vector<C2Param*> ¶ms,
825 c2_blocking_t mayBlock,
826 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
827 return mImpl->config(params, mayBlock, failures);
828 }
829
querySupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const830 c2_status_t Codec2ConfigurableClient::querySupportedParams(
831 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
832 return mImpl->querySupportedParams(params);
833 }
834
querySupportedValues(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const835 c2_status_t Codec2ConfigurableClient::querySupportedValues(
836 std::vector<C2FieldSupportedValuesQuery>& fields,
837 c2_blocking_t mayBlock) const {
838 return mImpl->querySupportedValues(fields, mayBlock);
839 }
840
841
842 // Codec2Client::Component::HidlListener
843 struct Codec2Client::Component::HidlListener : public c2_hidl::IComponentListener {
844 std::weak_ptr<Component> component;
845 std::weak_ptr<Listener> base;
846
onWorkDoneandroid::Codec2Client::Component::HidlListener847 virtual Return<void> onWorkDone(const c2_hidl::WorkBundle& workBundle) override {
848 std::list<std::unique_ptr<C2Work>> workItems;
849 if (!c2_hidl::utils::objcpy(&workItems, workBundle)) {
850 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
851 return Void();
852 }
853 // release input buffers potentially held by the component from queue
854 std::shared_ptr<Codec2Client::Component> strongComponent =
855 component.lock();
856 if (strongComponent) {
857 strongComponent->handleOnWorkDone(workItems);
858 }
859 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
860 listener->onWorkDone(component, workItems);
861 } else {
862 LOG(DEBUG) << "onWorkDone -- listener died.";
863 }
864 return Void();
865 }
866
onTrippedandroid::Codec2Client::Component::HidlListener867 virtual Return<void> onTripped(
868 const hidl_vec<c2_hidl::SettingResult>& settingResults) override {
869 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
870 settingResults.size());
871 for (size_t i = 0; i < settingResults.size(); ++i) {
872 std::unique_ptr<C2SettingResult> c2SettingResult;
873 if (!c2_hidl::utils::objcpy(&c2SettingResult, settingResults[i])) {
874 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
875 return Void();
876 }
877 c2SettingResults[i] = std::move(c2SettingResult);
878 }
879 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
880 listener->onTripped(component, c2SettingResults);
881 } else {
882 LOG(DEBUG) << "onTripped -- listener died.";
883 }
884 return Void();
885 }
886
onErrorandroid::Codec2Client::Component::HidlListener887 virtual Return<void> onError(c2_hidl::Status s, uint32_t errorCode) override {
888 LOG(DEBUG) << "onError --"
889 << " status = " << s
890 << ", errorCode = " << errorCode
891 << ".";
892 if (std::shared_ptr<Listener> listener = base.lock()) {
893 listener->onError(component, s == c2_hidl::Status::OK ?
894 errorCode : static_cast<c2_status_t>(s));
895 } else {
896 LOG(DEBUG) << "onError -- listener died.";
897 }
898 return Void();
899 }
900
onFramesRenderedandroid::Codec2Client::Component::HidlListener901 virtual Return<void> onFramesRendered(
902 const hidl_vec<RenderedFrame>& renderedFrames) override {
903 std::shared_ptr<Listener> listener = base.lock();
904 if (!listener) {
905 LOG(DEBUG) << "onFramesRendered -- listener died.";
906 return Void();
907 }
908 for (const RenderedFrame& renderedFrame : renderedFrames) {
909 listener->onFrameRendered(
910 renderedFrame.bufferQueueId,
911 renderedFrame.slotId,
912 renderedFrame.timestampNs);
913 }
914 return Void();
915 }
916
onInputBuffersReleasedandroid::Codec2Client::Component::HidlListener917 virtual Return<void> onInputBuffersReleased(
918 const hidl_vec<InputBuffer>& inputBuffers) override {
919 std::shared_ptr<Listener> listener = base.lock();
920 if (!listener) {
921 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
922 return Void();
923 }
924 for (const InputBuffer& inputBuffer : inputBuffers) {
925 LOG(VERBOSE) << "onInputBuffersReleased --"
926 " received death notification of"
927 " input buffer:"
928 " frameIndex = " << inputBuffer.frameIndex
929 << ", bufferIndex = " << inputBuffer.arrayIndex
930 << ".";
931 listener->onInputBufferDone(
932 inputBuffer.frameIndex, inputBuffer.arrayIndex);
933 }
934 return Void();
935 }
936
937 };
938
939 // Codec2Client::Component::AidlListener
940 struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
941 std::weak_ptr<Component> component;
942 std::weak_ptr<Listener> base;
943
onWorkDoneandroid::Codec2Client::Component::AidlListener944 virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
945 std::list<std::unique_ptr<C2Work>> workItems;
946 if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
947 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
948 return ::ndk::ScopedAStatus::ok();
949 }
950 // release input buffers potentially held by the component from queue
951 std::shared_ptr<Codec2Client::Component> strongComponent =
952 component.lock();
953 if (strongComponent) {
954 strongComponent->handleOnWorkDone(workItems);
955 }
956 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
957 listener->onWorkDone(component, workItems);
958 } else {
959 LOG(DEBUG) << "onWorkDone -- listener died.";
960 }
961 return ::ndk::ScopedAStatus::ok();
962 }
963
onTrippedandroid::Codec2Client::Component::AidlListener964 virtual ::ndk::ScopedAStatus onTripped(
965 const std::vector<c2_aidl::SettingResult>& settingResults) override {
966 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
967 settingResults.size());
968 for (size_t i = 0; i < settingResults.size(); ++i) {
969 std::unique_ptr<C2SettingResult> c2SettingResult;
970 if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
971 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
972 return ::ndk::ScopedAStatus::ok();
973 }
974 c2SettingResults[i] = std::move(c2SettingResult);
975 }
976 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
977 listener->onTripped(component, c2SettingResults);
978 } else {
979 LOG(DEBUG) << "onTripped -- listener died.";
980 }
981 return ::ndk::ScopedAStatus::ok();
982 }
983
onErrorandroid::Codec2Client::Component::AidlListener984 virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
985 LOG(DEBUG) << "onError --"
986 << " status = " << s.status
987 << ", errorCode = " << errorCode
988 << ".";
989 if (std::shared_ptr<Listener> listener = base.lock()) {
990 listener->onError(component, s.status == c2_aidl::Status::OK ?
991 errorCode : static_cast<c2_status_t>(s.status));
992 } else {
993 LOG(DEBUG) << "onError -- listener died.";
994 }
995 return ::ndk::ScopedAStatus::ok();
996 }
997
onFramesRenderedandroid::Codec2Client::Component::AidlListener998 virtual ::ndk::ScopedAStatus onFramesRendered(
999 const std::vector<RenderedFrame>& renderedFrames) override {
1000 std::shared_ptr<Listener> listener = base.lock();
1001 if (!listener) {
1002 LOG(DEBUG) << "onFramesRendered -- listener died.";
1003 return ::ndk::ScopedAStatus::ok();
1004 }
1005 for (const RenderedFrame& renderedFrame : renderedFrames) {
1006 listener->onFrameRendered(
1007 renderedFrame.bufferQueueId,
1008 renderedFrame.slotId,
1009 renderedFrame.timestampNs);
1010 }
1011 return ::ndk::ScopedAStatus::ok();
1012 }
1013
onInputBuffersReleasedandroid::Codec2Client::Component::AidlListener1014 virtual ::ndk::ScopedAStatus onInputBuffersReleased(
1015 const std::vector<InputBuffer>& inputBuffers) override {
1016 std::shared_ptr<Listener> listener = base.lock();
1017 if (!listener) {
1018 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
1019 return ::ndk::ScopedAStatus::ok();
1020 }
1021 for (const InputBuffer& inputBuffer : inputBuffers) {
1022 LOG(VERBOSE) << "onInputBuffersReleased --"
1023 " received death notification of"
1024 " input buffer:"
1025 " frameIndex = " << inputBuffer.frameIndex
1026 << ", bufferIndex = " << inputBuffer.arrayIndex
1027 << ".";
1028 listener->onInputBufferDone(
1029 inputBuffer.frameIndex, inputBuffer.arrayIndex);
1030 }
1031 return ::ndk::ScopedAStatus::ok();
1032 }
1033
1034 };
1035
1036 // Codec2Client::Component::HidlBufferPoolSender
1037 struct Codec2Client::Component::HidlBufferPoolSender :
1038 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
HidlBufferPoolSenderandroid::Codec2Client::Component::HidlBufferPoolSender1039 HidlBufferPoolSender()
1040 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
1041 }
1042 };
1043
1044 // Codec2Client::Component::AidlBufferPoolSender
1045 struct Codec2Client::Component::AidlBufferPoolSender :
1046 c2_aidl::utils::DefaultBufferPoolSender {
AidlBufferPoolSenderandroid::Codec2Client::Component::AidlBufferPoolSender1047 AidlBufferPoolSender()
1048 : c2_aidl::utils::DefaultBufferPoolSender() {
1049 }
1050 };
1051
1052 // Codec2Client::Component::OutputBufferQueue
1053 struct Codec2Client::Component::OutputBufferQueue :
1054 hardware::media::c2::OutputBufferQueue {
OutputBufferQueueandroid::Codec2Client::Component::OutputBufferQueue1055 OutputBufferQueue()
1056 : hardware::media::c2::OutputBufferQueue() {
1057 }
1058 };
1059
1060 // The class holds GraphicBufferAllocator and the associated id of
1061 // HAL side BlockPool.
1062 // This is tightly coupled with BlockPool creation and destruction.
1063 // The life cycle inside class will be as follows.
1064 //
1065 // On createBlockPool client request.
1066 // 1. this::create() creates a GraphicBufferAllocator and set it as
1067 // the current.
1068 // 2. C2AIDL_HAL::createBlockPool() creates a C2BlockPool using
1069 // the GraphicBufferAllocator created in #1.
1070 // 3. this::setCurrentId() associates the id returned in #2 to the current
1071 //
1072 // On destroyBlockPool cliet request
1073 // 1. C2AIDL_HAL::destroyBlockPool() destroys the block pool
1074 // from HAL process.
1075 // 2. this::remove() destroys GraphicBufferAllocator which is associatted
1076 // with the C2BlockPool in #1.
1077 //
1078 struct Codec2Client::Component::GraphicBufferAllocators {
1079 private:
1080 std::optional<C2BlockPool::local_id_t> mCurrentId;
1081 std::shared_ptr<AidlGraphicBufferAllocator> mCurrent;
1082
1083 // A new BlockPool is created before the old BlockPool is destroyed.
1084 // This holds the reference of the old BlockPool when a new BlockPool is
1085 // created until the old BlockPool is explicitly requested for destruction.
1086 std::map<C2BlockPool::local_id_t, std::shared_ptr<AidlGraphicBufferAllocator>> mOlds;
1087 std::mutex mMutex;
1088
1089 public:
1090 // Creates a GraphicBufferAllocator which will be passed to HAL
1091 // for creating C2BlockPool. And the created GraphicBufferAllocator
1092 // will be used afterwards by current().
createandroid::Codec2Client::Component::GraphicBufferAllocators1093 std::shared_ptr<AidlGraphicBufferAllocator> create() {
1094 std::unique_lock<std::mutex> l(mMutex);
1095 if (mCurrent) {
1096 // If this is not stopped.
1097 mCurrent->reset();
1098 if (mCurrentId.has_value()) {
1099 mOlds.emplace(mCurrentId.value(), mCurrent);
1100 }
1101 mCurrentId.reset();
1102 mCurrent.reset();
1103 }
1104 // TODO: integrate initial value with CCodec/CCodecBufferChannel
1105 mCurrent =
1106 AidlGraphicBufferAllocator::CreateGraphicBufferAllocator(3 /* maxDequeueCount */);
1107 ALOGD("GraphicBufferAllocator created");
1108 return mCurrent;
1109 }
1110
1111 // Associates the blockpool Id returned from HAL to the
1112 // current GraphicBufferAllocator.
setCurrentIdandroid::Codec2Client::Component::GraphicBufferAllocators1113 void setCurrentId(C2BlockPool::local_id_t id) {
1114 std::unique_lock<std::mutex> l(mMutex);
1115 CHECK(!mCurrentId.has_value());
1116 mCurrentId = id;
1117 }
1118
1119 // Returns the current GraphicBufferAllocator.
currentandroid::Codec2Client::Component::GraphicBufferAllocators1120 std::shared_ptr<AidlGraphicBufferAllocator> current() {
1121 std::unique_lock<std::mutex> l(mMutex);
1122 return mCurrent;
1123 }
1124
1125 // Removes the GraphicBufferAllocator associated with given \p id.
removeandroid::Codec2Client::Component::GraphicBufferAllocators1126 void remove(C2BlockPool::local_id_t id) {
1127 std::unique_lock<std::mutex> l(mMutex);
1128 mOlds.erase(id);
1129 if (mCurrentId == id) {
1130 if (mCurrent) {
1131 mCurrent->reset();
1132 mCurrent.reset();
1133 }
1134 mCurrentId.reset();
1135 }
1136 }
1137 };
1138
1139 // Codec2Client
Codec2Client(sp<HidlBase> const & base,sp<c2_hidl::IConfigurable> const & configurable,size_t serviceIndex)1140 Codec2Client::Codec2Client(sp<HidlBase> const& base,
1141 sp<c2_hidl::IConfigurable> const& configurable,
1142 size_t serviceIndex)
1143 : Configurable{configurable},
1144 mHidlBase1_0{base},
1145 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1146 mHidlBase1_2{HidlBase1_2::castFrom(base)},
1147 mServiceIndex{serviceIndex} {
1148 Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
1149 if (!transResult.isOk()) {
1150 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
1151 } else {
1152 mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
1153 }
1154 }
1155
Codec2Client(std::shared_ptr<AidlBase> const & base,std::shared_ptr<c2_aidl::IConfigurable> const & configurable,size_t serviceIndex)1156 Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
1157 std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
1158 size_t serviceIndex)
1159 : Configurable{configurable},
1160 mAidlBase{base},
1161 mServiceIndex{serviceIndex} {
1162 ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
1163 if (!transStatus.isOk()) {
1164 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
1165 mAidlHostPoolManager.reset();
1166 }
1167 }
1168
getHidlBase() const1169 sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
1170 return mHidlBase1_0;
1171 }
1172
getHidlBase1_0() const1173 sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
1174 return mHidlBase1_0;
1175 }
1176
getHidlBase1_1() const1177 sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
1178 return mHidlBase1_1;
1179 }
1180
getHidlBase1_2() const1181 sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
1182 return mHidlBase1_2;
1183 }
1184
getAidlBase() const1185 ::ndk::SpAIBinder Codec2Client::getAidlBase() const {
1186 return mAidlBase ? mAidlBase->asBinder() : nullptr;
1187 }
1188
getServiceName() const1189 std::string const& Codec2Client::getServiceName() const {
1190 return GetServiceNames()[mServiceIndex];
1191 }
1192
createComponent(const C2String & name,const std::shared_ptr<Codec2Client::Listener> & listener,std::shared_ptr<Codec2Client::Component> * const component)1193 c2_status_t Codec2Client::createComponent(
1194 const C2String& name,
1195 const std::shared_ptr<Codec2Client::Listener>& listener,
1196 std::shared_ptr<Codec2Client::Component>* const component) {
1197 if (mAidlBase) {
1198 std::shared_ptr<Component::AidlListener> aidlListener =
1199 Component::AidlListener::make<Component::AidlListener>();
1200 aidlListener->base = listener;
1201 std::shared_ptr<c2_aidl::IComponent> aidlComponent;
1202 ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
1203 name,
1204 aidlListener,
1205 bufferpool2_aidl::implementation::ClientManager::getInstance(),
1206 &aidlComponent);
1207 c2_status_t status = GetC2Status(transStatus, "createComponent");
1208 if (status != C2_OK) {
1209 return status;
1210 } else if (!aidlComponent) {
1211 LOG(ERROR) << "createComponent(" << name.c_str()
1212 << ") -- null component.";
1213 return C2_CORRUPTED;
1214 }
1215 *component = std::make_shared<Codec2Client::Component>(aidlComponent);
1216 status = (*component)->setDeathListener((*component), listener);
1217 if (status != C2_OK) {
1218 LOG(ERROR) << "createComponent(" << name.c_str()
1219 << ") -- failed to set up death listener: "
1220 << status << ".";
1221 }
1222 (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
1223 aidlListener->component = *component;
1224 return status;
1225 }
1226
1227 c2_status_t status;
1228 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
1229 hidlListener->base = listener;
1230 Return<void> transStatus;
1231 if (mHidlBase1_2) {
1232 transStatus = mHidlBase1_2->createComponent_1_2(
1233 name,
1234 hidlListener,
1235 bufferpool_hidl::implementation::ClientManager::getInstance(),
1236 [&status, component, hidlListener](
1237 c2_hidl::Status s,
1238 const sp<c2_hidl::IComponent>& c) {
1239 status = static_cast<c2_status_t>(s);
1240 if (status != C2_OK) {
1241 return;
1242 }
1243 *component = std::make_shared<Codec2Client::Component>(c);
1244 hidlListener->component = *component;
1245 });
1246 }
1247 else if (mHidlBase1_1) {
1248 transStatus = mHidlBase1_1->createComponent_1_1(
1249 name,
1250 hidlListener,
1251 bufferpool_hidl::implementation::ClientManager::getInstance(),
1252 [&status, component, hidlListener](
1253 c2_hidl::Status s,
1254 const sp<c2_hidl_base::V1_1::IComponent>& c) {
1255 status = static_cast<c2_status_t>(s);
1256 if (status != C2_OK) {
1257 return;
1258 }
1259 *component = std::make_shared<Codec2Client::Component>(c);
1260 hidlListener->component = *component;
1261 });
1262 } else if (mHidlBase1_0) { // ver1_0
1263 transStatus = mHidlBase1_0->createComponent(
1264 name,
1265 hidlListener,
1266 bufferpool_hidl::implementation::ClientManager::getInstance(),
1267 [&status, component, hidlListener](
1268 c2_hidl::Status s,
1269 const sp<c2_hidl_base::V1_0::IComponent>& c) {
1270 status = static_cast<c2_status_t>(s);
1271 if (status != C2_OK) {
1272 return;
1273 }
1274 *component = std::make_shared<Codec2Client::Component>(c);
1275 hidlListener->component = *component;
1276 });
1277 } else {
1278 status = C2_CORRUPTED;
1279 }
1280 if (!transStatus.isOk()) {
1281 LOG(ERROR) << "createComponent(" << name.c_str()
1282 << ") -- transaction failed.";
1283 return C2_TRANSACTION_FAILED;
1284 } else if (status != C2_OK) {
1285 if (status == C2_NOT_FOUND) {
1286 LOG(VERBOSE) << "createComponent(" << name.c_str()
1287 << ") -- component not found.";
1288 } else {
1289 LOG(ERROR) << "createComponent(" << name.c_str()
1290 << ") -- call failed: " << status << ".";
1291 }
1292 return status;
1293 } else if (!*component) {
1294 LOG(ERROR) << "createComponent(" << name.c_str()
1295 << ") -- null component.";
1296 return C2_CORRUPTED;
1297 }
1298
1299 status = (*component)->setDeathListener(*component, listener);
1300 if (status != C2_OK) {
1301 LOG(ERROR) << "createComponent(" << name.c_str()
1302 << ") -- failed to set up death listener: "
1303 << status << ".";
1304 }
1305
1306 (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
1307 return status;
1308 }
1309
createInterface(const C2String & name,std::shared_ptr<Codec2Client::Interface> * const interface)1310 c2_status_t Codec2Client::createInterface(
1311 const C2String& name,
1312 std::shared_ptr<Codec2Client::Interface>* const interface) {
1313 if (mAidlBase) {
1314 std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
1315 ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
1316 name,
1317 &aidlInterface);
1318 c2_status_t status = GetC2Status(transStatus, "createInterface");
1319 if (status != C2_OK) {
1320 return status;
1321 } else if (!aidlInterface) {
1322 LOG(ERROR) << "createInterface(" << name.c_str()
1323 << ") -- null interface.";
1324 return C2_CORRUPTED;
1325 }
1326 interface->reset(new Codec2Client::Interface(aidlInterface));
1327 return C2_OK;
1328 }
1329
1330 c2_status_t status;
1331 Return<void> transStatus = mHidlBase1_0->createInterface(
1332 name,
1333 [&status, interface](
1334 c2_hidl::Status s,
1335 const sp<c2_hidl::IComponentInterface>& i) {
1336 status = static_cast<c2_status_t>(s);
1337 if (status != C2_OK) {
1338 return;
1339 }
1340 *interface = std::make_shared<Interface>(i);
1341 });
1342 if (!transStatus.isOk()) {
1343 LOG(ERROR) << "createInterface(" << name.c_str()
1344 << ") -- transaction failed.";
1345 return C2_TRANSACTION_FAILED;
1346 } else if (status != C2_OK) {
1347 if (status == C2_NOT_FOUND) {
1348 LOG(VERBOSE) << "createInterface(" << name.c_str()
1349 << ") -- component not found.";
1350 } else {
1351 LOG(ERROR) << "createInterface(" << name.c_str()
1352 << ") -- call failed: " << status << ".";
1353 }
1354 return status;
1355 }
1356
1357 return status;
1358 }
1359
createInputSurface(std::shared_ptr<InputSurface> * const inputSurface)1360 c2_status_t Codec2Client::createInputSurface(
1361 std::shared_ptr<InputSurface>* const inputSurface) {
1362 if (mAidlBase) {
1363 // FIXME
1364 return C2_OMITTED;
1365 }
1366
1367 c2_status_t status;
1368 Return<void> transStatus = mHidlBase1_0->createInputSurface(
1369 [&status, inputSurface](
1370 c2_hidl::Status s,
1371 const sp<c2_hidl::IInputSurface>& i) {
1372 status = static_cast<c2_status_t>(s);
1373 if (status != C2_OK) {
1374 return;
1375 }
1376 *inputSurface = std::make_shared<InputSurface>(i);
1377 });
1378 if (!transStatus.isOk()) {
1379 LOG(ERROR) << "createInputSurface -- transaction failed.";
1380 return C2_TRANSACTION_FAILED;
1381 } else if (status != C2_OK) {
1382 LOG(DEBUG) << "createInputSurface -- call failed: "
1383 << status << ".";
1384 }
1385 return status;
1386 }
1387
listComponents() const1388 std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
1389 return Cache::List()[mServiceIndex].getTraits();
1390 }
1391
_listComponents(bool * success) const1392 std::vector<C2Component::Traits> Codec2Client::_listComponents(
1393 bool* success) const {
1394 std::vector<C2Component::Traits> traits;
1395 std::string const& serviceName = getServiceName();
1396
1397 if (mAidlBase) {
1398 std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
1399 ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
1400 if (!transStatus.isOk()) {
1401 LOG(ERROR) << "_listComponents -- transaction failed.";
1402 *success = false;
1403 } else {
1404 traits.resize(aidlTraits.size());
1405 *success = true;
1406 for (size_t i = 0; i < aidlTraits.size(); ++i) {
1407 if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
1408 LOG(ERROR) << "_listComponents -- corrupted output.";
1409 *success = false;
1410 traits.clear();
1411 break;
1412 }
1413 traits[i].owner = serviceName;
1414 }
1415 }
1416 return traits;
1417 }
1418 Return<void> transStatus = mHidlBase1_0->listComponents(
1419 [&traits, &serviceName](c2_hidl::Status s,
1420 const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
1421 if (s != c2_hidl::Status::OK) {
1422 LOG(DEBUG) << "_listComponents -- call failed: "
1423 << static_cast<c2_status_t>(s) << ".";
1424 return;
1425 }
1426 traits.resize(t.size());
1427 for (size_t i = 0; i < t.size(); ++i) {
1428 if (!c2_hidl::utils::objcpy(&traits[i], t[i])) {
1429 LOG(ERROR) << "_listComponents -- corrupted output.";
1430 return;
1431 }
1432 traits[i].owner = serviceName;
1433 }
1434 });
1435 if (!transStatus.isOk()) {
1436 LOG(ERROR) << "_listComponents -- transaction failed.";
1437 *success = false;
1438 } else {
1439 *success = true;
1440 }
1441 return traits;
1442 }
1443
copyBuffer(const std::shared_ptr<C2Buffer> & src,const std::shared_ptr<C2Buffer> & dst)1444 c2_status_t Codec2Client::copyBuffer(
1445 const std::shared_ptr<C2Buffer>& src,
1446 const std::shared_ptr<C2Buffer>& dst) {
1447 // TODO: Implement?
1448 (void)src;
1449 (void)dst;
1450 LOG(ERROR) << "copyBuffer not implemented";
1451 return C2_OMITTED;
1452 }
1453
getParamReflector()1454 std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
1455 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
1456 // should reflect the HAL API.
1457 struct HidlSimpleParamReflector : public C2ParamReflector {
1458 std::unique_ptr<C2StructDescriptor> describe(
1459 C2Param::CoreIndex coreIndex) const override {
1460 hidl_vec<c2_hidl::ParamIndex> indices(1);
1461 indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
1462 std::unique_ptr<C2StructDescriptor> descriptor;
1463 Return<void> transStatus = mBase->getStructDescriptors(
1464 indices,
1465 [&descriptor](
1466 c2_hidl::Status s,
1467 const hidl_vec<c2_hidl::StructDescriptor>& sd) {
1468 c2_status_t status = static_cast<c2_status_t>(s);
1469 if (status != C2_OK) {
1470 LOG(DEBUG) << "SimpleParamReflector -- "
1471 "getStructDescriptors() failed: "
1472 << status << ".";
1473 descriptor.reset();
1474 return;
1475 }
1476 if (sd.size() != 1) {
1477 LOG(DEBUG) << "SimpleParamReflector -- "
1478 "getStructDescriptors() "
1479 "returned vector of size "
1480 << sd.size() << ". "
1481 "It should be 1.";
1482 descriptor.reset();
1483 return;
1484 }
1485 if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
1486 LOG(DEBUG) << "SimpleParamReflector -- "
1487 "getStructDescriptors() returned "
1488 "corrupted data.";
1489 descriptor.reset();
1490 return;
1491 }
1492 });
1493 if (!transStatus.isOk()) {
1494 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
1495 << transStatus.description();
1496 descriptor.reset();
1497 }
1498 return descriptor;
1499 }
1500
1501 HidlSimpleParamReflector(sp<HidlBase> base)
1502 : mBase(base) { }
1503
1504 sp<HidlBase> mBase;
1505 };
1506 struct AidlSimpleParamReflector : public C2ParamReflector {
1507 std::unique_ptr<C2StructDescriptor> describe(
1508 C2Param::CoreIndex coreIndex) const override {
1509 std::vector<c2_aidl::StructDescriptor> aidlDesc;
1510 std::unique_ptr<C2StructDescriptor> descriptor;
1511 ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
1512 {int32_t(coreIndex.coreIndex())},
1513 &aidlDesc);
1514 c2_status_t status = GetC2Status(transStatus, "describe");
1515 if (status != C2_OK) {
1516 descriptor.reset();
1517 } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
1518 LOG(ERROR) << "describe -- conversion failed.";
1519 descriptor.reset();
1520 }
1521 return descriptor;
1522 }
1523
1524 AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
1525 : mBase(base) { }
1526
1527 std::shared_ptr<AidlBase> mBase;
1528 };
1529
1530 if (mAidlBase) {
1531 return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
1532 }
1533 return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
1534 };
1535
CacheServiceNames()1536 std::vector<std::string> Codec2Client::CacheServiceNames() {
1537 std::vector<std::string> names;
1538
1539 if (c2_aidl::utils::IsSelected()) {
1540 if (__builtin_available(android __ANDROID_API_S__, *)) {
1541 // Get AIDL service names
1542 AServiceManager_forEachDeclaredInstance(
1543 AidlBase::descriptor, &names, [](const char *name, void *context) {
1544 std::vector<std::string> *names = (std::vector<std::string> *)context;
1545 names->emplace_back(name);
1546 });
1547 } else {
1548 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
1549 }
1550 } else {
1551 // Get HIDL service names
1552 using ::android::hardware::media::c2::V1_0::IComponentStore;
1553 using ::android::hidl::manager::V1_2::IServiceManager;
1554 while (true) {
1555 sp<IServiceManager> serviceManager = IServiceManager::getService();
1556 CHECK(serviceManager) << "Hardware service manager is not running.";
1557
1558 Return<void> transResult;
1559 transResult = serviceManager->listManifestByInterface(
1560 IComponentStore::descriptor,
1561 [&names](
1562 hidl_vec<hidl_string> const& instanceNames) {
1563 names.insert(names.end(), instanceNames.begin(), instanceNames.end());
1564 });
1565 if (transResult.isOk()) {
1566 break;
1567 }
1568 LOG(ERROR) << "Could not retrieve the list of service instances of "
1569 << IComponentStore::descriptor
1570 << ". Retrying...";
1571 }
1572 }
1573 // Sort service names in each category.
1574 std::stable_sort(
1575 names.begin(), names.end(),
1576 [](const std::string &a, const std::string &b) {
1577 // First compare by prefix: default -> vendor -> {everything else}
1578 constexpr int DEFAULT = 1;
1579 constexpr int VENDOR = 2;
1580 constexpr int OTHER = 3;
1581 int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
1582 (a.compare(0, 6, "vendor") == 0) ? VENDOR :
1583 OTHER);
1584 int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
1585 (b.compare(0, 6, "vendor") == 0) ? VENDOR :
1586 OTHER);
1587 if (aPrefix != bPrefix) {
1588 return aPrefix < bPrefix;
1589 }
1590 // If the prefix is the same, compare alphabetically
1591 return a < b;
1592 });
1593
1594 // Summarize to logcat.
1595 if (names.empty()) {
1596 LOG(INFO) << "No Codec2 services declared in the manifest.";
1597 } else {
1598 std::stringstream stringOutput;
1599 stringOutput << "Available Codec2 services:";
1600 for (std::string const& name : names) {
1601 stringOutput << " \"" << name << "\"";
1602 }
1603 LOG(INFO) << stringOutput.str();
1604 }
1605
1606 return names;
1607 }
1608
GetServiceNames()1609 std::vector<std::string> const& Codec2Client::GetServiceNames() {
1610 static std::vector<std::string> sServiceNames = CacheServiceNames();
1611 return sServiceNames;
1612 }
1613
CreateFromService(const char * name,bool setAsPreferredCodec2ComponentStore)1614 std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
1615 const char* name,
1616 bool setAsPreferredCodec2ComponentStore) {
1617 size_t index = getServiceIndex(name);
1618 if (index == GetServiceNames().size()) {
1619 if (setAsPreferredCodec2ComponentStore) {
1620 LOG(WARNING) << "CreateFromService(" << name
1621 << ") -- preferred C2ComponentStore not set.";
1622 }
1623 return nullptr;
1624 }
1625 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
1626 if (setAsPreferredCodec2ComponentStore) {
1627 SetPreferredCodec2ComponentStore(
1628 std::make_shared<Client2Store>(client));
1629 LOG(INFO) << "CreateFromService(" << name
1630 << ") -- service set as preferred C2ComponentStore.";
1631 }
1632 return client;
1633 }
1634
1635 std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
CreateFromAllServices()1636 CreateFromAllServices() {
1637 std::vector<std::shared_ptr<Codec2Client>> clients(
1638 GetServiceNames().size());
1639 for (size_t i = GetServiceNames().size(); i > 0; ) {
1640 --i;
1641 clients[i] = _CreateFromIndex(i);
1642 }
1643 return clients;
1644 }
1645
_CreateFromIndex(size_t index)1646 std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
1647 std::string const& name = GetServiceNames()[index];
1648 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
1649
1650 if (c2_aidl::utils::IsSelected()) {
1651 if (__builtin_available(android __ANDROID_API_S__, *)) {
1652 std::string instanceName =
1653 ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
1654 if (AServiceManager_isDeclared(instanceName.c_str())) {
1655 std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
1656 ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
1657 CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
1658 " inaccessible for unknown reasons.";
1659 LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
1660 std::shared_ptr<c2_aidl::IConfigurable> configurable;
1661 ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
1662 CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
1663 "does not have IConfigurable.";
1664 return std::make_shared<Codec2Client>(baseStore, configurable, index);
1665 } else {
1666 LOG(ERROR) << "Codec2 AIDL service \"" << name << "\" is not declared";
1667 }
1668 } else {
1669 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
1670 }
1671 } else {
1672 std::string instanceName = "android.hardware.media.c2/" + name;
1673 sp<HidlBase> baseStore = HidlBase::getService(name);
1674 CHECK(baseStore) << "Codec2 service \"" << name << "\""
1675 " inaccessible for unknown reasons.";
1676 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
1677 Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
1678 CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
1679 "does not have IConfigurable.";
1680 sp<c2_hidl::IConfigurable> configurable =
1681 static_cast<sp<c2_hidl::IConfigurable>>(transResult);
1682 return std::make_shared<Codec2Client>(baseStore, configurable, index);
1683 }
1684 return nullptr;
1685 }
1686
ForAllServices(const std::string & key,size_t numberOfAttempts,std::function<c2_status_t (const std::shared_ptr<Codec2Client> &)> predicate)1687 c2_status_t Codec2Client::ForAllServices(
1688 const std::string &key,
1689 size_t numberOfAttempts,
1690 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1691 predicate) {
1692 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1693
1694 // Cache the mapping key -> index of Codec2Client in Cache::List().
1695 static std::mutex key2IndexMutex;
1696 static std::map<std::string, size_t> key2Index;
1697
1698 // By default try all stores. However, try the last known client first. If
1699 // the last known client fails, retry once. We do this by pushing the last
1700 // known client in front of the list of all clients.
1701 std::deque<size_t> indices;
1702 for (size_t index = Cache::List().size(); index > 0; ) {
1703 indices.push_front(--index);
1704 }
1705
1706 bool wasMapped = false;
1707 {
1708 std::scoped_lock lock{key2IndexMutex};
1709 auto it = key2Index.find(key);
1710 if (it != key2Index.end()) {
1711 indices.push_front(it->second);
1712 wasMapped = true;
1713 }
1714 }
1715
1716 for (size_t index : indices) {
1717 Cache& cache = Cache::List()[index];
1718 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1719 std::shared_ptr<Codec2Client> client{cache.getClient()};
1720 status = predicate(client);
1721 if (status == C2_OK) {
1722 std::scoped_lock lock{key2IndexMutex};
1723 key2Index[key] = index; // update last known client index
1724 return C2_OK;
1725 } else if (status == C2_NO_MEMORY) {
1726 return C2_NO_MEMORY;
1727 } else if (status == C2_TRANSACTION_FAILED) {
1728 LOG(WARNING) << "\"" << key << "\" failed for service \""
1729 << client->getName()
1730 << "\" due to transaction failure. "
1731 << "(Service may have crashed.)"
1732 << (tries > 1 ? " Retrying..." : "");
1733 cache.invalidate();
1734 continue;
1735 }
1736 if (wasMapped) {
1737 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1738 << client->getName() << "\". Retrying...";
1739 wasMapped = false;
1740 }
1741 break;
1742 }
1743 }
1744 return status; // return the last status from a valid client
1745 }
1746
CreateComponentByName(const char * componentName,const std::shared_ptr<Listener> & listener,std::shared_ptr<Component> * component,std::shared_ptr<Codec2Client> * owner,size_t numberOfAttempts)1747 c2_status_t Codec2Client::CreateComponentByName(
1748 const char* componentName,
1749 const std::shared_ptr<Listener>& listener,
1750 std::shared_ptr<Component>* component,
1751 std::shared_ptr<Codec2Client>* owner,
1752 size_t numberOfAttempts) {
1753 std::string key{"create:"};
1754 key.append(componentName);
1755 c2_status_t status = ForAllServices(
1756 key,
1757 numberOfAttempts,
1758 [owner, component, componentName, &listener](
1759 const std::shared_ptr<Codec2Client> &client)
1760 -> c2_status_t {
1761 c2_status_t status = client->createComponent(componentName,
1762 listener,
1763 component);
1764 if (status == C2_OK) {
1765 if (owner) {
1766 *owner = client;
1767 }
1768 } else if (status != C2_NOT_FOUND) {
1769 LOG(DEBUG) << "IComponentStore("
1770 << client->getServiceName()
1771 << ")::createComponent(\"" << componentName
1772 << "\") returned status = "
1773 << status << ".";
1774 }
1775 return status;
1776 });
1777 if (status != C2_OK) {
1778 LOG(DEBUG) << "Failed to create component \"" << componentName
1779 << "\" from all known services. "
1780 "Last returned status = " << status << ".";
1781 }
1782 return status;
1783 }
1784
CreateInterfaceByName(const char * interfaceName,std::shared_ptr<Codec2Client> * owner,size_t numberOfAttempts)1785 std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
1786 const char* interfaceName,
1787 std::shared_ptr<Codec2Client>* owner,
1788 size_t numberOfAttempts) {
1789 std::string key{"create:"};
1790 key.append(interfaceName);
1791 std::shared_ptr<Interface> interface;
1792 c2_status_t status = ForAllServices(
1793 key,
1794 numberOfAttempts,
1795 [owner, &interface, interfaceName](
1796 const std::shared_ptr<Codec2Client> &client)
1797 -> c2_status_t {
1798 c2_status_t status = client->createInterface(interfaceName,
1799 &interface);
1800 if (status == C2_OK) {
1801 if (owner) {
1802 *owner = client;
1803 }
1804 } else if (status != C2_NOT_FOUND) {
1805 LOG(DEBUG) << "IComponentStore("
1806 << client->getServiceName()
1807 << ")::createInterface(\"" << interfaceName
1808 << "\") returned status = "
1809 << status << ".";
1810 }
1811 return status;
1812 });
1813 if (status != C2_OK) {
1814 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1815 << "\" from all known services. "
1816 "Last returned status = " << status << ".";
1817 }
1818 return interface;
1819 }
1820
ListComponents()1821 std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1822 static std::vector<C2Component::Traits> sList{[]() {
1823 std::vector<C2Component::Traits> list;
1824 for (Cache& cache : Cache::List()) {
1825 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1826 list.insert(list.end(), traits.begin(), traits.end());
1827 }
1828 return list;
1829 }()};
1830 return sList;
1831 }
1832
CreateInputSurface(char const * serviceName)1833 std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1834 char const* serviceName) {
1835 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1836 "debug.stagefright.c2inputsurface", int32_t(0));
1837 if (inputSurfaceSetting <= 0) {
1838 return nullptr;
1839 }
1840 size_t index = GetServiceNames().size();
1841 if (serviceName) {
1842 index = getServiceIndex(serviceName);
1843 if (index == GetServiceNames().size()) {
1844 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1845 << serviceName << "\"";
1846 }
1847 }
1848
1849 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
1850 if (index != GetServiceNames().size()) {
1851 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1852 if (client->createInputSurface(&inputSurface) == C2_OK) {
1853 return inputSurface;
1854 }
1855 }
1856 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1857 "from all services...";
1858 for (Cache& cache : Cache::List()) {
1859 std::shared_ptr<Codec2Client> client = cache.getClient();
1860 if (client->createInputSurface(&inputSurface) == C2_OK) {
1861 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1862 "service \"" << client->getServiceName() << "\"";
1863 return inputSurface;
1864 }
1865 }
1866 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1867 "from all services";
1868 return nullptr;
1869 }
1870
IsAidlSelected()1871 bool Codec2Client::IsAidlSelected() {
1872 return c2_aidl::utils::IsSelected();
1873 }
1874
1875 // Codec2Client::Interface
Interface(const sp<HidlBase> & base)1876 Codec2Client::Interface::Interface(const sp<HidlBase>& base)
1877 : Configurable{
1878 [base]() -> sp<c2_hidl::IConfigurable> {
1879 Return<sp<c2_hidl::IConfigurable>> transResult =
1880 base->getConfigurable();
1881 return transResult.isOk() ?
1882 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
1883 nullptr;
1884 }()
1885 },
1886 mHidlBase{base} {
1887 }
1888
Interface(const std::shared_ptr<AidlBase> & base)1889 Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
1890 : Configurable{
1891 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
1892 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
1893 ::ndk::ScopedAStatus transStatus =
1894 base->getConfigurable(&aidlConfigurable);
1895 return transStatus.isOk() ? aidlConfigurable : nullptr;
1896 }()
1897 },
1898 mAidlBase{base} {
1899 }
1900
1901 // Codec2Client::Component
1902
1903 class Codec2Client::Component::AidlDeathManager {
1904 public:
AidlDeathManager()1905 AidlDeathManager()
1906 : mSeq(0),
1907 mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
1908 }
1909
1910 ~AidlDeathManager() = default;
1911
linkToDeath(const std::shared_ptr<Component> & comp,const std::shared_ptr<Listener> & listener,size_t * seqPtr)1912 bool linkToDeath(
1913 const std::shared_ptr<Component> &comp,
1914 const std::shared_ptr<Listener> &listener,
1915 size_t *seqPtr) {
1916 std::unique_lock lock(mMutex);
1917 size_t seq = mSeq++;
1918 if (!mMap.try_emplace(seq, comp, listener).second) {
1919 return false;
1920 }
1921 if (STATUS_OK != AIBinder_linkToDeath(
1922 comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
1923 mMap.erase(seq);
1924 return false;
1925 }
1926 *seqPtr = seq;
1927 return true;
1928 }
1929
unlinkToDeath(size_t seq,const std::shared_ptr<AidlBase> & base)1930 void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
1931 std::unique_lock lock(mMutex);
1932 AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
1933 mMap.erase(seq);
1934 }
1935
1936 private:
1937 std::mutex mMutex;
1938 size_t mSeq;
1939 typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
1940 std::map<size_t, Context> mMap;
1941 ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
1942
extractContext(size_t seq,Context * context)1943 bool extractContext(size_t seq, Context *context) {
1944 std::unique_lock lock(mMutex);
1945 auto node = mMap.extract(seq);
1946 if (!node) {
1947 return false;
1948 }
1949 *context = node.mapped();
1950 return true;
1951 }
1952
OnBinderDied(void * cookie)1953 static void OnBinderDied(void *cookie) {
1954 size_t seq = size_t(cookie);
1955 Context context;
1956 if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
1957 return;
1958 }
1959 std::weak_ptr<Component> weakComponent;
1960 std::weak_ptr<Listener> weakListener;
1961 std::tie(weakComponent, weakListener) = context;
1962 if (std::shared_ptr<Listener> listener = weakListener.lock()) {
1963 listener->onDeath(weakComponent);
1964 } else {
1965 LOG(DEBUG) << "onDeath -- listener died.";
1966 }
1967 }
1968 };
1969
Component(const sp<HidlBase> & base)1970 Codec2Client::Component::Component(const sp<HidlBase>& base)
1971 : Configurable{
1972 [base]() -> sp<c2_hidl::IConfigurable> {
1973 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
1974 base->getInterface();
1975 if (!transResult1.isOk()) {
1976 return nullptr;
1977 }
1978 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1979 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
1980 getConfigurable();
1981 return transResult2.isOk() ?
1982 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
1983 nullptr;
1984 }()
1985 },
1986 mHidlBase1_0{base},
1987 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1988 mHidlBase1_2{HidlBase1_2::castFrom(base)},
1989 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
1990 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1991 }
1992
Component(const sp<HidlBase1_1> & base)1993 Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
1994 : Configurable{
1995 [base]() -> sp<c2_hidl::IConfigurable> {
1996 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
1997 base->getInterface();
1998 if (!transResult1.isOk()) {
1999 return nullptr;
2000 }
2001 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2002 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
2003 getConfigurable();
2004 return transResult2.isOk() ?
2005 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
2006 nullptr;
2007 }()
2008 },
2009 mHidlBase1_0{base},
2010 mHidlBase1_1{base},
2011 mHidlBase1_2{HidlBase1_2::castFrom(base)},
2012 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
2013 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2014 }
2015
Component(const sp<HidlBase1_2> & base)2016 Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
2017 : Configurable{
2018 [base]() -> sp<c2_hidl::IConfigurable> {
2019 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
2020 base->getInterface();
2021 if (!transResult1.isOk()) {
2022 return nullptr;
2023 }
2024 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2025 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
2026 getConfigurable();
2027 return transResult2.isOk() ?
2028 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
2029 nullptr;
2030 }()
2031 },
2032 mHidlBase1_0{base},
2033 mHidlBase1_1{base},
2034 mHidlBase1_2{base},
2035 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
2036 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2037 }
2038
Component(const std::shared_ptr<AidlBase> & base)2039 Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
2040 : Configurable{
2041 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
2042 std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
2043 ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
2044 if (!transStatus.isOk()) {
2045 return nullptr;
2046 }
2047 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
2048 transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
2049 return transStatus.isOk() ? aidlConfigurable : nullptr;
2050 }()
2051 },
2052 mAidlBase{base},
2053 mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
2054 mGraphicBufferAllocators{std::make_unique<GraphicBufferAllocators>()} {
2055 }
2056
~Component()2057 Codec2Client::Component::~Component() {
2058 if (mAidlDeathSeq) {
2059 GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
2060 }
2061 }
2062
createBlockPool(C2Allocator::id_t id,C2BlockPool::local_id_t * blockPoolId,std::shared_ptr<Codec2Client::Configurable> * configurable)2063 c2_status_t Codec2Client::Component::createBlockPool(
2064 C2Allocator::id_t id,
2065 C2BlockPool::local_id_t* blockPoolId,
2066 std::shared_ptr<Codec2Client::Configurable>* configurable) {
2067 if (mAidlBase) {
2068 c2_aidl::IComponent::BlockPool aidlBlockPool;
2069 c2_status_t status = C2_OK;
2070
2071 // TODO: Temporary mapping for the current CCodecBufferChannel.
2072 // Handle this properly and remove this temporary allocator mapping.
2073 id = id == C2PlatformAllocatorStore::BUFFERQUEUE ?
2074 C2PlatformAllocatorStore::IGBA : id;
2075
2076 c2_aidl::IComponent::BlockPoolAllocator allocator;
2077 allocator.allocatorId = id;
2078 if (id == C2PlatformAllocatorStore::IGBA) {
2079 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2080 mGraphicBufferAllocators->create();
2081 ::ndk::ScopedFileDescriptor waitableFd;
2082 ::ndk::ScopedAStatus ret = gba->getWaitableFd(&waitableFd);
2083 status = GetC2Status(ret, "Gba::getWaitableFd");
2084 if (status != C2_OK) {
2085 return status;
2086 }
2087 c2_aidl::IComponent::GbAllocator gbAllocator;
2088 gbAllocator.waitableFd = std::move(waitableFd);
2089 gbAllocator.igba =
2090 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
2091 allocator.gbAllocator = std::move(gbAllocator);
2092 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
2093 allocator, &aidlBlockPool);
2094 status = GetC2Status(transStatus, "createBlockPool");
2095 if (status != C2_OK) {
2096 return status;
2097 }
2098 mGraphicBufferAllocators->setCurrentId(aidlBlockPool.blockPoolId);
2099 } else {
2100 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
2101 allocator, &aidlBlockPool);
2102 status = GetC2Status(transStatus, "createBlockPool");
2103 if (status != C2_OK) {
2104 return status;
2105 }
2106 }
2107 *blockPoolId = aidlBlockPool.blockPoolId;
2108 *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
2109 return C2_OK;
2110 }
2111 c2_status_t status;
2112 Return<void> transStatus = mHidlBase1_0->createBlockPool(
2113 static_cast<uint32_t>(id),
2114 [&status, blockPoolId, configurable](
2115 c2_hidl::Status s,
2116 uint64_t pId,
2117 const sp<c2_hidl::IConfigurable>& c) {
2118 status = static_cast<c2_status_t>(s);
2119 configurable->reset();
2120 if (status != C2_OK) {
2121 LOG(DEBUG) << "createBlockPool -- call failed: "
2122 << status << ".";
2123 return;
2124 }
2125 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
2126 *configurable = std::make_shared<Configurable>(c);
2127 });
2128 if (!transStatus.isOk()) {
2129 LOG(ERROR) << "createBlockPool -- transaction failed.";
2130 return C2_TRANSACTION_FAILED;
2131 }
2132 return status;
2133 }
2134
destroyBlockPool(C2BlockPool::local_id_t localId)2135 c2_status_t Codec2Client::Component::destroyBlockPool(
2136 C2BlockPool::local_id_t localId) {
2137 if (mAidlBase) {
2138 mGraphicBufferAllocators->remove(localId);
2139 ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
2140 return GetC2Status(transStatus, "destroyBlockPool");
2141 }
2142 Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
2143 static_cast<uint64_t>(localId));
2144 if (!transResult.isOk()) {
2145 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
2146 return C2_TRANSACTION_FAILED;
2147 }
2148 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
2149 }
2150
handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> & workItems)2151 void Codec2Client::Component::handleOnWorkDone(
2152 const std::list<std::unique_ptr<C2Work>> &workItems) {
2153 if (mAidlBase) {
2154 holdIgbaBlocks(workItems);
2155 } else {
2156 // Output bufferqueue-based blocks' lifetime management
2157 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
2158 }
2159 }
2160
queue(std::list<std::unique_ptr<C2Work>> * const items)2161 c2_status_t Codec2Client::Component::queue(
2162 std::list<std::unique_ptr<C2Work>>* const items) {
2163 if (mAidlBase) {
2164 c2_aidl::WorkBundle workBundle;
2165 if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
2166 LOG(ERROR) << "queue -- bad input.";
2167 return C2_TRANSACTION_FAILED;
2168 }
2169 ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
2170 return GetC2Status(transStatus, "queue");
2171 }
2172 c2_hidl::WorkBundle workBundle;
2173 if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
2174 LOG(ERROR) << "queue -- bad input.";
2175 return C2_TRANSACTION_FAILED;
2176 }
2177 Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
2178 if (!transStatus.isOk()) {
2179 LOG(ERROR) << "queue -- transaction failed.";
2180 return C2_TRANSACTION_FAILED;
2181 }
2182 c2_status_t status =
2183 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2184 if (status != C2_OK) {
2185 LOG(DEBUG) << "queue -- call failed: " << status << ".";
2186 }
2187 return status;
2188 }
2189
flush(C2Component::flush_mode_t mode,std::list<std::unique_ptr<C2Work>> * const flushedWork)2190 c2_status_t Codec2Client::Component::flush(
2191 C2Component::flush_mode_t mode,
2192 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
2193 (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
2194 c2_status_t status = C2_OK;
2195 if (mAidlBase) {
2196 c2_aidl::WorkBundle workBundle;
2197 ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
2198 c2_status_t status = GetC2Status(transStatus, "flush");
2199 if (status != C2_OK) {
2200 return status;
2201 }
2202 if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
2203 LOG(DEBUG) << "flush -- flushedWork corrupted.";
2204 return C2_CORRUPTED;
2205 }
2206 } else {
2207 Return<void> transStatus = mHidlBase1_0->flush(
2208 [&status, flushedWork](
2209 c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
2210 status = static_cast<c2_status_t>(s);
2211 if (status != C2_OK) {
2212 LOG(DEBUG) << "flush -- call failed: " << status << ".";
2213 return;
2214 }
2215 if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
2216 status = C2_CORRUPTED;
2217 } else {
2218 status = C2_OK;
2219 }
2220 });
2221 if (!transStatus.isOk()) {
2222 LOG(ERROR) << "flush -- transaction failed.";
2223 return C2_TRANSACTION_FAILED;
2224 }
2225 }
2226
2227 // Indices of flushed work items.
2228 std::vector<uint64_t> flushedIndices;
2229 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
2230 if (work) {
2231 if (work->worklets.empty()
2232 || !work->worklets.back()
2233 || (work->worklets.back()->output.flags &
2234 C2FrameData::FLAG_INCOMPLETE) == 0) {
2235 // input is complete
2236 flushedIndices.emplace_back(
2237 work->input.ordinal.frameIndex.peeku());
2238 }
2239 }
2240 }
2241
2242 if (mAidlBase) {
2243 holdIgbaBlocks(*flushedWork);
2244 } else {
2245 // Output bufferqueue-based blocks' lifetime management
2246 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
2247 }
2248
2249 return status;
2250 }
2251
drain(C2Component::drain_mode_t mode)2252 c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
2253 if (mAidlBase) {
2254 ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
2255 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
2256 return GetC2Status(transStatus, "drain");
2257 }
2258 Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
2259 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
2260 if (!transStatus.isOk()) {
2261 LOG(ERROR) << "drain -- transaction failed.";
2262 return C2_TRANSACTION_FAILED;
2263 }
2264 c2_status_t status =
2265 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2266 if (status != C2_OK) {
2267 LOG(DEBUG) << "drain -- call failed: " << status << ".";
2268 }
2269 return status;
2270 }
2271
start()2272 c2_status_t Codec2Client::Component::start() {
2273 if (mAidlBase) {
2274 ::ndk::ScopedAStatus transStatus = mAidlBase->start();
2275 return GetC2Status(transStatus, "start");
2276 }
2277 Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
2278 if (!transStatus.isOk()) {
2279 LOG(ERROR) << "start -- transaction failed.";
2280 return C2_TRANSACTION_FAILED;
2281 }
2282 c2_status_t status =
2283 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2284 if (status != C2_OK) {
2285 LOG(DEBUG) << "start -- call failed: " << status << ".";
2286 }
2287 return status;
2288 }
2289
stop()2290 c2_status_t Codec2Client::Component::stop() {
2291 if (mAidlBase) {
2292 ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
2293 return GetC2Status(transStatus, "stop");
2294 }
2295 Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
2296 if (!transStatus.isOk()) {
2297 LOG(ERROR) << "stop -- transaction failed.";
2298 return C2_TRANSACTION_FAILED;
2299 }
2300 c2_status_t status =
2301 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2302 if (status != C2_OK) {
2303 LOG(DEBUG) << "stop -- call failed: " << status << ".";
2304 }
2305 return status;
2306 }
2307
reset()2308 c2_status_t Codec2Client::Component::reset() {
2309 if (mAidlBase) {
2310 ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
2311 return GetC2Status(transStatus, "reset");
2312 }
2313 Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
2314 if (!transStatus.isOk()) {
2315 LOG(ERROR) << "reset -- transaction failed.";
2316 return C2_TRANSACTION_FAILED;
2317 }
2318 c2_status_t status =
2319 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2320 if (status != C2_OK) {
2321 LOG(DEBUG) << "reset -- call failed: " << status << ".";
2322 }
2323 return status;
2324 }
2325
release()2326 c2_status_t Codec2Client::Component::release() {
2327 if (mAidlBase) {
2328 ::ndk::ScopedAStatus transStatus = mAidlBase->release();
2329 return GetC2Status(transStatus, "release");
2330 }
2331 Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
2332 if (!transStatus.isOk()) {
2333 LOG(ERROR) << "release -- transaction failed.";
2334 return C2_TRANSACTION_FAILED;
2335 }
2336 c2_status_t status =
2337 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2338 if (status != C2_OK) {
2339 LOG(DEBUG) << "release -- call failed: " << status << ".";
2340 }
2341 return status;
2342 }
2343
configureVideoTunnel(uint32_t avSyncHwId,native_handle_t ** sidebandHandle)2344 c2_status_t Codec2Client::Component::configureVideoTunnel(
2345 uint32_t avSyncHwId,
2346 native_handle_t** sidebandHandle) {
2347 *sidebandHandle = nullptr;
2348 if (mAidlBase) {
2349 ::aidl::android::hardware::common::NativeHandle handle;
2350 ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
2351 c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
2352 if (status != C2_OK) {
2353 return status;
2354 }
2355 if (isAidlNativeHandleEmpty(handle)) {
2356 LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
2357 } else {
2358 *sidebandHandle = dupFromAidl(handle);
2359 }
2360 return C2_OK;
2361 }
2362 if (!mHidlBase1_1) {
2363 return C2_OMITTED;
2364 }
2365 c2_status_t status{};
2366 Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
2367 [&status, sidebandHandle](
2368 c2_hidl::Status s, hardware::hidl_handle const& h) {
2369 status = static_cast<c2_status_t>(s);
2370 if (h.getNativeHandle()) {
2371 *sidebandHandle = native_handle_clone(h.getNativeHandle());
2372 }
2373 });
2374 if (!transStatus.isOk()) {
2375 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
2376 return C2_TRANSACTION_FAILED;
2377 }
2378 return status;
2379 }
2380
setOutputSurface(C2BlockPool::local_id_t blockPoolId,const sp<IGraphicBufferProducer> & surface,uint32_t generation,int maxDequeueCount)2381 c2_status_t Codec2Client::Component::setOutputSurface(
2382 C2BlockPool::local_id_t blockPoolId,
2383 const sp<IGraphicBufferProducer>& surface,
2384 uint32_t generation,
2385 int maxDequeueCount) {
2386 if (mAidlBase) {
2387 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2388 mGraphicBufferAllocators->current();
2389 if (!gba) {
2390 LOG(ERROR) << "setOutputSurface for AIDL -- "
2391 "GraphicBufferAllocator was not created.";
2392 return C2_CORRUPTED;
2393 }
2394 bool ret = gba->configure(surface, generation, maxDequeueCount);
2395 return ret ? C2_OK : C2_CORRUPTED;
2396 }
2397 uint64_t bqId = 0;
2398 sp<IGraphicBufferProducer> nullIgbp;
2399 sp<HGraphicBufferProducer2> nullHgbp;
2400
2401 sp<HGraphicBufferProducer2> igbp = surface ?
2402 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
2403 if (surface && !igbp) {
2404 igbp = new B2HGraphicBufferProducer2(surface);
2405 }
2406
2407 std::scoped_lock lock(mOutputMutex);
2408 std::shared_ptr<SurfaceSyncObj> syncObj;
2409
2410 if (!surface) {
2411 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
2412 } else if (surface->getUniqueId(&bqId) != OK) {
2413 LOG(ERROR) << "setOutputSurface -- "
2414 "cannot obtain bufferqueue id.";
2415 bqId = 0;
2416 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
2417 } else {
2418 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
2419 mHidlBase1_2 ? &syncObj : nullptr);
2420 }
2421
2422 // set consumer bits
2423 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
2424 // can be set atomically?
2425 uint64_t consumerUsage = kDefaultConsumerUsage;
2426 {
2427 if (surface) {
2428 uint64_t usage = 0;
2429 status_t err = surface->getConsumerUsage(&usage);
2430 if (err != NO_ERROR) {
2431 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
2432 err, asString(err));
2433 } else {
2434 // Note: we are adding the default usage because components must support
2435 // producing output frames that can be displayed an all output surfaces.
2436
2437 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
2438 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
2439 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
2440 // through the sideband channel.
2441
2442 consumerUsage = usage | kDefaultConsumerUsage;
2443 }
2444 }
2445
2446 C2StreamUsageTuning::output outputUsage{
2447 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
2448 std::vector<std::unique_ptr<C2SettingResult>> failures;
2449 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
2450 if (err != C2_OK) {
2451 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
2452 err, asString(err));
2453 }
2454 }
2455 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
2456 generation, (long long)consumerUsage, syncObj ? " sync" : "");
2457
2458 Return<c2_hidl::Status> transStatus = syncObj ?
2459 mHidlBase1_2->setOutputSurfaceWithSyncObj(
2460 static_cast<uint64_t>(blockPoolId),
2461 bqId == 0 ? nullHgbp : igbp, *syncObj) :
2462 mHidlBase1_0->setOutputSurface(
2463 static_cast<uint64_t>(blockPoolId),
2464 bqId == 0 ? nullHgbp : igbp);
2465
2466 mOutputBufferQueue->expireOldWaiters();
2467
2468 if (!transStatus.isOk()) {
2469 LOG(ERROR) << "setOutputSurface -- transaction failed.";
2470 return C2_TRANSACTION_FAILED;
2471 }
2472 c2_status_t status =
2473 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2474 if (status != C2_OK) {
2475 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
2476 }
2477 ALOGD("Surface configure completed");
2478 return status;
2479 }
2480
queueToOutputSurface(const C2ConstGraphicBlock & block,const QueueBufferInput & input,QueueBufferOutput * output)2481 status_t Codec2Client::Component::queueToOutputSurface(
2482 const C2ConstGraphicBlock& block,
2483 const QueueBufferInput& input,
2484 QueueBufferOutput* output) {
2485 ScopedTrace trace(ATRACE_TAG,"Codec2Client::Component::queueToOutputSurface");
2486 if (mAidlBase) {
2487 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2488 mGraphicBufferAllocators->current();
2489 if (gba) {
2490 return gba->displayBuffer(block, input, output);
2491 } else {
2492 return C2_NOT_FOUND;
2493 }
2494 }
2495 return mOutputBufferQueue->outputBuffer(block, input, output);
2496 }
2497
pollForRenderedFrames(FrameEventHistoryDelta * delta)2498 void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
2499 if (mAidlBase) {
2500 // TODO b/311348680
2501 return;
2502 }
2503 mOutputBufferQueue->pollForRenderedFrames(delta);
2504 }
2505
setOutputSurfaceMaxDequeueCount(int maxDequeueCount)2506 void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
2507 int maxDequeueCount) {
2508 if (mAidlBase) {
2509 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2510 mGraphicBufferAllocators->current();
2511 if (gba) {
2512 gba->updateMaxDequeueBufferCount(maxDequeueCount);
2513 }
2514 return;
2515 }
2516 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
2517 }
2518
stopUsingOutputSurface(C2BlockPool::local_id_t blockPoolId)2519 void Codec2Client::Component::stopUsingOutputSurface(
2520 C2BlockPool::local_id_t blockPoolId) {
2521 if (mAidlBase) {
2522 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2523 mGraphicBufferAllocators->current();
2524 if (gba) {
2525 gba->reset();
2526 }
2527 return;
2528 }
2529 std::scoped_lock lock(mOutputMutex);
2530 mOutputBufferQueue->stop();
2531 Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
2532 static_cast<uint64_t>(blockPoolId), nullptr);
2533 if (!transStatus.isOk()) {
2534 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
2535 } else {
2536 c2_status_t status =
2537 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2538 if (status != C2_OK) {
2539 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
2540 << status << ".";
2541 }
2542 }
2543 mOutputBufferQueue->expireOldWaiters();
2544 }
2545
onBufferReleasedFromOutputSurface(uint32_t generation)2546 void Codec2Client::Component::onBufferReleasedFromOutputSurface(
2547 uint32_t generation) {
2548 if (mAidlBase) {
2549 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2550 mGraphicBufferAllocators->current();
2551 if (gba) {
2552 gba->onBufferReleased(generation);
2553 }
2554 return;
2555 }
2556 mOutputBufferQueue->onBufferReleased(generation);
2557 }
2558
holdIgbaBlocks(const std::list<std::unique_ptr<C2Work>> & workList)2559 void Codec2Client::Component::holdIgbaBlocks(
2560 const std::list<std::unique_ptr<C2Work>>& workList) {
2561 if (!mAidlBase) {
2562 return;
2563 }
2564 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2565 mGraphicBufferAllocators->current();
2566 if (!gba) {
2567 return;
2568 }
2569 std::shared_ptr<c2_aidl::IGraphicBufferAllocator> igba =
2570 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
2571 for (const std::unique_ptr<C2Work>& work : workList) {
2572 if (!work) [[unlikely]] {
2573 continue;
2574 }
2575 for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
2576 if (!worklet) {
2577 continue;
2578 }
2579 for (const std::shared_ptr<C2Buffer>& buffer : worklet->output.buffers) {
2580 if (buffer) {
2581 for (const C2ConstGraphicBlock& block : buffer->data().graphicBlocks()) {
2582 std::shared_ptr<_C2BlockPoolData> poolData =
2583 _C2BlockFactory::GetGraphicBlockPoolData(block);
2584 _C2BlockFactory::RegisterIgba(poolData, igba);
2585 }
2586 }
2587 }
2588 }
2589 }
2590 }
2591
connectToInputSurface(const std::shared_ptr<InputSurface> & inputSurface,std::shared_ptr<InputSurfaceConnection> * connection)2592 c2_status_t Codec2Client::Component::connectToInputSurface(
2593 const std::shared_ptr<InputSurface>& inputSurface,
2594 std::shared_ptr<InputSurfaceConnection>* connection) {
2595 if (mAidlBase) {
2596 // FIXME
2597 return C2_OMITTED;
2598 }
2599 c2_status_t status;
2600 Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
2601 inputSurface->mBase,
2602 [&status, connection](
2603 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
2604 status = static_cast<c2_status_t>(s);
2605 if (status != C2_OK) {
2606 LOG(DEBUG) << "connectToInputSurface -- call failed: "
2607 << status << ".";
2608 return;
2609 }
2610 *connection = std::make_shared<InputSurfaceConnection>(c);
2611 });
2612 if (!transStatus.isOk()) {
2613 LOG(ERROR) << "connectToInputSurface -- transaction failed";
2614 return C2_TRANSACTION_FAILED;
2615 }
2616 return status;
2617 }
2618
connectToOmxInputSurface(const sp<HGraphicBufferProducer1> & producer,const sp<HGraphicBufferSource> & source,std::shared_ptr<InputSurfaceConnection> * connection)2619 c2_status_t Codec2Client::Component::connectToOmxInputSurface(
2620 const sp<HGraphicBufferProducer1>& producer,
2621 const sp<HGraphicBufferSource>& source,
2622 std::shared_ptr<InputSurfaceConnection>* connection) {
2623 if (mAidlBase) {
2624 LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
2625 return C2_OMITTED;
2626 }
2627 c2_status_t status;
2628 Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
2629 producer, source,
2630 [&status, connection](
2631 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
2632 status = static_cast<c2_status_t>(s);
2633 if (status != C2_OK) {
2634 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
2635 << status << ".";
2636 return;
2637 }
2638 *connection = std::make_shared<InputSurfaceConnection>(c);
2639 });
2640 if (!transStatus.isOk()) {
2641 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
2642 return C2_TRANSACTION_FAILED;
2643 }
2644 return status;
2645 }
2646
disconnectFromInputSurface()2647 c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
2648 if (mAidlBase) {
2649 // FIXME
2650 return C2_OMITTED;
2651 }
2652 Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
2653 if (!transStatus.isOk()) {
2654 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
2655 return C2_TRANSACTION_FAILED;
2656 }
2657 c2_status_t status =
2658 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
2659 if (status != C2_OK) {
2660 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
2661 << status << ".";
2662 }
2663 return status;
2664 }
2665
GetAidlDeathManager()2666 Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
2667 // This object never gets destructed
2668 static AidlDeathManager *sManager = new AidlDeathManager();
2669 return sManager;
2670 }
2671
setDeathListener(const std::shared_ptr<Component> & component,const std::shared_ptr<Listener> & listener)2672 c2_status_t Codec2Client::Component::setDeathListener(
2673 const std::shared_ptr<Component>& component,
2674 const std::shared_ptr<Listener>& listener) {
2675
2676 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
2677 std::weak_ptr<Component> component;
2678 std::weak_ptr<Listener> base;
2679
2680 virtual void serviceDied(
2681 uint64_t /* cookie */,
2682 const wp<::android::hidl::base::V1_0::IBase>& /* who */
2683 ) override {
2684 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
2685 listener->onDeath(component);
2686 } else {
2687 LOG(DEBUG) << "onDeath -- listener died.";
2688 }
2689 }
2690 };
2691
2692 if (component->mAidlBase) {
2693 size_t seq;
2694 if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
2695 component->mAidlDeathSeq = seq;
2696 }
2697 return C2_OK;
2698 }
2699
2700 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
2701 deathRecipient->base = listener;
2702 deathRecipient->component = component;
2703
2704 component->mDeathRecipient = deathRecipient;
2705 Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
2706 component->mDeathRecipient, 0);
2707 if (!transResult.isOk()) {
2708 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
2709 return C2_TRANSACTION_FAILED;
2710 }
2711 if (!static_cast<bool>(transResult)) {
2712 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
2713 return C2_CORRUPTED;
2714 }
2715 return C2_OK;
2716 }
2717
2718 // Codec2Client::InputSurface
InputSurface(const sp<c2_hidl::IInputSurface> & base)2719 Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
2720 : Configurable{
2721 [base]() -> sp<c2_hidl::IConfigurable> {
2722 Return<sp<c2_hidl::IConfigurable>> transResult =
2723 base->getConfigurable();
2724 return transResult.isOk() ?
2725 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
2726 nullptr;
2727 }()
2728 },
2729 mBase{base},
2730 mGraphicBufferProducer{new
__anonfa4150792402() 2731 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
2732 Return<sp<HGraphicBufferProducer2>> transResult =
2733 base->getGraphicBufferProducer();
2734 return transResult.isOk() ?
2735 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
2736 nullptr;
2737 }())} {
2738 }
2739
2740 sp<IGraphicBufferProducer>
getGraphicBufferProducer() const2741 Codec2Client::InputSurface::getGraphicBufferProducer() const {
2742 return mGraphicBufferProducer;
2743 }
2744
getHalInterface() const2745 sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
2746 return mBase;
2747 }
2748
2749 // Codec2Client::InputSurfaceConnection
InputSurfaceConnection(const sp<c2_hidl::IInputSurfaceConnection> & base)2750 Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
2751 const sp<c2_hidl::IInputSurfaceConnection>& base)
2752 : Configurable{
2753 [base]() -> sp<c2_hidl::IConfigurable> {
2754 Return<sp<c2_hidl::IConfigurable>> transResult =
2755 base->getConfigurable();
2756 return transResult.isOk() ?
2757 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
2758 nullptr;
2759 }()
2760 },
2761 mBase{base} {
2762 }
2763
disconnect()2764 c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
2765 Return<c2_hidl::Status> transResult = mBase->disconnect();
2766 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
2767 }
2768
2769 } // namespace android
2770