• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "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 &params,
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*> &params,
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(&paramPointers, 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*> &params,
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, &params, 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*> &params,
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(&paramPointers, 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*> &params,
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*> &params,
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