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