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