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