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