1 #include <private/dvr/buffer_hub_client.h> 2 3 #include <log/log.h> 4 #include <poll.h> 5 #include <sys/epoll.h> 6 #include <utils/Trace.h> 7 8 #include <mutex> 9 10 #include <pdx/default_transport/client_channel.h> 11 #include <pdx/default_transport/client_channel_factory.h> 12 13 #include "include/private/dvr/bufferhub_rpc.h" 14 15 using android::pdx::LocalChannelHandle; 16 using android::pdx::LocalHandle; 17 using android::pdx::Status; 18 using android::pdx::default_transport::ClientChannel; 19 using android::pdx::default_transport::ClientChannelFactory; 20 21 namespace android { 22 namespace dvr { 23 24 BufferHubClient::BufferHubClient() 25 : Client(ClientChannelFactory::Create(BufferHubRPC::kClientPath)) {} 26 27 BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle) 28 : Client(ClientChannel::Create(std::move(channel_handle))) {} 29 30 bool BufferHubClient::IsValid() const { 31 return IsConnected() && GetChannelHandle().valid(); 32 } 33 34 LocalChannelHandle BufferHubClient::TakeChannelHandle() { 35 if (IsConnected()) { 36 return std::move(GetChannelHandle()); 37 } else { 38 return {}; 39 } 40 } 41 42 BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle) 43 : Client{pdx::default_transport::ClientChannel::Create( 44 std::move(channel_handle))}, 45 id_(-1) {} 46 BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path) 47 : Client{pdx::default_transport::ClientChannelFactory::Create( 48 endpoint_path)}, 49 id_(-1) {} 50 51 BufferHubBuffer::~BufferHubBuffer() { 52 if (metadata_header_ != nullptr) { 53 metadata_buffer_.Unlock(); 54 } 55 } 56 57 Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() { 58 Status<LocalChannelHandle> status = 59 InvokeRemoteMethod<BufferHubRPC::NewConsumer>(); 60 ALOGE_IF(!status, 61 "BufferHub::CreateConsumer: Failed to create consumer channel: %s", 62 status.GetErrorMessage().c_str()); 63 return status; 64 } 65 66 int BufferHubBuffer::ImportBuffer() { 67 ATRACE_NAME("BufferHubBuffer::ImportBuffer"); 68 69 Status<BufferDescription<LocalHandle>> status = 70 InvokeRemoteMethod<BufferHubRPC::GetBuffer>(); 71 if (!status) { 72 ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s", 73 status.GetErrorMessage().c_str()); 74 return -status.error(); 75 } else if (status.get().id() < 0) { 76 ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!"); 77 return -EIO; 78 } 79 80 auto buffer_desc = status.take(); 81 82 // Stash the buffer id to replace the value in id_. 83 const int new_id = buffer_desc.id(); 84 85 // Import the buffer. 86 IonBuffer ion_buffer; 87 ALOGD_IF(TRACE, "BufferHubBuffer::ImportBuffer: id=%d.", buffer_desc.id()); 88 89 if (const int ret = buffer_desc.ImportBuffer(&ion_buffer)) 90 return ret; 91 92 // Import the metadata. 93 IonBuffer metadata_buffer; 94 if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) { 95 ALOGE("Failed to import metadata buffer, error=%d", ret); 96 return ret; 97 } 98 size_t metadata_buf_size = metadata_buffer.width(); 99 if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) { 100 ALOGE("BufferHubBuffer::ImportBuffer: metadata buffer too small: %zu", 101 metadata_buf_size); 102 return -ENOMEM; 103 } 104 105 // If all imports succee, replace the previous buffer and id. 106 buffer_ = std::move(ion_buffer); 107 metadata_buffer_ = std::move(metadata_buffer); 108 metadata_buf_size_ = metadata_buf_size; 109 user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize; 110 111 void* metadata_ptr = nullptr; 112 if (const int ret = 113 metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0, 114 /*y=*/0, metadata_buf_size_, 115 /*height=*/1, &metadata_ptr)) { 116 ALOGE("BufferHubBuffer::ImportBuffer: Failed to lock metadata."); 117 return ret; 118 } 119 120 // Set up shared fences. 121 shared_acquire_fence_ = buffer_desc.take_acquire_fence(); 122 shared_release_fence_ = buffer_desc.take_release_fence(); 123 if (!shared_acquire_fence_ || !shared_release_fence_) { 124 ALOGE("BufferHubBuffer::ImportBuffer: Failed to import shared fences."); 125 return -EIO; 126 } 127 128 metadata_header_ = 129 reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr); 130 if (user_metadata_size_) { 131 user_metadata_ptr_ = 132 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) + 133 BufferHubDefs::kMetadataHeaderSize); 134 } else { 135 user_metadata_ptr_ = nullptr; 136 } 137 138 id_ = new_id; 139 buffer_state_bit_ = buffer_desc.buffer_state_bit(); 140 141 // Note that here the buffer state is mapped from shared memory as an atomic 142 // object. The std::atomic's constructor will not be called so that the 143 // original value stored in the memory region will be preserved. 144 buffer_state_ = &metadata_header_->buffer_state; 145 ALOGD_IF(TRACE, 146 "BufferHubBuffer::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".", 147 id(), buffer_state_->load()); 148 fence_state_ = &metadata_header_->fence_state; 149 ALOGD_IF(TRACE, 150 "BufferHubBuffer::ImportBuffer: id=%d, fence_state=%" PRIx64 ".", 151 id(), fence_state_->load()); 152 153 return 0; 154 } 155 156 inline int BufferHubBuffer::CheckMetadata(size_t user_metadata_size) const { 157 if (user_metadata_size && !user_metadata_ptr_) { 158 ALOGE("BufferHubBuffer::CheckMetadata: doesn't support custom metadata."); 159 return -EINVAL; 160 } 161 if (user_metadata_size > user_metadata_size_) { 162 ALOGE("BufferHubBuffer::CheckMetadata: too big: %zu, maximum: %zu.", 163 user_metadata_size, user_metadata_size_); 164 return -E2BIG; 165 } 166 return 0; 167 } 168 169 int BufferHubBuffer::UpdateSharedFence(const LocalHandle& new_fence, 170 const LocalHandle& shared_fence) { 171 if (pending_fence_fd_.Get() != new_fence.Get()) { 172 // First, replace the old fd if there was already one. Skipping if the new 173 // one is the same as the old. 174 if (pending_fence_fd_.IsValid()) { 175 const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL, 176 pending_fence_fd_.Get(), nullptr); 177 ALOGW_IF(ret, 178 "BufferHubBuffer::UpdateSharedFence: failed to remove old fence " 179 "fd from epoll set, error: %s.", 180 strerror(errno)); 181 } 182 183 if (new_fence.IsValid()) { 184 // If ready fence is valid, we put that into the epoll set. 185 epoll_event event; 186 event.events = EPOLLIN; 187 event.data.u64 = buffer_state_bit(); 188 pending_fence_fd_ = new_fence.Duplicate(); 189 if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(), 190 &event) < 0) { 191 const int error = errno; 192 ALOGE( 193 "BufferHubBuffer::UpdateSharedFence: failed to add new fence fd " 194 "into epoll set, error: %s.", 195 strerror(error)); 196 return -error; 197 } 198 // Set bit in fence state to indicate that there is a fence from this 199 // producer or consumer. 200 fence_state_->fetch_or(buffer_state_bit()); 201 } else { 202 // Unset bit in fence state to indicate that there is no fence, so that 203 // when consumer to acquire or producer to acquire, it knows no need to 204 // check fence for this buffer. 205 fence_state_->fetch_and(~buffer_state_bit()); 206 } 207 } 208 209 return 0; 210 } 211 212 int BufferHubBuffer::Poll(int timeout_ms) { 213 ATRACE_NAME("BufferHubBuffer::Poll"); 214 pollfd p = {event_fd(), POLLIN, 0}; 215 return poll(&p, 1, timeout_ms); 216 } 217 218 int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height, 219 void** address) { 220 return buffer_.Lock(usage, x, y, width, height, address); 221 } 222 223 int BufferHubBuffer::Unlock() { return buffer_.Unlock(); } 224 225 int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) { 226 int width = static_cast<int>(size); 227 int height = 1; 228 int ret = Lock(usage(), 0, 0, width, height, addr); 229 if (ret == 0) 230 Unlock(); 231 return ret; 232 } 233 234 int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) { 235 return GetBlobReadWritePointer(size, addr); 236 } 237 238 void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count, 239 size_t max_fds_count) const { 240 size_t numFds = static_cast<size_t>(native_handle()->numFds); 241 *fds_count = std::min(max_fds_count, numFds); 242 std::copy(native_handle()->data, native_handle()->data + *fds_count, fds); 243 } 244 245 BufferConsumer::BufferConsumer(LocalChannelHandle channel) 246 : BASE(std::move(channel)) { 247 const int ret = ImportBuffer(); 248 if (ret < 0) { 249 ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s", 250 strerror(-ret)); 251 Close(ret); 252 } 253 } 254 255 std::unique_ptr<BufferConsumer> BufferConsumer::Import( 256 LocalChannelHandle channel) { 257 ATRACE_NAME("BufferConsumer::Import"); 258 ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value()); 259 return BufferConsumer::Create(std::move(channel)); 260 } 261 262 std::unique_ptr<BufferConsumer> BufferConsumer::Import( 263 Status<LocalChannelHandle> status) { 264 return Import(status ? status.take() 265 : LocalChannelHandle{nullptr, -status.error()}); 266 } 267 268 int BufferConsumer::LocalAcquire(DvrNativeBufferMetadata* out_meta, 269 LocalHandle* out_fence) { 270 if (!out_meta) 271 return -EINVAL; 272 273 // Only check producer bit and this consumer buffer's particular consumer bit. 274 // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit 275 // is not set. 276 uint64_t buffer_state = buffer_state_->load(); 277 if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) { 278 ALOGE("BufferConsumer::LocalAcquire: not posted, id=%d state=%" PRIx64 279 " buffer_state_bit=%" PRIx64 ".", 280 id(), buffer_state, buffer_state_bit()); 281 return -EBUSY; 282 } 283 284 // Copy the canonical metadata. 285 void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata); 286 memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata)); 287 // Fill in the user_metadata_ptr in address space of the local process. 288 if (out_meta->user_metadata_size) { 289 out_meta->user_metadata_ptr = 290 reinterpret_cast<uint64_t>(user_metadata_ptr_); 291 } else { 292 out_meta->user_metadata_ptr = 0; 293 } 294 295 uint64_t fence_state = fence_state_->load(); 296 // If there is an acquire fence from producer, we need to return it. 297 if (fence_state & BufferHubDefs::kProducerStateBit) { 298 *out_fence = shared_acquire_fence_.Duplicate(); 299 } 300 301 // Set the consumer bit unique to this consumer. 302 BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit()); 303 return 0; 304 } 305 306 int BufferConsumer::Acquire(LocalHandle* ready_fence) { 307 return Acquire(ready_fence, nullptr, 0); 308 } 309 310 int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta, 311 size_t user_metadata_size) { 312 ATRACE_NAME("BufferConsumer::Acquire"); 313 314 if (const int error = CheckMetadata(user_metadata_size)) 315 return error; 316 317 DvrNativeBufferMetadata canonical_meta; 318 if (const int error = LocalAcquire(&canonical_meta, ready_fence)) 319 return error; 320 321 if (meta && user_metadata_size) { 322 void* metadata_src = 323 reinterpret_cast<void*>(canonical_meta.user_metadata_ptr); 324 if (metadata_src) { 325 memcpy(meta, metadata_src, user_metadata_size); 326 } else { 327 ALOGW("BufferConsumer::Acquire: no user-defined metadata."); 328 } 329 } 330 331 auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>(); 332 if (!status) 333 return -status.error(); 334 return 0; 335 } 336 337 int BufferConsumer::AcquireAsync(DvrNativeBufferMetadata* out_meta, 338 LocalHandle* out_fence) { 339 ATRACE_NAME("BufferConsumer::AcquireAsync"); 340 341 if (const int error = LocalAcquire(out_meta, out_fence)) 342 return error; 343 344 auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode); 345 if (!status) 346 return -status.error(); 347 return 0; 348 } 349 350 int BufferConsumer::LocalRelease(const DvrNativeBufferMetadata* meta, 351 const LocalHandle& release_fence) { 352 if (const int error = CheckMetadata(meta->user_metadata_size)) 353 return error; 354 355 // Check invalid state transition. 356 uint64_t buffer_state = buffer_state_->load(); 357 if (!BufferHubDefs::IsBufferAcquired(buffer_state)) { 358 ALOGE("BufferConsumer::LocalRelease: not acquired id=%d state=%" PRIx64 ".", 359 id(), buffer_state); 360 return -EBUSY; 361 } 362 363 // On release, only the user requested metadata is copied back into the shared 364 // memory for metadata. Since there are multiple consumers, it doesn't make 365 // sense to send the canonical metadata back to the producer. However, one of 366 // the consumer can still choose to write up to user_metadata_size bytes of 367 // data into user_metadata_ptr. 368 if (meta->user_metadata_ptr && meta->user_metadata_size) { 369 void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr); 370 memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size); 371 } 372 373 // Send out the release fence through the shared epoll fd. Note that during 374 // releasing the producer is not expected to be polling on the fence. 375 if (const int error = UpdateSharedFence(release_fence, shared_release_fence_)) 376 return error; 377 378 // For release operation, the client don't need to change the state as it's 379 // bufferhubd's job to flip the produer bit once all consumers are released. 380 return 0; 381 } 382 383 int BufferConsumer::Release(const LocalHandle& release_fence) { 384 ATRACE_NAME("BufferConsumer::Release"); 385 386 DvrNativeBufferMetadata meta; 387 if (const int error = LocalRelease(&meta, release_fence)) 388 return error; 389 390 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>( 391 BorrowedFence(release_fence.Borrow()))); 392 } 393 394 int BufferConsumer::ReleaseAsync() { 395 DvrNativeBufferMetadata meta; 396 return ReleaseAsync(&meta, LocalHandle()); 397 } 398 399 int BufferConsumer::ReleaseAsync(const DvrNativeBufferMetadata* meta, 400 const LocalHandle& release_fence) { 401 ATRACE_NAME("BufferConsumer::ReleaseAsync"); 402 403 if (const int error = LocalRelease(meta, release_fence)) 404 return error; 405 406 return ReturnStatusOrError( 407 SendImpulse(BufferHubRPC::ConsumerRelease::Opcode)); 408 } 409 410 int BufferConsumer::Discard() { return Release(LocalHandle()); } 411 412 int BufferConsumer::SetIgnore(bool ignore) { 413 return ReturnStatusOrError( 414 InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore)); 415 } 416 417 BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format, 418 uint64_t usage, size_t user_metadata_size) 419 : BASE(BufferHubRPC::kClientPath) { 420 ATRACE_NAME("BufferProducer::BufferProducer"); 421 ALOGD_IF(TRACE, 422 "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u " 423 "usage=%" PRIx64 " user_metadata_size=%zu", 424 event_fd(), width, height, format, usage, user_metadata_size); 425 426 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( 427 width, height, format, usage, user_metadata_size); 428 if (!status) { 429 ALOGE( 430 "BufferProducer::BufferProducer: Failed to create producer buffer: %s", 431 status.GetErrorMessage().c_str()); 432 Close(-status.error()); 433 return; 434 } 435 436 const int ret = ImportBuffer(); 437 if (ret < 0) { 438 ALOGE( 439 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 440 strerror(-ret)); 441 Close(ret); 442 } 443 } 444 445 BufferProducer::BufferProducer(uint64_t usage, size_t size) 446 : BASE(BufferHubRPC::kClientPath) { 447 ATRACE_NAME("BufferProducer::BufferProducer"); 448 ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%" PRIx64 " size=%zu", 449 usage, size); 450 const int width = static_cast<int>(size); 451 const int height = 1; 452 const int format = HAL_PIXEL_FORMAT_BLOB; 453 const size_t user_metadata_size = 0; 454 455 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( 456 width, height, format, usage, user_metadata_size); 457 if (!status) { 458 ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s", 459 status.GetErrorMessage().c_str()); 460 Close(-status.error()); 461 return; 462 } 463 464 const int ret = ImportBuffer(); 465 if (ret < 0) { 466 ALOGE( 467 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 468 strerror(-ret)); 469 Close(ret); 470 } 471 } 472 473 BufferProducer::BufferProducer(LocalChannelHandle channel) 474 : BASE(std::move(channel)) { 475 const int ret = ImportBuffer(); 476 if (ret < 0) { 477 ALOGE( 478 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 479 strerror(-ret)); 480 Close(ret); 481 } 482 } 483 484 int BufferProducer::LocalPost(const DvrNativeBufferMetadata* meta, 485 const LocalHandle& ready_fence) { 486 if (const int error = CheckMetadata(meta->user_metadata_size)) 487 return error; 488 489 // Check invalid state transition. 490 uint64_t buffer_state = buffer_state_->load(); 491 if (!BufferHubDefs::IsBufferGained(buffer_state)) { 492 ALOGE("BufferProducer::LocalPost: not gained, id=%d state=%" PRIx64 ".", 493 id(), buffer_state); 494 return -EBUSY; 495 } 496 497 // Copy the canonical metadata. 498 void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata); 499 memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata)); 500 // Copy extra user requested metadata. 501 if (meta->user_metadata_ptr && meta->user_metadata_size) { 502 void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr); 503 memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size); 504 } 505 506 // Send out the acquire fence through the shared epoll fd. Note that during 507 // posting no consumer is not expected to be polling on the fence. 508 if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_)) 509 return error; 510 511 // Set the producer bit atomically to transit into posted state. 512 BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, 513 BufferHubDefs::kProducerStateBit); 514 return 0; 515 } 516 517 int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta, 518 size_t user_metadata_size) { 519 ATRACE_NAME("BufferProducer::Post"); 520 521 // Populate cononical metadata for posting. 522 DvrNativeBufferMetadata canonical_meta; 523 canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta); 524 canonical_meta.user_metadata_size = user_metadata_size; 525 526 if (const int error = LocalPost(&canonical_meta, ready_fence)) 527 return error; 528 529 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>( 530 BorrowedFence(ready_fence.Borrow()))); 531 } 532 533 int BufferProducer::PostAsync(const DvrNativeBufferMetadata* meta, 534 const LocalHandle& ready_fence) { 535 ATRACE_NAME("BufferProducer::PostAsync"); 536 537 if (const int error = LocalPost(meta, ready_fence)) 538 return error; 539 540 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode)); 541 } 542 543 int BufferProducer::LocalGain(DvrNativeBufferMetadata* out_meta, 544 LocalHandle* out_fence) { 545 uint64_t buffer_state = buffer_state_->load(); 546 ALOGD_IF(TRACE, "BufferProducer::LocalGain: buffer=%d, state=%" PRIx64 ".", 547 id(), buffer_state); 548 549 if (!out_meta) 550 return -EINVAL; 551 552 if (!BufferHubDefs::IsBufferReleased(buffer_state)) { 553 if (BufferHubDefs::IsBufferGained(buffer_state)) { 554 // We don't want to log error when gaining a newly allocated 555 // buffer. 556 ALOGI("BufferProducer::LocalGain: already gained id=%d.", id()); 557 return -EALREADY; 558 } 559 ALOGE("BufferProducer::LocalGain: not released id=%d state=%" PRIx64 ".", 560 id(), buffer_state); 561 return -EBUSY; 562 } 563 564 // Canonical metadata is undefined on Gain. Except for user_metadata and 565 // release_fence_mask. Fill in the user_metadata_ptr in address space of the 566 // local process. 567 if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) { 568 out_meta->user_metadata_size = 569 metadata_header_->metadata.user_metadata_size; 570 out_meta->user_metadata_ptr = 571 reinterpret_cast<uint64_t>(user_metadata_ptr_); 572 } else { 573 out_meta->user_metadata_size = 0; 574 out_meta->user_metadata_ptr = 0; 575 } 576 577 uint64_t fence_state = fence_state_->load(); 578 // If there is an release fence from consumer, we need to return it. 579 if (fence_state & BufferHubDefs::kConsumerStateMask) { 580 *out_fence = shared_release_fence_.Duplicate(); 581 out_meta->release_fence_mask = 582 fence_state & BufferHubDefs::kConsumerStateMask; 583 } 584 585 // Clear out all bits and the buffer is now back to gained state. 586 buffer_state_->store(0ULL); 587 return 0; 588 } 589 590 int BufferProducer::Gain(LocalHandle* release_fence) { 591 ATRACE_NAME("BufferProducer::Gain"); 592 593 DvrNativeBufferMetadata meta; 594 if (const int error = LocalGain(&meta, release_fence)) 595 return error; 596 597 auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>(); 598 if (!status) 599 return -status.error(); 600 return 0; 601 } 602 603 int BufferProducer::GainAsync(DvrNativeBufferMetadata* out_meta, 604 LocalHandle* release_fence) { 605 ATRACE_NAME("BufferProducer::GainAsync"); 606 607 if (const int error = LocalGain(out_meta, release_fence)) 608 return error; 609 610 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode)); 611 } 612 613 int BufferProducer::GainAsync() { 614 DvrNativeBufferMetadata meta; 615 LocalHandle fence; 616 return GainAsync(&meta, &fence); 617 } 618 619 std::unique_ptr<BufferProducer> BufferProducer::Import( 620 LocalChannelHandle channel) { 621 ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value()); 622 return BufferProducer::Create(std::move(channel)); 623 } 624 625 std::unique_ptr<BufferProducer> BufferProducer::Import( 626 Status<LocalChannelHandle> status) { 627 return Import(status ? status.take() 628 : LocalChannelHandle{nullptr, -status.error()}); 629 } 630 631 Status<LocalChannelHandle> BufferProducer::Detach() { 632 uint64_t buffer_state = buffer_state_->load(); 633 if (!BufferHubDefs::IsBufferGained(buffer_state)) { 634 // Can only detach a BufferProducer when it's in gained state. 635 ALOGW("BufferProducer::Detach: The buffer (id=%d, state=0x%" PRIx64 636 ") is not in gained state.", 637 id(), buffer_state); 638 return {}; 639 } 640 641 Status<LocalChannelHandle> status = 642 InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>(); 643 ALOGE_IF(!status, 644 "BufferProducer::Detach: Failed to detach buffer (id=%d): %s.", id(), 645 status.GetErrorMessage().c_str()); 646 return status; 647 } 648 649 } // namespace dvr 650 } // namespace android 651