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
BufferHubClient()24 BufferHubClient::BufferHubClient()
25 : Client(ClientChannelFactory::Create(BufferHubRPC::kClientPath)) {}
26
BufferHubClient(LocalChannelHandle channel_handle)27 BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle)
28 : Client(ClientChannel::Create(std::move(channel_handle))) {}
29
IsValid() const30 bool BufferHubClient::IsValid() const {
31 return IsConnected() && GetChannelHandle().valid();
32 }
33
TakeChannelHandle()34 LocalChannelHandle BufferHubClient::TakeChannelHandle() {
35 if (IsConnected()) {
36 return std::move(GetChannelHandle());
37 } else {
38 return {};
39 }
40 }
41
BufferHubBuffer(LocalChannelHandle channel_handle)42 BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
43 : Client{pdx::default_transport::ClientChannel::Create(
44 std::move(channel_handle))},
45 id_(-1) {}
BufferHubBuffer(const std::string & endpoint_path)46 BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
47 : Client{pdx::default_transport::ClientChannelFactory::Create(
48 endpoint_path)},
49 id_(-1) {}
50
~BufferHubBuffer()51 BufferHubBuffer::~BufferHubBuffer() {
52 if (metadata_header_ != nullptr) {
53 metadata_buffer_.Unlock();
54 }
55 }
56
CreateConsumer()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
ImportBuffer()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
CheckMetadata(size_t user_metadata_size) const156 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
UpdateSharedFence(const LocalHandle & new_fence,const LocalHandle & shared_fence)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
Poll(int timeout_ms)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
Lock(int usage,int x,int y,int width,int height,void ** address)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
Unlock()223 int BufferHubBuffer::Unlock() { return buffer_.Unlock(); }
224
GetBlobReadWritePointer(size_t size,void ** addr)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
GetBlobReadOnlyPointer(size_t size,void ** addr)234 int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) {
235 return GetBlobReadWritePointer(size, addr);
236 }
237
GetBlobFds(int * fds,size_t * fds_count,size_t max_fds_count) const238 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
BufferConsumer(LocalChannelHandle channel)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
Import(LocalChannelHandle channel)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
Import(Status<LocalChannelHandle> status)262 std::unique_ptr<BufferConsumer> BufferConsumer::Import(
263 Status<LocalChannelHandle> status) {
264 return Import(status ? status.take()
265 : LocalChannelHandle{nullptr, -status.error()});
266 }
267
LocalAcquire(DvrNativeBufferMetadata * out_meta,LocalHandle * out_fence)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
Acquire(LocalHandle * ready_fence)306 int BufferConsumer::Acquire(LocalHandle* ready_fence) {
307 return Acquire(ready_fence, nullptr, 0);
308 }
309
Acquire(LocalHandle * ready_fence,void * meta,size_t user_metadata_size)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
AcquireAsync(DvrNativeBufferMetadata * out_meta,LocalHandle * out_fence)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
LocalRelease(const DvrNativeBufferMetadata * meta,const LocalHandle & release_fence)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
Release(const LocalHandle & release_fence)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
ReleaseAsync()394 int BufferConsumer::ReleaseAsync() {
395 DvrNativeBufferMetadata meta;
396 return ReleaseAsync(&meta, LocalHandle());
397 }
398
ReleaseAsync(const DvrNativeBufferMetadata * meta,const LocalHandle & release_fence)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
Discard()410 int BufferConsumer::Discard() { return Release(LocalHandle()); }
411
SetIgnore(bool ignore)412 int BufferConsumer::SetIgnore(bool ignore) {
413 return ReturnStatusOrError(
414 InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
415 }
416
BufferProducer(uint32_t width,uint32_t height,uint32_t format,uint64_t usage,size_t user_metadata_size)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
BufferProducer(uint64_t usage,size_t size)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
BufferProducer(LocalChannelHandle channel)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
LocalPost(const DvrNativeBufferMetadata * meta,const LocalHandle & ready_fence)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
Post(const LocalHandle & ready_fence,const void * meta,size_t user_metadata_size)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
PostAsync(const DvrNativeBufferMetadata * meta,const LocalHandle & ready_fence)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
LocalGain(DvrNativeBufferMetadata * out_meta,LocalHandle * out_fence)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
Gain(LocalHandle * release_fence)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
GainAsync(DvrNativeBufferMetadata * out_meta,LocalHandle * release_fence)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
GainAsync()613 int BufferProducer::GainAsync() {
614 DvrNativeBufferMetadata meta;
615 LocalHandle fence;
616 return GainAsync(&meta, &fence);
617 }
618
Import(LocalChannelHandle channel)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
Import(Status<LocalChannelHandle> status)625 std::unique_ptr<BufferProducer> BufferProducer::Import(
626 Status<LocalChannelHandle> status) {
627 return Import(status ? status.take()
628 : LocalChannelHandle{nullptr, -status.error()});
629 }
630
Detach()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