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 #include <android-base/logging.h>
20 
21 #include <codec2/hidl/client.h>
22 
23 #include <deque>
24 #include <iterator>
25 #include <limits>
26 #include <map>
27 #include <mutex>
28 #include <sstream>
29 #include <thread>
30 #include <type_traits>
31 #include <vector>
32 
33 #include <android-base/properties.h>
34 #include <bufferpool/ClientManager.h>
35 #include <cutils/native_handle.h>
36 #include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
37 #include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
38 #include <hidl/HidlSupport.h>
39 
40 #include <android/hardware/media/bufferpool/2.0/IClientManager.h>
41 #include <android/hardware/media/c2/1.0/IComponent.h>
42 #include <android/hardware/media/c2/1.0/IComponentInterface.h>
43 #include <android/hardware/media/c2/1.0/IComponentListener.h>
44 #include <android/hardware/media/c2/1.0/IComponentStore.h>
45 #include <android/hardware/media/c2/1.0/IConfigurable.h>
46 #include <android/hidl/manager/1.2/IServiceManager.h>
47 
48 #include <C2Debug.h>
49 #include <C2BufferPriv.h>
50 #include <C2PlatformSupport.h>
51 
52 namespace android {
53 
54 using ::android::hardware::hidl_vec;
55 using ::android::hardware::hidl_string;
56 using ::android::hardware::Return;
57 using ::android::hardware::Void;
58 
59 using namespace ::android::hardware::media::c2::V1_0;
60 using namespace ::android::hardware::media::c2::V1_0::utils;
61 using namespace ::android::hardware::media::bufferpool::V2_0;
62 using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
63 
64 using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
65         V1_0::IGraphicBufferProducer;
66 using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
67         V2_0::IGraphicBufferProducer;
68 using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
69         V2_0::utils::B2HGraphicBufferProducer;
70 using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
71         V2_0::utils::H2BGraphicBufferProducer;
72 
73 namespace /* unnamed */ {
74 
75 // c2_status_t value that corresponds to hwbinder transaction failure.
76 constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
77 
78 // Searches for a name in GetServiceNames() and returns the index found. If the
79 // name is not found, the returned index will be equal to
80 // GetServiceNames().size().
getServiceIndex(char const * name)81 size_t getServiceIndex(char const* name) {
82     std::vector<std::string> const& names = Codec2Client::GetServiceNames();
83     size_t i = 0;
84     for (; i < names.size(); ++i) {
85         if (name == names[i]) {
86             break;
87         }
88     }
89     return i;
90 }
91 
92 }  // unnamed namespace
93 
94 // This class caches a Codec2Client object and its component traits. The client
95 // will be created the first time it is needed, and it can be refreshed if the
96 // service dies (by calling invalidate()). The first time listComponents() is
97 // called from the client, the result will be cached.
98 class Codec2Client::Cache {
99     // Cached client
100     std::shared_ptr<Codec2Client> mClient;
101     mutable std::mutex mClientMutex;
102 
103     // Cached component traits
104     std::vector<C2Component::Traits> mTraits;
105     std::once_flag mTraitsInitializationFlag;
106 
107     // The index of the service. This is based on GetServiceNames().
108     size_t mIndex;
109     // Called by s() exactly once to initialize the cache. The index must be a
110     // valid index into the vector returned by GetServiceNames(). Calling
111     // init(index) will associate the cache to the service with name
112     // GetServiceNames()[index].
init(size_t index)113     void init(size_t index) {
114         mIndex = index;
115     }
116 
117 public:
118     Cache() = default;
119 
120     // Initializes mClient if needed, then returns mClient.
121     // If the service is unavailable but listed in the manifest, this function
122     // will block indefinitely.
getClient()123     std::shared_ptr<Codec2Client> getClient() {
124         std::scoped_lock lock{mClientMutex};
125         if (!mClient) {
126             mClient = Codec2Client::_CreateFromIndex(mIndex);
127         }
128         CHECK(mClient) << "Failed to create Codec2Client to service \""
129                        << GetServiceNames()[mIndex] << "\". (Index = "
130                        << mIndex << ").";
131         return mClient;
132     }
133 
134     // Causes a subsequent call to getClient() to create a new client. This
135     // function should be called after the service dies.
136     //
137     // Note: This function is called only by ForAllServices().
invalidate()138     void invalidate() {
139         std::scoped_lock lock{mClientMutex};
140         mClient = nullptr;
141     }
142 
143     // Returns a list of traits for components supported by the service. This
144     // list is cached.
getTraits()145     std::vector<C2Component::Traits> const& getTraits() {
146         std::call_once(mTraitsInitializationFlag, [this]() {
147             bool success{false};
148             // Spin until _listComponents() is successful.
149             while (true) {
150                 std::shared_ptr<Codec2Client> client = getClient();
151                 mTraits = client->_listComponents(&success);
152                 if (success) {
153                     break;
154                 }
155                 using namespace std::chrono_literals;
156                 static constexpr auto kServiceRetryPeriod = 5s;
157                 LOG(INFO) << "Failed to retrieve component traits from service "
158                              "\"" << GetServiceNames()[mIndex] << "\". "
159                              "Retrying...";
160                 std::this_thread::sleep_for(kServiceRetryPeriod);
161             }
162         });
163         return mTraits;
164     }
165 
166     // List() returns the list of all caches.
List()167     static std::vector<Cache>& List() {
168         static std::vector<Cache> sCaches{[]() {
169             size_t numServices = GetServiceNames().size();
170             std::vector<Cache> caches(numServices);
171             for (size_t i = 0; i < numServices; ++i) {
172                 caches[i].init(i);
173             }
174             return caches;
175         }()};
176         return sCaches;
177     }
178 };
179 
180 // Codec2ConfigurableClient
181 
getName() const182 const C2String& Codec2ConfigurableClient::getName() const {
183     return mName;
184 }
185 
Codec2ConfigurableClient(const sp<IConfigurable> & base)186 Codec2ConfigurableClient::Codec2ConfigurableClient(
187         const sp<IConfigurable>& base)
188       : mBase{base},
__anon272953510402() 189         mName{[base]() -> C2String {
190                 C2String outName;
191                 Return<void> transStatus = base->getName(
192                         [&outName](const hidl_string& name) {
193                             outName = name.c_str();
194                         });
195                 return transStatus.isOk() ? outName : "";
196             }()} {
197 }
198 
query(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const heapParams) const199 c2_status_t Codec2ConfigurableClient::query(
200         const std::vector<C2Param*> &stackParams,
201         const std::vector<C2Param::Index> &heapParamIndices,
202         c2_blocking_t mayBlock,
203         std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
204     hidl_vec<ParamIndex> indices(
205             stackParams.size() + heapParamIndices.size());
206     size_t numIndices = 0;
207     for (C2Param* const& stackParam : stackParams) {
208         if (!stackParam) {
209             LOG(WARNING) << "query -- null stack param encountered.";
210             continue;
211         }
212         indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
213     }
214     size_t numStackIndices = numIndices;
215     for (const C2Param::Index& index : heapParamIndices) {
216         indices[numIndices++] =
217                 static_cast<ParamIndex>(static_cast<uint32_t>(index));
218     }
219     indices.resize(numIndices);
220     if (heapParams) {
221         heapParams->reserve(heapParams->size() + numIndices);
222     }
223     c2_status_t status;
224     Return<void> transStatus = mBase->query(
225             indices,
226             mayBlock == C2_MAY_BLOCK,
227             [&status, &numStackIndices, &stackParams, heapParams](
228                     Status s, const Params& p) {
229                 status = static_cast<c2_status_t>(s);
230                 if (status != C2_OK && status != C2_BAD_INDEX) {
231                     LOG(DEBUG) << "query -- call failed: "
232                                << status << ".";
233                     return;
234                 }
235                 std::vector<C2Param*> paramPointers;
236                 if (!parseParamsBlob(&paramPointers, p)) {
237                     LOG(ERROR) << "query -- error while parsing params.";
238                     status = C2_CORRUPTED;
239                     return;
240                 }
241                 size_t i = 0;
242                 for (auto it = paramPointers.begin();
243                         it != paramPointers.end(); ) {
244                     C2Param* paramPointer = *it;
245                     if (numStackIndices > 0) {
246                         --numStackIndices;
247                         if (!paramPointer) {
248                             LOG(WARNING) << "query -- null stack param.";
249                             ++it;
250                             continue;
251                         }
252                         for (; i < stackParams.size() && !stackParams[i]; ) {
253                             ++i;
254                         }
255                         if (i >= stackParams.size()) {
256                             LOG(ERROR) << "query -- unexpected error.";
257                             status = C2_CORRUPTED;
258                             return;
259                         }
260                         if (stackParams[i]->index() != paramPointer->index()) {
261                             LOG(WARNING) << "query -- param skipped: "
262                                             "index = "
263                                          << stackParams[i]->index() << ".";
264                             stackParams[i++]->invalidate();
265                             continue;
266                         }
267                         if (!stackParams[i++]->updateFrom(*paramPointer)) {
268                             LOG(WARNING) << "query -- param update failed: "
269                                             "index = "
270                                          << paramPointer->index() << ".";
271                         }
272                     } else {
273                         if (!paramPointer) {
274                             LOG(WARNING) << "query -- null heap param.";
275                             ++it;
276                             continue;
277                         }
278                         if (!heapParams) {
279                             LOG(WARNING) << "query -- "
280                                             "unexpected extra stack param.";
281                         } else {
282                             heapParams->emplace_back(
283                                     C2Param::Copy(*paramPointer));
284                         }
285                     }
286                     ++it;
287                 }
288             });
289     if (!transStatus.isOk()) {
290         LOG(ERROR) << "query -- transaction failed.";
291         return C2_TRANSACTION_FAILED;
292     }
293     return status;
294 }
295 
config(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)296 c2_status_t Codec2ConfigurableClient::config(
297         const std::vector<C2Param*> &params,
298         c2_blocking_t mayBlock,
299         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
300     Params hidlParams;
301     if (!createParamsBlob(&hidlParams, params)) {
302         LOG(ERROR) << "config -- bad input.";
303         return C2_TRANSACTION_FAILED;
304     }
305     c2_status_t status;
306     Return<void> transStatus = mBase->config(
307             hidlParams,
308             mayBlock == C2_MAY_BLOCK,
309             [&status, &params, failures](
310                     Status s,
311                     const hidl_vec<SettingResult> f,
312                     const Params& o) {
313                 status = static_cast<c2_status_t>(s);
314                 if (status != C2_OK && status != C2_BAD_INDEX) {
315                     LOG(DEBUG) << "config -- call failed: "
316                                << status << ".";
317                 }
318                 size_t i = failures->size();
319                 failures->resize(i + f.size());
320                 for (const SettingResult& sf : f) {
321                     if (!objcpy(&(*failures)[i++], sf)) {
322                         LOG(ERROR) << "config -- "
323                                    << "invalid SettingResult returned.";
324                         return;
325                     }
326                 }
327                 if (!updateParamsFromBlob(params, o)) {
328                     LOG(ERROR) << "config -- "
329                                << "failed to parse returned params.";
330                     status = C2_CORRUPTED;
331                 }
332             });
333     if (!transStatus.isOk()) {
334         LOG(ERROR) << "config -- transaction failed.";
335         return C2_TRANSACTION_FAILED;
336     }
337     return status;
338 }
339 
querySupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const340 c2_status_t Codec2ConfigurableClient::querySupportedParams(
341         std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
342     // TODO: Cache and query properly!
343     c2_status_t status;
344     Return<void> transStatus = mBase->querySupportedParams(
345             std::numeric_limits<uint32_t>::min(),
346             std::numeric_limits<uint32_t>::max(),
347             [&status, params](
348                     Status s,
349                     const hidl_vec<ParamDescriptor>& p) {
350                 status = static_cast<c2_status_t>(s);
351                 if (status != C2_OK) {
352                     LOG(DEBUG) << "querySupportedParams -- call failed: "
353                                << status << ".";
354                     return;
355                 }
356                 size_t i = params->size();
357                 params->resize(i + p.size());
358                 for (const ParamDescriptor& sp : p) {
359                     if (!objcpy(&(*params)[i++], sp)) {
360                         LOG(ERROR) << "querySupportedParams -- "
361                                    << "invalid returned ParamDescriptor.";
362                         return;
363                     }
364                 }
365             });
366     if (!transStatus.isOk()) {
367         LOG(ERROR) << "querySupportedParams -- transaction failed.";
368         return C2_TRANSACTION_FAILED;
369     }
370     return status;
371 }
372 
querySupportedValues(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const373 c2_status_t Codec2ConfigurableClient::querySupportedValues(
374         std::vector<C2FieldSupportedValuesQuery>& fields,
375         c2_blocking_t mayBlock) const {
376     hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
377     for (size_t i = 0; i < fields.size(); ++i) {
378         if (!objcpy(&inFields[i], fields[i])) {
379             LOG(ERROR) << "querySupportedValues -- bad input";
380             return C2_TRANSACTION_FAILED;
381         }
382     }
383 
384     c2_status_t status;
385     Return<void> transStatus = mBase->querySupportedValues(
386             inFields,
387             mayBlock == C2_MAY_BLOCK,
388             [&status, &inFields, &fields](
389                     Status s,
390                     const hidl_vec<FieldSupportedValuesQueryResult>& r) {
391                 status = static_cast<c2_status_t>(s);
392                 if (status != C2_OK) {
393                     LOG(DEBUG) << "querySupportedValues -- call failed: "
394                                << status << ".";
395                     return;
396                 }
397                 if (r.size() != fields.size()) {
398                     LOG(ERROR) << "querySupportedValues -- "
399                                   "input and output lists "
400                                   "have different sizes.";
401                     status = C2_CORRUPTED;
402                     return;
403                 }
404                 for (size_t i = 0; i < fields.size(); ++i) {
405                     if (!objcpy(&fields[i], inFields[i], r[i])) {
406                         LOG(ERROR) << "querySupportedValues -- "
407                                       "invalid returned value.";
408                         status = C2_CORRUPTED;
409                         return;
410                     }
411                 }
412             });
413     if (!transStatus.isOk()) {
414         LOG(ERROR) << "querySupportedValues -- transaction failed.";
415         return C2_TRANSACTION_FAILED;
416     }
417     return status;
418 }
419 
420 // Codec2Client::Component::HidlListener
421 struct Codec2Client::Component::HidlListener : public IComponentListener {
422     std::weak_ptr<Component> component;
423     std::weak_ptr<Listener> base;
424 
onWorkDoneandroid::Codec2Client::Component::HidlListener425     virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
426         std::list<std::unique_ptr<C2Work>> workItems;
427         if (!objcpy(&workItems, workBundle)) {
428             LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
429             return Void();
430         }
431         // release input buffers potentially held by the component from queue
432         std::shared_ptr<Codec2Client::Component> strongComponent =
433                 component.lock();
434         if (strongComponent) {
435             strongComponent->handleOnWorkDone(workItems);
436         }
437         if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
438             listener->onWorkDone(component, workItems);
439         } else {
440             LOG(DEBUG) << "onWorkDone -- listener died.";
441         }
442         return Void();
443     }
444 
onTrippedandroid::Codec2Client::Component::HidlListener445     virtual Return<void> onTripped(
446             const hidl_vec<SettingResult>& settingResults) override {
447         std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
448                 settingResults.size());
449         for (size_t i = 0; i < settingResults.size(); ++i) {
450             std::unique_ptr<C2SettingResult> c2SettingResult;
451             if (!objcpy(&c2SettingResult, settingResults[i])) {
452                 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
453                 return Void();
454             }
455             c2SettingResults[i] = std::move(c2SettingResult);
456         }
457         if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
458             listener->onTripped(component, c2SettingResults);
459         } else {
460             LOG(DEBUG) << "onTripped -- listener died.";
461         }
462         return Void();
463     }
464 
onErrorandroid::Codec2Client::Component::HidlListener465     virtual Return<void> onError(Status s, uint32_t errorCode) override {
466         LOG(DEBUG) << "onError --"
467                    << " status = " << s
468                    << ", errorCode = " << errorCode
469                    << ".";
470         if (std::shared_ptr<Listener> listener = base.lock()) {
471             listener->onError(component, s == Status::OK ?
472                     errorCode : static_cast<c2_status_t>(s));
473         } else {
474             LOG(DEBUG) << "onError -- listener died.";
475         }
476         return Void();
477     }
478 
onFramesRenderedandroid::Codec2Client::Component::HidlListener479     virtual Return<void> onFramesRendered(
480             const hidl_vec<RenderedFrame>& renderedFrames) override {
481         std::shared_ptr<Listener> listener = base.lock();
482         if (!listener) {
483             LOG(DEBUG) << "onFramesRendered -- listener died.";
484             return Void();
485         }
486         for (const RenderedFrame& renderedFrame : renderedFrames) {
487             listener->onFrameRendered(
488                     renderedFrame.bufferQueueId,
489                     renderedFrame.slotId,
490                     renderedFrame.timestampNs);
491         }
492         return Void();
493     }
494 
onInputBuffersReleasedandroid::Codec2Client::Component::HidlListener495     virtual Return<void> onInputBuffersReleased(
496             const hidl_vec<InputBuffer>& inputBuffers) override {
497         std::shared_ptr<Listener> listener = base.lock();
498         if (!listener) {
499             LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
500             return Void();
501         }
502         for (const InputBuffer& inputBuffer : inputBuffers) {
503             LOG(VERBOSE) << "onInputBuffersReleased --"
504                             " received death notification of"
505                             " input buffer:"
506                             " frameIndex = " << inputBuffer.frameIndex
507                          << ", bufferIndex = " << inputBuffer.arrayIndex
508                          << ".";
509             listener->onInputBufferDone(
510                     inputBuffer.frameIndex, inputBuffer.arrayIndex);
511         }
512         return Void();
513     }
514 
515 };
516 
517 // Codec2Client
Codec2Client(const sp<IComponentStore> & base,size_t serviceIndex)518 Codec2Client::Codec2Client(const sp<IComponentStore>& base,
519                            size_t serviceIndex)
520       : Configurable{
521             [base]() -> sp<IConfigurable> {
522                 Return<sp<IConfigurable>> transResult =
523                         base->getConfigurable();
524                 return transResult.isOk() ?
525                         static_cast<sp<IConfigurable>>(transResult) :
526                         nullptr;
527             }()
528         },
529         mBase{base},
530         mServiceIndex{serviceIndex} {
531     Return<sp<IClientManager>> transResult = base->getPoolClientManager();
532     if (!transResult.isOk()) {
533         LOG(ERROR) << "getPoolClientManager -- transaction failed.";
534     } else {
535         mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
536     }
537 }
538 
getBase() const539 sp<Codec2Client::Base> const& Codec2Client::getBase() const {
540     return mBase;
541 }
542 
getServiceName() const543 std::string const& Codec2Client::getServiceName() const {
544     return GetServiceNames()[mServiceIndex];
545 }
546 
createComponent(const C2String & name,const std::shared_ptr<Codec2Client::Listener> & listener,std::shared_ptr<Codec2Client::Component> * const component)547 c2_status_t Codec2Client::createComponent(
548         const C2String& name,
549         const std::shared_ptr<Codec2Client::Listener>& listener,
550         std::shared_ptr<Codec2Client::Component>* const component) {
551 
552     c2_status_t status;
553     sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
554     hidlListener->base = listener;
555     Return<void> transStatus = mBase->createComponent(
556             name,
557             hidlListener,
558             ClientManager::getInstance(),
559             [&status, component, hidlListener](
560                     Status s,
561                     const sp<IComponent>& c) {
562                 status = static_cast<c2_status_t>(s);
563                 if (status != C2_OK) {
564                     return;
565                 }
566                 *component = std::make_shared<Codec2Client::Component>(c);
567                 hidlListener->component = *component;
568             });
569     if (!transStatus.isOk()) {
570         LOG(ERROR) << "createComponent(" << name.c_str()
571                    << ") -- transaction failed.";
572         return C2_TRANSACTION_FAILED;
573     } else if (status != C2_OK) {
574         LOG(ERROR) << "createComponent(" << name.c_str()
575                    << ") -- call failed: " << status << ".";
576         return status;
577     } else if (!*component) {
578         LOG(ERROR) << "createComponent(" << name.c_str()
579                    << ") -- null component.";
580         return C2_CORRUPTED;
581     }
582 
583     status = (*component)->setDeathListener(*component, listener);
584     if (status != C2_OK) {
585         LOG(ERROR) << "createComponent(" << name.c_str()
586                    << ") -- failed to set up death listener: "
587                    << status << ".";
588     }
589 
590     (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
591     return status;
592 }
593 
createInterface(const C2String & name,std::shared_ptr<Codec2Client::Interface> * const interface)594 c2_status_t Codec2Client::createInterface(
595         const C2String& name,
596         std::shared_ptr<Codec2Client::Interface>* const interface) {
597     c2_status_t status;
598     Return<void> transStatus = mBase->createInterface(
599             name,
600             [&status, interface](
601                     Status s,
602                     const sp<IComponentInterface>& i) {
603                 status = static_cast<c2_status_t>(s);
604                 if (status != C2_OK) {
605                     return;
606                 }
607                 *interface = std::make_shared<Interface>(i);
608             });
609     if (!transStatus.isOk()) {
610         LOG(ERROR) << "createInterface(" << name.c_str()
611                    << ") -- transaction failed.";
612         return C2_TRANSACTION_FAILED;
613     } else if (status != C2_OK) {
614         LOG(ERROR) << "createComponent(" << name.c_str()
615                    << ") -- call failed: " << status << ".";
616         return status;
617     }
618 
619     return status;
620 }
621 
createInputSurface(std::shared_ptr<InputSurface> * const inputSurface)622 c2_status_t Codec2Client::createInputSurface(
623         std::shared_ptr<InputSurface>* const inputSurface) {
624     c2_status_t status;
625     Return<void> transStatus = mBase->createInputSurface(
626             [&status, inputSurface](
627                     Status s,
628                     const sp<IInputSurface>& i) {
629                 status = static_cast<c2_status_t>(s);
630                 if (status != C2_OK) {
631                     return;
632                 }
633                 *inputSurface = std::make_shared<InputSurface>(i);
634             });
635     if (!transStatus.isOk()) {
636         LOG(ERROR) << "createInputSurface -- transaction failed.";
637         return C2_TRANSACTION_FAILED;
638     } else if (status != C2_OK) {
639         LOG(DEBUG) << "createInputSurface -- call failed: "
640                    << status << ".";
641     }
642     return status;
643 }
644 
listComponents() const645 std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
646     return Cache::List()[mServiceIndex].getTraits();
647 }
648 
_listComponents(bool * success) const649 std::vector<C2Component::Traits> Codec2Client::_listComponents(
650         bool* success) const {
651     std::vector<C2Component::Traits> traits;
652     std::string const& serviceName = getServiceName();
653     Return<void> transStatus = mBase->listComponents(
654             [&traits, &serviceName](Status s,
655                    const hidl_vec<IComponentStore::ComponentTraits>& t) {
656                 if (s != Status::OK) {
657                     LOG(DEBUG) << "_listComponents -- call failed: "
658                                << static_cast<c2_status_t>(s) << ".";
659                     return;
660                 }
661                 traits.resize(t.size());
662                 for (size_t i = 0; i < t.size(); ++i) {
663                     if (!objcpy(&traits[i], t[i])) {
664                         LOG(ERROR) << "_listComponents -- corrupted output.";
665                         return;
666                     }
667                     traits[i].owner = serviceName;
668                 }
669             });
670     if (!transStatus.isOk()) {
671         LOG(ERROR) << "_listComponents -- transaction failed.";
672         *success = false;
673     } else {
674         *success = true;
675     }
676     return traits;
677 }
678 
copyBuffer(const std::shared_ptr<C2Buffer> & src,const std::shared_ptr<C2Buffer> & dst)679 c2_status_t Codec2Client::copyBuffer(
680         const std::shared_ptr<C2Buffer>& src,
681         const std::shared_ptr<C2Buffer>& dst) {
682     // TODO: Implement?
683     (void)src;
684     (void)dst;
685     LOG(ERROR) << "copyBuffer not implemented";
686     return C2_OMITTED;
687 }
688 
689 std::shared_ptr<C2ParamReflector>
getParamReflector()690         Codec2Client::getParamReflector() {
691     // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
692     // should reflect the HAL API.
693     struct SimpleParamReflector : public C2ParamReflector {
694         virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
695             hidl_vec<ParamIndex> indices(1);
696             indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
697             std::unique_ptr<C2StructDescriptor> descriptor;
698             Return<void> transStatus = mBase->getStructDescriptors(
699                     indices,
700                     [&descriptor](
701                             Status s,
702                             const hidl_vec<StructDescriptor>& sd) {
703                         c2_status_t status = static_cast<c2_status_t>(s);
704                         if (status != C2_OK) {
705                             LOG(DEBUG) << "SimpleParamReflector -- "
706                                           "getStructDescriptors() failed: "
707                                        << status << ".";
708                             descriptor.reset();
709                             return;
710                         }
711                         if (sd.size() != 1) {
712                             LOG(DEBUG) << "SimpleParamReflector -- "
713                                           "getStructDescriptors() "
714                                           "returned vector of size "
715                                        << sd.size() << ". "
716                                           "It should be 1.";
717                             descriptor.reset();
718                             return;
719                         }
720                         if (!objcpy(&descriptor, sd[0])) {
721                             LOG(DEBUG) << "SimpleParamReflector -- "
722                                           "getStructDescriptors() returned "
723                                           "corrupted data.";
724                             descriptor.reset();
725                             return;
726                         }
727                     });
728             return descriptor;
729         }
730 
731         SimpleParamReflector(sp<Base> base)
732             : mBase(base) { }
733 
734         sp<Base> mBase;
735     };
736 
737     return std::make_shared<SimpleParamReflector>(mBase);
738 };
739 
GetServiceNames()740 std::vector<std::string> const& Codec2Client::GetServiceNames() {
741     static std::vector<std::string> sServiceNames{[]() {
742         using ::android::hardware::media::c2::V1_0::IComponentStore;
743         using ::android::hidl::manager::V1_2::IServiceManager;
744 
745         while (true) {
746             sp<IServiceManager> serviceManager = IServiceManager::getService();
747             CHECK(serviceManager) << "Hardware service manager is not running.";
748 
749             // There are three categories of services based on names.
750             std::vector<std::string> defaultNames; // Prefixed with "default"
751             std::vector<std::string> vendorNames;  // Prefixed with "vendor"
752             std::vector<std::string> otherNames;   // Others
753             Return<void> transResult;
754             transResult = serviceManager->listManifestByInterface(
755                     IComponentStore::descriptor,
756                     [&defaultNames, &vendorNames, &otherNames](
757                             hidl_vec<hidl_string> const& instanceNames) {
758                         for (hidl_string const& instanceName : instanceNames) {
759                             char const* name = instanceName.c_str();
760                             if (strncmp(name, "default", 7) == 0) {
761                                 defaultNames.emplace_back(name);
762                             } else if (strncmp(name, "vendor", 6) == 0) {
763                                 vendorNames.emplace_back(name);
764                             } else {
765                                 otherNames.emplace_back(name);
766                             }
767                         }
768                     });
769             if (transResult.isOk()) {
770                 // Sort service names in each category.
771                 std::sort(defaultNames.begin(), defaultNames.end());
772                 std::sort(vendorNames.begin(), vendorNames.end());
773                 std::sort(otherNames.begin(), otherNames.end());
774 
775                 // Concatenate the three lists in this order: default, vendor,
776                 // other.
777                 std::vector<std::string>& names = defaultNames;
778                 names.reserve(names.size() + vendorNames.size() + otherNames.size());
779                 names.insert(names.end(),
780                              std::make_move_iterator(vendorNames.begin()),
781                              std::make_move_iterator(vendorNames.end()));
782                 names.insert(names.end(),
783                              std::make_move_iterator(otherNames.begin()),
784                              std::make_move_iterator(otherNames.end()));
785 
786                 // Summarize to logcat.
787                 if (names.empty()) {
788                     LOG(INFO) << "No Codec2 services declared in the manifest.";
789                 } else {
790                     std::stringstream stringOutput;
791                     stringOutput << "Available Codec2 services:";
792                     for (std::string const& name : names) {
793                         stringOutput << " \"" << name << "\"";
794                     }
795                     LOG(INFO) << stringOutput.str();
796                 }
797 
798                 return names;
799             }
800             LOG(ERROR) << "Could not retrieve the list of service instances of "
801                        << IComponentStore::descriptor
802                        << ". Retrying...";
803         }
804     }()};
805     return sServiceNames;
806 }
807 
CreateFromService(const char * name)808 std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
809         const char* name) {
810     size_t index = getServiceIndex(name);
811     return index == GetServiceNames().size() ?
812             nullptr : _CreateFromIndex(index);
813 }
814 
815 std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
CreateFromAllServices()816         CreateFromAllServices() {
817     std::vector<std::shared_ptr<Codec2Client>> clients(
818             GetServiceNames().size());
819     for (size_t i = GetServiceNames().size(); i > 0; ) {
820         --i;
821         clients[i] = _CreateFromIndex(i);
822     }
823     return clients;
824 }
825 
_CreateFromIndex(size_t index)826 std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
827     std::string const& name = GetServiceNames()[index];
828     LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
829     sp<Base> baseStore = Base::getService(name);
830     CHECK(baseStore) << "Codec2 service \"" << name << "\""
831                         " inaccessible for unknown reasons.";
832     LOG(INFO) << "Client to Codec2 service \"" << name << "\" created";
833     return std::make_shared<Codec2Client>(baseStore, index);
834 }
835 
ForAllServices(const std::string & key,size_t numberOfAttempts,std::function<c2_status_t (const std::shared_ptr<Codec2Client> &)> predicate)836 c2_status_t Codec2Client::ForAllServices(
837         const std::string &key,
838         size_t numberOfAttempts,
839         std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
840             predicate) {
841     c2_status_t status = C2_NO_INIT;  // no IComponentStores present
842 
843     // Cache the mapping key -> index of Codec2Client in Cache::List().
844     static std::mutex key2IndexMutex;
845     static std::map<std::string, size_t> key2Index;
846 
847     // By default try all stores. However, try the last known client first. If
848     // the last known client fails, retry once. We do this by pushing the last
849     // known client in front of the list of all clients.
850     std::deque<size_t> indices;
851     for (size_t index = Cache::List().size(); index > 0; ) {
852         indices.push_front(--index);
853     }
854 
855     bool wasMapped = false;
856     {
857         std::scoped_lock lock{key2IndexMutex};
858         auto it = key2Index.find(key);
859         if (it != key2Index.end()) {
860             indices.push_front(it->second);
861             wasMapped = true;
862         }
863     }
864 
865     for (size_t index : indices) {
866         Cache& cache = Cache::List()[index];
867         for (size_t tries = numberOfAttempts; tries > 0; --tries) {
868             std::shared_ptr<Codec2Client> client{cache.getClient()};
869             status = predicate(client);
870             if (status == C2_OK) {
871                 std::scoped_lock lock{key2IndexMutex};
872                 key2Index[key] = index; // update last known client index
873                 return C2_OK;
874             } else if (status == C2_TRANSACTION_FAILED) {
875                 LOG(WARNING) << "\"" << key << "\" failed for service \""
876                              << client->getName()
877                              << "\" due to transaction failure. "
878                              << "(Service may have crashed.)"
879                              << (tries > 1 ? " Retrying..." : "");
880                 cache.invalidate();
881                 continue;
882             }
883             if (wasMapped) {
884                 LOG(INFO) << "\"" << key << "\" became invalid in service \""
885                           << client->getName() << "\". Retrying...";
886                 wasMapped = false;
887             }
888             break;
889         }
890     }
891     return status; // return the last status from a valid client
892 }
893 
894 std::shared_ptr<Codec2Client::Component>
CreateComponentByName(const char * componentName,const std::shared_ptr<Listener> & listener,std::shared_ptr<Codec2Client> * owner,size_t numberOfAttempts)895         Codec2Client::CreateComponentByName(
896         const char* componentName,
897         const std::shared_ptr<Listener>& listener,
898         std::shared_ptr<Codec2Client>* owner,
899         size_t numberOfAttempts) {
900     std::string key{"create:"};
901     key.append(componentName);
902     std::shared_ptr<Component> component;
903     c2_status_t status = ForAllServices(
904             key,
905             numberOfAttempts,
906             [owner, &component, componentName, &listener](
907                     const std::shared_ptr<Codec2Client> &client)
908                         -> c2_status_t {
909                 c2_status_t status = client->createComponent(componentName,
910                                                              listener,
911                                                              &component);
912                 if (status == C2_OK) {
913                     if (owner) {
914                         *owner = client;
915                     }
916                 } else if (status != C2_NOT_FOUND) {
917                     LOG(DEBUG) << "IComponentStore("
918                                    << client->getServiceName()
919                                << ")::createComponent(\"" << componentName
920                                << "\") returned status = "
921                                << status << ".";
922                 }
923                 return status;
924             });
925     if (status != C2_OK) {
926         LOG(DEBUG) << "Failed to create component \"" << componentName
927                    << "\" from all known services. "
928                       "Last returned status = " << status << ".";
929     }
930     return component;
931 }
932 
933 std::shared_ptr<Codec2Client::Interface>
CreateInterfaceByName(const char * interfaceName,std::shared_ptr<Codec2Client> * owner,size_t numberOfAttempts)934         Codec2Client::CreateInterfaceByName(
935         const char* interfaceName,
936         std::shared_ptr<Codec2Client>* owner,
937         size_t numberOfAttempts) {
938     std::string key{"create:"};
939     key.append(interfaceName);
940     std::shared_ptr<Interface> interface;
941     c2_status_t status = ForAllServices(
942             key,
943             numberOfAttempts,
944             [owner, &interface, interfaceName](
945                     const std::shared_ptr<Codec2Client> &client)
946                         -> c2_status_t {
947                 c2_status_t status = client->createInterface(interfaceName,
948                                                              &interface);
949                 if (status == C2_OK) {
950                     if (owner) {
951                         *owner = client;
952                     }
953                 } else if (status != C2_NOT_FOUND) {
954                     LOG(DEBUG) << "IComponentStore("
955                                    << client->getServiceName()
956                                << ")::createInterface(\"" << interfaceName
957                                << "\") returned status = "
958                                << status << ".";
959                 }
960                 return status;
961             });
962     if (status != C2_OK) {
963         LOG(DEBUG) << "Failed to create interface \"" << interfaceName
964                    << "\" from all known services. "
965                       "Last returned status = " << status << ".";
966     }
967     return interface;
968 }
969 
ListComponents()970 std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
971     static std::vector<C2Component::Traits> sList{[]() {
972         std::vector<C2Component::Traits> list;
973         for (Cache& cache : Cache::List()) {
974             std::vector<C2Component::Traits> const& traits = cache.getTraits();
975             list.insert(list.end(), traits.begin(), traits.end());
976         }
977         return list;
978     }()};
979     return sList;
980 }
981 
CreateInputSurface(char const * serviceName)982 std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
983         char const* serviceName) {
984     int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
985             "debug.stagefright.c2inputsurface", int32_t(0));
986     if (inputSurfaceSetting <= 0) {
987         return nullptr;
988     }
989     size_t index = GetServiceNames().size();
990     if (serviceName) {
991         index = getServiceIndex(serviceName);
992         if (index == GetServiceNames().size()) {
993             LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
994                        << serviceName << "\"";
995         }
996     }
997 
998     std::shared_ptr<Codec2Client::InputSurface> inputSurface;
999     if (index != GetServiceNames().size()) {
1000         std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1001         if (client->createInputSurface(&inputSurface) == C2_OK) {
1002             return inputSurface;
1003         }
1004     }
1005     LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1006                  "from all services...";
1007     for (Cache& cache : Cache::List()) {
1008         std::shared_ptr<Codec2Client> client = cache.getClient();
1009         if (client->createInputSurface(&inputSurface) == C2_OK) {
1010             LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1011                          "service \"" << client->getServiceName() << "\"";
1012             return inputSurface;
1013         }
1014     }
1015     LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1016                     "from all services";
1017     return nullptr;
1018 }
1019 
1020 // Codec2Client::Listener
1021 
~Listener()1022 Codec2Client::Listener::~Listener() {
1023 }
1024 
1025 // Codec2Client::Interface
Interface(const sp<Base> & base)1026 Codec2Client::Interface::Interface(const sp<Base>& base)
1027       : Configurable{
1028             [base]() -> sp<IConfigurable> {
1029                 Return<sp<IConfigurable>> transResult =
1030                         base->getConfigurable();
1031                 return transResult.isOk() ?
1032                         static_cast<sp<IConfigurable>>(transResult) :
1033                         nullptr;
1034             }()
1035         },
1036         mBase{base} {
1037 }
1038 
1039 // Codec2Client::Component
Component(const sp<Base> & base)1040 Codec2Client::Component::Component(const sp<Base>& base)
1041       : Configurable{
1042             [base]() -> sp<IConfigurable> {
1043                 Return<sp<IComponentInterface>> transResult1 =
1044                         base->getInterface();
1045                 if (!transResult1.isOk()) {
1046                     return nullptr;
1047                 }
1048                 Return<sp<IConfigurable>> transResult2 =
1049                         static_cast<sp<IComponentInterface>>(transResult1)->
1050                         getConfigurable();
1051                 return transResult2.isOk() ?
1052                         static_cast<sp<IConfigurable>>(transResult2) :
1053                         nullptr;
1054             }()
1055         },
1056         mBase{base},
1057         mBufferPoolSender{nullptr} {
1058 }
1059 
~Component()1060 Codec2Client::Component::~Component() {
1061 }
1062 
createBlockPool(C2Allocator::id_t id,C2BlockPool::local_id_t * blockPoolId,std::shared_ptr<Codec2Client::Configurable> * configurable)1063 c2_status_t Codec2Client::Component::createBlockPool(
1064         C2Allocator::id_t id,
1065         C2BlockPool::local_id_t* blockPoolId,
1066         std::shared_ptr<Codec2Client::Configurable>* configurable) {
1067     c2_status_t status;
1068     Return<void> transStatus = mBase->createBlockPool(
1069             static_cast<uint32_t>(id),
1070             [&status, blockPoolId, configurable](
1071                     Status s,
1072                     uint64_t pId,
1073                     const sp<IConfigurable>& c) {
1074                 status = static_cast<c2_status_t>(s);
1075                 configurable->reset();
1076                 if (status != C2_OK) {
1077                     LOG(DEBUG) << "createBlockPool -- call failed: "
1078                                << status << ".";
1079                     return;
1080                 }
1081                 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
1082                 *configurable = std::make_shared<Configurable>(c);
1083             });
1084     if (!transStatus.isOk()) {
1085         LOG(ERROR) << "createBlockPool -- transaction failed.";
1086         return C2_TRANSACTION_FAILED;
1087     }
1088     return status;
1089 }
1090 
destroyBlockPool(C2BlockPool::local_id_t localId)1091 c2_status_t Codec2Client::Component::destroyBlockPool(
1092         C2BlockPool::local_id_t localId) {
1093     Return<Status> transResult = mBase->destroyBlockPool(
1094             static_cast<uint64_t>(localId));
1095     if (!transResult.isOk()) {
1096         LOG(ERROR) << "destroyBlockPool -- transaction failed.";
1097         return C2_TRANSACTION_FAILED;
1098     }
1099     return static_cast<c2_status_t>(static_cast<Status>(transResult));
1100 }
1101 
handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> & workItems)1102 void Codec2Client::Component::handleOnWorkDone(
1103         const std::list<std::unique_ptr<C2Work>> &workItems) {
1104     // Output bufferqueue-based blocks' lifetime management
1105     mOutputBufferQueue.holdBufferQueueBlocks(workItems);
1106 }
1107 
queue(std::list<std::unique_ptr<C2Work>> * const items)1108 c2_status_t Codec2Client::Component::queue(
1109         std::list<std::unique_ptr<C2Work>>* const items) {
1110     WorkBundle workBundle;
1111     if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
1112         LOG(ERROR) << "queue -- bad input.";
1113         return C2_TRANSACTION_FAILED;
1114     }
1115     Return<Status> transStatus = mBase->queue(workBundle);
1116     if (!transStatus.isOk()) {
1117         LOG(ERROR) << "queue -- transaction failed.";
1118         return C2_TRANSACTION_FAILED;
1119     }
1120     c2_status_t status =
1121             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1122     if (status != C2_OK) {
1123         LOG(DEBUG) << "queue -- call failed: " << status << ".";
1124     }
1125     return status;
1126 }
1127 
flush(C2Component::flush_mode_t mode,std::list<std::unique_ptr<C2Work>> * const flushedWork)1128 c2_status_t Codec2Client::Component::flush(
1129         C2Component::flush_mode_t mode,
1130         std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1131     (void)mode; // Flush mode isn't supported in HIDL yet.
1132     c2_status_t status;
1133     Return<void> transStatus = mBase->flush(
1134             [&status, flushedWork](
1135                     Status s, const WorkBundle& wb) {
1136                 status = static_cast<c2_status_t>(s);
1137                 if (status != C2_OK) {
1138                     LOG(DEBUG) << "flush -- call failed: " << status << ".";
1139                     return;
1140                 }
1141                 if (!objcpy(flushedWork, wb)) {
1142                     status = C2_CORRUPTED;
1143                 } else {
1144                     status = C2_OK;
1145                 }
1146             });
1147     if (!transStatus.isOk()) {
1148         LOG(ERROR) << "flush -- transaction failed.";
1149         return C2_TRANSACTION_FAILED;
1150     }
1151 
1152     // Indices of flushed work items.
1153     std::vector<uint64_t> flushedIndices;
1154     for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1155         if (work) {
1156             if (work->worklets.empty()
1157                     || !work->worklets.back()
1158                     || (work->worklets.back()->output.flags &
1159                         C2FrameData::FLAG_INCOMPLETE) == 0) {
1160                 // input is complete
1161                 flushedIndices.emplace_back(
1162                         work->input.ordinal.frameIndex.peeku());
1163             }
1164         }
1165     }
1166 
1167     // Output bufferqueue-based blocks' lifetime management
1168     mOutputBufferQueue.holdBufferQueueBlocks(*flushedWork);
1169 
1170     return status;
1171 }
1172 
drain(C2Component::drain_mode_t mode)1173 c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
1174     Return<Status> transStatus = mBase->drain(
1175             mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1176     if (!transStatus.isOk()) {
1177         LOG(ERROR) << "drain -- transaction failed.";
1178         return C2_TRANSACTION_FAILED;
1179     }
1180     c2_status_t status =
1181             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1182     if (status != C2_OK) {
1183         LOG(DEBUG) << "drain -- call failed: " << status << ".";
1184     }
1185     return status;
1186 }
1187 
start()1188 c2_status_t Codec2Client::Component::start() {
1189     Return<Status> transStatus = mBase->start();
1190     if (!transStatus.isOk()) {
1191         LOG(ERROR) << "start -- transaction failed.";
1192         return C2_TRANSACTION_FAILED;
1193     }
1194     c2_status_t status =
1195             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1196     if (status != C2_OK) {
1197         LOG(DEBUG) << "start -- call failed: " << status << ".";
1198     }
1199     return status;
1200 }
1201 
stop()1202 c2_status_t Codec2Client::Component::stop() {
1203     Return<Status> transStatus = mBase->stop();
1204     if (!transStatus.isOk()) {
1205         LOG(ERROR) << "stop -- transaction failed.";
1206         return C2_TRANSACTION_FAILED;
1207     }
1208     c2_status_t status =
1209             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1210     if (status != C2_OK) {
1211         LOG(DEBUG) << "stop -- call failed: " << status << ".";
1212     }
1213     return status;
1214 }
1215 
reset()1216 c2_status_t Codec2Client::Component::reset() {
1217     Return<Status> transStatus = mBase->reset();
1218     if (!transStatus.isOk()) {
1219         LOG(ERROR) << "reset -- transaction failed.";
1220         return C2_TRANSACTION_FAILED;
1221     }
1222     c2_status_t status =
1223             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1224     if (status != C2_OK) {
1225         LOG(DEBUG) << "reset -- call failed: " << status << ".";
1226     }
1227     return status;
1228 }
1229 
release()1230 c2_status_t Codec2Client::Component::release() {
1231     Return<Status> transStatus = mBase->release();
1232     if (!transStatus.isOk()) {
1233         LOG(ERROR) << "release -- transaction failed.";
1234         return C2_TRANSACTION_FAILED;
1235     }
1236     c2_status_t status =
1237             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1238     if (status != C2_OK) {
1239         LOG(DEBUG) << "release -- call failed: " << status << ".";
1240     }
1241     return status;
1242 }
1243 
setOutputSurface(C2BlockPool::local_id_t blockPoolId,const sp<IGraphicBufferProducer> & surface,uint32_t generation)1244 c2_status_t Codec2Client::Component::setOutputSurface(
1245         C2BlockPool::local_id_t blockPoolId,
1246         const sp<IGraphicBufferProducer>& surface,
1247         uint32_t generation) {
1248     uint64_t bqId = 0;
1249     sp<IGraphicBufferProducer> nullIgbp;
1250     sp<HGraphicBufferProducer2> nullHgbp;
1251 
1252     sp<HGraphicBufferProducer2> igbp = surface ?
1253             surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1254     if (surface && !igbp) {
1255         igbp = new B2HGraphicBufferProducer2(surface);
1256     }
1257 
1258     if (!surface) {
1259         mOutputBufferQueue.configure(nullIgbp, generation, 0);
1260     } else if (surface->getUniqueId(&bqId) != OK) {
1261         LOG(ERROR) << "setOutputSurface -- "
1262                    "cannot obtain bufferqueue id.";
1263         bqId = 0;
1264         mOutputBufferQueue.configure(nullIgbp, generation, 0);
1265     } else {
1266         mOutputBufferQueue.configure(surface, generation, bqId);
1267     }
1268     ALOGD("generation remote change %u", generation);
1269 
1270     Return<Status> transStatus = mBase->setOutputSurface(
1271             static_cast<uint64_t>(blockPoolId),
1272             bqId == 0 ? nullHgbp : igbp);
1273     if (!transStatus.isOk()) {
1274         LOG(ERROR) << "setOutputSurface -- transaction failed.";
1275         return C2_TRANSACTION_FAILED;
1276     }
1277     c2_status_t status =
1278             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1279     if (status != C2_OK) {
1280         LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
1281     }
1282     return status;
1283 }
1284 
queueToOutputSurface(const C2ConstGraphicBlock & block,const QueueBufferInput & input,QueueBufferOutput * output)1285 status_t Codec2Client::Component::queueToOutputSurface(
1286         const C2ConstGraphicBlock& block,
1287         const QueueBufferInput& input,
1288         QueueBufferOutput* output) {
1289     return mOutputBufferQueue.outputBuffer(block, input, output);
1290 }
1291 
connectToInputSurface(const std::shared_ptr<InputSurface> & inputSurface,std::shared_ptr<InputSurfaceConnection> * connection)1292 c2_status_t Codec2Client::Component::connectToInputSurface(
1293         const std::shared_ptr<InputSurface>& inputSurface,
1294         std::shared_ptr<InputSurfaceConnection>* connection) {
1295     c2_status_t status;
1296     Return<void> transStatus = mBase->connectToInputSurface(
1297             inputSurface->mBase,
1298             [&status, connection](
1299                     Status s, const sp<IInputSurfaceConnection>& c) {
1300                 status = static_cast<c2_status_t>(s);
1301                 if (status != C2_OK) {
1302                     LOG(DEBUG) << "connectToInputSurface -- call failed: "
1303                                << status << ".";
1304                     return;
1305                 }
1306                 *connection = std::make_shared<InputSurfaceConnection>(c);
1307             });
1308     if (!transStatus.isOk()) {
1309         LOG(ERROR) << "connectToInputSurface -- transaction failed";
1310         return C2_TRANSACTION_FAILED;
1311     }
1312     return status;
1313 }
1314 
connectToOmxInputSurface(const sp<HGraphicBufferProducer1> & producer,const sp<HGraphicBufferSource> & source,std::shared_ptr<InputSurfaceConnection> * connection)1315 c2_status_t Codec2Client::Component::connectToOmxInputSurface(
1316         const sp<HGraphicBufferProducer1>& producer,
1317         const sp<HGraphicBufferSource>& source,
1318         std::shared_ptr<InputSurfaceConnection>* connection) {
1319     c2_status_t status;
1320     Return<void> transStatus = mBase->connectToOmxInputSurface(
1321             producer, source,
1322             [&status, connection](
1323                     Status s, const sp<IInputSurfaceConnection>& c) {
1324                 status = static_cast<c2_status_t>(s);
1325                 if (status != C2_OK) {
1326                     LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1327                                << status << ".";
1328                     return;
1329                 }
1330                 *connection = std::make_shared<InputSurfaceConnection>(c);
1331             });
1332     if (!transStatus.isOk()) {
1333         LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1334         return C2_TRANSACTION_FAILED;
1335     }
1336     return status;
1337 }
1338 
disconnectFromInputSurface()1339 c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
1340     Return<Status> transStatus = mBase->disconnectFromInputSurface();
1341     if (!transStatus.isOk()) {
1342         LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
1343         return C2_TRANSACTION_FAILED;
1344     }
1345     c2_status_t status =
1346             static_cast<c2_status_t>(static_cast<Status>(transStatus));
1347     if (status != C2_OK) {
1348         LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1349                    << status << ".";
1350     }
1351     return status;
1352 }
1353 
setDeathListener(const std::shared_ptr<Component> & component,const std::shared_ptr<Listener> & listener)1354 c2_status_t Codec2Client::Component::setDeathListener(
1355         const std::shared_ptr<Component>& component,
1356         const std::shared_ptr<Listener>& listener) {
1357 
1358     struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1359         std::weak_ptr<Component> component;
1360         std::weak_ptr<Listener> base;
1361 
1362         virtual void serviceDied(
1363                 uint64_t /* cookie */,
1364                 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1365                 ) override {
1366             if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1367                 listener->onDeath(component);
1368             } else {
1369                 LOG(DEBUG) << "onDeath -- listener died.";
1370             }
1371         }
1372     };
1373 
1374     sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1375     deathRecipient->base = listener;
1376     deathRecipient->component = component;
1377 
1378     component->mDeathRecipient = deathRecipient;
1379     Return<bool> transResult = component->mBase->linkToDeath(
1380             component->mDeathRecipient, 0);
1381     if (!transResult.isOk()) {
1382         LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
1383         return C2_TRANSACTION_FAILED;
1384     }
1385     if (!static_cast<bool>(transResult)) {
1386         LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
1387         return C2_CORRUPTED;
1388     }
1389     return C2_OK;
1390 }
1391 
1392 // Codec2Client::InputSurface
InputSurface(const sp<IInputSurface> & base)1393 Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1394       : Configurable{
1395             [base]() -> sp<IConfigurable> {
1396                 Return<sp<IConfigurable>> transResult =
1397                         base->getConfigurable();
1398                 return transResult.isOk() ?
1399                         static_cast<sp<IConfigurable>>(transResult) :
1400                         nullptr;
1401             }()
1402         },
1403         mBase{base},
1404         mGraphicBufferProducer{new
__anon272953511c02() 1405             H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1406                 Return<sp<HGraphicBufferProducer2>> transResult =
1407                         base->getGraphicBufferProducer();
1408                 return transResult.isOk() ?
1409                         static_cast<sp<HGraphicBufferProducer2>>(transResult) :
1410                         nullptr;
1411             }())} {
1412 }
1413 
1414 sp<IGraphicBufferProducer>
getGraphicBufferProducer() const1415         Codec2Client::InputSurface::getGraphicBufferProducer() const {
1416     return mGraphicBufferProducer;
1417 }
1418 
getHalInterface() const1419 sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
1420     return mBase;
1421 }
1422 
1423 // Codec2Client::InputSurfaceConnection
InputSurfaceConnection(const sp<IInputSurfaceConnection> & base)1424 Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
1425         const sp<IInputSurfaceConnection>& base)
1426       : Configurable{
1427             [base]() -> sp<IConfigurable> {
1428                 Return<sp<IConfigurable>> transResult =
1429                         base->getConfigurable();
1430                 return transResult.isOk() ?
1431                         static_cast<sp<IConfigurable>>(transResult) :
1432                         nullptr;
1433             }()
1434         },
1435         mBase{base} {
1436 }
1437 
disconnect()1438 c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
1439     Return<Status> transResult = mBase->disconnect();
1440     return static_cast<c2_status_t>(static_cast<Status>(transResult));
1441 }
1442 
1443 }  // namespace android
1444 
1445