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(¶mPointers, 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*> ¶ms, 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, ¶ms, 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