1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "Codec2Client"
19 #include <log/log.h>
20 
21 #include <codec2/hidl/client.h>
22 
23 #include <deque>
24 #include <limits>
25 #include <map>
26 #include <type_traits>
27 #include <vector>
28 
29 #include <android-base/properties.h>
30 #include <bufferpool/ClientManager.h>
31 #include <cutils/native_handle.h>
32 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
33 #include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
34 #include <hidl/HidlSupport.h>
35 #undef LOG
36 
37 #include <android/hardware/media/bufferpool/1.0/IClientManager.h>
38 #include <hardware/google/media/c2/1.0/IComponent.h>
39 #include <hardware/google/media/c2/1.0/IComponentInterface.h>
40 #include <hardware/google/media/c2/1.0/IComponentListener.h>
41 #include <hardware/google/media/c2/1.0/IComponentStore.h>
42 #include <hardware/google/media/c2/1.0/IConfigurable.h>
43 
44 #include <C2Debug.h>
45 #include <C2BufferPriv.h>
46 #include <C2PlatformSupport.h>
47 
48 namespace android {
49 
50 using ::android::hardware::hidl_vec;
51 using ::android::hardware::hidl_string;
52 using ::android::hardware::Return;
53 using ::android::hardware::Void;
54 using ::android::TWGraphicBufferProducer;
55 
56 using namespace ::hardware::google::media::c2::V1_0;
57 using namespace ::hardware::google::media::c2::V1_0::utils;
58 using namespace ::android::hardware::media::bufferpool::V1_0;
59 using namespace ::android::hardware::media::bufferpool::V1_0::implementation;
60 
61 namespace /* unnamed */ {
62 
63 // c2_status_t value that corresponds to hwbinder transaction failure.
64 constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
65 
66 // List of known IComponentStore services in the decreasing order of preference.
67 constexpr const char* kClientNames[] = {
68         "default",
69         "software",
70     };
71 
72 // Number of known IComponentStore services.
73 constexpr size_t kNumClients = std::extent<decltype(kClientNames)>::value;
74 
75 typedef std::array<std::shared_ptr<Codec2Client>, kNumClients> ClientList;
76 
77 // Convenience methods to obtain known clients.
getClient(size_t index)78 std::shared_ptr<Codec2Client> getClient(size_t index) {
79     return Codec2Client::CreateFromService(kClientNames[index]);
80 }
81 
getClientList()82 ClientList getClientList() {
83     ClientList list;
84     for (size_t i = 0; i < list.size(); ++i) {
85         list[i] = getClient(i);
86     }
87     return list;
88 }
89 
90 } // unnamed
91 
92 // Codec2ConfigurableClient
93 
getName() const94 const C2String& Codec2ConfigurableClient::getName() const {
95     return mName;
96 }
97 
base() const98 Codec2ConfigurableClient::Base* Codec2ConfigurableClient::base() const {
99     return static_cast<Base*>(mBase.get());
100 }
101 
Codec2ConfigurableClient(const sp<Codec2ConfigurableClient::Base> & base)102 Codec2ConfigurableClient::Codec2ConfigurableClient(
103         const sp<Codec2ConfigurableClient::Base>& base) : mBase(base) {
104     Return<void> transStatus = base->getName(
105             [this](const hidl_string& name) {
106                 mName = name.c_str();
107             });
108     if (!transStatus.isOk()) {
109         ALOGE("Cannot obtain name from IConfigurable.");
110     }
111 }
112 
query(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const heapParams) const113 c2_status_t Codec2ConfigurableClient::query(
114         const std::vector<C2Param*> &stackParams,
115         const std::vector<C2Param::Index> &heapParamIndices,
116         c2_blocking_t mayBlock,
117         std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
118     hidl_vec<ParamIndex> indices(
119             stackParams.size() + heapParamIndices.size());
120     size_t numIndices = 0;
121     for (C2Param* const& stackParam : stackParams) {
122         if (!stackParam) {
123             ALOGW("query -- null stack param encountered.");
124             continue;
125         }
126         indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
127     }
128     size_t numStackIndices = numIndices;
129     for (const C2Param::Index& index : heapParamIndices) {
130         indices[numIndices++] =
131                 static_cast<ParamIndex>(static_cast<uint32_t>(index));
132     }
133     indices.resize(numIndices);
134     if (heapParams) {
135         heapParams->reserve(heapParams->size() + numIndices);
136     }
137     c2_status_t status;
138     Return<void> transStatus = base()->query(
139             indices,
140             mayBlock == C2_MAY_BLOCK,
141             [&status, &numStackIndices, &stackParams, heapParams](
142                     Status s, const Params& p) {
143                 status = static_cast<c2_status_t>(s);
144                 if (status != C2_OK && status != C2_BAD_INDEX) {
145                     ALOGE("query -- call failed. "
146                             "Error code = %d", static_cast<int>(status));
147                     return;
148                 }
149                 std::vector<C2Param*> paramPointers;
150                 c2_status_t parseStatus = parseParamsBlob(&paramPointers, p);
151                 if (parseStatus != C2_OK) {
152                     ALOGE("query -- error while parsing params. "
153                             "Error code = %d", static_cast<int>(status));
154                     status = parseStatus;
155                     return;
156                 }
157                 size_t i = 0;
158                 for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
159                     C2Param* paramPointer = *it;
160                     if (numStackIndices > 0) {
161                         --numStackIndices;
162                         if (!paramPointer) {
163                             ALOGW("query -- null stack param.");
164                             ++it;
165                             continue;
166                         }
167                         for (; i < stackParams.size() && !stackParams[i]; ) {
168                             ++i;
169                         }
170                         if (i >= stackParams.size()) {
171                             ALOGE("query -- unexpected error.");
172                             status = C2_CORRUPTED;
173                             return;
174                         }
175                         if (stackParams[i]->index() != paramPointer->index()) {
176                             ALOGW("query -- param skipped. index = %d",
177                                     static_cast<int>(stackParams[i]->index()));
178                             stackParams[i++]->invalidate();
179                             continue;
180                         }
181                         if (!stackParams[i++]->updateFrom(*paramPointer)) {
182                             ALOGW("query -- param update failed. index = %d",
183                                     static_cast<int>(paramPointer->index()));
184                         }
185                     } else {
186                         if (!paramPointer) {
187                             ALOGW("query -- null heap param.");
188                             ++it;
189                             continue;
190                         }
191                         if (!heapParams) {
192                             ALOGW("query -- unexpected extra stack param.");
193                         } else {
194                             heapParams->emplace_back(C2Param::Copy(*paramPointer));
195                         }
196                     }
197                     ++it;
198                 }
199             });
200     if (!transStatus.isOk()) {
201         ALOGE("query -- transaction failed.");
202         return C2_TRANSACTION_FAILED;
203     }
204     return status;
205 }
206 
config(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)207 c2_status_t Codec2ConfigurableClient::config(
208         const std::vector<C2Param*> &params,
209         c2_blocking_t mayBlock,
210         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
211     Params hidlParams;
212     Status hidlStatus = createParamsBlob(&hidlParams, params);
213     if (hidlStatus != Status::OK) {
214         ALOGE("config -- bad input.");
215         return C2_TRANSACTION_FAILED;
216     }
217     c2_status_t status;
218     Return<void> transStatus = base()->config(
219             hidlParams,
220             mayBlock == C2_MAY_BLOCK,
221             [&status, &params, failures](
222                     Status s,
223                     const hidl_vec<SettingResult> f,
224                     const Params& o) {
225                 status = static_cast<c2_status_t>(s);
226                 if (status != C2_OK) {
227                     ALOGD("config -- call failed. "
228                             "Error code = %d", static_cast<int>(status));
229                 }
230                 size_t i = failures->size();
231                 failures->resize(i + f.size());
232                 for (const SettingResult& sf : f) {
233                     status = objcpy(&(*failures)[i++], sf);
234                     if (status != C2_OK) {
235                         ALOGE("config -- invalid returned SettingResult. "
236                                 "Error code = %d", static_cast<int>(status));
237                         return;
238                     }
239                 }
240                 status = updateParamsFromBlob(params, o);
241             });
242     if (!transStatus.isOk()) {
243         ALOGE("config -- transaction failed.");
244         return C2_TRANSACTION_FAILED;
245     }
246     return status;
247 }
248 
querySupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const249 c2_status_t Codec2ConfigurableClient::querySupportedParams(
250         std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
251     // TODO: Cache and query properly!
252     c2_status_t status;
253     Return<void> transStatus = base()->querySupportedParams(
254             std::numeric_limits<uint32_t>::min(),
255             std::numeric_limits<uint32_t>::max(),
256             [&status, params](
257                     Status s,
258                     const hidl_vec<ParamDescriptor>& p) {
259                 status = static_cast<c2_status_t>(s);
260                 if (status != C2_OK) {
261                     ALOGE("querySupportedParams -- call failed. "
262                             "Error code = %d", static_cast<int>(status));
263                     return;
264                 }
265                 size_t i = params->size();
266                 params->resize(i + p.size());
267                 for (const ParamDescriptor& sp : p) {
268                     status = objcpy(&(*params)[i++], sp);
269                     if (status != C2_OK) {
270                         ALOGE("querySupportedParams -- "
271                                 "invalid returned ParamDescriptor. "
272                                 "Error code = %d", static_cast<int>(status));
273                         return;
274                     }
275                 }
276             });
277     if (!transStatus.isOk()) {
278         ALOGE("querySupportedParams -- transaction failed.");
279         return C2_TRANSACTION_FAILED;
280     }
281     return status;
282 }
283 
querySupportedValues(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const284 c2_status_t Codec2ConfigurableClient::querySupportedValues(
285         std::vector<C2FieldSupportedValuesQuery>& fields,
286         c2_blocking_t mayBlock) const {
287     hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
288     for (size_t i = 0; i < fields.size(); ++i) {
289         Status hidlStatus = objcpy(&inFields[i], fields[i]);
290         if (hidlStatus != Status::OK) {
291             ALOGE("querySupportedValues -- bad input");
292             return C2_TRANSACTION_FAILED;
293         }
294     }
295 
296     c2_status_t status;
297     Return<void> transStatus = base()->querySupportedValues(
298             inFields,
299             mayBlock == C2_MAY_BLOCK,
300             [&status, &inFields, &fields](
301                     Status s,
302                     const hidl_vec<FieldSupportedValuesQueryResult>& r) {
303                 status = static_cast<c2_status_t>(s);
304                 if (status != C2_OK) {
305                     ALOGE("querySupportedValues -- call failed. "
306                             "Error code = %d", static_cast<int>(status));
307                     return;
308                 }
309                 if (r.size() != fields.size()) {
310                     ALOGE("querySupportedValues -- input and output lists "
311                             "have different sizes.");
312                     status = C2_CORRUPTED;
313                     return;
314                 }
315                 for (size_t i = 0; i < fields.size(); ++i) {
316                     status = objcpy(&fields[i], inFields[i], r[i]);
317                     if (status != C2_OK) {
318                         ALOGE("querySupportedValues -- invalid returned value. "
319                                 "Error code = %d", static_cast<int>(status));
320                         return;
321                     }
322                 }
323             });
324     if (!transStatus.isOk()) {
325         ALOGE("querySupportedValues -- transaction failed.");
326         return C2_TRANSACTION_FAILED;
327     }
328     return status;
329 }
330 
331 // Codec2Client::Component::HidlListener
332 struct Codec2Client::Component::HidlListener : public IComponentListener {
333     std::weak_ptr<Component> component;
334     std::weak_ptr<Listener> base;
335 
onWorkDoneandroid::Codec2Client::Component::HidlListener336     virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
337         std::list<std::unique_ptr<C2Work>> workItems;
338         c2_status_t status = objcpy(&workItems, workBundle);
339         if (status != C2_OK) {
340             ALOGI("onWorkDone -- received corrupted WorkBundle. "
341                     "status = %d.", static_cast<int>(status));
342             return Void();
343         }
344         // release input buffers potentially held by the component from queue
345         size_t numDiscardedInputBuffers = 0;
346         std::shared_ptr<Codec2Client::Component> strongComponent = component.lock();
347         if (strongComponent) {
348             numDiscardedInputBuffers = strongComponent->handleOnWorkDone(workItems);
349         }
350         if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
351             listener->onWorkDone(component, workItems, numDiscardedInputBuffers);
352         } else {
353             ALOGD("onWorkDone -- listener died.");
354         }
355         return Void();
356     }
357 
onTrippedandroid::Codec2Client::Component::HidlListener358     virtual Return<void> onTripped(
359             const hidl_vec<SettingResult>& settingResults) override {
360         std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
361                 settingResults.size());
362         c2_status_t status;
363         for (size_t i = 0; i < settingResults.size(); ++i) {
364             std::unique_ptr<C2SettingResult> c2SettingResult;
365             status = objcpy(&c2SettingResult, settingResults[i]);
366             if (status != C2_OK) {
367                 ALOGI("onTripped -- received corrupted SettingResult. "
368                         "status = %d.", static_cast<int>(status));
369                 return Void();
370             }
371             c2SettingResults[i] = std::move(c2SettingResult);
372         }
373         if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
374             listener->onTripped(component, c2SettingResults);
375         } else {
376             ALOGD("onTripped -- listener died.");
377         }
378         return Void();
379     }
380 
onErrorandroid::Codec2Client::Component::HidlListener381     virtual Return<void> onError(Status s, uint32_t errorCode) override {
382         ALOGD("onError -- status = %d, errorCode = %u.",
383                 static_cast<int>(s),
384                 static_cast<unsigned>(errorCode));
385         if (std::shared_ptr<Listener> listener = base.lock()) {
386             listener->onError(component, s == Status::OK ?
387                     errorCode : static_cast<c2_status_t>(s));
388         } else {
389             ALOGD("onError -- listener died.");
390         }
391         return Void();
392     }
393 
onFramesRenderedandroid::Codec2Client::Component::HidlListener394     virtual Return<void> onFramesRendered(
395             const hidl_vec<RenderedFrame>& renderedFrames) override {
396         std::shared_ptr<Listener> listener = base.lock();
397         std::vector<Codec2Client::Listener::RenderedFrame> rfs;
398         rfs.reserve(renderedFrames.size());
399         for (const RenderedFrame& rf : renderedFrames) {
400             if (rf.slotId >= 0) {
401                 if (listener) {
402                     rfs.emplace_back(rf.bufferQueueId,
403                                      rf.slotId,
404                                      rf.timestampNs);
405                 }
406             } else {
407                 std::shared_ptr<Codec2Client::Component> strongComponent =
408                         component.lock();
409                 if (strongComponent) {
410                     uint64_t frameIndex = rf.bufferQueueId;
411                     size_t bufferIndex = static_cast<size_t>(~rf.slotId);
412                     ALOGV("Received death notification of input buffer: "
413                           "frameIndex = %llu, bufferIndex = %zu.",
414                           static_cast<long long unsigned>(frameIndex),
415                           bufferIndex);
416                     std::shared_ptr<C2Buffer> buffer =
417                             strongComponent->freeInputBuffer(
418                                 frameIndex, bufferIndex);
419                     if (buffer) {
420                         listener->onInputBufferDone(buffer);
421                     }
422                 }
423             }
424         }
425         if (!rfs.empty()) {
426             if (listener) {
427                 listener->onFramesRendered(rfs);
428             } else {
429                 ALOGD("onFramesRendered -- listener died.");
430             }
431         }
432         return Void();
433     }
434 };
435 
436 // Codec2Client
base() const437 Codec2Client::Base* Codec2Client::base() const {
438     return static_cast<Base*>(mBase.get());
439 }
440 
Codec2Client(const sp<Codec2Client::Base> & base,std::string instanceName)441 Codec2Client::Codec2Client(const sp<Codec2Client::Base>& base, std::string instanceName) :
442     Codec2ConfigurableClient(base), mListed(false), mInstanceName(instanceName) {
443     Return<sp<IClientManager>> transResult = base->getPoolClientManager();
444     if (!transResult.isOk()) {
445         ALOGE("getPoolClientManager -- failed transaction.");
446     } else {
447         mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
448     }
449 }
450 
createComponent(const C2String & name,const std::shared_ptr<Codec2Client::Listener> & listener,std::shared_ptr<Codec2Client::Component> * const component)451 c2_status_t Codec2Client::createComponent(
452         const C2String& name,
453         const std::shared_ptr<Codec2Client::Listener>& listener,
454         std::shared_ptr<Codec2Client::Component>* const component) {
455 
456     // TODO: Add support for Bufferpool
457 
458 
459     c2_status_t status;
460     sp<Component::HidlListener> hidlListener = new Component::HidlListener();
461     hidlListener->base = listener;
462     Return<void> transStatus = base()->createComponent(
463             name,
464             hidlListener,
465             ClientManager::getInstance(),
466             [&status, component, hidlListener](
467                     Status s,
468                     const sp<IComponent>& c) {
469                 status = static_cast<c2_status_t>(s);
470                 if (status != C2_OK) {
471                     return;
472                 }
473                 *component = std::make_shared<Codec2Client::Component>(c);
474                 hidlListener->component = *component;
475             });
476     if (!transStatus.isOk()) {
477         ALOGE("createComponent -- failed transaction.");
478         return C2_TRANSACTION_FAILED;
479     }
480 
481     if (status != C2_OK) {
482         return status;
483     }
484 
485     if (!*component) {
486         ALOGE("createComponent -- null component.");
487         return C2_CORRUPTED;
488     }
489 
490     status = (*component)->setDeathListener(*component, listener);
491     if (status != C2_OK) {
492         ALOGE("createComponent -- setDeathListener returned error: %d.",
493                 static_cast<int>(status));
494     }
495 
496     (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
497     return status;
498 }
499 
createInterface(const C2String & name,std::shared_ptr<Codec2Client::Interface> * const interface)500 c2_status_t Codec2Client::createInterface(
501         const C2String& name,
502         std::shared_ptr<Codec2Client::Interface>* const interface) {
503     c2_status_t status;
504     Return<void> transStatus = base()->createInterface(
505             name,
506             [&status, interface](
507                     Status s,
508                     const sp<IComponentInterface>& i) {
509                 status = static_cast<c2_status_t>(s);
510                 if (status != C2_OK) {
511                     ALOGE("createInterface -- call failed. "
512                             "Error code = %d", static_cast<int>(status));
513                     return;
514                 }
515                 *interface = std::make_shared<Codec2Client::Interface>(i);
516             });
517     if (!transStatus.isOk()) {
518         ALOGE("createInterface -- failed transaction.");
519         return C2_TRANSACTION_FAILED;
520     }
521     return status;
522 }
523 
createInputSurface(std::shared_ptr<Codec2Client::InputSurface> * const inputSurface)524 c2_status_t Codec2Client::createInputSurface(
525         std::shared_ptr<Codec2Client::InputSurface>* const inputSurface) {
526     Return<sp<IInputSurface>> transResult = base()->createInputSurface();
527     if (!transResult.isOk()) {
528         ALOGE("createInputSurface -- failed transaction.");
529         return C2_TRANSACTION_FAILED;
530     }
531     sp<IInputSurface> result = static_cast<sp<IInputSurface>>(transResult);
532     if (!result) {
533         *inputSurface = nullptr;
534         return C2_OK;
535     }
536     *inputSurface = std::make_shared<InputSurface>(result);
537     if (!*inputSurface) {
538         ALOGE("createInputSurface -- unknown error.");
539         return C2_CORRUPTED;
540     }
541     return C2_OK;
542 }
543 
listComponents() const544 const std::vector<C2Component::Traits>& Codec2Client::listComponents() const {
545     std::lock_guard<std::mutex> lock(mMutex);
546     if (mListed) {
547         return mTraitsList;
548     }
549     Return<void> transStatus = base()->listComponents(
550             [this](const hidl_vec<IComponentStore::ComponentTraits>& t) {
551                 mTraitsList.resize(t.size());
552                 mAliasesBuffer.resize(t.size());
553                 for (size_t i = 0; i < t.size(); ++i) {
554                     c2_status_t status = objcpy(
555                             &mTraitsList[i], &mAliasesBuffer[i], t[i]);
556                     mTraitsList[i].owner = mInstanceName;
557                     if (status != C2_OK) {
558                         ALOGE("listComponents -- corrupted output.");
559                         return;
560                     }
561                 }
562             });
563     if (!transStatus.isOk()) {
564         ALOGE("listComponents -- failed transaction.");
565     }
566     mListed = true;
567     return mTraitsList;
568 }
569 
copyBuffer(const std::shared_ptr<C2Buffer> & src,const std::shared_ptr<C2Buffer> & dst)570 c2_status_t Codec2Client::copyBuffer(
571         const std::shared_ptr<C2Buffer>& src,
572         const std::shared_ptr<C2Buffer>& dst) {
573     // TODO: Implement?
574     (void)src;
575     (void)dst;
576     ALOGE("copyBuffer not implemented");
577     return C2_OMITTED;
578 }
579 
580 std::shared_ptr<C2ParamReflector>
getParamReflector()581         Codec2Client::getParamReflector() {
582     // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
583     // should reflect the HAL API.
584     struct SimpleParamReflector : public C2ParamReflector {
585         virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
586             hidl_vec<ParamIndex> indices(1);
587             indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
588             std::unique_ptr<C2StructDescriptor> descriptor;
589             Return<void> transStatus = mBase->getStructDescriptors(
590                     indices,
591                     [&descriptor](
592                             Status s,
593                             const hidl_vec<StructDescriptor>& sd) {
594                         c2_status_t status = static_cast<c2_status_t>(s);
595                         if (status != C2_OK) {
596                             ALOGE("getStructDescriptors -- call failed. "
597                                     "Error code = %d", static_cast<int>(status));
598                             descriptor.reset();
599                             return;
600                         }
601                         if (sd.size() != 1) {
602                             ALOGD("getStructDescriptors -- returned vector of size %zu.",
603                                     sd.size());
604                             descriptor.reset();
605                             return;
606                         }
607                         status = objcpy(&descriptor, sd[0]);
608                         if (status != C2_OK) {
609                             ALOGD("getStructDescriptors -- failed to convert. "
610                                     "Error code = %d", static_cast<int>(status));
611                             descriptor.reset();
612                             return;
613                         }
614                     });
615             return descriptor;
616         }
617 
618         SimpleParamReflector(sp<Base> base)
619             : mBase(base) { }
620 
621         sp<Base> mBase;
622     };
623 
624     return std::make_shared<SimpleParamReflector>(base());
625 };
626 
CreateFromService(const char * instanceName,bool waitForService)627 std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
628         const char* instanceName, bool waitForService) {
629     if (!instanceName) {
630         return nullptr;
631     }
632     sp<Base> baseStore = waitForService ?
633             Base::getService(instanceName) :
634             Base::tryGetService(instanceName);
635     if (!baseStore) {
636         if (waitForService) {
637             ALOGE("Codec2.0 service inaccessible. Check the device manifest.");
638         } else {
639             ALOGW("Codec2.0 service not available right now. Try again later.");
640         }
641         return nullptr;
642     }
643     return std::make_shared<Codec2Client>(baseStore, instanceName);
644 }
645 
ForAllStores(const std::string & key,std::function<c2_status_t (const std::shared_ptr<Codec2Client> &)> predicate)646 c2_status_t Codec2Client::ForAllStores(
647         const std::string &key,
648         std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)> predicate) {
649     c2_status_t status = C2_NO_INIT;  // no IComponentStores present
650 
651     // Cache the mapping key -> index of Codec2Client in getClient().
652     static std::mutex key2IndexMutex;
653     static std::map<std::string, size_t> key2Index;
654 
655     // By default try all stores. However, try the last known client first. If the last known
656     // client fails, retry once. We do this by pushing the last known client in front of the
657     // list of all clients.
658     std::deque<size_t> indices;
659     for (size_t index = kNumClients; index > 0; ) {
660         indices.push_front(--index);
661     }
662 
663     bool wasMapped = false;
664     std::unique_lock<std::mutex> lock(key2IndexMutex);
665     auto it = key2Index.find(key);
666     if (it != key2Index.end()) {
667         indices.push_front(it->second);
668         wasMapped = true;
669     }
670     lock.unlock();
671 
672     for (size_t index : indices) {
673         std::shared_ptr<Codec2Client> client = getClient(index);
674         if (client) {
675             status = predicate(client);
676             if (status == C2_OK) {
677                 lock.lock();
678                 key2Index[key] = index; // update last known client index
679                 return status;
680             }
681         }
682         if (wasMapped) {
683             ALOGI("Could not find '%s' in last instance. Retrying...", key.c_str());
684             wasMapped = false;
685         }
686     }
687     return status;  // return the last status from a valid client
688 }
689 
690 std::shared_ptr<Codec2Client::Component>
CreateComponentByName(const char * componentName,const std::shared_ptr<Listener> & listener,std::shared_ptr<Codec2Client> * owner)691         Codec2Client::CreateComponentByName(
692         const char* componentName,
693         const std::shared_ptr<Listener>& listener,
694         std::shared_ptr<Codec2Client>* owner) {
695     std::shared_ptr<Component> component;
696     c2_status_t status = ForAllStores(
697             componentName,
698             [owner, &component, componentName, &listener](
699                     const std::shared_ptr<Codec2Client> &client) -> c2_status_t {
700                 c2_status_t status = client->createComponent(componentName, listener, &component);
701                 if (status == C2_OK) {
702                     if (owner) {
703                         *owner = client;
704                     }
705                 } else if (status != C2_NOT_FOUND) {
706                     ALOGD("IComponentStore(%s)::createComponent('%s') returned %s",
707                             client->getInstanceName().c_str(), componentName, asString(status));
708                 }
709                 return status;
710             });
711     if (status != C2_OK) {
712         ALOGI("Could not create component '%s' (%s)", componentName, asString(status));
713     }
714     return component;
715 }
716 
717 std::shared_ptr<Codec2Client::Interface>
CreateInterfaceByName(const char * interfaceName,std::shared_ptr<Codec2Client> * owner)718         Codec2Client::CreateInterfaceByName(
719         const char* interfaceName,
720         std::shared_ptr<Codec2Client>* owner) {
721     std::shared_ptr<Interface> interface;
722     c2_status_t status = ForAllStores(
723             interfaceName,
724             [owner, &interface, interfaceName](
725                     const std::shared_ptr<Codec2Client> &client) -> c2_status_t {
726                 c2_status_t status = client->createInterface(interfaceName, &interface);
727                 if (status == C2_OK) {
728                     if (owner) {
729                         *owner = client;
730                     }
731                 } else if (status != C2_NOT_FOUND) {
732                     ALOGD("IComponentStore(%s)::createInterface('%s') returned %s",
733                             client->getInstanceName().c_str(), interfaceName, asString(status));
734                 }
735                 return status;
736             });
737     if (status != C2_OK) {
738         ALOGI("Could not create interface '%s' (%s)", interfaceName, asString(status));
739     }
740     return interface;
741 }
742 
CreateInputSurface()743 std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface() {
744     uint32_t serviceMask = ::android::base::GetUintProperty(
745             "debug.stagefright.c2inputsurface", uint32_t(0));
746     for (size_t i = 0; i < kNumClients; ++i) {
747         if ((1 << i) & serviceMask) {
748             std::shared_ptr<Codec2Client> client = getClient(i);
749             std::shared_ptr<Codec2Client::InputSurface> inputSurface;
750             if (client &&
751                     client->createInputSurface(&inputSurface) == C2_OK &&
752                     inputSurface) {
753                 return inputSurface;
754             }
755         }
756     }
757     ALOGW("Could not create an input surface from any Codec2.0 services.");
758     return nullptr;
759 }
760 
ListComponents()761 const std::vector<C2Component::Traits>& Codec2Client::ListComponents() {
762     static std::vector<C2Component::Traits> traitsList = [](){
763         std::vector<C2Component::Traits> list;
764         size_t listSize = 0;
765         ClientList clientList = getClientList();
766         for (const std::shared_ptr<Codec2Client>& client : clientList) {
767             if (!client) {
768                 continue;
769             }
770             listSize += client->listComponents().size();
771         }
772         list.reserve(listSize);
773         for (const std::shared_ptr<Codec2Client>& client : clientList) {
774             if (!client) {
775                 continue;
776             }
777             list.insert(
778                     list.end(),
779                     client->listComponents().begin(),
780                     client->listComponents().end());
781         }
782         return list;
783     }();
784 
785     return traitsList;
786 }
787 
788 // Codec2Client::Listener
789 
~Listener()790 Codec2Client::Listener::~Listener() {
791 }
792 
793 // Codec2Client::Component
794 
base() const795 Codec2Client::Component::Base* Codec2Client::Component::base() const {
796     return static_cast<Base*>(mBase.get());
797 }
798 
Component(const sp<Codec2Client::Component::Base> & base)799 Codec2Client::Component::Component(const sp<Codec2Client::Component::Base>& base) :
800     Codec2Client::Configurable(base),
801     mBufferPoolSender(nullptr) {
802 }
803 
~Component()804 Codec2Client::Component::~Component() {
805 }
806 
createBlockPool(C2Allocator::id_t id,C2BlockPool::local_id_t * blockPoolId,std::shared_ptr<Codec2Client::Configurable> * configurable)807 c2_status_t Codec2Client::Component::createBlockPool(
808         C2Allocator::id_t id,
809         C2BlockPool::local_id_t* blockPoolId,
810         std::shared_ptr<Codec2Client::Configurable>* configurable) {
811     c2_status_t status;
812     Return<void> transStatus = base()->createBlockPool(
813             static_cast<uint32_t>(id),
814             [&status, blockPoolId, configurable](
815                     Status s,
816                     uint64_t pId,
817                     const sp<IConfigurable>& c) {
818                 status = static_cast<c2_status_t>(s);
819                 configurable->reset();
820                 if (status != C2_OK) {
821                     ALOGE("createBlockPool -- call failed. "
822                             "Error code = %d", static_cast<int>(status));
823                     return;
824                 }
825                 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
826                 *configurable = std::make_shared<Codec2Client::Configurable>(c);
827             });
828     if (!transStatus.isOk()) {
829         ALOGE("createBlockPool -- transaction failed.");
830         return C2_TRANSACTION_FAILED;
831     }
832     return status;
833 }
834 
destroyBlockPool(C2BlockPool::local_id_t localId)835 c2_status_t Codec2Client::Component::destroyBlockPool(
836         C2BlockPool::local_id_t localId) {
837     Return<Status> transResult = base()->destroyBlockPool(
838             static_cast<uint64_t>(localId));
839     if (!transResult.isOk()) {
840         ALOGE("destroyBlockPool -- transaction failed.");
841         return C2_TRANSACTION_FAILED;
842     }
843     return static_cast<c2_status_t>(static_cast<Status>(transResult));
844 }
845 
handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> & workItems)846 size_t Codec2Client::Component::handleOnWorkDone(
847         const std::list<std::unique_ptr<C2Work>> &workItems) {
848     // Input buffers' lifetime management
849     std::vector<uint64_t> inputDone;
850     for (const std::unique_ptr<C2Work> &work : workItems) {
851         if (work) {
852             if (work->worklets.empty()
853                     || !work->worklets.back()
854                     || (work->worklets.back()->output.flags & C2FrameData::FLAG_INCOMPLETE) == 0) {
855                 // input is complete
856                 inputDone.emplace_back(work->input.ordinal.frameIndex.peeku());
857             }
858         }
859     }
860 
861     size_t numDiscardedInputBuffers = 0;
862     {
863         std::lock_guard<std::mutex> lock(mInputBuffersMutex);
864         for (uint64_t inputIndex : inputDone) {
865             auto it = mInputBuffers.find(inputIndex);
866             if (it == mInputBuffers.end()) {
867                 ALOGV("onWorkDone -- returned consumed/unknown "
868                       "input frame: index %llu",
869                         (long long)inputIndex);
870             } else {
871                 ALOGV("onWorkDone -- processed input frame: "
872                       "index %llu (containing %zu buffers)",
873                         (long long)inputIndex, it->second.size());
874                 mInputBuffers.erase(it);
875                 mInputBufferCount.erase(inputIndex);
876                 ++numDiscardedInputBuffers;
877             }
878         }
879     }
880 
881     // Output bufferqueue-based blocks' lifetime management
882     mOutputBufferQueueMutex.lock();
883     sp<IGraphicBufferProducer> igbp = mOutputIgbp;
884     uint64_t bqId = mOutputBqId;
885     uint32_t generation = mOutputGeneration;
886     mOutputBufferQueueMutex.unlock();
887 
888     if (igbp) {
889         holdBufferQueueBlocks(workItems, igbp, bqId, generation);
890     }
891     return numDiscardedInputBuffers;
892 }
893 
freeInputBuffer(uint64_t frameIndex,size_t bufferIndex)894 std::shared_ptr<C2Buffer> Codec2Client::Component::freeInputBuffer(
895         uint64_t frameIndex,
896         size_t bufferIndex) {
897     std::shared_ptr<C2Buffer> buffer;
898     std::lock_guard<std::mutex> lock(mInputBuffersMutex);
899     auto it = mInputBuffers.find(frameIndex);
900     if (it == mInputBuffers.end()) {
901         ALOGI("freeInputBuffer -- Unrecognized input frame index %llu.",
902               static_cast<long long unsigned>(frameIndex));
903         return nullptr;
904     }
905     if (bufferIndex >= it->second.size()) {
906         ALOGI("freeInputBuffer -- Input buffer no. %zu is invalid in "
907               "input frame index %llu.",
908               bufferIndex, static_cast<long long unsigned>(frameIndex));
909         return nullptr;
910     }
911     buffer = it->second[bufferIndex];
912     if (!buffer) {
913         ALOGI("freeInputBuffer -- Input buffer no. %zu in "
914               "input frame index %llu has already been freed.",
915               bufferIndex, static_cast<long long unsigned>(frameIndex));
916         return nullptr;
917     }
918     it->second[bufferIndex] = nullptr;
919     if (--mInputBufferCount[frameIndex] == 0) {
920         mInputBuffers.erase(it);
921         mInputBufferCount.erase(frameIndex);
922     }
923     return buffer;
924 }
925 
queue(std::list<std::unique_ptr<C2Work>> * const items)926 c2_status_t Codec2Client::Component::queue(
927         std::list<std::unique_ptr<C2Work>>* const items) {
928     // remember input buffers queued to hold reference to them
929     {
930         std::lock_guard<std::mutex> lock(mInputBuffersMutex);
931         for (const std::unique_ptr<C2Work> &work : *items) {
932             if (!work) {
933                 continue;
934             }
935             if (work->input.buffers.size() == 0) {
936                 continue;
937             }
938 
939             uint64_t inputIndex = work->input.ordinal.frameIndex.peeku();
940             auto res = mInputBuffers.emplace(inputIndex, work->input.buffers);
941             if (!res.second) {
942                 // TODO: append? - for now we are replacing
943                 res.first->second = work->input.buffers;
944                 ALOGI("queue -- duplicate input frame: index %llu. "
945                       "Discarding the old input frame...",
946                         (long long)inputIndex);
947             }
948             mInputBufferCount[inputIndex] = work->input.buffers.size();
949             ALOGV("queue -- queueing input frame: "
950                   "index %llu (containing %zu buffers)",
951                     (long long)inputIndex, work->input.buffers.size());
952         }
953     }
954 
955     WorkBundle workBundle;
956     Status hidlStatus = objcpy(&workBundle, *items, &mBufferPoolSender);
957     if (hidlStatus != Status::OK) {
958         ALOGE("queue -- bad input.");
959         return C2_TRANSACTION_FAILED;
960     }
961     Return<Status> transStatus = base()->queue(workBundle);
962     if (!transStatus.isOk()) {
963         ALOGE("queue -- transaction failed.");
964         return C2_TRANSACTION_FAILED;
965     }
966     c2_status_t status =
967             static_cast<c2_status_t>(static_cast<Status>(transStatus));
968     if (status != C2_OK) {
969         ALOGE("queue -- call failed. "
970                 "Error code = %d", static_cast<int>(status));
971     }
972     return status;
973 }
974 
flush(C2Component::flush_mode_t mode,std::list<std::unique_ptr<C2Work>> * const flushedWork)975 c2_status_t Codec2Client::Component::flush(
976         C2Component::flush_mode_t mode,
977         std::list<std::unique_ptr<C2Work>>* const flushedWork) {
978     (void)mode; // Flush mode isn't supported in HIDL yet.
979     c2_status_t status;
980     Return<void> transStatus = base()->flush(
981             [&status, flushedWork](
982                     Status s, const WorkBundle& wb) {
983                 status = static_cast<c2_status_t>(s);
984                 if (status != C2_OK) {
985                     ALOGE("flush -- call failed. "
986                             "Error code = %d", static_cast<int>(status));
987                     return;
988                 }
989                 status = objcpy(flushedWork, wb);
990             });
991     if (!transStatus.isOk()) {
992         ALOGE("flush -- transaction failed.");
993         return C2_TRANSACTION_FAILED;
994     }
995 
996     // Indices of flushed work items.
997     std::vector<uint64_t> flushedIndices;
998     for (const std::unique_ptr<C2Work> &work : *flushedWork) {
999         if (work) {
1000             if (work->worklets.empty()
1001                     || !work->worklets.back()
1002                     || (work->worklets.back()->output.flags &
1003                         C2FrameData::FLAG_INCOMPLETE) == 0) {
1004                 // input is complete
1005                 flushedIndices.emplace_back(
1006                         work->input.ordinal.frameIndex.peeku());
1007             }
1008         }
1009     }
1010 
1011     // Input buffers' lifetime management
1012     for (uint64_t flushedIndex : flushedIndices) {
1013         std::lock_guard<std::mutex> lock(mInputBuffersMutex);
1014         auto it = mInputBuffers.find(flushedIndex);
1015         if (it == mInputBuffers.end()) {
1016             ALOGV("flush -- returned consumed/unknown input frame: "
1017                   "index %llu",
1018                     (long long)flushedIndex);
1019         } else {
1020             ALOGV("flush -- returned unprocessed input frame: "
1021                   "index %llu (containing %zu buffers)",
1022                     (long long)flushedIndex, mInputBufferCount[flushedIndex]);
1023             mInputBuffers.erase(it);
1024             mInputBufferCount.erase(flushedIndex);
1025         }
1026     }
1027 
1028     // Output bufferqueue-based blocks' lifetime management
1029     mOutputBufferQueueMutex.lock();
1030     sp<IGraphicBufferProducer> igbp = mOutputIgbp;
1031     uint64_t bqId = mOutputBqId;
1032     uint32_t generation = mOutputGeneration;
1033     mOutputBufferQueueMutex.unlock();
1034 
1035     if (igbp) {
1036         holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
1037     }
1038 
1039     return status;
1040 }
1041 
drain(C2Component::drain_mode_t mode)1042 c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
1043     Return<Status> transStatus = base()->drain(
1044             mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1045     if (!transStatus.isOk()) {
1046         ALOGE("drain -- transaction failed.");
1047         return C2_TRANSACTION_FAILED;
1048     }
1049     c2_status_t status =
1050             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1051     if (status != C2_OK) {
1052         ALOGE("drain -- call failed. "
1053                 "Error code = %d", static_cast<int>(status));
1054     }
1055     return status;
1056 }
1057 
start()1058 c2_status_t Codec2Client::Component::start() {
1059     Return<Status> transStatus = base()->start();
1060     if (!transStatus.isOk()) {
1061         ALOGE("start -- transaction failed.");
1062         return C2_TRANSACTION_FAILED;
1063     }
1064     c2_status_t status =
1065             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1066     if (status != C2_OK) {
1067         ALOGE("start -- call failed. "
1068                 "Error code = %d", static_cast<int>(status));
1069     }
1070     return status;
1071 }
1072 
stop()1073 c2_status_t Codec2Client::Component::stop() {
1074     Return<Status> transStatus = base()->stop();
1075     if (!transStatus.isOk()) {
1076         ALOGE("stop -- transaction failed.");
1077         return C2_TRANSACTION_FAILED;
1078     }
1079     c2_status_t status =
1080             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1081     if (status != C2_OK) {
1082         ALOGE("stop -- call failed. "
1083                 "Error code = %d", static_cast<int>(status));
1084     }
1085     mInputBuffersMutex.lock();
1086     mInputBuffers.clear();
1087     mInputBufferCount.clear();
1088     mInputBuffersMutex.unlock();
1089     return status;
1090 }
1091 
reset()1092 c2_status_t Codec2Client::Component::reset() {
1093     Return<Status> transStatus = base()->reset();
1094     if (!transStatus.isOk()) {
1095         ALOGE("reset -- transaction failed.");
1096         return C2_TRANSACTION_FAILED;
1097     }
1098     c2_status_t status =
1099             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1100     if (status != C2_OK) {
1101         ALOGE("reset -- call failed. "
1102                 "Error code = %d", static_cast<int>(status));
1103     }
1104     mInputBuffersMutex.lock();
1105     mInputBuffers.clear();
1106     mInputBufferCount.clear();
1107     mInputBuffersMutex.unlock();
1108     return status;
1109 }
1110 
release()1111 c2_status_t Codec2Client::Component::release() {
1112     Return<Status> transStatus = base()->release();
1113     if (!transStatus.isOk()) {
1114         ALOGE("release -- transaction failed.");
1115         return C2_TRANSACTION_FAILED;
1116     }
1117     c2_status_t status =
1118             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1119     if (status != C2_OK) {
1120         ALOGE("release -- call failed. "
1121                 "Error code = %d", static_cast<int>(status));
1122     }
1123     mInputBuffersMutex.lock();
1124     mInputBuffers.clear();
1125     mInputBufferCount.clear();
1126     mInputBuffersMutex.unlock();
1127     return status;
1128 }
1129 
setOutputSurface(C2BlockPool::local_id_t blockPoolId,const sp<IGraphicBufferProducer> & surface,uint32_t generation)1130 c2_status_t Codec2Client::Component::setOutputSurface(
1131         C2BlockPool::local_id_t blockPoolId,
1132         const sp<IGraphicBufferProducer>& surface,
1133         uint32_t generation) {
1134     sp<HGraphicBufferProducer> igbp =
1135             surface->getHalInterface<HGraphicBufferProducer>();
1136     if (!igbp) {
1137         igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface);
1138     }
1139 
1140     Return<Status> transStatus = base()->setOutputSurface(
1141             static_cast<uint64_t>(blockPoolId), igbp);
1142     if (!transStatus.isOk()) {
1143         ALOGE("setOutputSurface -- transaction failed.");
1144         return C2_TRANSACTION_FAILED;
1145     }
1146     c2_status_t status =
1147             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1148     if (status != C2_OK) {
1149         ALOGE("setOutputSurface -- call failed. "
1150                 "Error code = %d", static_cast<int>(status));
1151     } else {
1152         std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
1153         if (mOutputIgbp != surface) {
1154             mOutputIgbp = surface;
1155             if (!surface) {
1156                 mOutputBqId = 0;
1157             } else if (surface->getUniqueId(&mOutputBqId) != OK) {
1158                 ALOGE("setOutputSurface -- cannot obtain bufferqueue id.");
1159             }
1160         }
1161         mOutputGeneration = generation;
1162     }
1163     return status;
1164 }
1165 
queueToOutputSurface(const C2ConstGraphicBlock & block,const QueueBufferInput & input,QueueBufferOutput * output)1166 status_t Codec2Client::Component::queueToOutputSurface(
1167         const C2ConstGraphicBlock& block,
1168         const QueueBufferInput& input,
1169         QueueBufferOutput* output) {
1170     uint32_t generation;
1171     uint64_t bqId;
1172     int32_t bqSlot;
1173     if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
1174             bqId == 0) {
1175         // Block not from bufferqueue -- it must be attached before queuing.
1176 
1177         mOutputBufferQueueMutex.lock();
1178         sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1179         uint32_t outputGeneration = mOutputGeneration;
1180         mOutputBufferQueueMutex.unlock();
1181 
1182         status_t status = !attachToBufferQueue(block,
1183                                                outputIgbp,
1184                                                outputGeneration,
1185                                                &bqSlot);
1186         if (status != OK) {
1187             ALOGW("queueToOutputSurface -- attaching failed.");
1188             return INVALID_OPERATION;
1189         }
1190 
1191         status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1192                                          input, output);
1193         if (status != OK) {
1194             ALOGE("queueToOutputSurface -- queueBuffer() failed "
1195                     "on non-bufferqueue-based block. "
1196                     "Error code = %d.",
1197                     static_cast<int>(status));
1198             return status;
1199         }
1200         return OK;
1201     }
1202 
1203     mOutputBufferQueueMutex.lock();
1204     sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1205     uint64_t outputBqId = mOutputBqId;
1206     uint32_t outputGeneration = mOutputGeneration;
1207     mOutputBufferQueueMutex.unlock();
1208 
1209     if (!outputIgbp) {
1210         ALOGV("queueToOutputSurface -- output surface is null.");
1211         return NO_INIT;
1212     }
1213 
1214     if (bqId != outputBqId) {
1215         ALOGV("queueToOutputSurface -- bufferqueue ids mismatch.");
1216         return DEAD_OBJECT;
1217     }
1218 
1219     if (generation != outputGeneration) {
1220         ALOGV("queueToOutputSurface -- generation numbers mismatch.");
1221         return DEAD_OBJECT;
1222     }
1223 
1224     status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1225                                               input, output);
1226     if (status != OK) {
1227         ALOGD("queueToOutputSurface -- queueBuffer() failed "
1228                 "on bufferqueue-based block. "
1229                 "Error code = %d.",
1230                 static_cast<int>(status));
1231         return status;
1232     }
1233     if (!yieldBufferQueueBlock(block)) {
1234         ALOGD("queueToOutputSurface -- cannot yield bufferqueue-based block "
1235                 "to the bufferqueue.");
1236         return UNKNOWN_ERROR;
1237     }
1238     return OK;
1239 }
1240 
connectToOmxInputSurface(const sp<HGraphicBufferProducer> & producer,const sp<HGraphicBufferSource> & source)1241 c2_status_t Codec2Client::Component::connectToOmxInputSurface(
1242         const sp<HGraphicBufferProducer>& producer,
1243         const sp<HGraphicBufferSource>& source) {
1244     Return<Status> transStatus = base()->connectToOmxInputSurface(
1245             producer, source);
1246     if (!transStatus.isOk()) {
1247         ALOGE("connectToOmxInputSurface -- transaction failed.");
1248         return C2_TRANSACTION_FAILED;
1249     }
1250     c2_status_t status =
1251             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1252     if (status != C2_OK) {
1253         ALOGE("connectToOmxInputSurface -- call failed. "
1254                 "Error code = %d", static_cast<int>(status));
1255     }
1256     return status;
1257 }
1258 
disconnectFromInputSurface()1259 c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
1260     Return<Status> transStatus = base()->disconnectFromInputSurface();
1261     if (!transStatus.isOk()) {
1262         ALOGE("disconnectToInputSurface -- transaction failed.");
1263         return C2_TRANSACTION_FAILED;
1264     }
1265     c2_status_t status =
1266             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1267     if (status != C2_OK) {
1268         ALOGE("disconnectFromInputSurface -- call failed. "
1269                 "Error code = %d", static_cast<int>(status));
1270     }
1271     return status;
1272 }
1273 
setDeathListener(const std::shared_ptr<Component> & component,const std::shared_ptr<Listener> & listener)1274 c2_status_t Codec2Client::Component::setDeathListener(
1275         const std::shared_ptr<Component>& component,
1276         const std::shared_ptr<Listener>& listener) {
1277 
1278     struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1279         std::weak_ptr<Component> component;
1280         std::weak_ptr<Listener> base;
1281 
1282         virtual void serviceDied(
1283                 uint64_t /* cookie */,
1284                 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1285                 ) override {
1286             if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1287                 listener->onDeath(component);
1288             } else {
1289                 ALOGW("onDeath -- listener died.");
1290             }
1291         }
1292     };
1293 
1294     sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1295     deathRecipient->base = listener;
1296     deathRecipient->component = component;
1297 
1298     component->mDeathRecipient = deathRecipient;
1299     Return<bool> transResult = component->base()->linkToDeath(
1300             component->mDeathRecipient, 0);
1301     if (!transResult.isOk()) {
1302         ALOGE("setDeathListener -- failed transaction: linkToDeath.");
1303         return C2_TRANSACTION_FAILED;
1304     }
1305     if (!static_cast<bool>(transResult)) {
1306         ALOGE("setDeathListener -- linkToDeath call failed.");
1307         return C2_CORRUPTED;
1308     }
1309     return C2_OK;
1310 }
1311 
1312 // Codec2Client::InputSurface
1313 
base() const1314 Codec2Client::InputSurface::Base* Codec2Client::InputSurface::base() const {
1315     return static_cast<Base*>(mBase.get());
1316 }
1317 
InputSurface(const sp<IInputSurface> & base)1318 Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base) :
1319     mBase(base),
1320     mGraphicBufferProducer(new
1321             ::android::hardware::graphics::bufferqueue::V1_0::utils::
1322             H2BGraphicBufferProducer(base)) {
1323 }
1324 
connectToComponent(const std::shared_ptr<Codec2Client::Component> & component,std::shared_ptr<Connection> * connection)1325 c2_status_t Codec2Client::InputSurface::connectToComponent(
1326         const std::shared_ptr<Codec2Client::Component>& component,
1327         std::shared_ptr<Connection>* connection) {
1328     c2_status_t status;
1329     Return<void> transStatus = base()->connectToComponent(
1330         component->base(),
1331         [&status, connection](
1332                 Status s,
1333                 const sp<IInputSurfaceConnection>& c) {
1334             status = static_cast<c2_status_t>(s);
1335             if (status != C2_OK) {
1336                 ALOGE("connectToComponent -- call failed. "
1337                         "Error code = %d", static_cast<int>(status));
1338                 return;
1339             }
1340             *connection = std::make_shared<Connection>(c);
1341         });
1342     if (!transStatus.isOk()) {
1343         ALOGE("connect -- transaction failed.");
1344         return C2_TRANSACTION_FAILED;
1345     }
1346     return status;
1347 }
1348 
1349 std::shared_ptr<Codec2Client::Configurable>
getConfigurable() const1350         Codec2Client::InputSurface::getConfigurable() const {
1351     Return<sp<IConfigurable>> transResult = base()->getConfigurable();
1352     if (!transResult.isOk()) {
1353         ALOGW("getConfigurable -- transaction failed.");
1354         return nullptr;
1355     }
1356     if (!static_cast<sp<IConfigurable>>(transResult)) {
1357         ALOGW("getConfigurable -- null pointer.");
1358         return nullptr;
1359     }
1360     return std::make_shared<Configurable>(transResult);
1361 }
1362 
1363 const sp<IGraphicBufferProducer>&
getGraphicBufferProducer() const1364         Codec2Client::InputSurface::getGraphicBufferProducer() const {
1365     return mGraphicBufferProducer;
1366 }
1367 
getHalInterface() const1368 const sp<IInputSurface>& Codec2Client::InputSurface::getHalInterface() const {
1369     return mBase;
1370 }
1371 
1372 // Codec2Client::InputSurfaceConnection
1373 
1374 Codec2Client::InputSurfaceConnection::Base*
base() const1375         Codec2Client::InputSurfaceConnection::base() const {
1376     return static_cast<Base*>(mBase.get());
1377 }
1378 
InputSurfaceConnection(const sp<Codec2Client::InputSurfaceConnection::Base> & base)1379 Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
1380         const sp<Codec2Client::InputSurfaceConnection::Base>& base) :
1381     mBase(base) {
1382 }
1383 
disconnect()1384 c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
1385     Return<Status> transResult = base()->disconnect();
1386     return static_cast<c2_status_t>(static_cast<Status>(transResult));
1387 }
1388 
1389 }  // namespace android
1390 
1391