summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorey Tabaka2017-09-13 20:02:48 -0500
committerJiwen 'Steve' Cai2017-10-10 22:39:56 -0500
commit52ea25cf06cef250ec73052611b48556b3fce4d5 (patch)
tree6595f49407fbe45702f943d913a1d34bd1910fb8
parent35b5114be8da71c69fc8a1ff8fb457c912c0992f (diff)
downloadframeworks-native-52ea25cf06cef250ec73052611b48556b3fce4d5.tar.gz
frameworks-native-52ea25cf06cef250ec73052611b48556b3fce4d5.tar.xz
frameworks-native-52ea25cf06cef250ec73052611b48556b3fce4d5.zip
Add shared memory based buffer metadata
This CLs reduces BufferHub CPU consumption by adding asynchronous state transition so that out-of-process VR composition can run on 2016 pixel devices smoothly. In addition, this CL addresses a couple corner cases in the existing bufferhub logic, which fixes various blackscreen issues. 1/ Tracks buffer transition states (gained, posted, acquired, released) from the client side via atomic shared memory and adds PostAsync/AcquireAsync/ReleaseAsync/GainAsync with metadata and fence support. 2/ Adds dequeue order guarantee for buffers enqueued with dvrWriteBufferQueuePostBuffer. 3/ Synchronous BuffeHub operations are still supported. 4/ Bump up the bufferhubd's soft limit of open file descriptor. 5/ Handle orphaned consumer in acquired state. This is a corner case that consumer process goes aways (most likely due to a crash) leaving buffer stuck in acquired state with inconsistent buffer state. 6/ Fixes a race condition for released buffer to be Gain'ed and Acquire'd when a new consumer is created in released state. 7/ Improve silent consumer queue efficiency: Silent queues no longer import buffers or receive signals about new buffers and they are limited to only spawning other consumers and notifications about producers hanging up. 8/ Modify PDX/UDS channel event signaling to work around epoll behavior. PDX UDS uses a combination of an eventfd and an epoll set to simulate the original PDX transport channel events. An odd behavior discovered in the kernel implementation of epoll was found that causes the epoll fd to "unsignal" itself whenever epoll_wait() is called on it, regardless of whether it should still be pending. This breaks the edge triggerd behavior in nested epoll sets that channel events depend on. Since this is unlikely to ever be fixed in the kernel we work around the behavior by using the epoll set only as a logical OR of two eventfds and never calling epoll_wait() on it. When polling is required we use regluar poll() with the eventfds and data fd to avoid the bad behavior in epoll_wait(). 9/ Keep reading data after PDX hangup signal. UDS will signal hangup when the other end of the socket closes. However, data could still be in the kerenl buffer and should be consumed. Fix an issue where the service misses an impulse sent right before the socket is closed. Bug: 65455724 Bug: 65458354 Bug: 65458312 Bug: 64027135 Bug: 67424527 Test: libpdx_uds_tests bufferhub_tests buffer_hub_queue-test buffer_hub_queue_producer-test dvr_api-test Change-Id: Id07db1f206ccf4e06f7ee3c671193334408971ca
-rw-r--r--libs/vr/libbufferhub/Android.bp9
-rw-r--r--libs/vr/libbufferhub/buffer_hub_client.cpp428
-rw-r--r--libs/vr/libbufferhub/bufferhub_tests.cpp313
-rw-r--r--libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h95
-rw-r--r--libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h147
-rw-r--r--libs/vr/libbufferhubqueue/Android.bp1
-rw-r--r--libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp300
-rw-r--r--libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp6
-rw-r--r--libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h68
-rw-r--r--libs/vr/libbufferhubqueue/tests/Android.bp5
-rw-r--r--libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp139
-rw-r--r--libs/vr/libdvr/dvr_buffer_queue.cpp158
-rw-r--r--libs/vr/libdvr/dvr_buffer_queue_internal.h6
-rw-r--r--libs/vr/libdvr/include/dvr/dvr_api.h51
-rw-r--r--libs/vr/libdvr/tests/Android.bp1
-rw-r--r--libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp14
-rw-r--r--libs/vr/libpdx/Android.bp1
-rw-r--r--libs/vr/libpdx/private/pdx/client_channel.h11
-rw-r--r--libs/vr/libpdx/private/pdx/mock_client_channel.h1
-rw-r--r--libs/vr/libpdx/private/pdx/trace.h97
-rw-r--r--libs/vr/libpdx_uds/channel_event_set.cpp182
-rw-r--r--libs/vr/libpdx_uds/channel_manager.cpp22
-rw-r--r--libs/vr/libpdx_uds/client_channel.cpp10
-rw-r--r--libs/vr/libpdx_uds/client_channel_factory.cpp21
-rw-r--r--libs/vr/libpdx_uds/private/uds/channel_event_set.h40
-rw-r--r--libs/vr/libpdx_uds/private/uds/channel_manager.h12
-rw-r--r--libs/vr/libpdx_uds/private/uds/client_channel.h14
-rw-r--r--libs/vr/libpdx_uds/private/uds/ipc_helper.h6
-rw-r--r--libs/vr/libpdx_uds/private/uds/service_endpoint.h4
-rw-r--r--libs/vr/libpdx_uds/service_endpoint.cpp77
-rw-r--r--libs/vr/libpdx_uds/service_framework_tests.cpp52
-rw-r--r--libs/vr/libvrflinger/display_surface.cpp12
-rw-r--r--services/vr/bufferhubd/Android.mk4
-rw-r--r--services/vr/bufferhubd/buffer_hub.cpp87
-rw-r--r--services/vr/bufferhubd/buffer_hub.h16
-rw-r--r--services/vr/bufferhubd/bufferhubd.cpp18
-rw-r--r--services/vr/bufferhubd/consumer_channel.cpp29
-rw-r--r--services/vr/bufferhubd/consumer_channel.h11
-rw-r--r--services/vr/bufferhubd/consumer_queue_channel.cpp34
-rw-r--r--services/vr/bufferhubd/consumer_queue_channel.h6
-rw-r--r--services/vr/bufferhubd/producer_channel.cpp303
-rw-r--r--services/vr/bufferhubd/producer_channel.h39
-rw-r--r--services/vr/bufferhubd/producer_queue_channel.cpp14
-rw-r--r--services/vr/bufferhubd/producer_queue_channel.h2
44 files changed, 2072 insertions, 794 deletions
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index da0ea24da..f32720038 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -37,7 +37,8 @@ sharedLibraries = [
37 "libnativewindow" 37 "libnativewindow"
38] 38]
39 39
40HeaderLibraries = [ 40headerLibraries = [
41 "libdvr_headers",
41 "libnativebase_headers", 42 "libnativebase_headers",
42] 43]
43 44
@@ -45,12 +46,13 @@ cc_library {
45 srcs: sourceFiles, 46 srcs: sourceFiles,
46 cflags: [ 47 cflags: [
47 "-DLOG_TAG=\"libbufferhub\"", 48 "-DLOG_TAG=\"libbufferhub\"",
48 "-DTRACE=0" 49 "-DTRACE=0",
50 "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
49 ], 51 ],
50 export_include_dirs: localIncludeFiles, 52 export_include_dirs: localIncludeFiles,
51 static_libs: staticLibraries, 53 static_libs: staticLibraries,
52 shared_libs: sharedLibraries, 54 shared_libs: sharedLibraries,
53 header_libs: HeaderLibraries, 55 header_libs: headerLibraries,
54 name: "libbufferhub", 56 name: "libbufferhub",
55 export_header_lib_headers: [ 57 export_header_lib_headers: [
56 "libnativebase_headers", 58 "libnativebase_headers",
@@ -62,6 +64,7 @@ cc_test {
62 srcs: ["bufferhub_tests.cpp"], 64 srcs: ["bufferhub_tests.cpp"],
63 static_libs: ["libbufferhub"] + staticLibraries, 65 static_libs: ["libbufferhub"] + staticLibraries,
64 shared_libs: sharedLibraries, 66 shared_libs: sharedLibraries,
67 header_libs: headerLibraries,
65 name: "bufferhub_tests", 68 name: "bufferhub_tests",
66} 69}
67 70
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index b9a53b0ce..97341b147 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -2,7 +2,7 @@
2 2
3#include <log/log.h> 3#include <log/log.h>
4#include <poll.h> 4#include <poll.h>
5#define ATRACE_TAG ATRACE_TAG_GRAPHICS 5#include <sys/epoll.h>
6#include <utils/Trace.h> 6#include <utils/Trace.h>
7 7
8#include <mutex> 8#include <mutex>
@@ -12,9 +12,8 @@
12 12
13#include "include/private/dvr/bufferhub_rpc.h" 13#include "include/private/dvr/bufferhub_rpc.h"
14 14
15using android::pdx::LocalHandle;
16using android::pdx::LocalChannelHandle; 15using android::pdx::LocalChannelHandle;
17using android::pdx::rpc::WrapBuffer; 16using android::pdx::LocalHandle;
18using android::pdx::Status; 17using android::pdx::Status;
19 18
20namespace android { 19namespace android {
@@ -29,7 +28,11 @@ BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
29 endpoint_path)}, 28 endpoint_path)},
30 id_(-1) {} 29 id_(-1) {}
31 30
32BufferHubBuffer::~BufferHubBuffer() {} 31BufferHubBuffer::~BufferHubBuffer() {
32 if (metadata_header_ != nullptr) {
33 metadata_buffer_.Unlock();
34 }
35}
33 36
34Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() { 37Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
35 Status<LocalChannelHandle> status = 38 Status<LocalChannelHandle> status =
@@ -43,7 +46,7 @@ Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
43int BufferHubBuffer::ImportBuffer() { 46int BufferHubBuffer::ImportBuffer() {
44 ATRACE_NAME("BufferHubBuffer::ImportBuffer"); 47 ATRACE_NAME("BufferHubBuffer::ImportBuffer");
45 48
46 Status<NativeBufferHandle<LocalHandle>> status = 49 Status<BufferDescription<LocalHandle>> status =
47 InvokeRemoteMethod<BufferHubRPC::GetBuffer>(); 50 InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
48 if (!status) { 51 if (!status) {
49 ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s", 52 ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
@@ -54,24 +57,135 @@ int BufferHubBuffer::ImportBuffer() {
54 return -EIO; 57 return -EIO;
55 } 58 }
56 59
57 auto buffer_handle = status.take(); 60 auto buffer_desc = status.take();
58 61
59 // Stash the buffer id to replace the value in id_. 62 // Stash the buffer id to replace the value in id_.
60 const int new_id = buffer_handle.id(); 63 const int new_id = buffer_desc.id();
61 64
62 // Import the buffer. 65 // Import the buffer.
63 IonBuffer ion_buffer; 66 IonBuffer ion_buffer;
64 ALOGD_IF( 67 ALOGD_IF(TRACE, "BufferHubBuffer::ImportBuffer: id=%d.", buffer_desc.id());
65 TRACE, "BufferHubBuffer::ImportBuffer: id=%d FdCount=%zu IntCount=%zu",
66 buffer_handle.id(), buffer_handle.FdCount(), buffer_handle.IntCount());
67 68
68 const int ret = buffer_handle.Import(&ion_buffer); 69 if (const int ret = buffer_desc.ImportBuffer(&ion_buffer))
69 if (ret < 0)
70 return ret; 70 return ret;
71 71
72 // If the import succeeds, replace the previous buffer and id. 72 // Import the metadata.
73 IonBuffer metadata_buffer;
74 if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
75 ALOGE("Failed to import metadata buffer, error=%d", ret);
76 return ret;
77 }
78 size_t metadata_buf_size = metadata_buffer.width();
79 if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
80 ALOGE("BufferHubBuffer::ImportBuffer: metadata buffer too small: %zu",
81 metadata_buf_size);
82 return -ENOMEM;
83 }
84
85 // If all imports succee, replace the previous buffer and id.
73 buffer_ = std::move(ion_buffer); 86 buffer_ = std::move(ion_buffer);
87 metadata_buffer_ = std::move(metadata_buffer);
88 metadata_buf_size_ = metadata_buf_size;
89 user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize;
90
91 void* metadata_ptr = nullptr;
92 if (const int ret =
93 metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
94 /*y=*/0, metadata_buf_size_,
95 /*height=*/1, &metadata_ptr)) {
96 ALOGE("BufferHubBuffer::ImportBuffer: Failed to lock metadata.");
97 return ret;
98 }
99
100 // Set up shared fences.
101 shared_acquire_fence_ = buffer_desc.take_acquire_fence();
102 shared_release_fence_ = buffer_desc.take_release_fence();
103 if (!shared_acquire_fence_ || !shared_release_fence_) {
104 ALOGE("BufferHubBuffer::ImportBuffer: Failed to import shared fences.");
105 return -EIO;
106 }
107
108 metadata_header_ =
109 reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
110 if (user_metadata_size_) {
111 user_metadata_ptr_ =
112 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) +
113 BufferHubDefs::kMetadataHeaderSize);
114 } else {
115 user_metadata_ptr_ = nullptr;
116 }
117
74 id_ = new_id; 118 id_ = new_id;
119 buffer_state_bit_ = buffer_desc.buffer_state_bit();
120
121 // Note that here the buffer state is mapped from shared memory as an atomic
122 // object. The std::atomic's constructor will not be called so that the
123 // original value stored in the memory region will be preserved.
124 buffer_state_ = &metadata_header_->buffer_state;
125 ALOGD_IF(TRACE,
126 "BufferHubBuffer::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".",
127 id(), buffer_state_->load());
128 fence_state_ = &metadata_header_->fence_state;
129 ALOGD_IF(TRACE,
130 "BufferHubBuffer::ImportBuffer: id=%d, fence_state=%" PRIx64 ".",
131 id(), fence_state_->load());
132
133 return 0;
134}
135
136inline int BufferHubBuffer::CheckMetadata(size_t user_metadata_size) const {
137 if (user_metadata_size && !user_metadata_ptr_) {
138 ALOGE("BufferHubBuffer::CheckMetadata: doesn't support custom metadata.");
139 return -EINVAL;
140 }
141 if (user_metadata_size > user_metadata_size_) {
142 ALOGE("BufferHubBuffer::CheckMetadata: too big: %zu, maximum: %zu.",
143 user_metadata_size, user_metadata_size_);
144 return -E2BIG;
145 }
146 return 0;
147}
148
149int BufferHubBuffer::UpdateSharedFence(const LocalHandle& new_fence,
150 const LocalHandle& shared_fence) {
151 if (pending_fence_fd_.Get() != new_fence.Get()) {
152 // First, replace the old fd if there was already one. Skipping if the new
153 // one is the same as the old.
154 if (pending_fence_fd_.IsValid()) {
155 const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL,
156 pending_fence_fd_.Get(), nullptr);
157 ALOGW_IF(ret,
158 "BufferHubBuffer::UpdateSharedFence: failed to remove old fence "
159 "fd from epoll set, error: %s.",
160 strerror(errno));
161 }
162
163 if (new_fence.IsValid()) {
164 // If ready fence is valid, we put that into the epoll set.
165 epoll_event event;
166 event.events = EPOLLIN;
167 event.data.u64 = buffer_state_bit();
168 pending_fence_fd_ = new_fence.Duplicate();
169 if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(),
170 &event) < 0) {
171 const int error = errno;
172 ALOGE(
173 "BufferHubBuffer::UpdateSharedFence: failed to add new fence fd "
174 "into epoll set, error: %s.",
175 strerror(error));
176 return -error;
177 }
178 // Set bit in fence state to indicate that there is a fence from this
179 // producer or consumer.
180 fence_state_->fetch_or(buffer_state_bit());
181 } else {
182 // Unset bit in fence state to indicate that there is no fence, so that
183 // when consumer to acquire or producer to acquire, it knows no need to
184 // check fence for this buffer.
185 fence_state_->fetch_and(~buffer_state_bit());
186 }
187 }
188
75 return 0; 189 return 0;
76} 190}
77 191
@@ -131,31 +245,144 @@ std::unique_ptr<BufferConsumer> BufferConsumer::Import(
131 : LocalChannelHandle{nullptr, -status.error()}); 245 : LocalChannelHandle{nullptr, -status.error()});
132} 246}
133 247
248int BufferConsumer::LocalAcquire(DvrNativeBufferMetadata* out_meta,
249 LocalHandle* out_fence) {
250 if (!out_meta)
251 return -EINVAL;
252
253 // Only check producer bit and this consumer buffer's particular consumer bit.
254 // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
255 // is not set.
256 uint64_t buffer_state = buffer_state_->load();
257 if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) {
258 ALOGE("BufferConsumer::LocalAcquire: not posted, id=%d state=%" PRIx64
259 " buffer_state_bit=%" PRIx64 ".",
260 id(), buffer_state, buffer_state_bit());
261 return -EBUSY;
262 }
263
264 // Copy the canonical metadata.
265 void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
266 memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata));
267 // Fill in the user_metadata_ptr in address space of the local process.
268 if (out_meta->user_metadata_size) {
269 out_meta->user_metadata_ptr =
270 reinterpret_cast<uint64_t>(user_metadata_ptr_);
271 } else {
272 out_meta->user_metadata_ptr = 0;
273 }
274
275 uint64_t fence_state = fence_state_->load();
276 // If there is an acquire fence from producer, we need to return it.
277 if (fence_state & BufferHubDefs::kProducerStateBit) {
278 *out_fence = shared_acquire_fence_.Duplicate();
279 }
280
281 // Set the consumer bit unique to this consumer.
282 BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit());
283 return 0;
284}
285
134int BufferConsumer::Acquire(LocalHandle* ready_fence) { 286int BufferConsumer::Acquire(LocalHandle* ready_fence) {
135 return Acquire(ready_fence, nullptr, 0); 287 return Acquire(ready_fence, nullptr, 0);
136} 288}
137 289
138int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta, 290int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
139 size_t meta_size_bytes) { 291 size_t user_metadata_size) {
140 ATRACE_NAME("BufferConsumer::Acquire"); 292 ATRACE_NAME("BufferConsumer::Acquire");
141 LocalFence fence; 293
142 auto return_value = 294 if (const int error = CheckMetadata(user_metadata_size))
143 std::make_pair(std::ref(fence), WrapBuffer(meta, meta_size_bytes)); 295 return error;
144 auto status = InvokeRemoteMethodInPlace<BufferHubRPC::ConsumerAcquire>( 296
145 &return_value, meta_size_bytes); 297 DvrNativeBufferMetadata canonical_meta;
146 if (status && ready_fence) 298 if (const int error = LocalAcquire(&canonical_meta, ready_fence))
147 *ready_fence = fence.take(); 299 return error;
148 return status ? 0 : -status.error(); 300
301 if (meta && user_metadata_size) {
302 void* metadata_src =
303 reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
304 if (metadata_src) {
305 memcpy(meta, metadata_src, user_metadata_size);
306 } else {
307 ALOGW("BufferConsumer::Acquire: no user-defined metadata.");
308 }
309 }
310
311 auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
312 if (!status)
313 return -status.error();
314 return 0;
315}
316
317int BufferConsumer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
318 LocalHandle* out_fence) {
319 ATRACE_NAME("BufferConsumer::AcquireAsync");
320
321 if (const int error = LocalAcquire(out_meta, out_fence))
322 return error;
323
324 auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
325 if (!status)
326 return -status.error();
327 return 0;
328}
329
330int BufferConsumer::LocalRelease(const DvrNativeBufferMetadata* meta,
331 const LocalHandle& release_fence) {
332 if (const int error = CheckMetadata(meta->user_metadata_size))
333 return error;
334
335 // Check invalid state transition.
336 uint64_t buffer_state = buffer_state_->load();
337 if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
338 ALOGE("BufferConsumer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
339 id(), buffer_state);
340 return -EBUSY;
341 }
342
343 // On release, only the user requested metadata is copied back into the shared
344 // memory for metadata. Since there are multiple consumers, it doesn't make
345 // sense to send the canonical metadata back to the producer. However, one of
346 // the consumer can still choose to write up to user_metadata_size bytes of
347 // data into user_metadata_ptr.
348 if (meta->user_metadata_ptr && meta->user_metadata_size) {
349 void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
350 memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
351 }
352
353 // Send out the release fence through the shared epoll fd. Note that during
354 // releasing the producer is not expected to be polling on the fence.
355 if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
356 return error;
357
358 // For release operation, the client don't need to change the state as it's
359 // bufferhubd's job to flip the produer bit once all consumers are released.
360 return 0;
149} 361}
150 362
151int BufferConsumer::Release(const LocalHandle& release_fence) { 363int BufferConsumer::Release(const LocalHandle& release_fence) {
152 ATRACE_NAME("BufferConsumer::Release"); 364 ATRACE_NAME("BufferConsumer::Release");
365
366 DvrNativeBufferMetadata meta;
367 if (const int error = LocalRelease(&meta, release_fence))
368 return error;
369
153 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>( 370 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
154 BorrowedFence(release_fence.Borrow()))); 371 BorrowedFence(release_fence.Borrow())));
155} 372}
156 373
157int BufferConsumer::ReleaseAsync() { 374int BufferConsumer::ReleaseAsync() {
375 DvrNativeBufferMetadata meta;
376 return ReleaseAsync(&meta, LocalHandle());
377}
378
379int BufferConsumer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
380 const LocalHandle& release_fence) {
158 ATRACE_NAME("BufferConsumer::ReleaseAsync"); 381 ATRACE_NAME("BufferConsumer::ReleaseAsync");
382
383 if (const int error = LocalRelease(meta, release_fence))
384 return error;
385
159 return ReturnStatusOrError( 386 return ReturnStatusOrError(
160 SendImpulse(BufferHubRPC::ConsumerRelease::Opcode)); 387 SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
161} 388}
@@ -168,24 +395,25 @@ int BufferConsumer::SetIgnore(bool ignore) {
168} 395}
169 396
170BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format, 397BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
171 uint32_t usage, size_t metadata_size) 398 uint32_t usage, size_t user_metadata_size)
172 : BufferProducer(width, height, format, usage, usage, metadata_size) {} 399 : BufferProducer(width, height, format, usage, usage, user_metadata_size) {}
173 400
174BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format, 401BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
175 uint64_t producer_usage, uint64_t consumer_usage, 402 uint64_t producer_usage, uint64_t consumer_usage,
176 size_t metadata_size) 403 size_t user_metadata_size)
177 : BASE(BufferHubRPC::kClientPath) { 404 : BASE(BufferHubRPC::kClientPath) {
178 ATRACE_NAME("BufferProducer::BufferProducer"); 405 ATRACE_NAME("BufferProducer::BufferProducer");
179 ALOGD_IF(TRACE, 406 ALOGD_IF(TRACE,
180 "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u " 407 "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
181 "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 408 "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
182 " metadata_size=%zu", 409 " user_metadata_size=%zu",
183 event_fd(), width, height, format, producer_usage, consumer_usage, 410 event_fd(), width, height, format, producer_usage, consumer_usage,
184 metadata_size); 411 user_metadata_size);
185 412
186 // (b/37881101) Deprecate producer/consumer usage 413 // (b/37881101) Deprecate producer/consumer usage
187 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( 414 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
188 width, height, format, (producer_usage | consumer_usage), metadata_size); 415 width, height, format, (producer_usage | consumer_usage),
416 user_metadata_size);
189 if (!status) { 417 if (!status) {
190 ALOGE( 418 ALOGE(
191 "BufferProducer::BufferProducer: Failed to create producer buffer: %s", 419 "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -206,27 +434,28 @@ BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
206BufferProducer::BufferProducer(const std::string& name, int user_id, 434BufferProducer::BufferProducer(const std::string& name, int user_id,
207 int group_id, uint32_t width, uint32_t height, 435 int group_id, uint32_t width, uint32_t height,
208 uint32_t format, uint32_t usage, 436 uint32_t format, uint32_t usage,
209 size_t meta_size_bytes) 437 size_t user_metadata_size)
210 : BufferProducer(name, user_id, group_id, width, height, format, usage, 438 : BufferProducer(name, user_id, group_id, width, height, format, usage,
211 usage, meta_size_bytes) {} 439 usage, user_metadata_size) {}
212 440
213BufferProducer::BufferProducer(const std::string& name, int user_id, 441BufferProducer::BufferProducer(const std::string& name, int user_id,
214 int group_id, uint32_t width, uint32_t height, 442 int group_id, uint32_t width, uint32_t height,
215 uint32_t format, uint64_t producer_usage, 443 uint32_t format, uint64_t producer_usage,
216 uint64_t consumer_usage, size_t meta_size_bytes) 444 uint64_t consumer_usage,
445 size_t user_metadata_size)
217 : BASE(BufferHubRPC::kClientPath) { 446 : BASE(BufferHubRPC::kClientPath) {
218 ATRACE_NAME("BufferProducer::BufferProducer"); 447 ATRACE_NAME("BufferProducer::BufferProducer");
219 ALOGD_IF(TRACE, 448 ALOGD_IF(TRACE,
220 "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d " 449 "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
221 "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64 450 "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
222 " consumer_usage=%" PRIx64 " meta_size_bytes=%zu", 451 " consumer_usage=%" PRIx64 " user_metadata_size=%zu",
223 event_fd(), name.c_str(), user_id, group_id, width, height, format, 452 event_fd(), name.c_str(), user_id, group_id, width, height, format,
224 producer_usage, consumer_usage, meta_size_bytes); 453 producer_usage, consumer_usage, user_metadata_size);
225 454
226 // (b/37881101) Deprecate producer/consumer usage 455 // (b/37881101) Deprecate producer/consumer usage
227 auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>( 456 auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
228 name, user_id, group_id, width, height, format, 457 name, user_id, group_id, width, height, format,
229 (producer_usage | consumer_usage), meta_size_bytes); 458 (producer_usage | consumer_usage), user_metadata_size);
230 if (!status) { 459 if (!status) {
231 ALOGE( 460 ALOGE(
232 "BufferProducer::BufferProducer: Failed to create/get persistent " 461 "BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -260,12 +489,12 @@ BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
260 const int width = static_cast<int>(size); 489 const int width = static_cast<int>(size);
261 const int height = 1; 490 const int height = 1;
262 const int format = HAL_PIXEL_FORMAT_BLOB; 491 const int format = HAL_PIXEL_FORMAT_BLOB;
263 const size_t meta_size_bytes = 0; 492 const size_t user_metadata_size = 0;
264 493
265 // (b/37881101) Deprecate producer/consumer usage 494 // (b/37881101) Deprecate producer/consumer usage
266 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( 495 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
267 width, height, format, (producer_usage | consumer_usage), 496 width, height, format, (producer_usage | consumer_usage),
268 meta_size_bytes); 497 user_metadata_size);
269 if (!status) { 498 if (!status) {
270 ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s", 499 ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
271 status.GetErrorMessage().c_str()); 500 status.GetErrorMessage().c_str());
@@ -299,12 +528,12 @@ BufferProducer::BufferProducer(const std::string& name, int user_id,
299 const int width = static_cast<int>(size); 528 const int width = static_cast<int>(size);
300 const int height = 1; 529 const int height = 1;
301 const int format = HAL_PIXEL_FORMAT_BLOB; 530 const int format = HAL_PIXEL_FORMAT_BLOB;
302 const size_t meta_size_bytes = 0; 531 const size_t user_metadata_size = 0;
303 532
304 // (b/37881101) Deprecate producer/consumer usage 533 // (b/37881101) Deprecate producer/consumer usage
305 auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>( 534 auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
306 name, user_id, group_id, width, height, format, 535 name, user_id, group_id, width, height, format,
307 (producer_usage | consumer_usage), meta_size_bytes); 536 (producer_usage | consumer_usage), user_metadata_size);
308 if (!status) { 537 if (!status) {
309 ALOGE( 538 ALOGE(
310 "BufferProducer::BufferProducer: Failed to create persistent " 539 "BufferProducer::BufferProducer: Failed to create persistent "
@@ -360,28 +589,141 @@ BufferProducer::BufferProducer(LocalChannelHandle channel)
360 } 589 }
361} 590}
362 591
592int BufferProducer::LocalPost(const DvrNativeBufferMetadata* meta,
593 const LocalHandle& ready_fence) {
594 if (const int error = CheckMetadata(meta->user_metadata_size))
595 return error;
596
597 // Check invalid state transition.
598 uint64_t buffer_state = buffer_state_->load();
599 if (!BufferHubDefs::IsBufferGained(buffer_state)) {
600 ALOGE("BufferProducer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
601 id(), buffer_state);
602 return -EBUSY;
603 }
604
605 // Copy the canonical metadata.
606 void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
607 memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata));
608 // Copy extra user requested metadata.
609 if (meta->user_metadata_ptr && meta->user_metadata_size) {
610 void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
611 memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
612 }
613
614 // Send out the acquire fence through the shared epoll fd. Note that during
615 // posting no consumer is not expected to be polling on the fence.
616 if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_))
617 return error;
618
619 // Set the producer bit atomically to transit into posted state.
620 BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
621 BufferHubDefs::kProducerStateBit);
622 return 0;
623}
624
363int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta, 625int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
364 size_t meta_size_bytes) { 626 size_t user_metadata_size) {
365 ATRACE_NAME("BufferProducer::Post"); 627 ATRACE_NAME("BufferProducer::Post");
628
629 // Populate cononical metadata for posting.
630 DvrNativeBufferMetadata canonical_meta;
631 canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
632 canonical_meta.user_metadata_size = user_metadata_size;
633
634 if (const int error = LocalPost(&canonical_meta, ready_fence))
635 return error;
636
366 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>( 637 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
367 BorrowedFence(ready_fence.Borrow()), WrapBuffer(meta, meta_size_bytes))); 638 BorrowedFence(ready_fence.Borrow())));
639}
640
641int BufferProducer::PostAsync(const DvrNativeBufferMetadata* meta,
642 const LocalHandle& ready_fence) {
643 ATRACE_NAME("BufferProducer::PostAsync");
644
645 if (const int error = LocalPost(meta, ready_fence))
646 return error;
647
648 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
649}
650
651int BufferProducer::LocalGain(DvrNativeBufferMetadata* out_meta,
652 LocalHandle* out_fence) {
653 uint64_t buffer_state = buffer_state_->load();
654 ALOGD_IF(TRACE, "BufferProducer::LocalGain: buffer=%d, state=%" PRIx64 ".",
655 id(), buffer_state);
656
657 if (!out_meta)
658 return -EINVAL;
659
660 if (!BufferHubDefs::IsBufferReleased(buffer_state)) {
661 if (BufferHubDefs::IsBufferGained(buffer_state)) {
662 // We don't want to log error when gaining a newly allocated
663 // buffer.
664 ALOGI("BufferProducer::LocalGain: already gained id=%d.", id());
665 return -EALREADY;
666 }
667 ALOGE("BufferProducer::LocalGain: not released id=%d state=%" PRIx64 ".",
668 id(), buffer_state);
669 return -EBUSY;
670 }
671
672 // Canonical metadata is undefined on Gain. Except for user_metadata and
673 // release_fence_mask. Fill in the user_metadata_ptr in address space of the
674 // local process.
675 if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
676 out_meta->user_metadata_size =
677 metadata_header_->metadata.user_metadata_size;
678 out_meta->user_metadata_ptr =
679 reinterpret_cast<uint64_t>(user_metadata_ptr_);
680 } else {
681 out_meta->user_metadata_size = 0;
682 out_meta->user_metadata_ptr = 0;
683 }
684
685 uint64_t fence_state = fence_state_->load();
686 // If there is an release fence from consumer, we need to return it.
687 if (fence_state & BufferHubDefs::kConsumerStateMask) {
688 *out_fence = shared_release_fence_.Duplicate();
689 out_meta->release_fence_mask =
690 fence_state & BufferHubDefs::kConsumerStateMask;
691 }
692
693 // Clear out all bits and the buffer is now back to gained state.
694 buffer_state_->store(0ULL);
695 return 0;
368} 696}
369 697
370int BufferProducer::Gain(LocalHandle* release_fence) { 698int BufferProducer::Gain(LocalHandle* release_fence) {
371 ATRACE_NAME("BufferProducer::Gain"); 699 ATRACE_NAME("BufferProducer::Gain");
700
701 DvrNativeBufferMetadata meta;
702 if (const int error = LocalGain(&meta, release_fence))
703 return error;
704
372 auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>(); 705 auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
373 if (!status) 706 if (!status)
374 return -status.error(); 707 return -status.error();
375 if (release_fence)
376 *release_fence = status.take().take();
377 return 0; 708 return 0;
378} 709}
379 710
380int BufferProducer::GainAsync() { 711int BufferProducer::GainAsync(DvrNativeBufferMetadata* out_meta,
712 LocalHandle* release_fence) {
381 ATRACE_NAME("BufferProducer::GainAsync"); 713 ATRACE_NAME("BufferProducer::GainAsync");
714
715 if (const int error = LocalGain(out_meta, release_fence))
716 return error;
717
382 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode)); 718 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
383} 719}
384 720
721int BufferProducer::GainAsync() {
722 DvrNativeBufferMetadata meta;
723 LocalHandle fence;
724 return GainAsync(&meta, &fence);
725}
726
385std::unique_ptr<BufferProducer> BufferProducer::Import( 727std::unique_ptr<BufferProducer> BufferProducer::Import(
386 LocalChannelHandle channel) { 728 LocalChannelHandle channel) {
387 ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value()); 729 ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
diff --git a/libs/vr/libbufferhub/bufferhub_tests.cpp b/libs/vr/libbufferhub/bufferhub_tests.cpp
index 1daa5d62d..c4b9a8c88 100644
--- a/libs/vr/libbufferhub/bufferhub_tests.cpp
+++ b/libs/vr/libbufferhub/bufferhub_tests.cpp
@@ -1,5 +1,9 @@
1#include <gtest/gtest.h> 1#include <gtest/gtest.h>
2#include <poll.h>
2#include <private/dvr/buffer_hub_client.h> 3#include <private/dvr/buffer_hub_client.h>
4#include <private/dvr/bufferhub_rpc.h>
5#include <sys/epoll.h>
6#include <sys/eventfd.h>
3 7
4#include <mutex> 8#include <mutex>
5#include <thread> 9#include <thread>
@@ -13,8 +17,10 @@
13 return result; \ 17 return result; \
14 })() 18 })()
15 19
16using android::dvr::BufferProducer;
17using android::dvr::BufferConsumer; 20using android::dvr::BufferConsumer;
21using android::dvr::BufferHubDefs::kConsumerStateMask;
22using android::dvr::BufferHubDefs::kProducerStateBit;
23using android::dvr::BufferProducer;
18using android::pdx::LocalHandle; 24using android::pdx::LocalHandle;
19 25
20const int kWidth = 640; 26const int kWidth = 640;
@@ -37,29 +43,149 @@ TEST_F(LibBufferHubTest, TestBasicUsage) {
37 BufferConsumer::Import(c->CreateConsumer()); 43 BufferConsumer::Import(c->CreateConsumer());
38 ASSERT_TRUE(c2.get() != nullptr); 44 ASSERT_TRUE(c2.get() != nullptr);
39 45
46 // Producer state mask is unique, i.e. 1.
47 EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
48 // Consumer state mask cannot have producer bit on.
49 EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0);
50 // Consumer state mask must be a single, i.e. power of 2.
51 EXPECT_NE(c->buffer_state_bit(), 0);
52 EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0);
53 // Consumer state mask cannot have producer bit on.
54 EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0);
55 // Consumer state mask must be a single, i.e. power of 2.
56 EXPECT_NE(c2->buffer_state_bit(), 0);
57 EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0);
58 // Each consumer should have unique bit.
59 EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0);
60
61 // Initial state: producer not available, consumers not available.
62 EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
63 EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
64 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
65
40 EXPECT_EQ(0, p->Post(LocalHandle(), kContext)); 66 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
41 // Both consumers should be triggered. 67
42 EXPECT_GE(0, RETRY_EINTR(p->Poll(0))); 68 // New state: producer not available, consumers available.
43 EXPECT_LT(0, RETRY_EINTR(c->Poll(10))); 69 EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
44 EXPECT_LT(0, RETRY_EINTR(c2->Poll(10))); 70 EXPECT_EQ(1, RETRY_EINTR(c->Poll(100)));
71 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
45 72
46 uint64_t context; 73 uint64_t context;
47 LocalHandle fence; 74 LocalHandle fence;
48 EXPECT_LE(0, c->Acquire(&fence, &context)); 75 EXPECT_EQ(0, c->Acquire(&fence, &context));
49 EXPECT_EQ(kContext, context); 76 EXPECT_EQ(kContext, context);
50 EXPECT_GE(0, RETRY_EINTR(c->Poll(0))); 77 EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
78 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
51 79
52 EXPECT_LE(0, c2->Acquire(&fence, &context)); 80 EXPECT_EQ(0, c2->Acquire(&fence, &context));
53 EXPECT_EQ(kContext, context); 81 EXPECT_EQ(kContext, context);
54 EXPECT_GE(0, RETRY_EINTR(c2->Poll(0))); 82 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
83 EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
55 84
56 EXPECT_EQ(0, c->Release(LocalHandle())); 85 EXPECT_EQ(0, c->Release(LocalHandle()));
57 EXPECT_GE(0, RETRY_EINTR(p->Poll(0))); 86 EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
58 EXPECT_EQ(0, c2->Discard()); 87 EXPECT_EQ(0, c2->Discard());
59 88
60 EXPECT_LE(0, RETRY_EINTR(p->Poll(0))); 89 EXPECT_EQ(1, RETRY_EINTR(p->Poll(100)));
61 EXPECT_EQ(0, p->Gain(&fence)); 90 EXPECT_EQ(0, p->Gain(&fence));
62 EXPECT_GE(0, RETRY_EINTR(p->Poll(0))); 91 EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
92 EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
93 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
94}
95
96TEST_F(LibBufferHubTest, TestEpoll) {
97 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
98 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
99 ASSERT_TRUE(p.get() != nullptr);
100 std::unique_ptr<BufferConsumer> c =
101 BufferConsumer::Import(p->CreateConsumer());
102 ASSERT_TRUE(c.get() != nullptr);
103
104 LocalHandle epoll_fd{epoll_create1(EPOLL_CLOEXEC)};
105 ASSERT_TRUE(epoll_fd.IsValid());
106
107 epoll_event event;
108 std::array<epoll_event, 64> events;
109
110 auto event_sources = p->GetEventSources();
111 ASSERT_LT(event_sources.size(), events.size());
112
113 for (const auto& event_source : event_sources) {
114 event = {.events = event_source.event_mask | EPOLLET,
115 .data = {.fd = p->event_fd()}};
116 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
117 &event));
118 }
119
120 event_sources = c->GetEventSources();
121 ASSERT_LT(event_sources.size(), events.size());
122
123 for (const auto& event_source : event_sources) {
124 event = {.events = event_source.event_mask | EPOLLET,
125 .data = {.fd = c->event_fd()}};
126 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
127 &event));
128 }
129
130 // No events should be signaled initially.
131 ASSERT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 0));
132
133 // Post the producer and check for consumer signal.
134 EXPECT_EQ(0, p->Post({}, kContext));
135 ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
136 ASSERT_TRUE(events[0].events & EPOLLIN);
137 ASSERT_EQ(c->event_fd(), events[0].data.fd);
138
139 // Save the event bits to translate later.
140 event = events[0];
141
142 // Check for events again. Edge-triggered mode should prevent any.
143 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
144 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
145 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
146 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
147
148 // Translate the events.
149 auto event_status = c->GetEventMask(event.events);
150 ASSERT_TRUE(event_status);
151 ASSERT_TRUE(event_status.get() & EPOLLIN);
152
153 // Check for events again. Edge-triggered mode should prevent any.
154 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
155}
156
157TEST_F(LibBufferHubTest, TestStateMask) {
158 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
159 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
160 ASSERT_TRUE(p.get() != nullptr);
161
162 // It's ok to create up to 63 consumer buffers.
163 uint64_t buffer_state_bits = p->buffer_state_bit();
164 std::array<std::unique_ptr<BufferConsumer>, 63> cs;
165 for (size_t i = 0; i < 63; i++) {
166 cs[i] = BufferConsumer::Import(p->CreateConsumer());
167 ASSERT_TRUE(cs[i].get() != nullptr);
168 // Expect all buffers have unique state mask.
169 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
170 buffer_state_bits |= cs[i]->buffer_state_bit();
171 }
172 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
173
174 // The 64th creation will fail with out-of-memory error.
175 auto state = p->CreateConsumer();
176 EXPECT_EQ(state.error(), E2BIG);
177
178 // Release any consumer should allow us to re-create.
179 for (size_t i = 0; i < 63; i++) {
180 buffer_state_bits &= ~cs[i]->buffer_state_bit();
181 cs[i] = nullptr;
182 cs[i] = BufferConsumer::Import(p->CreateConsumer());
183 ASSERT_TRUE(cs[i].get() != nullptr);
184 // The released state mask will be reused.
185 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
186 buffer_state_bits |= cs[i]->buffer_state_bit();
187 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
188 }
63} 189}
64 190
65TEST_F(LibBufferHubTest, TestStateTransitions) { 191TEST_F(LibBufferHubTest, TestStateTransitions) {
@@ -98,6 +224,7 @@ TEST_F(LibBufferHubTest, TestStateTransitions) {
98 224
99 // Release in acquired state should succeed. 225 // Release in acquired state should succeed.
100 EXPECT_EQ(0, c->Release(LocalHandle())); 226 EXPECT_EQ(0, c->Release(LocalHandle()));
227 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
101 228
102 // Release, acquire, and post in released state should fail. 229 // Release, acquire, and post in released state should fail.
103 EXPECT_EQ(-EBUSY, c->Release(LocalHandle())); 230 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
@@ -144,6 +271,11 @@ TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
144 int64_t field1; 271 int64_t field1;
145 int64_t field2; 272 int64_t field2;
146 }; 273 };
274 struct OverSizedMetadata {
275 int64_t field1;
276 int64_t field2;
277 int64_t field3;
278 };
147 std::unique_ptr<BufferProducer> p = BufferProducer::Create( 279 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
148 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata)); 280 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
149 ASSERT_TRUE(p.get() != nullptr); 281 ASSERT_TRUE(p.get() != nullptr);
@@ -151,9 +283,16 @@ TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
151 BufferConsumer::Import(p->CreateConsumer()); 283 BufferConsumer::Import(p->CreateConsumer());
152 ASSERT_TRUE(c.get() != nullptr); 284 ASSERT_TRUE(c.get() != nullptr);
153 285
154 int64_t sequence = 3; 286 // It is illegal to post metadata larger than originally requested during
155 EXPECT_NE(0, p->Post(LocalHandle(), sequence)); 287 // buffer allocation.
288 OverSizedMetadata evil_meta = {};
289 EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
156 EXPECT_GE(0, RETRY_EINTR(c->Poll(10))); 290 EXPECT_GE(0, RETRY_EINTR(c->Poll(10)));
291
292 // It is ok to post metadata smaller than originally requested during
293 // buffer allocation.
294 int64_t sequence = 42;
295 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
157} 296}
158 297
159TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) { 298TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
@@ -161,6 +300,11 @@ TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
161 int64_t field1; 300 int64_t field1;
162 int64_t field2; 301 int64_t field2;
163 }; 302 };
303 struct OverSizedMetadata {
304 int64_t field1;
305 int64_t field2;
306 int64_t field3;
307 };
164 std::unique_ptr<BufferProducer> p = BufferProducer::Create( 308 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
165 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata)); 309 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
166 ASSERT_TRUE(p.get() != nullptr); 310 ASSERT_TRUE(p.get() != nullptr);
@@ -173,7 +317,16 @@ TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
173 317
174 LocalHandle fence; 318 LocalHandle fence;
175 int64_t sequence; 319 int64_t sequence;
176 EXPECT_NE(0, c->Acquire(&fence, &sequence)); 320 OverSizedMetadata e;
321
322 // It is illegal to acquire metadata larger than originally requested during
323 // buffer allocation.
324 EXPECT_NE(0, c->Acquire(&fence, &e));
325
326 // It is ok to acquire metadata smaller than originally requested during
327 // buffer allocation.
328 EXPECT_EQ(0, c->Acquire(&fence, &sequence));
329 EXPECT_EQ(m.field1, sequence);
177} 330}
178 331
179TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) { 332TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
@@ -266,12 +419,140 @@ TEST_F(LibBufferHubTest, TestRemovePersistentBuffer) {
266 LocalHandle fence; 419 LocalHandle fence;
267 auto c = BufferConsumer::Import(p->CreateConsumer()); 420 auto c = BufferConsumer::Import(p->CreateConsumer());
268 ASSERT_NE(nullptr, c); 421 ASSERT_NE(nullptr, c);
269 EXPECT_NE(-EPIPE, c->Acquire(&fence)); 422 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
423 EXPECT_EQ(0, c->Acquire(&fence));
424 EXPECT_EQ(0, c->Release(LocalHandle()));
425 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
270 426
271 // Test that removing persistence and closing the producer orphans the 427 // Test that removing persistence and closing the producer orphans the
272 // consumer. 428 // consumer.
429 EXPECT_EQ(0, p->Gain(&fence));
430 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
273 EXPECT_EQ(0, p->RemovePersistence()); 431 EXPECT_EQ(0, p->RemovePersistence());
274 p = nullptr; 432 p = nullptr;
275 433
434 // Orphaned consumer can acquire the posted buffer one more time in
435 // asynchronous manner. But synchronous call will fail.
436 DvrNativeBufferMetadata meta;
437 EXPECT_EQ(0, c->AcquireAsync(&meta, &fence));
276 EXPECT_EQ(-EPIPE, c->Release(LocalHandle())); 438 EXPECT_EQ(-EPIPE, c->Release(LocalHandle()));
277} 439}
440
441namespace {
442
443int PollFd(int fd, int timeout_ms) {
444 pollfd p = {fd, POLLIN, 0};
445 return poll(&p, 1, timeout_ms);
446}
447
448} // namespace
449
450TEST_F(LibBufferHubTest, TestAcquireFence) {
451 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
452 kWidth, kHeight, kFormat, kUsage, /*metadata_size=*/0);
453 ASSERT_TRUE(p.get() != nullptr);
454 std::unique_ptr<BufferConsumer> c =
455 BufferConsumer::Import(p->CreateConsumer());
456 ASSERT_TRUE(c.get() != nullptr);
457
458 DvrNativeBufferMetadata meta;
459 LocalHandle f1(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
460
461 // Post with unsignaled fence.
462 EXPECT_EQ(0, p->PostAsync(&meta, f1));
463
464 // Should acquire a valid fence.
465 LocalHandle f2;
466 EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
467 EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
468 EXPECT_TRUE(f2.IsValid());
469 // The original fence and acquired fence should have different fd number.
470 EXPECT_NE(f1.Get(), f2.Get());
471 EXPECT_GE(0, PollFd(f2.Get(), 0));
472
473 // Signal the original fence will trigger the new fence.
474 eventfd_write(f1.Get(), 1);
475 // Now the original FD has been signaled.
476 EXPECT_LT(0, PollFd(f2.Get(), 10));
477
478 // Release the consumer with an invalid fence.
479 EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
480
481 // Should gain an invalid fence.
482 LocalHandle f3;
483 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
484 EXPECT_EQ(0, p->GainAsync(&meta, &f3));
485 EXPECT_FALSE(f3.IsValid());
486
487 // Post with a signaled fence.
488 EXPECT_EQ(0, p->PostAsync(&meta, f1));
489
490 // Should acquire a valid fence and it's already signalled.
491 LocalHandle f4;
492 EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
493 EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
494 EXPECT_TRUE(f4.IsValid());
495 EXPECT_LT(0, PollFd(f4.Get(), 10));
496
497 // Release with an unsignalled fence and signal it immediately after release
498 // without producer gainning.
499 LocalHandle f5(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
500 EXPECT_EQ(0, c->ReleaseAsync(&meta, f5));
501 eventfd_write(f5.Get(), 1);
502
503 // Should gain a valid fence, which is already signaled.
504 LocalHandle f6;
505 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
506 EXPECT_EQ(0, p->GainAsync(&meta, &f6));
507 EXPECT_TRUE(f6.IsValid());
508 EXPECT_LT(0, PollFd(f6.Get(), 10));
509}
510
511TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
512 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
513 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
514 ASSERT_TRUE(p.get() != nullptr);
515 std::unique_ptr<BufferConsumer> c1 =
516 BufferConsumer::Import(p->CreateConsumer());
517 ASSERT_TRUE(c1.get() != nullptr);
518 const uint64_t consumer_state_bit1 = c1->buffer_state_bit();
519
520 DvrNativeBufferMetadata meta;
521 EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
522
523 LocalHandle fence;
524 EXPECT_LT(0, RETRY_EINTR(c1->Poll(10)));
525 EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
526 // Destroy the consumer now will make it orphaned and the buffer is still
527 // acquired.
528 c1 = nullptr;
529 EXPECT_GE(0, RETRY_EINTR(p->Poll(10)));
530
531 std::unique_ptr<BufferConsumer> c2 =
532 BufferConsumer::Import(p->CreateConsumer());
533 ASSERT_TRUE(c2.get() != nullptr);
534 const uint64_t consumer_state_bit2 = c2->buffer_state_bit();
535 EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
536
537 // The new consumer is available for acquire.
538 EXPECT_LT(0, RETRY_EINTR(c2->Poll(10)));
539 EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
540 // Releasing the consumer makes the buffer gainable.
541 EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
542
543 // The buffer is now available for the producer to gain.
544 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
545
546 // But if another consumer is created in released state.
547 std::unique_ptr<BufferConsumer> c3 =
548 BufferConsumer::Import(p->CreateConsumer());
549 ASSERT_TRUE(c3.get() != nullptr);
550 const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
551 EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
552 // The consumer buffer is not acquirable.
553 EXPECT_GE(0, RETRY_EINTR(c3->Poll(10)));
554 EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
555
556 // Producer should be able to gain no matter what.
557 EXPECT_EQ(0, p->GainAsync(&meta, &fence));
558}
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index be20e72a8..1186f9348 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -11,6 +11,8 @@
11 11
12#include <private/dvr/ion_buffer.h> 12#include <private/dvr/ion_buffer.h>
13 13
14#include "bufferhub_rpc.h"
15
14namespace android { 16namespace android {
15namespace dvr { 17namespace dvr {
16 18
@@ -75,6 +77,14 @@ class BufferHubBuffer : public pdx::Client {
75 } 77 }
76 } 78 }
77 79
80 std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
81 if (auto* client_channel = GetChannel()) {
82 return client_channel->GetEventSources();
83 } else {
84 return {};
85 }
86 }
87
78 native_handle_t* native_handle() const { 88 native_handle_t* native_handle() const {
79 return const_cast<native_handle_t*>(buffer_.handle()); 89 return const_cast<native_handle_t*>(buffer_.handle());
80 } 90 }
@@ -84,6 +94,10 @@ class BufferHubBuffer : public pdx::Client {
84 94
85 int id() const { return id_; } 95 int id() const { return id_; }
86 96
97 // A state mask which is unique to a buffer hub client among all its siblings
98 // sharing the same concrete graphic buffer.
99 uint64_t buffer_state_bit() const { return buffer_state_bit_; }
100
87 // The following methods return settings of the first buffer. Currently, 101 // The following methods return settings of the first buffer. Currently,
88 // it is only possible to create multi-buffer BufferHubBuffers with the same 102 // it is only possible to create multi-buffer BufferHubBuffers with the same
89 // settings. 103 // settings.
@@ -98,6 +112,9 @@ class BufferHubBuffer : public pdx::Client {
98 uint64_t producer_usage() const { return buffer_.usage(); } 112 uint64_t producer_usage() const { return buffer_.usage(); }
99 uint64_t consumer_usage() const { return buffer_.usage(); } 113 uint64_t consumer_usage() const { return buffer_.usage(); }
100 114
115 uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
116 void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
117
101 protected: 118 protected:
102 explicit BufferHubBuffer(LocalChannelHandle channel); 119 explicit BufferHubBuffer(LocalChannelHandle channel);
103 explicit BufferHubBuffer(const std::string& endpoint_path); 120 explicit BufferHubBuffer(const std::string& endpoint_path);
@@ -106,6 +123,31 @@ class BufferHubBuffer : public pdx::Client {
106 // Initialization helper. 123 // Initialization helper.
107 int ImportBuffer(); 124 int ImportBuffer();
108 125
126 // Check invalid metadata operation. Returns 0 if requested metadata is valid.
127 int CheckMetadata(size_t user_metadata_size) const;
128
129 // Send out the new fence by updating the shared fence (shared_release_fence
130 // for producer and shared_acquire_fence for consumer). Note that during this
131 // should only be used in LocalPost() or LocalRelease, and the shared fence
132 // shouldn't be poll'ed by the other end.
133 int UpdateSharedFence(const LocalHandle& new_fence,
134 const LocalHandle& shared_fence);
135
136 // IonBuffer that is shared between bufferhubd, producer, and consumers.
137 size_t metadata_buf_size_{0};
138 size_t user_metadata_size_{0};
139 BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
140 void* user_metadata_ptr_{nullptr};
141 std::atomic<uint64_t>* buffer_state_{nullptr};
142 std::atomic<uint64_t>* fence_state_{nullptr};
143
144 LocalHandle shared_acquire_fence_;
145 LocalHandle shared_release_fence_;
146
147 // A local fence fd that holds the ownership of the fence fd on Post (for
148 // producer) and Release (for consumer).
149 LocalHandle pending_fence_fd_;
150
109 private: 151 private:
110 BufferHubBuffer(const BufferHubBuffer&) = delete; 152 BufferHubBuffer(const BufferHubBuffer&) = delete;
111 void operator=(const BufferHubBuffer&) = delete; 153 void operator=(const BufferHubBuffer&) = delete;
@@ -114,8 +156,9 @@ class BufferHubBuffer : public pdx::Client {
114 // for logging and debugging purposes only and should not be used for lookup 156 // for logging and debugging purposes only and should not be used for lookup
115 // or any other functional purpose as a security precaution. 157 // or any other functional purpose as a security precaution.
116 int id_; 158 int id_;
117 159 uint64_t buffer_state_bit_{0ULL};
118 IonBuffer buffer_; 160 IonBuffer buffer_;
161 IonBuffer metadata_buffer_;
119}; 162};
120 163
121// This represents a writable buffer. Calling Post notifies all clients and 164// This represents a writable buffer. Calling Post notifies all clients and
@@ -136,12 +179,17 @@ class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
136 static std::unique_ptr<BufferProducer> Import( 179 static std::unique_ptr<BufferProducer> Import(
137 Status<LocalChannelHandle> status); 180 Status<LocalChannelHandle> status);
138 181
182 // Asynchronously posts a buffer. The fence and metadata are passed to
183 // consumer via shared fd and shared memory.
184 int PostAsync(const DvrNativeBufferMetadata* meta,
185 const LocalHandle& ready_fence);
186
139 // Post this buffer, passing |ready_fence| to the consumers. The bytes in 187 // Post this buffer, passing |ready_fence| to the consumers. The bytes in
140 // |meta| are passed unaltered to the consumers. The producer must not modify 188 // |meta| are passed unaltered to the consumers. The producer must not modify
141 // the buffer until it is re-gained. 189 // the buffer until it is re-gained.
142 // This returns zero or a negative unix error code. 190 // This returns zero or a negative unix error code.
143 int Post(const LocalHandle& ready_fence, const void* meta, 191 int Post(const LocalHandle& ready_fence, const void* meta,
144 size_t meta_size_bytes); 192 size_t user_metadata_size);
145 193
146 template <typename Meta, 194 template <typename Meta,
147 typename = typename std::enable_if<std::is_void<Meta>::value>::type> 195 typename = typename std::enable_if<std::is_void<Meta>::value>::type>
@@ -160,16 +208,15 @@ class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
160 // is in the released state. 208 // is in the released state.
161 // This returns zero or a negative unix error code. 209 // This returns zero or a negative unix error code.
162 int Gain(LocalHandle* release_fence); 210 int Gain(LocalHandle* release_fence);
211 int GainAsync();
163 212
164 // Asynchronously marks a released buffer as gained. This method is similar to 213 // Asynchronously marks a released buffer as gained. This method is similar to
165 // the synchronous version above, except that it does not wait for BufferHub 214 // the synchronous version above, except that it does not wait for BufferHub
166 // to acknowledge success or failure, nor does it transfer a release fence to 215 // to acknowledge success or failure. Because of the asynchronous nature of
167 // the client. This version may be used in situations where a release fence is 216 // the underlying message, no error is returned if this method is called when
168 // not needed. Because of the asynchronous nature of the underlying message, 217 // the buffer is in an incorrect state. Returns zero if sending the message
169 // no error is returned if this method is called when the buffer is in an 218 // succeeded, or a negative errno code if local error check fails.
170 // incorrect state. Returns zero if sending the message succeeded, or a 219 int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
171 // negative errno code otherwise.
172 int GainAsync();
173 220
174 // Attaches the producer to |name| so that it becomes a persistent buffer that 221 // Attaches the producer to |name| so that it becomes a persistent buffer that
175 // may be retrieved by name at a later time. This may be used in cases where a 222 // may be retrieved by name at a later time. This may be used in cases where a
@@ -216,7 +263,7 @@ class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
216 BufferProducer(const std::string& name, int user_id, int group_id, 263 BufferProducer(const std::string& name, int user_id, int group_id,
217 uint32_t width, uint32_t height, uint32_t format, 264 uint32_t width, uint32_t height, uint32_t format,
218 uint64_t producer_usage, uint64_t consumer_usage, 265 uint64_t producer_usage, uint64_t consumer_usage,
219 size_t meta_size_bytes); 266 size_t user_metadata_size);
220 267
221 // Constructs a blob (flat) buffer with the given usage flags. 268 // Constructs a blob (flat) buffer with the given usage flags.
222 BufferProducer(uint32_t usage, size_t size); 269 BufferProducer(uint32_t usage, size_t size);
@@ -234,6 +281,11 @@ class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
234 281
235 // Imports the given file handle to a producer channel, taking ownership. 282 // Imports the given file handle to a producer channel, taking ownership.
236 explicit BufferProducer(LocalChannelHandle channel); 283 explicit BufferProducer(LocalChannelHandle channel);
284
285 // Local state transition helpers.
286 int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
287 int LocalPost(const DvrNativeBufferMetadata* meta,
288 const LocalHandle& ready_fence);
237}; 289};
238 290
239// This is a connection to a producer buffer, which can be located in another 291// This is a connection to a producer buffer, which can be located in another
@@ -263,7 +315,7 @@ class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
263 // are available. This call will only succeed if the buffer is in the posted 315 // are available. This call will only succeed if the buffer is in the posted
264 // state. 316 // state.
265 // Returns zero on success, or a negative errno code otherwise. 317 // Returns zero on success, or a negative errno code otherwise.
266 int Acquire(LocalHandle* ready_fence, void* meta, size_t meta_size_bytes); 318 int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
267 319
268 // Attempt to retrieve a post event from buffer hub. If successful, 320 // Attempt to retrieve a post event from buffer hub. If successful,
269 // |ready_fence| is set to a fence to wait on until the buffer is ready. This 321 // |ready_fence| is set to a fence to wait on until the buffer is ready. This
@@ -274,20 +326,22 @@ class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
274 return Acquire(ready_fence, meta, sizeof(*meta)); 326 return Acquire(ready_fence, meta, sizeof(*meta));
275 } 327 }
276 328
329 // Asynchronously acquires a bufer.
330 int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
331
277 // This should be called after a successful Acquire call. If the fence is 332 // This should be called after a successful Acquire call. If the fence is
278 // valid the fence determines the buffer usage, otherwise the buffer is 333 // valid the fence determines the buffer usage, otherwise the buffer is
279 // released immediately. 334 // released immediately.
280 // This returns zero or a negative unix error code. 335 // This returns zero or a negative unix error code.
281 int Release(const LocalHandle& release_fence); 336 int Release(const LocalHandle& release_fence);
337 int ReleaseAsync();
282 338
283 // Asynchronously releases a buffer. Similar to the synchronous version above, 339 // Asynchronously releases a buffer. Similar to the synchronous version above,
284 // except that it does not wait for BufferHub to reply with success or error, 340 // except that it does not wait for BufferHub to reply with success or error.
285 // nor does it transfer a release fence. This version may be used in 341 // The fence and metadata are passed to consumer via shared fd and shared
286 // situations where a release fence is not needed. Because of the asynchronous 342 // memory.
287 // nature of the underlying message, no error is returned if this method is 343 int ReleaseAsync(const DvrNativeBufferMetadata* meta,
288 // called when the buffer is in an incorrect state. Returns zero if sending 344 const LocalHandle& release_fence);
289 // the message succeeded, or a negative errno code otherwise.
290 int ReleaseAsync();
291 345
292 // May be called after or instead of Acquire to indicate that the consumer 346 // May be called after or instead of Acquire to indicate that the consumer
293 // does not need to access the buffer this cycle. This returns zero or a 347 // does not need to access the buffer this cycle. This returns zero or a
@@ -305,6 +359,11 @@ class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
305 friend BASE; 359 friend BASE;
306 360
307 explicit BufferConsumer(LocalChannelHandle channel); 361 explicit BufferConsumer(LocalChannelHandle channel);
362
363 // Local state transition helpers.
364 int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
365 int LocalRelease(const DvrNativeBufferMetadata* meta,
366 const LocalHandle& release_fence);
308}; 367};
309 368
310} // namespace dvr 369} // namespace dvr
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index ca0e0e082..f9fd42d7b 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -5,6 +5,7 @@
5#include <gui/BufferQueueDefs.h> 5#include <gui/BufferQueueDefs.h>
6#include <sys/types.h> 6#include <sys/types.h>
7 7
8#include <dvr/dvr_api.h>
8#include <pdx/channel_handle.h> 9#include <pdx/channel_handle.h>
9#include <pdx/file_handle.h> 10#include <pdx/file_handle.h>
10#include <pdx/rpc/remote_method.h> 11#include <pdx/rpc/remote_method.h>
@@ -14,6 +15,71 @@
14namespace android { 15namespace android {
15namespace dvr { 16namespace dvr {
16 17
18namespace BufferHubDefs {
19
20static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB;
21static constexpr uint32_t kMetadataUsage =
22 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
23
24// Single producuer multiple (up to 63) consumers ownership signal.
25// 64-bit atomic unsigned int.
26//
27// MSB LSB
28// | |
29// v v
30// [P|C62|...|C1|C0]
31// Gain'ed state: [0|..|0|0] -> Exclusively Writable.
32// Post'ed state: [1|..|0|0]
33// Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits
34// Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits
35static constexpr uint64_t kProducerStateBit = 1ULL << 63;
36static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1;
37
38static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state,
39 uint64_t clear_mask, uint64_t set_mask) {
40 uint64_t old_state;
41 uint64_t new_state;
42 do {
43 old_state = buffer_state->load();
44 new_state = (old_state & ~clear_mask) | set_mask;
45 } while (!buffer_state->compare_exchange_weak(old_state, new_state));
46}
47
48static inline bool IsBufferGained(uint64_t state) { return state == 0; }
49
50static inline bool IsBufferPosted(uint64_t state,
51 uint64_t consumer_bit = kConsumerStateMask) {
52 return (state & kProducerStateBit) && !(state & consumer_bit);
53}
54
55static inline bool IsBufferAcquired(uint64_t state) {
56 return (state & kProducerStateBit) && (state & kConsumerStateMask);
57}
58
59static inline bool IsBufferReleased(uint64_t state) {
60 return !(state & kProducerStateBit) && (state & kConsumerStateMask);
61}
62
63struct __attribute__((packed, aligned(8))) MetadataHeader {
64 // Internal data format, which can be updated as long as the size, padding and
65 // field alignment of the struct is consistent within the same ABI. As this
66 // part is subject for future updates, it's not stable cross Android version,
67 // so don't have it visible from outside of the Android platform (include Apps
68 // and vendor HAL).
69 std::atomic<uint64_t> buffer_state;
70 std::atomic<uint64_t> fence_state;
71 uint64_t queue_index;
72
73 // Public data format, which should be updated with caution. See more details
74 // in dvr_api.h
75 DvrNativeBufferMetadata metadata;
76};
77
78static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size");
79static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader);
80
81} // namespace BufferHubDefs
82
17template <typename FileHandleType> 83template <typename FileHandleType>
18class NativeBufferHandle { 84class NativeBufferHandle {
19 public: 85 public:
@@ -93,6 +159,57 @@ class NativeBufferHandle {
93 void operator=(const NativeBufferHandle&) = delete; 159 void operator=(const NativeBufferHandle&) = delete;
94}; 160};
95 161
162template <typename FileHandleType>
163class BufferDescription {
164 public:
165 BufferDescription() = default;
166 BufferDescription(const IonBuffer& buffer, const IonBuffer& metadata, int id,
167 uint64_t buffer_state_bit,
168 const FileHandleType& acquire_fence_fd,
169 const FileHandleType& release_fence_fd)
170 : id_(id),
171 buffer_state_bit_(buffer_state_bit),
172 buffer_(buffer, id),
173 metadata_(metadata, id),
174 acquire_fence_fd_(acquire_fence_fd.Borrow()),
175 release_fence_fd_(release_fence_fd.Borrow()) {}
176
177 BufferDescription(BufferDescription&& other) = default;
178 BufferDescription& operator=(BufferDescription&& other) = default;
179
180 // ID of the buffer client. All BufferHubBuffer clients derived from the same
181 // buffer in bufferhubd share the same buffer id.
182 int id() const { return id_; }
183 // State mask of the buffer client. Each BufferHubBuffer client backed by the
184 // same buffer channel has uniqued state bit among its siblings. For a
185 // producer buffer the bit must be kProducerStateBit; for a consumer the bit
186 // must be one of the kConsumerStateMask.
187 uint64_t buffer_state_bit() const { return buffer_state_bit_; }
188 FileHandleType take_acquire_fence() { return std::move(acquire_fence_fd_); }
189 FileHandleType take_release_fence() { return std::move(release_fence_fd_); }
190
191 int ImportBuffer(IonBuffer* buffer) { return buffer_.Import(buffer); }
192 int ImportMetadata(IonBuffer* metadata) { return metadata_.Import(metadata); }
193
194 private:
195 int id_{-1};
196 uint64_t buffer_state_bit_{0};
197 // Two IonBuffers: one for the graphic buffer and one for metadata.
198 NativeBufferHandle<FileHandleType> buffer_;
199 NativeBufferHandle<FileHandleType> metadata_;
200
201 // Pamameters for shared fences.
202 FileHandleType acquire_fence_fd_;
203 FileHandleType release_fence_fd_;
204
205 PDX_SERIALIZABLE_MEMBERS(BufferDescription<FileHandleType>, id_,
206 buffer_state_bit_, buffer_, metadata_,
207 acquire_fence_fd_, release_fence_fd_);
208
209 BufferDescription(const BufferDescription&) = delete;
210 void operator=(const BufferDescription&) = delete;
211};
212
96using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>; 213using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>;
97using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>; 214using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>;
98 215
@@ -149,11 +266,11 @@ struct ProducerQueueConfig {
149 266
150 // Size of the meta data associated with all the buffers allocated from the 267 // Size of the meta data associated with all the buffers allocated from the
151 // queue. 268 // queue.
152 size_t meta_size_bytes; 269 size_t user_metadata_size;
153 270
154 private: 271 private:
155 PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, is_async, default_width, 272 PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, is_async, default_width,
156 default_height, default_format, meta_size_bytes); 273 default_height, default_format, user_metadata_size);
157}; 274};
158 275
159class ProducerQueueConfigBuilder { 276class ProducerQueueConfigBuilder {
@@ -161,7 +278,7 @@ class ProducerQueueConfigBuilder {
161 // Build a ProducerQueueConfig object. 278 // Build a ProducerQueueConfig object.
162 ProducerQueueConfig Build() { 279 ProducerQueueConfig Build() {
163 return {is_async_, default_width_, default_height_, default_format_, 280 return {is_async_, default_width_, default_height_, default_format_,
164 meta_size_bytes_}; 281 user_metadata_size_};
165 } 282 }
166 283
167 ProducerQueueConfigBuilder& SetIsAsync(bool is_async) { 284 ProducerQueueConfigBuilder& SetIsAsync(bool is_async) {
@@ -186,12 +303,12 @@ class ProducerQueueConfigBuilder {
186 303
187 template <typename Meta> 304 template <typename Meta>
188 ProducerQueueConfigBuilder& SetMetadata() { 305 ProducerQueueConfigBuilder& SetMetadata() {
189 meta_size_bytes_ = sizeof(Meta); 306 user_metadata_size_ = sizeof(Meta);
190 return *this; 307 return *this;
191 } 308 }
192 309
193 ProducerQueueConfigBuilder& SetMetadataSize(size_t meta_size_bytes) { 310 ProducerQueueConfigBuilder& SetMetadataSize(size_t user_metadata_size) {
194 meta_size_bytes_ = meta_size_bytes; 311 user_metadata_size_ = user_metadata_size;
195 return *this; 312 return *this;
196 } 313 }
197 314
@@ -200,7 +317,7 @@ class ProducerQueueConfigBuilder {
200 uint32_t default_width_{1}; 317 uint32_t default_width_{1};
201 uint32_t default_height_{1}; 318 uint32_t default_height_{1};
202 uint32_t default_format_{1}; // PIXEL_FORMAT_RGBA_8888 319 uint32_t default_format_{1}; // PIXEL_FORMAT_RGBA_8888
203 size_t meta_size_bytes_{0}; 320 size_t user_metadata_size_{0};
204}; 321};
205 322
206// Explicit specializations of ProducerQueueConfigBuilder::Build for void 323// Explicit specializations of ProducerQueueConfigBuilder::Build for void
@@ -208,7 +325,7 @@ class ProducerQueueConfigBuilder {
208template <> 325template <>
209inline ProducerQueueConfigBuilder& 326inline ProducerQueueConfigBuilder&
210ProducerQueueConfigBuilder::SetMetadata<void>() { 327ProducerQueueConfigBuilder::SetMetadata<void>() {
211 meta_size_bytes_ = 0; 328 user_metadata_size_ = 0;
212 return *this; 329 return *this;
213} 330}
214 331
@@ -269,7 +386,6 @@ struct BufferHubRPC {
269 }; 386 };
270 387
271 // Aliases. 388 // Aliases.
272 using MetaData = pdx::rpc::BufferWrapper<std::uint8_t*>;
273 using LocalChannelHandle = pdx::LocalChannelHandle; 389 using LocalChannelHandle = pdx::LocalChannelHandle;
274 using LocalHandle = pdx::LocalHandle; 390 using LocalHandle = pdx::LocalHandle;
275 using Void = pdx::rpc::Void; 391 using Void = pdx::rpc::Void;
@@ -277,25 +393,24 @@ struct BufferHubRPC {
277 // Methods. 393 // Methods.
278 PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer, 394 PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
279 void(uint32_t width, uint32_t height, uint32_t format, 395 void(uint32_t width, uint32_t height, uint32_t format,
280 uint64_t usage, size_t meta_size_bytes)); 396 uint64_t usage, size_t user_metadata_size));
281 PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer, 397 PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
282 void(const std::string& name, int user_id, int group_id, 398 void(const std::string& name, int user_id, int group_id,
283 uint32_t width, uint32_t height, uint32_t format, 399 uint32_t width, uint32_t height, uint32_t format,
284 uint64_t usage, size_t meta_size_bytes)); 400 uint64_t usage, size_t user_metadata_size));
285 PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer, 401 PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
286 void(const std::string& name)); 402 void(const std::string& name));
287 PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer, 403 PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
288 NativeBufferHandle<LocalHandle>(Void)); 404 BufferDescription<LocalHandle>(Void));
289 PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void)); 405 PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
290 PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent, 406 PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
291 void(const std::string& name, int user_id, int group_id)); 407 void(const std::string& name, int user_id, int group_id));
292 PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence, 408 PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence,
293 void(Void)); 409 void(Void));
294 PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost, 410 PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
295 void(LocalFence acquire_fence, MetaData)); 411 void(LocalFence acquire_fence));
296 PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void)); 412 PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
297 PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire, 413 PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire, LocalFence(Void));
298 std::pair<LocalFence, MetaData>(std::size_t metadata_size));
299 PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease, 414 PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
300 void(LocalFence release_fence)); 415 void(LocalFence release_fence));
301 PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore)); 416 PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
@@ -305,7 +420,7 @@ struct BufferHubRPC {
305 QueueInfo(const ProducerQueueConfig& producer_config, 420 QueueInfo(const ProducerQueueConfig& producer_config,
306 const UsagePolicy& usage_policy)); 421 const UsagePolicy& usage_policy));
307 PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue, 422 PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
308 LocalChannelHandle(Void)); 423 LocalChannelHandle(bool silent_queue));
309 PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void)); 424 PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void));
310 PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers, 425 PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
311 kOpProducerQueueAllocateBuffers, 426 kOpProducerQueueAllocateBuffers,
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 0b3b2f0fb..93ccd0fda 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -48,6 +48,7 @@ cc_library {
48 cflags: [ 48 cflags: [
49 "-DLOG_TAG=\"libbufferhubqueue\"", 49 "-DLOG_TAG=\"libbufferhubqueue\"",
50 "-DTRACE=0", 50 "-DTRACE=0",
51 "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
51 ], 52 ],
52 srcs: sourceFiles, 53 srcs: sourceFiles,
53 export_include_dirs: includeFiles, 54 export_include_dirs: includeFiles,
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index f9f87ff1b..8bea0cde7 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -10,6 +10,7 @@
10#include <pdx/default_transport/client_channel.h> 10#include <pdx/default_transport/client_channel.h>
11#include <pdx/default_transport/client_channel_factory.h> 11#include <pdx/default_transport/client_channel_factory.h>
12#include <pdx/file_handle.h> 12#include <pdx/file_handle.h>
13#include <pdx/trace.h>
13 14
14#define RETRY_EINTR(fnc_call) \ 15#define RETRY_EINTR(fnc_call) \
15 ([&]() -> decltype(fnc_call) { \ 16 ([&]() -> decltype(fnc_call) { \
@@ -44,17 +45,6 @@ Status<int> PollEvents(int fd, short events) {
44 } 45 }
45} 46}
46 47
47// Polls a buffer for the given events, taking care to do the proper
48// translation.
49Status<int> PollEvents(const std::shared_ptr<BufferHubBuffer>& buffer,
50 short events) {
51 auto poll_status = PollEvents(buffer->event_fd(), events);
52 if (!poll_status)
53 return poll_status;
54
55 return buffer->GetEventMask(poll_status.get());
56}
57
58std::pair<int32_t, int32_t> Unstuff(uint64_t value) { 48std::pair<int32_t, int32_t> Unstuff(uint64_t value) {
59 return {static_cast<int32_t>(value >> 32), 49 return {static_cast<int32_t>(value >> 32),
60 static_cast<int32_t>(value & ((1ull << 32) - 1))}; 50 static_cast<int32_t>(value & ((1ull << 32) - 1))};
@@ -115,27 +105,27 @@ void BufferHubQueue::SetupQueue(const QueueInfo& queue_info) {
115 default_width_ = queue_info.producer_config.default_width; 105 default_width_ = queue_info.producer_config.default_width;
116 default_height_ = queue_info.producer_config.default_height; 106 default_height_ = queue_info.producer_config.default_height;
117 default_format_ = queue_info.producer_config.default_format; 107 default_format_ = queue_info.producer_config.default_format;
118 meta_size_ = queue_info.producer_config.meta_size_bytes; 108 user_metadata_size_ = queue_info.producer_config.user_metadata_size;
119 id_ = queue_info.id; 109 id_ = queue_info.id;
120} 110}
121 111
122std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() { 112std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
123 if (auto status = CreateConsumerQueueHandle()) 113 if (auto status = CreateConsumerQueueHandle(/*silent*/ false))
124 return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take())); 114 return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
125 else 115 else
126 return nullptr; 116 return nullptr;
127} 117}
128 118
129std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateSilentConsumerQueue() { 119std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateSilentConsumerQueue() {
130 if (auto status = CreateConsumerQueueHandle()) 120 if (auto status = CreateConsumerQueueHandle(/*silent*/ true))
131 return std::unique_ptr<ConsumerQueue>( 121 return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
132 new ConsumerQueue(status.take(), true));
133 else 122 else
134 return nullptr; 123 return nullptr;
135} 124}
136 125
137Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle() { 126Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle(
138 auto status = InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>(); 127 bool silent) {
128 auto status = InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>(silent);
139 if (!status) { 129 if (!status) {
140 ALOGE( 130 ALOGE(
141 "BufferHubQueue::CreateConsumerQueue: Failed to create consumer queue: " 131 "BufferHubQueue::CreateConsumerQueue: Failed to create consumer queue: "
@@ -148,6 +138,7 @@ Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle() {
148} 138}
149 139
150bool BufferHubQueue::WaitForBuffers(int timeout) { 140bool BufferHubQueue::WaitForBuffers(int timeout) {
141 ATRACE_NAME("BufferHubQueue::WaitForBuffers");
151 std::array<epoll_event, kMaxEvents> events; 142 std::array<epoll_event, kMaxEvents> events;
152 143
153 // Loop at least once to check for hangups. 144 // Loop at least once to check for hangups.
@@ -178,13 +169,18 @@ bool BufferHubQueue::WaitForBuffers(int timeout) {
178 const int num_events = ret; 169 const int num_events = ret;
179 170
180 // A BufferQueue's epoll fd tracks N+1 events, where there are N events, 171 // A BufferQueue's epoll fd tracks N+1 events, where there are N events,
181 // one for each buffer, in the queue and one extra event for the queue 172 // one for each buffer in the queue, and one extra event for the queue
182 // client itself. 173 // client itself.
183 for (int i = 0; i < num_events; i++) { 174 for (int i = 0; i < num_events; i++) {
184 int32_t event_fd; 175 int32_t event_fd;
185 int32_t index; 176 int32_t index;
186 std::tie(event_fd, index) = Unstuff(events[i].data.u64); 177 std::tie(event_fd, index) = Unstuff(events[i].data.u64);
187 178
179 PDX_TRACE_FORMAT(
180 "epoll_event|queue_id=%d;num_events=%d;event_index=%d;event_fd=%d;"
181 "slot=%d|",
182 id(), num_events, i, event_fd, index);
183
188 ALOGD_IF(TRACE, 184 ALOGD_IF(TRACE,
189 "BufferHubQueue::WaitForBuffers: event %d: event_fd=%d index=%d", 185 "BufferHubQueue::WaitForBuffers: event %d: event_fd=%d index=%d",
190 i, event_fd, index); 186 i, event_fd, index);
@@ -208,6 +204,7 @@ bool BufferHubQueue::WaitForBuffers(int timeout) {
208 204
209Status<void> BufferHubQueue::HandleBufferEvent(size_t slot, int event_fd, 205Status<void> BufferHubQueue::HandleBufferEvent(size_t slot, int event_fd,
210 int poll_events) { 206 int poll_events) {
207 ATRACE_NAME("BufferHubQueue::HandleBufferEvent");
211 if (!buffers_[slot]) { 208 if (!buffers_[slot]) {
212 ALOGW("BufferHubQueue::HandleBufferEvent: Invalid buffer slot: %zu", slot); 209 ALOGW("BufferHubQueue::HandleBufferEvent: Invalid buffer slot: %zu", slot);
213 return ErrorStatus(ENOENT); 210 return ErrorStatus(ENOENT);
@@ -221,58 +218,19 @@ Status<void> BufferHubQueue::HandleBufferEvent(size_t slot, int event_fd,
221 } 218 }
222 219
223 const int events = status.get(); 220 const int events = status.get();
221 PDX_TRACE_FORMAT(
222 "buffer|queue_id=%d;buffer_id=%d;slot=%zu;event_fd=%d;poll_events=%x;"
223 "events=%d|",
224 id(), buffers_[slot]->id(), slot, event_fd, poll_events, events);
225
224 if (events & EPOLLIN) { 226 if (events & EPOLLIN) {
225 auto entry_status = OnBufferReady(buffers_[slot], slot); 227 return Enqueue({buffers_[slot], slot, buffers_[slot]->GetQueueIndex()});
226 if (entry_status.ok() || entry_status.error() == EALREADY) {
227 // Only enqueue the buffer if it moves to or is already in the state
228 // requested in OnBufferReady().
229 return Enqueue(entry_status.take());
230 } else if (entry_status.error() == EBUSY) {
231 // If the buffer is busy this means that the buffer moved from released to
232 // posted when a new consumer was created before the ProducerQueue had a
233 // chance to regain it. This is a valid transition that we have to handle
234 // because edge triggered poll events latch the ready state even if it is
235 // later de-asserted -- don't enqueue or print an error log in this case.
236 } else {
237 ALOGE(
238 "BufferHubQueue::HandleBufferEvent: Failed to set buffer ready, "
239 "queue_id=%d buffer_id=%d: %s",
240 id(), buffers_[slot]->id(), entry_status.GetErrorMessage().c_str());
241 }
242 } else if (events & EPOLLHUP) { 228 } else if (events & EPOLLHUP) {
243 // Check to see if the current buffer in the slot hung up. This is a bit of
244 // paranoia to deal with the epoll set getting out of sync with the buffer
245 // slots.
246 auto poll_status = PollEvents(buffers_[slot], POLLIN);
247 if (!poll_status && poll_status.error() != ETIMEDOUT) {
248 ALOGE("BufferHubQueue::HandleBufferEvent: Failed to poll buffer: %s",
249 poll_status.GetErrorMessage().c_str());
250 return poll_status.error_status();
251 }
252
253 const bool hangup_pending = status.ok() && (poll_status.get() & EPOLLHUP);
254
255 ALOGW( 229 ALOGW(
256 "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP event: slot=%zu " 230 "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP event: slot=%zu "
257 "event_fd=%d buffer_id=%d hangup_pending=%d poll_status=%x", 231 "event_fd=%d buffer_id=%d",
258 slot, buffers_[slot]->event_fd(), buffers_[slot]->id(), hangup_pending, 232 slot, buffers_[slot]->event_fd(), buffers_[slot]->id());
259 poll_status.get()); 233 return RemoveBuffer(slot);
260
261 if (hangup_pending) {
262 return RemoveBuffer(slot);
263 } else {
264 // Clean up the bookkeeping for the event fd. This is a bit of paranoia to
265 // deal with the epoll set getting out of sync with the buffer slots.
266 // Hitting this path should be very unusual.
267 const int ret = epoll_fd_.Control(EPOLL_CTL_DEL, event_fd, nullptr);
268 if (ret < 0) {
269 ALOGE(
270 "BufferHubQueue::HandleBufferEvent: Failed to remove fd=%d from "
271 "epoll set: %s",
272 event_fd, strerror(-ret));
273 return ErrorStatus(-ret);
274 }
275 }
276 } else { 234 } else {
277 ALOGW( 235 ALOGW(
278 "BufferHubQueue::HandleBufferEvent: Unknown event, slot=%zu, epoll " 236 "BufferHubQueue::HandleBufferEvent: Unknown event, slot=%zu, epoll "
@@ -284,6 +242,7 @@ Status<void> BufferHubQueue::HandleBufferEvent(size_t slot, int event_fd,
284} 242}
285 243
286Status<void> BufferHubQueue::HandleQueueEvent(int poll_event) { 244Status<void> BufferHubQueue::HandleQueueEvent(int poll_event) {
245 ATRACE_NAME("BufferHubQueue::HandleQueueEvent");
287 auto status = GetEventMask(poll_event); 246 auto status = GetEventMask(poll_event);
288 if (!status) { 247 if (!status) {
289 ALOGW("BufferHubQueue::HandleQueueEvent: Failed to get event mask: %s", 248 ALOGW("BufferHubQueue::HandleQueueEvent: Failed to get event mask: %s",
@@ -330,13 +289,16 @@ Status<void> BufferHubQueue::AddBuffer(
330 return remove_status.error_status(); 289 return remove_status.error_status();
331 } 290 }
332 291
333 epoll_event event = {.events = EPOLLIN | EPOLLET, 292 for (const auto& event_source : buffer->GetEventSources()) {
334 .data = {.u64 = Stuff(buffer->event_fd(), slot)}}; 293 epoll_event event = {.events = event_source.event_mask | EPOLLET,
335 const int ret = epoll_fd_.Control(EPOLL_CTL_ADD, buffer->event_fd(), &event); 294 .data = {.u64 = Stuff(buffer->event_fd(), slot)}};
336 if (ret < 0) { 295 const int ret =
337 ALOGE("BufferHubQueue::AddBuffer: Failed to add buffer to epoll set: %s", 296 epoll_fd_.Control(EPOLL_CTL_ADD, event_source.event_fd, &event);
338 strerror(-ret)); 297 if (ret < 0) {
339 return ErrorStatus(-ret); 298 ALOGE("BufferHubQueue::AddBuffer: Failed to add buffer to epoll set: %s",
299 strerror(-ret));
300 return ErrorStatus(-ret);
301 }
340 } 302 }
341 303
342 buffers_[slot] = buffer; 304 buffers_[slot] = buffer;
@@ -348,15 +310,16 @@ Status<void> BufferHubQueue::RemoveBuffer(size_t slot) {
348 ALOGD_IF(TRACE, "BufferHubQueue::RemoveBuffer: slot=%zu", slot); 310 ALOGD_IF(TRACE, "BufferHubQueue::RemoveBuffer: slot=%zu", slot);
349 311
350 if (buffers_[slot]) { 312 if (buffers_[slot]) {
351 const int ret = 313 for (const auto& event_source : buffers_[slot]->GetEventSources()) {
352 epoll_fd_.Control(EPOLL_CTL_DEL, buffers_[slot]->event_fd(), nullptr); 314 const int ret =
353 if (ret < 0) { 315 epoll_fd_.Control(EPOLL_CTL_DEL, event_source.event_fd, nullptr);
354 ALOGE( 316 if (ret < 0) {
355 "BufferHubQueue::RemoveBuffer: Failed to remove buffer from epoll " 317 ALOGE(
356 "set: " 318 "BufferHubQueue::RemoveBuffer: Failed to remove buffer from epoll "
357 "%s", 319 "set: %s",
358 strerror(-ret)); 320 strerror(-ret));
359 return ErrorStatus(-ret); 321 return ErrorStatus(-ret);
322 }
360 } 323 }
361 324
362 // Trigger OnBufferRemoved callback if registered. 325 // Trigger OnBufferRemoved callback if registered.
@@ -372,7 +335,7 @@ Status<void> BufferHubQueue::RemoveBuffer(size_t slot) {
372 335
373Status<void> BufferHubQueue::Enqueue(Entry entry) { 336Status<void> BufferHubQueue::Enqueue(Entry entry) {
374 if (!is_full()) { 337 if (!is_full()) {
375 available_buffers_.Append(std::move(entry)); 338 available_buffers_.push(std::move(entry));
376 339
377 // Trigger OnBufferAvailable callback if registered. 340 // Trigger OnBufferAvailable callback if registered.
378 if (on_buffer_available_) 341 if (on_buffer_available_)
@@ -385,25 +348,26 @@ Status<void> BufferHubQueue::Enqueue(Entry entry) {
385 } 348 }
386} 349}
387 350
388Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue( 351Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(int timeout,
389 int timeout, size_t* slot, void* meta, LocalHandle* fence) { 352 size_t* slot) {
390 ALOGD_IF(TRACE, "BufferHubQueue::Dequeue: count=%zu, timeout=%d", count(), 353 ALOGD_IF(TRACE, "BufferHubQueue::Dequeue: count=%zu, timeout=%d", count(),
391 timeout); 354 timeout);
392 355
393 if (!WaitForBuffers(timeout)) 356 PDX_TRACE_FORMAT("BufferHubQueue::Dequeue|count=%zu|", count());
394 return ErrorStatus(ETIMEDOUT); 357
358 if (count() == 0) {
359 if (!WaitForBuffers(timeout))
360 return ErrorStatus(ETIMEDOUT);
361 }
395 362
396 auto& entry = available_buffers_.Front(); 363 auto& entry = available_buffers_.top();
364 PDX_TRACE_FORMAT("buffer|buffer_id=%d;slot=%zu|", entry.buffer->id(),
365 entry.slot);
397 366
398 std::shared_ptr<BufferHubBuffer> buffer = std::move(entry.buffer); 367 std::shared_ptr<BufferHubBuffer> buffer = std::move(entry.buffer);
399 *slot = entry.slot; 368 *slot = entry.slot;
400 *fence = std::move(entry.fence);
401 if (meta && entry.metadata) {
402 std::copy(entry.metadata.get(), entry.metadata.get() + meta_size_,
403 reinterpret_cast<uint8_t*>(meta));
404 }
405 369
406 available_buffers_.PopFront(); 370 available_buffers_.pop();
407 371
408 return {std::move(buffer)}; 372 return {std::move(buffer)};
409} 373}
@@ -419,7 +383,8 @@ void BufferHubQueue::SetBufferRemovedCallback(BufferRemovedCallback callback) {
419 383
420pdx::Status<void> BufferHubQueue::FreeAllBuffers() { 384pdx::Status<void> BufferHubQueue::FreeAllBuffers() {
421 // Clear all available buffers. 385 // Clear all available buffers.
422 available_buffers_.Clear(); 386 while (!available_buffers_.empty())
387 available_buffers_.pop();
423 388
424 pdx::Status<void> last_error; // No error. 389 pdx::Status<void> last_error; // No error.
425 // Clear all buffers this producer queue is tracking. 390 // Clear all buffers this producer queue is tracking.
@@ -429,7 +394,7 @@ pdx::Status<void> BufferHubQueue::FreeAllBuffers() {
429 if (!status) { 394 if (!status) {
430 ALOGE( 395 ALOGE(
431 "ProducerQueue::FreeAllBuffers: Failed to remove buffer at " 396 "ProducerQueue::FreeAllBuffers: Failed to remove buffer at "
432 "slot=%d.", 397 "slot=%zu.",
433 slot); 398 slot);
434 last_error = status.error_status(); 399 last_error = status.error_status();
435 } 400 }
@@ -548,7 +513,7 @@ Status<void> ProducerQueue::AddBuffer(
548 if (!status) 513 if (!status)
549 return status; 514 return status;
550 515
551 return Enqueue(buffer, slot); 516 return BufferHubQueue::Enqueue({buffer, slot, 0ULL});
552} 517}
553 518
554Status<void> ProducerQueue::RemoveBuffer(size_t slot) { 519Status<void> ProducerQueue::RemoveBuffer(size_t slot) {
@@ -565,40 +530,33 @@ Status<void> ProducerQueue::RemoveBuffer(size_t slot) {
565 530
566Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue( 531Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
567 int timeout, size_t* slot, LocalHandle* release_fence) { 532 int timeout, size_t* slot, LocalHandle* release_fence) {
568 if (slot == nullptr || release_fence == nullptr) { 533 DvrNativeBufferMetadata canonical_meta;
569 ALOGE("ProducerQueue::Dequeue: Invalid parameter: slot=%p release_fence=%p", 534 return Dequeue(timeout, slot, &canonical_meta, release_fence);
570 slot, release_fence);
571 return ErrorStatus(EINVAL);
572 }
573
574 auto buffer_status =
575 BufferHubQueue::Dequeue(timeout, slot, nullptr, release_fence);
576 if (!buffer_status)
577 return buffer_status.error_status();
578
579 return {std::static_pointer_cast<BufferProducer>(buffer_status.take())};
580} 535}
581 536
582Status<BufferHubQueue::Entry> ProducerQueue::OnBufferReady( 537pdx::Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
583 const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) { 538 int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
584 ALOGD_IF(TRACE, 539 pdx::LocalHandle* release_fence) {
585 "ProducerQueue::OnBufferReady: queue_id=%d buffer_id=%d slot=%zu", 540 ATRACE_NAME("ProducerQueue::Dequeue");
586 id(), buffer->id(), slot); 541 if (slot == nullptr || out_meta == nullptr || release_fence == nullptr) {
542 ALOGE("ProducerQueue::Dequeue: Invalid parameter.");
543 return ErrorStatus(EINVAL);
544 }
587 545
588 // Avoid taking a transient reference, buffer is valid for the duration of 546 auto status = BufferHubQueue::Dequeue(timeout, slot);
589 // this method call. 547 if (!status)
590 auto* producer_buffer = static_cast<BufferProducer*>(buffer.get()); 548 return status.error_status();
591 LocalHandle release_fence;
592 549
593 const int ret = producer_buffer->Gain(&release_fence); 550 auto buffer = std::static_pointer_cast<BufferProducer>(status.take());
594 if (ret < 0) 551 const int ret = buffer->GainAsync(out_meta, release_fence);
552 if (ret < 0 && ret != -EALREADY)
595 return ErrorStatus(-ret); 553 return ErrorStatus(-ret);
596 else 554
597 return {{buffer, nullptr, std::move(release_fence), slot}}; 555 return {std::move(buffer)};
598} 556}
599 557
600ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import) 558ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
601 : BufferHubQueue(std::move(handle)), ignore_on_import_(ignore_on_import) { 559 : BufferHubQueue(std::move(handle)) {
602 auto status = ImportQueue(); 560 auto status = ImportQueue();
603 if (!status) { 561 if (!status) {
604 ALOGE("ConsumerQueue::ConsumerQueue: Failed to import queue: %s", 562 ALOGE("ConsumerQueue::ConsumerQueue: Failed to import queue: %s",
@@ -619,9 +577,17 @@ ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import)
619Status<size_t> ConsumerQueue::ImportBuffers() { 577Status<size_t> ConsumerQueue::ImportBuffers() {
620 auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>(); 578 auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>();
621 if (!status) { 579 if (!status) {
622 ALOGE("ConsumerQueue::ImportBuffers: Failed to import consumer buffer: %s", 580 if (status.error() == EBADR) {
581 ALOGI(
582 "ConsumerQueue::ImportBuffers: Queue is silent, no buffers "
583 "imported.");
584 return {0};
585 } else {
586 ALOGE(
587 "ConsumerQueue::ImportBuffers: Failed to import consumer buffer: %s",
623 status.GetErrorMessage().c_str()); 588 status.GetErrorMessage().c_str());
624 return status.error_status(); 589 return status.error_status();
590 }
625 } 591 }
626 592
627 int ret; 593 int ret;
@@ -642,22 +608,6 @@ Status<size_t> ConsumerQueue::ImportBuffers() {
642 continue; 608 continue;
643 } 609 }
644 610
645 // Setup ignore state before adding buffer to the queue.
646 if (ignore_on_import_) {
647 ALOGD_IF(TRACE,
648 "ConsumerQueue::ImportBuffers: Setting buffer to ignored state: "
649 "buffer_id=%d",
650 buffer_consumer->id());
651 ret = buffer_consumer->SetIgnore(true);
652 if (ret < 0) {
653 ALOGE(
654 "ConsumerQueue::ImportBuffers: Failed to set ignored state on "
655 "imported buffer buffer_id=%d: %s",
656 buffer_consumer->id(), strerror(-ret));
657 last_error = ErrorStatus(-ret);
658 }
659 }
660
661 auto add_status = 611 auto add_status =
662 AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second); 612 AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
663 if (!add_status) { 613 if (!add_status) {
@@ -685,7 +635,7 @@ Status<void> ConsumerQueue::AddBuffer(
685 635
686 // Check to see if the buffer is already signaled. This is necessary to catch 636 // Check to see if the buffer is already signaled. This is necessary to catch
687 // cases where buffers are already available; epoll edge triggered mode does 637 // cases where buffers are already available; epoll edge triggered mode does
688 // not fire until and edge transition when adding new buffers to the epoll 638 // not fire until an edge transition when adding new buffers to the epoll
689 // set. Note that we only poll the fd events because HandleBufferEvent() takes 639 // set. Note that we only poll the fd events because HandleBufferEvent() takes
690 // care of checking the translated buffer events. 640 // care of checking the translated buffer events.
691 auto poll_status = PollEvents(buffer->event_fd(), POLLIN); 641 auto poll_status = PollEvents(buffer->event_fd(), POLLIN);
@@ -703,51 +653,53 @@ Status<void> ConsumerQueue::AddBuffer(
703} 653}
704 654
705Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue( 655Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
706 int timeout, size_t* slot, void* meta, size_t meta_size, 656 int timeout, size_t* slot, void* meta, size_t user_metadata_size,
707 LocalHandle* acquire_fence) { 657 LocalHandle* acquire_fence) {
708 if (meta_size != meta_size_) { 658 if (user_metadata_size != user_metadata_size_) {
709 ALOGE( 659 ALOGE(
710 "ConsumerQueue::Dequeue: Metadata size (%zu) for the dequeuing buffer " 660 "ConsumerQueue::Dequeue: Metadata size (%zu) for the dequeuing buffer "
711 "does not match metadata size (%zu) for the queue.", 661 "does not match metadata size (%zu) for the queue.",
712 meta_size, meta_size_); 662 user_metadata_size, user_metadata_size_);
713 return ErrorStatus(EINVAL); 663 return ErrorStatus(EINVAL);
714 } 664 }
715 665
716 if (slot == nullptr || acquire_fence == nullptr) { 666 DvrNativeBufferMetadata canonical_meta;
717 ALOGE( 667 auto status = Dequeue(timeout, slot, &canonical_meta, acquire_fence);
718 "ConsumerQueue::Dequeue: Invalid parameter: slot=%p meta=%p " 668 if (!status)
719 "acquire_fence=%p", 669 return status.error_status();
720 slot, meta, acquire_fence);
721 return ErrorStatus(EINVAL);
722 }
723 670
724 auto buffer_status = 671 if (meta && user_metadata_size) {
725 BufferHubQueue::Dequeue(timeout, slot, meta, acquire_fence); 672 void* metadata_src =
726 if (!buffer_status) 673 reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
727 return buffer_status.error_status(); 674 if (metadata_src) {
675 memcpy(meta, metadata_src, user_metadata_size);
676 } else {
677 ALOGW("ConsumerQueue::Dequeue: no user-defined metadata.");
678 }
679 }
728 680
729 return {std::static_pointer_cast<BufferConsumer>(buffer_status.take())}; 681 return status;
730} 682}
731 683
732Status<BufferHubQueue::Entry> ConsumerQueue::OnBufferReady( 684Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
733 const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) { 685 int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
734 ALOGD_IF(TRACE, 686 pdx::LocalHandle* acquire_fence) {
735 "ConsumerQueue::OnBufferReady: queue_id=%d buffer_id=%d slot=%zu", 687 ATRACE_NAME("ConsumerQueue::Dequeue");
736 id(), buffer->id(), slot); 688 if (slot == nullptr || out_meta == nullptr || acquire_fence == nullptr) {
689 ALOGE("ConsumerQueue::Dequeue: Invalid parameter.");
690 return ErrorStatus(EINVAL);
691 }
737 692
738 // Avoid taking a transient reference, buffer is valid for the duration of 693 auto status = BufferHubQueue::Dequeue(timeout, slot);
739 // this method call. 694 if (!status)
740 auto* consumer_buffer = static_cast<BufferConsumer*>(buffer.get()); 695 return status.error_status();
741 std::unique_ptr<uint8_t[]> metadata(meta_size_ ? new uint8_t[meta_size_]
742 : nullptr);
743 LocalHandle acquire_fence;
744 696
745 const int ret = 697 auto buffer = std::static_pointer_cast<BufferConsumer>(status.take());
746 consumer_buffer->Acquire(&acquire_fence, metadata.get(), meta_size_); 698 const int ret = buffer->AcquireAsync(out_meta, acquire_fence);
747 if (ret < 0) 699 if (ret < 0)
748 return ErrorStatus(-ret); 700 return ErrorStatus(-ret);
749 else 701
750 return {{buffer, std::move(metadata), std::move(acquire_fence), slot}}; 702 return {std::move(buffer)};
751} 703}
752 704
753Status<void> ConsumerQueue::OnBufferAllocated() { 705Status<void> ConsumerQueue::OnBufferAllocated() {
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 53eed8924..221bc4f9d 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -328,7 +328,7 @@ status_t BufferHubQueueProducer::queueBuffer(int slot,
328 328
329 LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1); 329 LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
330 330
331 DvrNativeBufferMetadata meta_data = {}; 331 DvrNativeBufferMetadata meta_data;
332 meta_data.timestamp = timestamp; 332 meta_data.timestamp = timestamp;
333 meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp); 333 meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp);
334 meta_data.dataspace = static_cast<int32_t>(dataspace); 334 meta_data.dataspace = static_cast<int32_t>(dataspace);
@@ -339,7 +339,7 @@ status_t BufferHubQueueProducer::queueBuffer(int slot,
339 meta_data.scaling_mode = static_cast<int32_t>(scaling_mode); 339 meta_data.scaling_mode = static_cast<int32_t>(scaling_mode);
340 meta_data.transform = static_cast<int32_t>(transform); 340 meta_data.transform = static_cast<int32_t>(transform);
341 341
342 buffer_producer->Post(fence_fd, &meta_data, sizeof(meta_data)); 342 buffer_producer->PostAsync(&meta_data, fence_fd);
343 buffers_[slot].mBufferState.queue(); 343 buffers_[slot].mBufferState.queue();
344 344
345 output->width = buffer_producer->width(); 345 output->width = buffer_producer->width();
@@ -384,7 +384,7 @@ status_t BufferHubQueueProducer::cancelBuffer(int slot,
384 } 384 }
385 385
386 auto buffer_producer = buffers_[slot].mBufferProducer; 386 auto buffer_producer = buffers_[slot].mBufferProducer;
387 queue_->Enqueue(buffer_producer, slot); 387 queue_->Enqueue(buffer_producer, slot, 0ULL);
388 buffers_[slot].mBufferState.cancel(); 388 buffers_[slot].mBufferState.cancel();
389 buffers_[slot].mFence = fence; 389 buffers_[slot].mFence = fence;
390 ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot); 390 ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot);
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 0699fefd3..6962d6c9f 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -5,12 +5,13 @@
5 5
6#include <pdx/client.h> 6#include <pdx/client.h>
7#include <pdx/status.h> 7#include <pdx/status.h>
8#include <private/dvr/bufferhub_rpc.h>
9#include <private/dvr/buffer_hub_client.h> 8#include <private/dvr/buffer_hub_client.h>
9#include <private/dvr/bufferhub_rpc.h>
10#include <private/dvr/epoll_file_descriptor.h> 10#include <private/dvr/epoll_file_descriptor.h>
11#include <private/dvr/ring_buffer.h> 11#include <private/dvr/ring_buffer.h>
12 12
13#include <memory> 13#include <memory>
14#include <queue>
14#include <vector> 15#include <vector>
15 16
16namespace android { 17namespace android {
@@ -50,19 +51,22 @@ class BufferHubQueue : public pdx::Client {
50 uint32_t default_format() const { return default_format_; } 51 uint32_t default_format() const { return default_format_; }
51 52
52 // Creates a new consumer in handle form for immediate transport over RPC. 53 // Creates a new consumer in handle form for immediate transport over RPC.
53 pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle(); 54 pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle(
55 bool silent = false);
54 56
55 // Returns the number of buffers avaiable for dequeue. 57 // Returns the number of buffers avaiable for dequeue.
56 size_t count() const { return available_buffers_.GetSize(); } 58 size_t count() const { return available_buffers_.size(); }
57 59
58 // Returns the total number of buffers that the queue is tracking. 60 // Returns the total number of buffers that the queue is tracking.
59 size_t capacity() const { return capacity_; } 61 size_t capacity() const { return capacity_; }
60 62
61 // Returns the size of metadata structure associated with this queue. 63 // Returns the size of metadata structure associated with this queue.
62 size_t metadata_size() const { return meta_size_; } 64 size_t metadata_size() const { return user_metadata_size_; }
63 65
64 // Returns whether the buffer queue is full. 66 // Returns whether the buffer queue is full.
65 bool is_full() const { return available_buffers_.IsFull(); } 67 bool is_full() const {
68 return available_buffers_.size() >= kMaxQueueCapacity;
69 }
66 70
67 explicit operator bool() const { return epoll_fd_.IsValid(); } 71 explicit operator bool() const { return epoll_fd_.IsValid(); }
68 72
@@ -136,8 +140,8 @@ class BufferHubQueue : public pdx::Client {
136 // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely, 140 // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
137 // while specifying a timeout equal to zero cause Dequeue() to return 141 // while specifying a timeout equal to zero cause Dequeue() to return
138 // immediately, even if no buffers are available. 142 // immediately, even if no buffers are available.
139 pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue( 143 pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
140 int timeout, size_t* slot, void* meta, pdx::LocalHandle* fence); 144 size_t* slot);
141 145
142 // Waits for buffers to become available and adds them to the available queue. 146 // Waits for buffers to become available and adds them to the available queue.
143 bool WaitForBuffers(int timeout); 147 bool WaitForBuffers(int timeout);
@@ -150,8 +154,9 @@ class BufferHubQueue : public pdx::Client {
150 // per-buffer data. 154 // per-buffer data.
151 struct Entry { 155 struct Entry {
152 Entry() : slot(0) {} 156 Entry() : slot(0) {}
153 Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) 157 Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot,
154 : buffer(buffer), slot(slot) {} 158 uint64_t index)
159 : buffer(buffer), slot(slot), index(index) {}
155 Entry(const std::shared_ptr<BufferHubBuffer>& buffer, 160 Entry(const std::shared_ptr<BufferHubBuffer>& buffer,
156 std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence, 161 std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence,
157 size_t slot) 162 size_t slot)
@@ -166,20 +171,24 @@ class BufferHubQueue : public pdx::Client {
166 std::unique_ptr<uint8_t[]> metadata; 171 std::unique_ptr<uint8_t[]> metadata;
167 pdx::LocalHandle fence; 172 pdx::LocalHandle fence;
168 size_t slot; 173 size_t slot;
174 uint64_t index;
175 };
176
177 struct EntryComparator {
178 bool operator()(const Entry& lhs, const Entry& rhs) {
179 return lhs.index > rhs.index;
180 }
169 }; 181 };
170 182
171 // Enqueues a buffer to the available list (Gained for producer or Acquireed 183 // Enqueues a buffer to the available list (Gained for producer or Acquireed
172 // for consumer). 184 // for consumer).
173 pdx::Status<void> Enqueue(Entry entry); 185 pdx::Status<void> Enqueue(Entry entry);
174 186
175 virtual pdx::Status<Entry> OnBufferReady(
176 const std::shared_ptr<BufferHubBuffer>& buf, size_t slot) = 0;
177
178 // Called when a buffer is allocated remotely. 187 // Called when a buffer is allocated remotely.
179 virtual pdx::Status<void> OnBufferAllocated() { return {}; } 188 virtual pdx::Status<void> OnBufferAllocated() { return {}; }
180 189
181 // Size of the metadata that buffers in this queue cary. 190 // Size of the metadata that buffers in this queue cary.
182 size_t meta_size_{0}; 191 size_t user_metadata_size_{0};
183 192
184 private: 193 private:
185 void Initialize(); 194 void Initialize();
@@ -226,7 +235,9 @@ class BufferHubQueue : public pdx::Client {
226 std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_; 235 std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;
227 236
228 // Buffers and related data that are available for dequeue. 237 // Buffers and related data that are available for dequeue.
229 RingBuffer<Entry> available_buffers_{kMaxQueueCapacity}; 238 // RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
239 std::priority_queue<Entry, std::vector<Entry>, EntryComparator>
240 available_buffers_;
230 241
231 // Keeps track with how many buffers have been added into the queue. 242 // Keeps track with how many buffers have been added into the queue.
232 size_t capacity_{0}; 243 size_t capacity_{0};
@@ -316,11 +327,14 @@ class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
316 // to the consumer side. 327 // to the consumer side.
317 pdx::Status<std::shared_ptr<BufferProducer>> Dequeue( 328 pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
318 int timeout, size_t* slot, pdx::LocalHandle* release_fence); 329 int timeout, size_t* slot, pdx::LocalHandle* release_fence);
330 pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
331 int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
332 pdx::LocalHandle* release_fence);
319 333
320 // Enqueues a producer buffer in the queue. 334 // Enqueues a producer buffer in the queue.
321 pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer, 335 pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
322 size_t slot) { 336 size_t slot, uint64_t index) {
323 return BufferHubQueue::Enqueue({buffer, slot}); 337 return BufferHubQueue::Enqueue({buffer, slot, index});
324 } 338 }
325 339
326 private: 340 private:
@@ -331,9 +345,6 @@ class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
331 // arguments as the constructors. 345 // arguments as the constructors.
332 explicit ProducerQueue(pdx::LocalChannelHandle handle); 346 explicit ProducerQueue(pdx::LocalChannelHandle handle);
333 ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage); 347 ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage);
334
335 pdx::Status<Entry> OnBufferReady(
336 const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
337}; 348};
338 349
339class ConsumerQueue : public BufferHubQueue { 350class ConsumerQueue : public BufferHubQueue {
@@ -352,10 +363,9 @@ class ConsumerQueue : public BufferHubQueue {
352 // used to avoid participation in the buffer lifecycle by a consumer queue 363 // used to avoid participation in the buffer lifecycle by a consumer queue
353 // that is only used to spawn other consumer queues, such as in an 364 // that is only used to spawn other consumer queues, such as in an
354 // intermediate service. 365 // intermediate service.
355 static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle, 366 static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle) {
356 bool ignore_on_import = false) {
357 return std::unique_ptr<ConsumerQueue>( 367 return std::unique_ptr<ConsumerQueue>(
358 new ConsumerQueue(std::move(handle), ignore_on_import)); 368 new ConsumerQueue(std::move(handle)));
359 } 369 }
360 370
361 // Import newly created buffers from the service side. 371 // Import newly created buffers from the service side.
@@ -379,13 +389,16 @@ class ConsumerQueue : public BufferHubQueue {
379 } 389 }
380 390
381 pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue( 391 pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
382 int timeout, size_t* slot, void* meta, size_t meta_size, 392 int timeout, size_t* slot, void* meta, size_t user_metadata_size,
393 pdx::LocalHandle* acquire_fence);
394 pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
395 int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
383 pdx::LocalHandle* acquire_fence); 396 pdx::LocalHandle* acquire_fence);
384 397
385 private: 398 private:
386 friend BufferHubQueue; 399 friend BufferHubQueue;
387 400
388 ConsumerQueue(pdx::LocalChannelHandle handle, bool ignore_on_import = false); 401 ConsumerQueue(pdx::LocalChannelHandle handle);
389 402
390 // Add a consumer buffer to populate the queue. Once added, a consumer buffer 403 // Add a consumer buffer to populate the queue. Once added, a consumer buffer
391 // is NOT available to use until the producer side |Post| it. |WaitForBuffers| 404 // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
@@ -394,14 +407,7 @@ class ConsumerQueue : public BufferHubQueue {
394 pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer, 407 pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
395 size_t slot); 408 size_t slot);
396 409
397 pdx::Status<Entry> OnBufferReady(
398 const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
399
400 pdx::Status<void> OnBufferAllocated() override; 410 pdx::Status<void> OnBufferAllocated() override;
401
402 // Flag indicating that imported (consumer) buffers should be ignored when
403 // imported to avoid participating in the buffer ownership flow.
404 bool ignore_on_import_;
405}; 411};
406 412
407} // namespace dvr 413} // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index 865573caf..8bd1ef141 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -1,4 +1,7 @@
1 1
2header_libraries = [
3 "libdvr_headers",
4]
2 5
3shared_libraries = [ 6shared_libraries = [
4 "libbase", 7 "libbase",
@@ -21,6 +24,7 @@ static_libraries = [
21 24
22cc_test { 25cc_test {
23 srcs: ["buffer_hub_queue-test.cpp"], 26 srcs: ["buffer_hub_queue-test.cpp"],
27 header_libs: header_libraries,
24 static_libs: static_libraries, 28 static_libs: static_libraries,
25 shared_libs: shared_libraries, 29 shared_libs: shared_libraries,
26 cflags: [ 30 cflags: [
@@ -35,6 +39,7 @@ cc_test {
35 39
36cc_test { 40cc_test {
37 srcs: ["buffer_hub_queue_producer-test.cpp"], 41 srcs: ["buffer_hub_queue_producer-test.cpp"],
42 header_libs: header_libraries,
38 static_libs: static_libraries, 43 static_libs: static_libraries,
39 shared_libs: shared_libraries, 44 shared_libs: shared_libraries,
40 cflags: [ 45 cflags: [
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 7581a065b..8a72531ed 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -3,6 +3,8 @@
3#include <private/dvr/buffer_hub_queue_client.h> 3#include <private/dvr/buffer_hub_queue_client.h>
4 4
5#include <gtest/gtest.h> 5#include <gtest/gtest.h>
6#include <poll.h>
7#include <sys/eventfd.h>
6 8
7#include <vector> 9#include <vector>
8 10
@@ -46,9 +48,9 @@ class BufferHubQueueTest : public ::testing::Test {
46 48
47 void AllocateBuffer(size_t* slot_out = nullptr) { 49 void AllocateBuffer(size_t* slot_out = nullptr) {
48 // Create producer buffer. 50 // Create producer buffer.
49 auto status = producer_queue_->AllocateBuffer( 51 auto status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
50 kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat, 52 kBufferLayerCount,
51 kBufferUsage); 53 kBufferFormat, kBufferUsage);
52 54
53 ASSERT_TRUE(status.ok()); 55 ASSERT_TRUE(status.ok());
54 size_t slot = status.take(); 56 size_t slot = status.take();
@@ -56,6 +58,23 @@ class BufferHubQueueTest : public ::testing::Test {
56 *slot_out = slot; 58 *slot_out = slot;
57 } 59 }
58 60
61 bool WaitAndHandleOnce(BufferHubQueue* queue, int timeout_ms) {
62 pollfd pfd{queue->queue_fd(), POLLIN, 0};
63 int ret;
64 do {
65 ret = poll(&pfd, 1, timeout_ms);
66 } while (ret == -1 && errno == EINTR);
67
68 if (ret < 0) {
69 ALOGW("Failed to poll queue %d's event fd, error: %s.", queue->id(),
70 strerror(errno));
71 return false;
72 } else if (ret == 0) {
73 return false;
74 }
75 return queue->HandleQueueEvents();
76 }
77
59 protected: 78 protected:
60 ProducerQueueConfigBuilder config_builder_; 79 ProducerQueueConfigBuilder config_builder_;
61 std::unique_ptr<ProducerQueue> producer_queue_; 80 std::unique_ptr<ProducerQueue> producer_queue_;
@@ -75,7 +94,7 @@ TEST_F(BufferHubQueueTest, TestDequeue) {
75 for (size_t i = 0; i < nb_dequeue_times; i++) { 94 for (size_t i = 0; i < nb_dequeue_times; i++) {
76 size_t slot; 95 size_t slot;
77 LocalHandle fence; 96 LocalHandle fence;
78 auto p1_status = producer_queue_->Dequeue(0, &slot, &fence); 97 auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
79 ASSERT_TRUE(p1_status.ok()); 98 ASSERT_TRUE(p1_status.ok());
80 auto p1 = p1_status.take(); 99 auto p1 = p1_status.take();
81 ASSERT_NE(nullptr, p1); 100 ASSERT_NE(nullptr, p1);
@@ -113,31 +132,26 @@ TEST_F(BufferHubQueueTest, TestProducerConsumer) {
113 // Dequeue returns timeout since no buffer is ready to consumer, but 132 // Dequeue returns timeout since no buffer is ready to consumer, but
114 // this implicitly triggers buffer import and bump up |capacity|. 133 // this implicitly triggers buffer import and bump up |capacity|.
115 LocalHandle fence; 134 LocalHandle fence;
116 auto status = consumer_queue_->Dequeue(0, &slot, &seq, &fence); 135 auto status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
117 ASSERT_FALSE(status.ok()); 136 ASSERT_FALSE(status.ok());
118 ASSERT_EQ(ETIMEDOUT, status.error()); 137 ASSERT_EQ(ETIMEDOUT, status.error());
119 ASSERT_EQ(consumer_queue_->capacity(), i + 1); 138 ASSERT_EQ(consumer_queue_->capacity(), i + 1);
120 } 139 }
121 140
122 // Use /dev/zero as a stand-in for a fence. As long as BufferHub does not need 141 // Use eventfd as a stand-in for a fence.
123 // to merge fences, which only happens when multiple consumers release the 142 LocalHandle post_fence(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
124 // same buffer with release fences, the file object should simply pass
125 // through.
126 LocalHandle post_fence("/dev/zero", O_RDONLY);
127 struct stat post_fence_stat;
128 ASSERT_EQ(0, fstat(post_fence.Get(), &post_fence_stat));
129 143
130 for (size_t i = 0; i < kBufferCount; i++) { 144 for (size_t i = 0; i < kBufferCount; i++) {
131 LocalHandle fence; 145 LocalHandle fence;
132 146
133 // First time there is no buffer available to dequeue. 147 // First time there is no buffer available to dequeue.
134 auto consumer_status = consumer_queue_->Dequeue(0, &slot, &seq, &fence); 148 auto consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
135 ASSERT_FALSE(consumer_status.ok()); 149 ASSERT_FALSE(consumer_status.ok());
136 ASSERT_EQ(ETIMEDOUT, consumer_status.error()); 150 ASSERT_EQ(ETIMEDOUT, consumer_status.error());
137 151
138 // Make sure Producer buffer is POSTED so that it's ready to Accquire 152 // Make sure Producer buffer is POSTED so that it's ready to Accquire
139 // in the consumer's Dequeue() function. 153 // in the consumer's Dequeue() function.
140 auto producer_status = producer_queue_->Dequeue(0, &slot, &fence); 154 auto producer_status = producer_queue_->Dequeue(100, &slot, &fence);
141 ASSERT_TRUE(producer_status.ok()); 155 ASSERT_TRUE(producer_status.ok());
142 auto producer = producer_status.take(); 156 auto producer = producer_status.take();
143 ASSERT_NE(nullptr, producer); 157 ASSERT_NE(nullptr, producer);
@@ -147,20 +161,10 @@ TEST_F(BufferHubQueueTest, TestProducerConsumer) {
147 161
148 // Second time the just the POSTED buffer should be dequeued. 162 // Second time the just the POSTED buffer should be dequeued.
149 uint64_t seq_out = 0; 163 uint64_t seq_out = 0;
150 consumer_status = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence); 164 consumer_status = consumer_queue_->Dequeue(100, &slot, &seq_out, &fence);
151 ASSERT_TRUE(consumer_status.ok()); 165 ASSERT_TRUE(consumer_status.ok());
152 EXPECT_TRUE(fence.IsValid()); 166 EXPECT_TRUE(fence.IsValid());
153 167
154 struct stat acquire_fence_stat;
155 ASSERT_EQ(0, fstat(fence.Get(), &acquire_fence_stat));
156
157 // The file descriptors should refer to the same file object. Testing the
158 // device id and inode is a proxy for testing that the fds refer to the same
159 // file object.
160 EXPECT_NE(post_fence.Get(), fence.Get());
161 EXPECT_EQ(post_fence_stat.st_dev, acquire_fence_stat.st_dev);
162 EXPECT_EQ(post_fence_stat.st_ino, acquire_fence_stat.st_ino);
163
164 auto consumer = consumer_status.take(); 168 auto consumer = consumer_status.take();
165 ASSERT_NE(nullptr, consumer); 169 ASSERT_NE(nullptr, consumer);
166 ASSERT_EQ(seq_in, seq_out); 170 ASSERT_EQ(seq_in, seq_out);
@@ -196,12 +200,11 @@ TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
196 200
197 for (size_t i = 0; i < kBufferCount; i++) { 201 for (size_t i = 0; i < kBufferCount; i++) {
198 Entry* entry = &buffers[i]; 202 Entry* entry = &buffers[i];
199 auto producer_status = 203 auto producer_status = producer_queue_->Dequeue(
200 producer_queue_->Dequeue(0, &entry->slot, &entry->fence); 204 /*timeout_ms=*/100, &entry->slot, &entry->fence);
201 ASSERT_TRUE(producer_status.ok()); 205 ASSERT_TRUE(producer_status.ok());
202 entry->buffer = producer_status.take(); 206 entry->buffer = producer_status.take();
203 ASSERT_NE(nullptr, entry->buffer); 207 ASSERT_NE(nullptr, entry->buffer);
204 EXPECT_EQ(i, entry->slot);
205 } 208 }
206 209
207 // Remove a buffer and make sure both queues reflect the change. 210 // Remove a buffer and make sure both queues reflect the change.
@@ -218,8 +221,8 @@ TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
218 buffers[0].buffer = nullptr; 221 buffers[0].buffer = nullptr;
219 222
220 // Now the consumer queue should know it's gone. 223 // Now the consumer queue should know it's gone.
221 EXPECT_FALSE(consumer_queue_->HandleQueueEvents()); 224 EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100));
222 EXPECT_EQ(kBufferCount - 1, consumer_queue_->capacity()); 225 ASSERT_EQ(kBufferCount - 1, consumer_queue_->capacity());
223 226
224 // Allocate a new buffer. This should take the first empty slot. 227 // Allocate a new buffer. This should take the first empty slot.
225 size_t slot; 228 size_t slot;
@@ -286,17 +289,20 @@ TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
286 auto silent_queue = producer_queue_->CreateSilentConsumerQueue(); 289 auto silent_queue = producer_queue_->CreateSilentConsumerQueue();
287 ASSERT_NE(nullptr, silent_queue); 290 ASSERT_NE(nullptr, silent_queue);
288 291
289 // Check that buffers are correctly imported on construction. 292 // Check that silent queue doesn't import buffers on creation.
290 EXPECT_EQ(kBufferCount, silent_queue->capacity()); 293 EXPECT_EQ(0, silent_queue->capacity());
291 294
292 // Dequeue and post a buffer. 295 // Dequeue and post a buffer.
293 size_t slot; 296 size_t slot;
294 LocalHandle fence; 297 LocalHandle fence;
295 auto producer_status = producer_queue_->Dequeue(0, &slot, &fence); 298 auto producer_status =
299 producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
296 ASSERT_TRUE(producer_status.ok()); 300 ASSERT_TRUE(producer_status.ok());
297 auto producer_buffer = producer_status.take(); 301 auto producer_buffer = producer_status.take();
298 ASSERT_NE(nullptr, producer_buffer); 302 ASSERT_NE(nullptr, producer_buffer);
299 ASSERT_EQ(0, producer_buffer->Post<void>({})); 303 ASSERT_EQ(0, producer_buffer->Post<void>({}));
304 // After post, check the number of remaining available buffers.
305 EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
300 306
301 // Currently we expect no buffer to be available prior to calling 307 // Currently we expect no buffer to be available prior to calling
302 // WaitForBuffers/HandleQueueEvents. 308 // WaitForBuffers/HandleQueueEvents.
@@ -314,23 +320,30 @@ TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
314 EXPECT_EQ(1u, consumer_queue_->count()); 320 EXPECT_EQ(1u, consumer_queue_->count());
315 321
316 // Reclaim released/ignored buffers. 322 // Reclaim released/ignored buffers.
317 producer_queue_->HandleQueueEvents(); 323 ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
324
325 usleep(10000);
326 WaitAndHandleOnce(producer_queue_.get(), /*timeout_ms=*/100);
318 ASSERT_EQ(kBufferCount - 1, producer_queue_->count()); 327 ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
319 328
320 // Post another buffer. 329 // Post another buffer.
321 producer_status = producer_queue_->Dequeue(0, &slot, &fence); 330 producer_status = producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
322 ASSERT_TRUE(producer_status.ok()); 331 ASSERT_TRUE(producer_status.ok());
323 producer_buffer = producer_status.take(); 332 producer_buffer = producer_status.take();
324 ASSERT_NE(nullptr, producer_buffer); 333 ASSERT_NE(nullptr, producer_buffer);
325 ASSERT_EQ(0, producer_buffer->Post<void>({})); 334 ASSERT_EQ(0, producer_buffer->Post<void>({}));
326 335
327 // Verify that the consumer queue receives it. 336 // Verify that the consumer queue receives it.
328 EXPECT_EQ(1u, consumer_queue_->count()); 337 size_t consumer_queue_count = consumer_queue_->count();
329 EXPECT_TRUE(consumer_queue_->HandleQueueEvents()); 338 WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100);
330 EXPECT_EQ(2u, consumer_queue_->count()); 339 EXPECT_LT(consumer_queue_count, consumer_queue_->count());
340
341 // Save the current consumer queue buffer count to compare after the dequeue.
342 consumer_queue_count = consumer_queue_->count();
331 343
332 // Dequeue and acquire/release (discard) buffers on the consumer end. 344 // Dequeue and acquire/release (discard) buffers on the consumer end.
333 auto consumer_status = consumer_queue_->Dequeue(0, &slot, &fence); 345 auto consumer_status =
346 consumer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
334 ASSERT_TRUE(consumer_status.ok()); 347 ASSERT_TRUE(consumer_status.ok());
335 auto consumer_buffer = consumer_status.take(); 348 auto consumer_buffer = consumer_status.take();
336 ASSERT_NE(nullptr, consumer_buffer); 349 ASSERT_NE(nullptr, consumer_buffer);
@@ -338,7 +351,7 @@ TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
338 351
339 // Buffer should be returned to the producer queue without being handled by 352 // Buffer should be returned to the producer queue without being handled by
340 // the silent consumer queue. 353 // the silent consumer queue.
341 EXPECT_EQ(1u, consumer_queue_->count()); 354 EXPECT_GT(consumer_queue_count, consumer_queue_->count());
342 EXPECT_EQ(kBufferCount - 2, producer_queue_->count()); 355 EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
343 EXPECT_TRUE(producer_queue_->HandleQueueEvents()); 356 EXPECT_TRUE(producer_queue_->HandleQueueEvents());
344 EXPECT_EQ(kBufferCount - 1, producer_queue_->count()); 357 EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
@@ -362,13 +375,13 @@ TEST_F(BufferHubQueueTest, TestMetadata) {
362 for (auto mi : ms) { 375 for (auto mi : ms) {
363 size_t slot; 376 size_t slot;
364 LocalHandle fence; 377 LocalHandle fence;
365 auto p1_status = producer_queue_->Dequeue(0, &slot, &fence); 378 auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
366 ASSERT_TRUE(p1_status.ok()); 379 ASSERT_TRUE(p1_status.ok());
367 auto p1 = p1_status.take(); 380 auto p1 = p1_status.take();
368 ASSERT_NE(nullptr, p1); 381 ASSERT_NE(nullptr, p1);
369 ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0); 382 ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
370 TestMetadata mo; 383 TestMetadata mo;
371 auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence); 384 auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
372 ASSERT_TRUE(c1_status.ok()); 385 ASSERT_TRUE(c1_status.ok());
373 auto c1 = c1_status.take(); 386 auto c1 = c1_status.take();
374 ASSERT_EQ(mi.a, mo.a); 387 ASSERT_EQ(mi.a, mo.a);
@@ -387,7 +400,7 @@ TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
387 int64_t mi = 3; 400 int64_t mi = 3;
388 size_t slot; 401 size_t slot;
389 LocalHandle fence; 402 LocalHandle fence;
390 auto p1_status = producer_queue_->Dequeue(0, &slot, &fence); 403 auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
391 ASSERT_TRUE(p1_status.ok()); 404 ASSERT_TRUE(p1_status.ok());
392 auto p1 = p1_status.take(); 405 auto p1 = p1_status.take();
393 ASSERT_NE(nullptr, p1); 406 ASSERT_NE(nullptr, p1);
@@ -395,7 +408,7 @@ TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
395 408
396 int32_t mo; 409 int32_t mo;
397 // Acquire a buffer with mismatched metadata is not OK. 410 // Acquire a buffer with mismatched metadata is not OK.
398 auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence); 411 auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
399 ASSERT_FALSE(c1_status.ok()); 412 ASSERT_FALSE(c1_status.ok());
400} 413}
401 414
@@ -406,14 +419,14 @@ TEST_F(BufferHubQueueTest, TestEnqueue) {
406 419
407 size_t slot; 420 size_t slot;
408 LocalHandle fence; 421 LocalHandle fence;
409 auto p1_status = producer_queue_->Dequeue(0, &slot, &fence); 422 auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
410 ASSERT_TRUE(p1_status.ok()); 423 ASSERT_TRUE(p1_status.ok());
411 auto p1 = p1_status.take(); 424 auto p1 = p1_status.take();
412 ASSERT_NE(nullptr, p1); 425 ASSERT_NE(nullptr, p1);
413 426
414 int64_t mo; 427 int64_t mo;
415 producer_queue_->Enqueue(p1, slot); 428 producer_queue_->Enqueue(p1, slot, 0ULL);
416 auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence); 429 auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
417 ASSERT_FALSE(c1_status.ok()); 430 ASSERT_FALSE(c1_status.ok());
418} 431}
419 432
@@ -424,14 +437,14 @@ TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
424 size_t s1; 437 size_t s1;
425 AllocateBuffer(); 438 AllocateBuffer();
426 LocalHandle fence; 439 LocalHandle fence;
427 auto p1_status = producer_queue_->Dequeue(0, &s1, &fence); 440 auto p1_status = producer_queue_->Dequeue(100, &s1, &fence);
428 ASSERT_TRUE(p1_status.ok()); 441 ASSERT_TRUE(p1_status.ok());
429 auto p1 = p1_status.take(); 442 auto p1 = p1_status.take();
430 ASSERT_NE(nullptr, p1); 443 ASSERT_NE(nullptr, p1);
431 444
432 // producer queue is exhausted 445 // producer queue is exhausted
433 size_t s2; 446 size_t s2;
434 auto p2_status = producer_queue_->Dequeue(0, &s2, &fence); 447 auto p2_status = producer_queue_->Dequeue(100, &s2, &fence);
435 ASSERT_FALSE(p2_status.ok()); 448 ASSERT_FALSE(p2_status.ok());
436 ASSERT_EQ(ETIMEDOUT, p2_status.error()); 449 ASSERT_EQ(ETIMEDOUT, p2_status.error());
437 450
@@ -441,7 +454,7 @@ TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
441 ASSERT_EQ(producer_queue_->capacity(), 2U); 454 ASSERT_EQ(producer_queue_->capacity(), 2U);
442 455
443 // now we can dequeue again 456 // now we can dequeue again
444 p2_status = producer_queue_->Dequeue(0, &s2, &fence); 457 p2_status = producer_queue_->Dequeue(100, &s2, &fence);
445 ASSERT_TRUE(p2_status.ok()); 458 ASSERT_TRUE(p2_status.ok());
446 auto p2 = p2_status.take(); 459 auto p2 = p2_status.take();
447 ASSERT_NE(nullptr, p2); 460 ASSERT_NE(nullptr, p2);
@@ -456,7 +469,7 @@ TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
456 int64_t seq = 1; 469 int64_t seq = 1;
457 ASSERT_EQ(p1->Post(LocalHandle(), seq), 0); 470 ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
458 size_t cs1, cs2; 471 size_t cs1, cs2;
459 auto c1_status = consumer_queue_->Dequeue(0, &cs1, &seq, &fence); 472 auto c1_status = consumer_queue_->Dequeue(100, &cs1, &seq, &fence);
460 ASSERT_TRUE(c1_status.ok()); 473 ASSERT_TRUE(c1_status.ok());
461 auto c1 = c1_status.take(); 474 auto c1 = c1_status.take();
462 ASSERT_NE(nullptr, c1); 475 ASSERT_NE(nullptr, c1);
@@ -465,7 +478,7 @@ TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
465 ASSERT_EQ(cs1, s1); 478 ASSERT_EQ(cs1, s1);
466 479
467 ASSERT_EQ(p2->Post(LocalHandle(), seq), 0); 480 ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
468 auto c2_status = consumer_queue_->Dequeue(0, &cs2, &seq, &fence); 481 auto c2_status = consumer_queue_->Dequeue(100, &cs2, &seq, &fence);
469 ASSERT_TRUE(c2_status.ok()); 482 ASSERT_TRUE(c2_status.ok());
470 auto c2 = c2_status.take(); 483 auto c2 = c2_status.take();
471 ASSERT_NE(nullptr, c2); 484 ASSERT_NE(nullptr, c2);
@@ -485,7 +498,7 @@ TEST_F(BufferHubQueueTest, TestUsageSetMask) {
485 498
486 LocalHandle fence; 499 LocalHandle fence;
487 size_t slot; 500 size_t slot;
488 auto p1_status = producer_queue_->Dequeue(0, &slot, &fence); 501 auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
489 ASSERT_TRUE(p1_status.ok()); 502 ASSERT_TRUE(p1_status.ok());
490 auto p1 = p1_status.take(); 503 auto p1 = p1_status.take();
491 ASSERT_EQ(p1->usage() & set_mask, set_mask); 504 ASSERT_EQ(p1->usage() & set_mask, set_mask);
@@ -504,7 +517,7 @@ TEST_F(BufferHubQueueTest, TestUsageClearMask) {
504 517
505 LocalHandle fence; 518 LocalHandle fence;
506 size_t slot; 519 size_t slot;
507 auto p1_status = producer_queue_->Dequeue(0, &slot, &fence); 520 auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
508 ASSERT_TRUE(p1_status.ok()); 521 ASSERT_TRUE(p1_status.ok());
509 auto p1 = p1_status.take(); 522 auto p1 = p1_status.take();
510 ASSERT_EQ(0u, p1->usage() & clear_mask); 523 ASSERT_EQ(0u, p1->usage() & clear_mask);
@@ -543,9 +556,9 @@ TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
543 ASSERT_TRUE(status.ok()); 556 ASSERT_TRUE(status.ok());
544 557
545 // While allocation without those bits should fail. 558 // While allocation without those bits should fail.
546 status = producer_queue_->AllocateBuffer( 559 status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
547 kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat, 560 kBufferLayerCount, kBufferFormat,
548 kBufferUsage & ~deny_clear_mask); 561 kBufferUsage & ~deny_clear_mask);
549 ASSERT_FALSE(status.ok()); 562 ASSERT_FALSE(status.ok());
550 ASSERT_EQ(EINVAL, status.error()); 563 ASSERT_EQ(EINVAL, status.error());
551} 564}
@@ -603,7 +616,7 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
603 616
604 // Free all buffers when one buffer is dequeued. 617 // Free all buffers when one buffer is dequeued.
605 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount); 618 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
606 producer_status = producer_queue_->Dequeue(0, &slot, &fence); 619 producer_status = producer_queue_->Dequeue(100, &slot, &fence);
607 ASSERT_TRUE(producer_status.ok()); 620 ASSERT_TRUE(producer_status.ok());
608 status = producer_queue_->FreeAllBuffers(); 621 status = producer_queue_->FreeAllBuffers();
609 EXPECT_TRUE(status.ok()); 622 EXPECT_TRUE(status.ok());
@@ -611,7 +624,7 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
611 // Free all buffers when all buffers are dequeued. 624 // Free all buffers when all buffers are dequeued.
612 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount); 625 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
613 for (size_t i = 0; i < kBufferCount; i++) { 626 for (size_t i = 0; i < kBufferCount; i++) {
614 producer_status = producer_queue_->Dequeue(0, &slot, &fence); 627 producer_status = producer_queue_->Dequeue(100, &slot, &fence);
615 ASSERT_TRUE(producer_status.ok()); 628 ASSERT_TRUE(producer_status.ok());
616 } 629 }
617 status = producer_queue_->FreeAllBuffers(); 630 status = producer_queue_->FreeAllBuffers();
@@ -619,7 +632,7 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
619 632
620 // Free all buffers when one buffer is posted. 633 // Free all buffers when one buffer is posted.
621 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount); 634 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
622 producer_status = producer_queue_->Dequeue(0, &slot, &fence); 635 producer_status = producer_queue_->Dequeue(100, &slot, &fence);
623 ASSERT_TRUE(producer_status.ok()); 636 ASSERT_TRUE(producer_status.ok());
624 producer_buffer = producer_status.take(); 637 producer_buffer = producer_status.take();
625 ASSERT_NE(nullptr, producer_buffer); 638 ASSERT_NE(nullptr, producer_buffer);
@@ -630,7 +643,7 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
630 // Free all buffers when all buffers are posted. 643 // Free all buffers when all buffers are posted.
631 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount); 644 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
632 for (size_t i = 0; i < kBufferCount; i++) { 645 for (size_t i = 0; i < kBufferCount; i++) {
633 producer_status = producer_queue_->Dequeue(0, &slot, &fence); 646 producer_status = producer_queue_->Dequeue(100, &slot, &fence);
634 ASSERT_TRUE(producer_status.ok()); 647 ASSERT_TRUE(producer_status.ok());
635 producer_buffer = producer_status.take(); 648 producer_buffer = producer_status.take();
636 ASSERT_NE(nullptr, producer_buffer); 649 ASSERT_NE(nullptr, producer_buffer);
@@ -642,12 +655,12 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
642 // Free all buffers when all buffers are acquired. 655 // Free all buffers when all buffers are acquired.
643 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount); 656 CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
644 for (size_t i = 0; i < kBufferCount; i++) { 657 for (size_t i = 0; i < kBufferCount; i++) {
645 producer_status = producer_queue_->Dequeue(0, &slot, &fence); 658 producer_status = producer_queue_->Dequeue(100, &slot, &fence);
646 ASSERT_TRUE(producer_status.ok()); 659 ASSERT_TRUE(producer_status.ok());
647 producer_buffer = producer_status.take(); 660 producer_buffer = producer_status.take();
648 ASSERT_NE(nullptr, producer_buffer); 661 ASSERT_NE(nullptr, producer_buffer);
649 ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq))); 662 ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
650 consumer_status = consumer_queue_->Dequeue(0, &slot, &seq, &fence); 663 consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
651 ASSERT_TRUE(consumer_status.ok()); 664 ASSERT_TRUE(consumer_status.ok());
652 } 665 }
653 666
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 035252d0b..09a49dd71 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -27,15 +27,6 @@ DvrWriteBufferQueue::DvrWriteBufferQueue(
27 format_(producer_queue->default_format()) {} 27 format_(producer_queue->default_format()) {}
28 28
29int DvrWriteBufferQueue::GetNativeWindow(ANativeWindow** out_window) { 29int DvrWriteBufferQueue::GetNativeWindow(ANativeWindow** out_window) {
30 if (producer_queue_->metadata_size() != sizeof(DvrNativeBufferMetadata)) {
31 ALOGE(
32 "DvrWriteBufferQueue::GetNativeWindow: The size of buffer metadata "
33 "(%zu) of the write queue does not match of size of "
34 "DvrNativeBufferMetadata (%zu).",
35 producer_queue_->metadata_size(), sizeof(DvrNativeBufferMetadata));
36 return -EINVAL;
37 }
38
39 if (native_window_ == nullptr) { 30 if (native_window_ == nullptr) {
40 // Lazy creation of |native_window|, as not everyone is using 31 // Lazy creation of |native_window|, as not everyone is using
41 // DvrWriteBufferQueue as an external surface. 32 // DvrWriteBufferQueue as an external surface.
@@ -63,10 +54,27 @@ int DvrWriteBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) {
63} 54}
64 55
65int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer, 56int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,
66 int* out_fence_fd, size_t* out_slot) { 57 int* out_fence_fd) {
58 DvrNativeBufferMetadata meta;
59 DvrWriteBuffer* buffer = nullptr;
60 int fence_fd = -1;
61 if (const int ret = GainBuffer(timeout, &buffer, &meta, &fence_fd))
62 return ret;
63 if (!buffer)
64 return -ENOMEM;
65
66 write_buffers_[buffer->slot].reset(buffer);
67 write_buffer->write_buffer = std::move(buffer->write_buffer);
68 *out_fence_fd = fence_fd;
69 return 0;
70}
71
72int DvrWriteBufferQueue::GainBuffer(int timeout,
73 DvrWriteBuffer** out_write_buffer,
74 DvrNativeBufferMetadata* out_meta,
75 int* out_fence_fd) {
67 size_t slot; 76 size_t slot;
68 pdx::LocalHandle fence; 77 pdx::LocalHandle release_fence;
69 std::shared_ptr<BufferProducer> buffer_producer;
70 78
71 // Need to retry N+1 times, where N is total number of buffers in the queue. 79 // Need to retry N+1 times, where N is total number of buffers in the queue.
72 // As in the worst case, we will dequeue all N buffers and reallocate them, on 80 // As in the worst case, we will dequeue all N buffers and reallocate them, on
@@ -75,15 +83,29 @@ int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,
75 size_t retry = 0; 83 size_t retry = 0;
76 84
77 for (; retry < max_retries; retry++) { 85 for (; retry < max_retries; retry++) {
78 auto buffer_status = producer_queue_->Dequeue(timeout, &slot, &fence); 86 auto buffer_status =
87 producer_queue_->Dequeue(timeout, &slot, out_meta, &release_fence);
79 if (!buffer_status) { 88 if (!buffer_status) {
80 ALOGE_IF(buffer_status.error() != ETIMEDOUT, 89 ALOGE_IF(buffer_status.error() != ETIMEDOUT,
81 "DvrWriteBufferQueue::Dequeue: Failed to dequeue buffer: %s", 90 "DvrWriteBufferQueue::GainBuffer: Failed to dequeue buffer: %s",
82 buffer_status.GetErrorMessage().c_str()); 91 buffer_status.GetErrorMessage().c_str());
83 return -buffer_status.error(); 92 return -buffer_status.error();
84 } 93 }
85 94
86 buffer_producer = buffer_status.take(); 95 if (write_buffers_[slot] == nullptr) {
96 // Lazy initialization of a write_buffers_ slot. Note that a slot will
97 // only be dynamically allocated once during the entire cycle life of a
98 // queue.
99 write_buffers_[slot] = std::make_unique<DvrWriteBuffer>();
100 write_buffers_[slot]->slot = slot;
101 }
102
103 LOG_ALWAYS_FATAL_IF(
104 write_buffers_[slot]->write_buffer,
105 "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
106 write_buffers_[slot]->write_buffer = std::move(buffer_status.take());
107
108 const auto& buffer_producer = write_buffers_[slot]->write_buffer;
87 if (!buffer_producer) 109 if (!buffer_producer)
88 return -ENOMEM; 110 return -ENOMEM;
89 111
@@ -122,6 +144,9 @@ int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,
122 remove_status.GetErrorMessage().c_str()); 144 remove_status.GetErrorMessage().c_str());
123 return -remove_status.error(); 145 return -remove_status.error();
124 } 146 }
147 // Make sure that the previously allocated buffer is dereferenced from
148 // write_buffers_ array.
149 write_buffers_[slot]->write_buffer = nullptr;
125 150
126 auto allocate_status = producer_queue_->AllocateBuffer( 151 auto allocate_status = producer_queue_->AllocateBuffer(
127 width_, height_, old_layer_count, format_, old_usage); 152 width_, height_, old_layer_count, format_, old_usage);
@@ -139,46 +164,8 @@ int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,
139 return -ENOMEM; 164 return -ENOMEM;
140 } 165 }
141 166
142 write_buffer->write_buffer = std::move(buffer_producer);
143 *out_fence_fd = fence.Release();
144 if (out_slot) {
145 // TODO(b/65469368): Remove this null check once dvrWriteBufferQueueDequeue
146 // is deprecated.
147 *out_slot = slot;
148 }
149 return 0;
150}
151
152int DvrWriteBufferQueue::GainBuffer(int timeout,
153 DvrWriteBuffer** out_write_buffer,
154 DvrNativeBufferMetadata* out_meta,
155 int* out_fence_fd) {
156 DvrWriteBuffer write_buffer;
157 int fence_fd;
158 size_t slot;
159 const int ret = Dequeue(timeout, &write_buffer, &fence_fd, &slot);
160 if (ret < 0) {
161 ALOGE_IF(
162 ret != -ETIMEDOUT,
163 "DvrWriteBufferQueue::GainBuffer: Failed to dequeue buffer, ret=%d",
164 ret);
165 return ret;
166 }
167
168 if (write_buffers_[slot] == nullptr) {
169 // Lazy initialization of a write_buffers_ slot. Note that a slot will only
170 // be dynamically allocated once during the entire cycle life of a queue.
171 write_buffers_[slot] = std::make_unique<DvrWriteBuffer>();
172 write_buffers_[slot]->slot = slot;
173 }
174
175 LOG_ALWAYS_FATAL_IF(
176 write_buffers_[slot]->write_buffer,
177 "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
178 write_buffers_[slot]->write_buffer = std::move(write_buffer.write_buffer);
179
180 *out_write_buffer = write_buffers_[slot].release(); 167 *out_write_buffer = write_buffers_[slot].release();
181 *out_fence_fd = fence_fd; 168 *out_fence_fd = release_fence.Release();
182 169
183 return 0; 170 return 0;
184} 171}
@@ -202,14 +189,16 @@ int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer,
202 } 189 }
203 if (write_buffer->write_buffer->id() != producer_queue_->GetBufferId(slot)) { 190 if (write_buffer->write_buffer->id() != producer_queue_->GetBufferId(slot)) {
204 ALOGE( 191 ALOGE(
205 "DvrWriteBufferQueue::PostBuffer: Buffer to be released does not " 192 "DvrWriteBufferQueue::PostBuffer: Buffer to be posted does not "
206 "belong to this buffer queue."); 193 "belong to this buffer queue. Posting buffer: id=%d, buffer in "
194 "queue: id=%d",
195 write_buffer->write_buffer->id(), producer_queue_->GetBufferId(slot));
207 return -EINVAL; 196 return -EINVAL;
208 } 197 }
209 198
199 write_buffer->write_buffer->SetQueueIndex(next_post_index_++);
210 pdx::LocalHandle fence(ready_fence_fd); 200 pdx::LocalHandle fence(ready_fence_fd);
211 // TODO(b/65455724): All BufferHub operations should be async. 201 const int ret = write_buffer->write_buffer->PostAsync(meta, fence);
212 const int ret = write_buffer->write_buffer->Post(fence, meta, sizeof(*meta));
213 if (ret < 0) { 202 if (ret < 0) {
214 ALOGE("DvrWriteBufferQueue::PostBuffer: Failed to post buffer, ret=%d", 203 ALOGE("DvrWriteBufferQueue::PostBuffer: Failed to post buffer, ret=%d",
215 ret); 204 ret);
@@ -316,8 +305,7 @@ int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
316 if (!write_queue || !write_buffer || !out_fence_fd) 305 if (!write_queue || !write_buffer || !out_fence_fd)
317 return -EINVAL; 306 return -EINVAL;
318 307
319 // TODO(b/65469368): Deprecate this API once new GainBuffer API is in use. 308 return write_queue->Dequeue(timeout, write_buffer, out_fence_fd);
320 return write_queue->Dequeue(timeout, write_buffer, out_fence_fd, nullptr);
321} 309}
322 310
323int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout, 311int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout,
@@ -370,8 +358,8 @@ int DvrReadBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) {
370} 358}
371 359
372int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer, 360int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer,
373 int* out_fence_fd, size_t* out_slot, 361 int* out_fence_fd, void* out_meta,
374 void* out_meta, size_t meta_size_bytes) { 362 size_t meta_size_bytes) {
375 if (meta_size_bytes != consumer_queue_->metadata_size()) { 363 if (meta_size_bytes != consumer_queue_->metadata_size()) {
376 ALOGE( 364 ALOGE(
377 "DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), " 365 "DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), "
@@ -394,11 +382,6 @@ int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer,
394 read_buffer->read_buffer = buffer_status.take(); 382 read_buffer->read_buffer = buffer_status.take();
395 *out_fence_fd = acquire_fence.Release(); 383 *out_fence_fd = acquire_fence.Release();
396 384
397 if (out_slot) {
398 // TODO(b/65469368): Remove this null check once dvrReadBufferQueueDequeue
399 // is deprecated.
400 *out_slot = slot;
401 }
402 return 0; 385 return 0;
403} 386}
404 387
@@ -406,17 +389,15 @@ int DvrReadBufferQueue::AcquireBuffer(int timeout,
406 DvrReadBuffer** out_read_buffer, 389 DvrReadBuffer** out_read_buffer,
407 DvrNativeBufferMetadata* out_meta, 390 DvrNativeBufferMetadata* out_meta,
408 int* out_fence_fd) { 391 int* out_fence_fd) {
409 DvrReadBuffer read_buffer;
410 int fence_fd;
411 size_t slot; 392 size_t slot;
412 const int ret = Dequeue(timeout, &read_buffer, &fence_fd, &slot, out_meta, 393 pdx::LocalHandle acquire_fence;
413 sizeof(*out_meta)); 394 auto buffer_status =
414 if (ret < 0) { 395 consumer_queue_->Dequeue(timeout, &slot, out_meta, &acquire_fence);
415 ALOGE_IF( 396 if (!buffer_status) {
416 ret != -ETIMEDOUT, 397 ALOGE_IF(buffer_status.error() != ETIMEDOUT,
417 "DvrReadBufferQueue::AcquireBuffer: Failed to dequeue buffer, error=%d", 398 "DvrReadBufferQueue::AcquireBuffer: Failed to dequeue buffer: %s",
418 ret); 399 buffer_status.GetErrorMessage().c_str());
419 return ret; 400 return -buffer_status.error();
420 } 401 }
421 402
422 if (read_buffers_[slot] == nullptr) { 403 if (read_buffers_[slot] == nullptr) {
@@ -429,10 +410,10 @@ int DvrReadBufferQueue::AcquireBuffer(int timeout,
429 LOG_FATAL_IF( 410 LOG_FATAL_IF(
430 read_buffers_[slot]->read_buffer, 411 read_buffers_[slot]->read_buffer,
431 "DvrReadBufferQueue::AcquireBuffer: Buffer slot is not empty: %zu", slot); 412 "DvrReadBufferQueue::AcquireBuffer: Buffer slot is not empty: %zu", slot);
432 read_buffers_[slot]->read_buffer = std::move(read_buffer.read_buffer); 413 read_buffers_[slot]->read_buffer = std::move(buffer_status.take());
433 414
434 *out_read_buffer = read_buffers_[slot].release(); 415 *out_read_buffer = read_buffers_[slot].release();
435 *out_fence_fd = fence_fd; 416 *out_fence_fd = acquire_fence.Release();
436 417
437 return 0; 418 return 0;
438} 419}
@@ -457,20 +438,14 @@ int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer,
457 if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) { 438 if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) {
458 ALOGE( 439 ALOGE(
459 "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not " 440 "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not "
460 "belong to this buffer queue."); 441 "belong to this buffer queue. Releasing buffer: id=%d, buffer in "
442 "queue: id=%d",
443 read_buffer->read_buffer->id(), consumer_queue_->GetBufferId(slot));
461 return -EINVAL; 444 return -EINVAL;
462 } 445 }
463 446
464 pdx::LocalHandle fence(release_fence_fd); 447 pdx::LocalHandle fence(release_fence_fd);
465 int ret = 0; 448 int ret = read_buffer->read_buffer->ReleaseAsync(meta, fence);
466 if (fence) {
467 ret = read_buffer->read_buffer->Release(fence);
468 } else {
469 // TODO(b/65458354): Send metadata back to producer once shared memory based
470 // metadata is implemented.
471 // TODO(b/65455724): All BufferHub operations should be async.
472 ret = read_buffer->read_buffer->ReleaseAsync();
473 }
474 if (ret < 0) { 449 if (ret < 0) {
475 ALOGE("DvrReadBufferQueue::ReleaseBuffer: Failed to release buffer, ret=%d", 450 ALOGE("DvrReadBufferQueue::ReleaseBuffer: Failed to release buffer, ret=%d",
476 ret); 451 ret);
@@ -559,9 +534,8 @@ int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
559 if (meta_size_bytes != 0 && !out_meta) 534 if (meta_size_bytes != 0 && !out_meta)
560 return -EINVAL; 535 return -EINVAL;
561 536
562 // TODO(b/65469368): Deprecate this API once new AcquireBuffer API is in use. 537 return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, out_meta,
563 return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, nullptr, 538 meta_size_bytes);
564 out_meta, meta_size_bytes);
565} 539}
566 540
567int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout, 541int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout,
diff --git a/libs/vr/libdvr/dvr_buffer_queue_internal.h b/libs/vr/libdvr/dvr_buffer_queue_internal.h
index f9c0bfd7c..e53a6868f 100644
--- a/libs/vr/libdvr/dvr_buffer_queue_internal.h
+++ b/libs/vr/libdvr/dvr_buffer_queue_internal.h
@@ -42,8 +42,7 @@ struct DvrWriteBufferQueue {
42 42
43 int GetNativeWindow(ANativeWindow** out_window); 43 int GetNativeWindow(ANativeWindow** out_window);
44 int CreateReadQueue(DvrReadBufferQueue** out_read_queue); 44 int CreateReadQueue(DvrReadBufferQueue** out_read_queue);
45 int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd, 45 int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd);
46 size_t* out_slot);
47 int GainBuffer(int timeout, DvrWriteBuffer** out_write_buffer, 46 int GainBuffer(int timeout, DvrWriteBuffer** out_write_buffer,
48 DvrNativeBufferMetadata* out_meta, int* out_fence_fd); 47 DvrNativeBufferMetadata* out_meta, int* out_fence_fd);
49 int PostBuffer(DvrWriteBuffer* write_buffer, 48 int PostBuffer(DvrWriteBuffer* write_buffer,
@@ -55,6 +54,7 @@ struct DvrWriteBufferQueue {
55 std::array<std::unique_ptr<DvrWriteBuffer>, BufferHubQueue::kMaxQueueCapacity> 54 std::array<std::unique_ptr<DvrWriteBuffer>, BufferHubQueue::kMaxQueueCapacity>
56 write_buffers_; 55 write_buffers_;
57 56
57 int64_t next_post_index_ = 0;
58 uint32_t width_; 58 uint32_t width_;
59 uint32_t height_; 59 uint32_t height_;
60 uint32_t format_; 60 uint32_t format_;
@@ -75,7 +75,7 @@ struct DvrReadBufferQueue {
75 75
76 int CreateReadQueue(DvrReadBufferQueue** out_read_queue); 76 int CreateReadQueue(DvrReadBufferQueue** out_read_queue);
77 int Dequeue(int timeout, DvrReadBuffer* read_buffer, int* out_fence_fd, 77 int Dequeue(int timeout, DvrReadBuffer* read_buffer, int* out_fence_fd,
78 size_t* out_slot, void* out_meta, size_t meta_size_bytes); 78 void* out_meta, size_t user_metadata_size);
79 int AcquireBuffer(int timeout, DvrReadBuffer** out_read_buffer, 79 int AcquireBuffer(int timeout, DvrReadBuffer** out_read_buffer,
80 DvrNativeBufferMetadata* out_meta, int* out_fence_fd); 80 DvrNativeBufferMetadata* out_meta, int* out_fence_fd);
81 int ReleaseBuffer(DvrReadBuffer* read_buffer, 81 int ReleaseBuffer(DvrReadBuffer* read_buffer,
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 8f45ce7e4..499b7c190 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -15,6 +15,12 @@
15extern "C" { 15extern "C" {
16#endif 16#endif
17 17
18#ifdef __GNUC__
19#define ALIGNED_DVR_STRUCT(x) __attribute__((packed, aligned(x)))
20#else
21#define ALIGNED_DVR_STRUCT(x)
22#endif
23
18typedef struct ANativeWindow ANativeWindow; 24typedef struct ANativeWindow ANativeWindow;
19 25
20typedef struct DvrPoseAsync DvrPoseAsync; 26typedef struct DvrPoseAsync DvrPoseAsync;
@@ -367,7 +373,24 @@ typedef int (*DvrPerformanceSetSchedulerPolicyPtr)(
367// existing data members. If new fields need to be added, please take extra care 373// existing data members. If new fields need to be added, please take extra care
368// to make sure that new data field is padded properly the size of the struct 374// to make sure that new data field is padded properly the size of the struct
369// stays same. 375// stays same.
370struct DvrNativeBufferMetadata { 376struct ALIGNED_DVR_STRUCT(8) DvrNativeBufferMetadata {
377#ifdef __cplusplus
378 DvrNativeBufferMetadata()
379 : timestamp(0),
380 is_auto_timestamp(0),
381 dataspace(0),
382 crop_left(0),
383 crop_top(0),
384 crop_right(0),
385 crop_bottom(0),
386 scaling_mode(0),
387 transform(0),
388 index(0),
389 user_metadata_size(0),
390 user_metadata_ptr(0),
391 release_fence_mask(0),
392 reserved{0} {}
393#endif
371 // Timestamp of the frame. 394 // Timestamp of the frame.
372 int64_t timestamp; 395 int64_t timestamp;
373 396
@@ -391,10 +414,32 @@ struct DvrNativeBufferMetadata {
391 // android/native_window.h 414 // android/native_window.h
392 int32_t transform; 415 int32_t transform;
393 416
394 // Reserved bytes for so that the struct is forward compatible. 417 // The index of the frame.
395 int32_t reserved[16]; 418 int64_t index;
419
420 // Size of additional metadata requested by user.
421 uint64_t user_metadata_size;
422
423 // Raw memory address of the additional user defined metadata. Only valid when
424 // user_metadata_size is non-zero.
425 uint64_t user_metadata_ptr;
426
427 // Only applicable for metadata retrieved from GainAsync. This indicates which
428 // consumer has pending fence that producer should epoll on.
429 uint64_t release_fence_mask;
430
431 // Reserved bytes for so that the struct is forward compatible and padding to
432 // 104 bytes so the size is a multiple of 8.
433 int32_t reserved[8];
396}; 434};
397 435
436#ifdef __cplusplus
437// Warning: DvrNativeBufferMetadata is part of the DVR API and changing its size
438// will cause compatiblity issues between different DVR API releases.
439static_assert(sizeof(DvrNativeBufferMetadata) == 104,
440 "Unexpected size for DvrNativeBufferMetadata");
441#endif
442
398struct DvrApi_v1 { 443struct DvrApi_v1 {
399// Defines an API entry for V1 (no version suffix). 444// Defines an API entry for V1 (no version suffix).
400#define DVR_V1_API_ENTRY(name) Dvr##name##Ptr name 445#define DVR_V1_API_ENTRY(name) Dvr##name##Ptr name
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index a9302a756..887766a53 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -42,6 +42,7 @@ cc_test {
42 "dvr_named_buffer-test.cpp", 42 "dvr_named_buffer-test.cpp",
43 ], 43 ],
44 44
45 header_libs: ["libdvr_headers"],
45 static_libs: static_libraries, 46 static_libs: static_libraries,
46 shared_libs: shared_libraries, 47 shared_libs: shared_libraries,
47 cflags: [ 48 cflags: [
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index f1c5e4891..62cd8d4e5 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -131,7 +131,7 @@ TEST_F(DvrBufferQueueTest, GainBuffer) {
131 DvrWriteBuffer* wb = nullptr; 131 DvrWriteBuffer* wb = nullptr;
132 EXPECT_FALSE(dvrWriteBufferIsValid(wb)); 132 EXPECT_FALSE(dvrWriteBufferIsValid(wb));
133 133
134 DvrNativeBufferMetadata meta = {0}; 134 DvrNativeBufferMetadata meta;
135 int fence_fd = -1; 135 int fence_fd = -1;
136 ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta, 136 ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta,
137 &fence_fd); 137 &fence_fd);
@@ -150,8 +150,8 @@ TEST_F(DvrBufferQueueTest, AcquirePostGainRelease) {
150 DvrReadBufferQueue* read_queue = nullptr; 150 DvrReadBufferQueue* read_queue = nullptr;
151 DvrReadBuffer* rb = nullptr; 151 DvrReadBuffer* rb = nullptr;
152 DvrWriteBuffer* wb = nullptr; 152 DvrWriteBuffer* wb = nullptr;
153 DvrNativeBufferMetadata meta1 = {0}; 153 DvrNativeBufferMetadata meta1;
154 DvrNativeBufferMetadata meta2 = {0}; 154 DvrNativeBufferMetadata meta2;
155 int fence_fd = -1; 155 int fence_fd = -1;
156 156
157 ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue); 157 ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
@@ -180,7 +180,7 @@ TEST_F(DvrBufferQueueTest, AcquirePostGainRelease) {
180 wb = nullptr; 180 wb = nullptr;
181 181
182 // Acquire buffer for reading. 182 // Acquire buffer for reading.
183 ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/0, &rb, &meta2, 183 ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10, &rb, &meta2,
184 &fence_fd); 184 &fence_fd);
185 ASSERT_EQ(ret, 0); 185 ASSERT_EQ(ret, 0);
186 ASSERT_NE(rb, nullptr); 186 ASSERT_NE(rb, nullptr);
@@ -245,7 +245,7 @@ TEST_F(DvrBufferQueueTest, ResizeBuffer) {
245 245
246 int fence_fd = -1; 246 int fence_fd = -1;
247 247
248 DvrNativeBufferMetadata meta = {0}; 248 DvrNativeBufferMetadata meta;
249 DvrReadBufferQueue* read_queue = nullptr; 249 DvrReadBufferQueue* read_queue = nullptr;
250 DvrWriteBuffer* wb1 = nullptr; 250 DvrWriteBuffer* wb1 = nullptr;
251 DvrWriteBuffer* wb2 = nullptr; 251 DvrWriteBuffer* wb2 = nullptr;
@@ -400,7 +400,7 @@ TEST_F(DvrBufferQueueTest, StableBufferIdAndHardwareBuffer) {
400 // This test runs the following operations many many times. Thus we prefer to 400 // This test runs the following operations many many times. Thus we prefer to
401 // use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output. 401 // use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output.
402 std::function<void(size_t i)> Gain = [&](size_t i) { 402 std::function<void(size_t i)> Gain = [&](size_t i) {
403 int ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, 403 int ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/10,
404 &wbs[i], &metas[i], &fence_fd); 404 &wbs[i], &metas[i], &fence_fd);
405 ASSERT_EQ(ret, 0); 405 ASSERT_EQ(ret, 0);
406 ASSERT_LT(fence_fd, 0); // expect invalid fence. 406 ASSERT_LT(fence_fd, 0); // expect invalid fence.
@@ -434,7 +434,7 @@ TEST_F(DvrBufferQueueTest, StableBufferIdAndHardwareBuffer) {
434 }; 434 };
435 435
436 std::function<void(size_t i)> Acquire = [&](size_t i) { 436 std::function<void(size_t i)> Acquire = [&](size_t i) {
437 int ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/0, 437 int ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10,
438 &rbs[i], &metas[i], &fence_fd); 438 &rbs[i], &metas[i], &fence_fd);
439 ASSERT_EQ(ret, 0); 439 ASSERT_EQ(ret, 0);
440 ASSERT_LT(fence_fd, 0); // expect invalid fence. 440 ASSERT_LT(fence_fd, 0); // expect invalid fence.
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 8fce14030..10c0b31c5 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -36,6 +36,7 @@ cc_test {
36 "variant_tests.cpp", 36 "variant_tests.cpp",
37 ], 37 ],
38 static_libs: [ 38 static_libs: [
39 "libcutils",
39 "libgmock", 40 "libgmock",
40 "libpdx", 41 "libpdx",
41 "liblog", 42 "liblog",
diff --git a/libs/vr/libpdx/private/pdx/client_channel.h b/libs/vr/libpdx/private/pdx/client_channel.h
index dbfd626d6..10a49bb8d 100644
--- a/libs/vr/libpdx/private/pdx/client_channel.h
+++ b/libs/vr/libpdx/private/pdx/client_channel.h
@@ -1,6 +1,8 @@
1#ifndef ANDROID_PDX_CLIENT_CHANNEL_H_ 1#ifndef ANDROID_PDX_CLIENT_CHANNEL_H_
2#define ANDROID_PDX_CLIENT_CHANNEL_H_ 2#define ANDROID_PDX_CLIENT_CHANNEL_H_
3 3
4#include <vector>
5
4#include <pdx/channel_handle.h> 6#include <pdx/channel_handle.h>
5#include <pdx/file_handle.h> 7#include <pdx/file_handle.h>
6#include <pdx/status.h> 8#include <pdx/status.h>
@@ -20,6 +22,15 @@ class ClientChannel {
20 virtual int event_fd() const = 0; 22 virtual int event_fd() const = 0;
21 virtual Status<int> GetEventMask(int events) = 0; 23 virtual Status<int> GetEventMask(int events) = 0;
22 24
25 struct EventSource {
26 int event_fd;
27 int event_mask;
28 };
29
30 // Returns a set of event-generating fds with and event mask for each. These
31 // fds are owned by the ClientChannel and must never be closed by the caller.
32 virtual std::vector<EventSource> GetEventSources() const = 0;
33
23 virtual LocalChannelHandle& GetChannelHandle() = 0; 34 virtual LocalChannelHandle& GetChannelHandle() = 0;
24 virtual void* AllocateTransactionState() = 0; 35 virtual void* AllocateTransactionState() = 0;
25 virtual void FreeTransactionState(void* state) = 0; 36 virtual void FreeTransactionState(void* state) = 0;
diff --git a/libs/vr/libpdx/private/pdx/mock_client_channel.h b/libs/vr/libpdx/private/pdx/mock_client_channel.h
index 561c939da..49e0682bc 100644
--- a/libs/vr/libpdx/private/pdx/mock_client_channel.h
+++ b/libs/vr/libpdx/private/pdx/mock_client_channel.h
@@ -11,6 +11,7 @@ class MockClientChannel : public ClientChannel {
11 public: 11 public:
12 MOCK_CONST_METHOD0(GetIpcTag, uint32_t()); 12 MOCK_CONST_METHOD0(GetIpcTag, uint32_t());
13 MOCK_CONST_METHOD0(event_fd, int()); 13 MOCK_CONST_METHOD0(event_fd, int());
14 MOCK_CONST_METHOD0(GetEventSources, std::vector<EventSource>());
14 MOCK_METHOD1(GetEventMask, Status<int>(int)); 15 MOCK_METHOD1(GetEventMask, Status<int>(int));
15 MOCK_METHOD0(GetChannelHandle, LocalChannelHandle&()); 16 MOCK_METHOD0(GetChannelHandle, LocalChannelHandle&());
16 MOCK_METHOD0(AllocateTransactionState, void*()); 17 MOCK_METHOD0(AllocateTransactionState, void*());
diff --git a/libs/vr/libpdx/private/pdx/trace.h b/libs/vr/libpdx/private/pdx/trace.h
index ebe8491eb..c687fd625 100644
--- a/libs/vr/libpdx/private/pdx/trace.h
+++ b/libs/vr/libpdx/private/pdx/trace.h
@@ -1,35 +1,82 @@
1#ifndef ANDROID_PDX_TRACE_H_ 1#ifndef ANDROID_PDX_TRACE_H_
2#define ANDROID_PDX_TRACE_H_ 2#define ANDROID_PDX_TRACE_H_
3 3
4// Tracing utilities for libpdx. Tracing in the service framework is enabled 4#include <array>
5// under these conditions:
6// 1. ATRACE_TAG is defined, AND
7// 2. ATRACE_TAG does not equal ATRACE_TAG_NEVER, AND
8// 3. PDX_TRACE_ENABLED is defined, AND
9// 4. PDX_TRACE_ENABLED is equal to logical true.
10//
11// If any of these conditions are not met tracing is completely removed from the
12// library and headers.
13
14// If ATRACE_TAG is not defined, default to never.
15#ifndef ATRACE_TAG
16#define ATRACE_TAG ATRACE_TAG_NEVER
17#endif
18 5
19// Include tracing functions after the trace tag is defined.
20#include <utils/Trace.h> 6#include <utils/Trace.h>
21 7
22// If PDX_TRACE_ENABLED is not defined, default to off. 8// Enables internal tracing in libpdx. This is disabled by default to avoid
23#ifndef PDX_TRACE_ENABLED 9// spamming the trace buffers during normal trace activities. libpdx must be
24#define PDX_TRACE_ENABLED 0 10// built with this set to true to enable internal tracing.
11#ifndef PDX_LIB_TRACE_ENABLED
12#define PDX_LIB_TRACE_ENABLED false
25#endif 13#endif
26 14
27#if (ATRACE_TAG) != (ATRACE_TAG_NEVER) && (PDX_TRACE_ENABLED) 15namespace android {
28#define PDX_TRACE_NAME ATRACE_NAME 16namespace pdx {
29#else 17
30#define PDX_TRACE_NAME(name) \ 18// Utility to generate scoped tracers with arguments.
31 do { \ 19class ScopedTraceArgs {
32 } while (0) 20 public:
33#endif 21 template <typename... Args>
22 ScopedTraceArgs(uint64_t tag, const char* format, Args&&... args)
23 : tag_{tag} {
24 if (atrace_is_tag_enabled(tag_)) {
25 std::array<char, 1024> buffer;
26 snprintf(buffer.data(), buffer.size(), format,
27 std::forward<Args>(args)...);
28 atrace_begin(tag_, buffer.data());
29 }
30 }
31
32 ~ScopedTraceArgs() { atrace_end(tag_); }
33
34 private:
35 uint64_t tag_;
36
37 ScopedTraceArgs(const ScopedTraceArgs&) = delete;
38 void operator=(const ScopedTraceArgs&) = delete;
39};
40
41// Utility to generate scoped tracers.
42class ScopedTrace {
43 public:
44 template <typename... Args>
45 ScopedTrace(uint64_t tag, bool enabled, const char* name)
46 : tag_{tag}, enabled_{enabled} {
47 if (enabled_)
48 atrace_begin(tag_, name);
49 }
50
51 ~ScopedTrace() {
52 if (enabled_)
53 atrace_end(tag_);
54 }
55
56 private:
57 uint64_t tag_;
58 bool enabled_;
59
60 ScopedTrace(const ScopedTrace&) = delete;
61 void operator=(const ScopedTrace&) = delete;
62};
63
64} // namespace pdx
65} // namespace android
66
67// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro
68// defined in utils/Trace.h.
69#define PDX_TRACE_FORMAT(format, ...) \
70 ::android::pdx::ScopedTraceArgs PASTE(__tracer, __LINE__) { \
71 ATRACE_TAG, format, ##__VA_ARGS__ \
72 }
73
74// TODO(eieio): Rename this to PDX_LIB_TRACE_NAME() for internal use by libpdx
75// and rename internal uses inside the library. This version is only enabled
76// when PDX_LIB_TRACE_ENABLED is true.
77#define PDX_TRACE_NAME(name) \
78 ::android::pdx::ScopedTrace PASTE(__tracer, __LINE__) { \
79 ATRACE_TAG, PDX_LIB_TRACE_ENABLED, name \
80 }
34 81
35#endif // ANDROID_PDX_TRACE_H_ 82#endif // ANDROID_PDX_TRACE_H_
diff --git a/libs/vr/libpdx_uds/channel_event_set.cpp b/libs/vr/libpdx_uds/channel_event_set.cpp
index ebe7cea7e..c68968e1f 100644
--- a/libs/vr/libpdx_uds/channel_event_set.cpp
+++ b/libs/vr/libpdx_uds/channel_event_set.cpp
@@ -1,6 +1,10 @@
1#include "private/uds/channel_event_set.h" 1#include "private/uds/channel_event_set.h"
2 2
3#include <errno.h>
3#include <log/log.h> 4#include <log/log.h>
5#include <poll.h>
6#include <sys/epoll.h>
7#include <sys/eventfd.h>
4 8
5#include <uds/ipc_helper.h> 9#include <uds/ipc_helper.h>
6 10
@@ -8,109 +12,137 @@ namespace android {
8namespace pdx { 12namespace pdx {
9namespace uds { 13namespace uds {
10 14
15namespace {
16
17template <typename FileHandleType>
18Status<void> SetupHandle(int fd, FileHandleType* handle,
19 const char* error_name) {
20 const int error = errno;
21 handle->Reset(fd);
22 if (!*handle) {
23 ALOGE("SetupHandle: Failed to setup %s handle: %s", error_name,
24 strerror(error));
25 return ErrorStatus{error};
26 }
27 return {};
28}
29
30} // anonymous namespace
31
11ChannelEventSet::ChannelEventSet() { 32ChannelEventSet::ChannelEventSet() {
12 const int flags = EFD_CLOEXEC | EFD_NONBLOCK; 33 const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
13 LocalHandle epoll_fd, event_fd; 34 LocalHandle pollin_event_fd, pollhup_event_fd;
14 35
15 if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll") || 36 if (!SetupHandle(eventfd(0, flags), &pollin_event_fd, "pollin_event") ||
16 !SetupHandle(eventfd(0, flags), &event_fd, "event")) { 37 !SetupHandle(eventfd(0, flags), &pollhup_event_fd, "pollhup_event")) {
38 return;
39 }
40
41 pollin_event_fd_ = std::move(pollin_event_fd);
42 pollhup_event_fd_ = std::move(pollhup_event_fd);
43}
44
45int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) {
46 ALOGD_IF(TRACE, "ChannelEventSet::ModifyEvents: clear_mask=%x set_mask=%x",
47 clear_mask, set_mask);
48 const int old_bits = event_bits_;
49 const int new_bits = (event_bits_ & ~clear_mask) | set_mask;
50 event_bits_ = new_bits;
51 eventfd_t value;
52
53 // Calculate which bits changed and how. Bits that haven't changed since last
54 // modification will not change the state of an eventfd.
55 const int set_bits = new_bits & ~old_bits;
56 const int clear_bits = ~new_bits & old_bits;
57
58 if (set_bits & EPOLLIN)
59 eventfd_write(pollin_event_fd_.Get(), 1);
60 else if (clear_bits & EPOLLIN)
61 eventfd_read(pollin_event_fd_.Get(), &value);
62
63 if (set_bits & EPOLLHUP)
64 eventfd_write(pollhup_event_fd_.Get(), 1);
65 else if (clear_bits & EPOLLHUP)
66 eventfd_read(pollhup_event_fd_.Get(), &value);
67
68 return 0;
69}
70
71ChannelEventReceiver::ChannelEventReceiver(LocalHandle data_fd,
72 LocalHandle pollin_event_fd,
73 LocalHandle pollhup_event_fd) {
74 LocalHandle epoll_fd;
75 if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll")) {
17 return; 76 return;
18 } 77 }
19 78
20 epoll_event event; 79 epoll_event event;
21 event.events = 0; 80 event.events = EPOLLHUP | EPOLLRDHUP;
22 event.data.u32 = 0; 81 event.data.u32 = 0;
23 if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_fd.Get(), &event) < 0) { 82 if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) {
24 const int error = errno; 83 const int error = errno;
25 ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s", 84 ALOGE("ChannelEventSet::ChannelEventSet: Failed to add data_fd: %s",
26 strerror(error)); 85 strerror(error));
27 return; 86 return;
28 } 87 }
29 88
30 epoll_fd_ = std::move(epoll_fd); 89 event.events = EPOLLIN;
31 event_fd_ = std::move(event_fd); 90 event.data.u32 = 0;
32} 91 if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollin_event_fd.Get(), &event) <
33 92 0) {
34Status<void> ChannelEventSet::AddDataFd(const LocalHandle& data_fd) {
35 epoll_event event;
36 event.events = EPOLLHUP | EPOLLRDHUP;
37 event.data.u32 = event.events;
38 if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) {
39 const int error = errno; 93 const int error = errno;
40 ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s", 94 ALOGE("ChannelEventSet::ChannelEventSet: Failed to add pollin_event_fd: %s",
41 strerror(error)); 95 strerror(error));
42 return ErrorStatus{error}; 96 return;
43 } else {
44 return {};
45 } 97 }
46}
47 98
48int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) { 99 event.events = EPOLLIN;
49 ALOGD_IF(TRACE, "ChannelEventSet::ModifyEvents: clear_mask=%x set_mask=%x", 100 event.data.u32 = 0;
50 clear_mask, set_mask); 101 if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollhup_event_fd.Get(), &event) <
51 const int old_bits = event_bits_; 102 0) {
52 const int new_bits = (event_bits_ & ~clear_mask) | set_mask; 103 const int error = errno;
53 event_bits_ = new_bits; 104 ALOGE(
54 105 "ChannelEventSet::ChannelEventSet: Failed to add pollhup_event_fd: %s",
55 // If anything changed clear the event and update the event mask. 106 strerror(error));
56 if (old_bits != new_bits) { 107 return;
57 eventfd_t value;
58 eventfd_read(event_fd_.Get(), &value);
59
60 epoll_event event;
61 event.events = POLLIN;
62 event.data.u32 = event_bits_;
63 if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, event_fd_.Get(), &event) <
64 0) {
65 const int error = errno;
66 ALOGE("ChannelEventSet::AddEventHandle: Failed to update event: %s",
67 strerror(error));
68 return -error;
69 }
70 } 108 }
71 109
72 // If there are any bits set, re-trigger the eventfd. 110 pollin_event_fd_ = std::move(pollin_event_fd);
73 if (new_bits) 111 pollhup_event_fd_ = std::move(pollhup_event_fd);
74 eventfd_write(event_fd_.Get(), 1); 112 data_fd_ = std::move(data_fd);
75 113 epoll_fd_ = std::move(epoll_fd);
76 return 0;
77} 114}
78 115
79Status<void> ChannelEventSet::SetupHandle(int fd, LocalHandle* handle, 116Status<int> ChannelEventReceiver::PollPendingEvents(int timeout_ms) const {
80 const char* error_name) { 117 std::array<pollfd, 3> pfds = {{{pollin_event_fd_.Get(), POLLIN, 0},
81 const int error = errno; 118 {pollhup_event_fd_.Get(), POLLIN, 0},
82 handle->Reset(fd); 119 {data_fd_.Get(), POLLHUP | POLLRDHUP, 0}}};
83 if (!*handle) { 120 if (RETRY_EINTR(poll(pfds.data(), pfds.size(), timeout_ms)) < 0) {
84 ALOGE("ChannelEventSet::SetupHandle: Failed to setup %s handle: %s", 121 const int error = errno;
85 error_name, strerror(error)); 122 ALOGE(
123 "ChannelEventReceiver::PollPendingEvents: Failed to poll for events: "
124 "%s",
125 strerror(error));
86 return ErrorStatus{error}; 126 return ErrorStatus{error};
87 } 127 }
88 return {}; 128
129 const int event_mask =
130 ((pfds[0].revents & POLLIN) ? EPOLLIN : 0) |
131 ((pfds[1].revents & POLLIN) ? EPOLLHUP : 0) |
132 ((pfds[2].revents & (POLLHUP | POLLRDHUP)) ? EPOLLHUP : 0);
133 return {event_mask};
89} 134}
90 135
91Status<int> ChannelEventReceiver::GetPendingEvents() const { 136Status<int> ChannelEventReceiver::GetPendingEvents() const {
92 constexpr long kTimeoutMs = 0; 137 constexpr long kTimeoutMs = 0;
93 epoll_event event; 138 return PollPendingEvents(kTimeoutMs);
94 const int count = 139}
95 RETRY_EINTR(epoll_wait(epoll_fd_.Get(), &event, 1, kTimeoutMs));
96
97 Status<int> status;
98 if (count < 0) {
99 status.SetError(errno);
100 ALOGE("ChannelEventReceiver::GetPendingEvents: Failed to get events: %s",
101 status.GetErrorMessage().c_str());
102 return status;
103 } else if (count == 0) {
104 status.SetError(ETIMEDOUT);
105 return status;
106 }
107
108 const int mask_out = event.data.u32;
109 ALOGD_IF(TRACE, "ChannelEventReceiver::GetPendingEvents: mask_out=%x",
110 mask_out);
111 140
112 status.SetValue(mask_out); 141std::vector<ClientChannel::EventSource> ChannelEventReceiver::GetEventSources()
113 return status; 142 const {
143 return {{data_fd_.Get(), EPOLLHUP | EPOLLRDHUP},
144 {pollin_event_fd_.Get(), EPOLLIN},
145 {pollhup_event_fd_.Get(), POLLIN}};
114} 146}
115 147
116} // namespace uds 148} // namespace uds
diff --git a/libs/vr/libpdx_uds/channel_manager.cpp b/libs/vr/libpdx_uds/channel_manager.cpp
index afc0a4f04..43ebe0502 100644
--- a/libs/vr/libpdx_uds/channel_manager.cpp
+++ b/libs/vr/libpdx_uds/channel_manager.cpp
@@ -22,18 +22,26 @@ void ChannelManager::CloseHandle(int32_t handle) {
22} 22}
23 23
24LocalChannelHandle ChannelManager::CreateHandle(LocalHandle data_fd, 24LocalChannelHandle ChannelManager::CreateHandle(LocalHandle data_fd,
25 LocalHandle event_fd) { 25 LocalHandle pollin_event_fd,
26 if (data_fd && event_fd) { 26 LocalHandle pollhup_event_fd) {
27 if (data_fd && pollin_event_fd && pollhup_event_fd) {
27 std::lock_guard<std::mutex> autolock(mutex_); 28 std::lock_guard<std::mutex> autolock(mutex_);
28 int32_t handle = data_fd.Get(); 29 const int32_t handle = data_fd.Get();
29 channels_.emplace(handle, 30 channels_.emplace(
30 ChannelData{std::move(data_fd), std::move(event_fd)}); 31 handle,
32 ChannelEventReceiver{std::move(data_fd), std::move(pollin_event_fd),
33 std::move(pollhup_event_fd)});
31 return LocalChannelHandle(this, handle); 34 return LocalChannelHandle(this, handle);
35 } else {
36 ALOGE(
37 "ChannelManager::CreateHandle: Invalid arguments: data_fd=%d "
38 "pollin_event_fd=%d pollhup_event_fd=%d",
39 data_fd.Get(), pollin_event_fd.Get(), pollhup_event_fd.Get());
40 return LocalChannelHandle(nullptr, -1);
32 } 41 }
33 return LocalChannelHandle(nullptr, -1);
34} 42}
35 43
36ChannelManager::ChannelData* ChannelManager::GetChannelData(int32_t handle) { 44ChannelEventReceiver* ChannelManager::GetChannelData(int32_t handle) {
37 std::lock_guard<std::mutex> autolock(mutex_); 45 std::lock_guard<std::mutex> autolock(mutex_);
38 auto channel = channels_.find(handle); 46 auto channel = channels_.find(handle);
39 return channel != channels_.end() ? &channel->second : nullptr; 47 return channel != channels_.end() ? &channel->second : nullptr;
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 3f785fa62..2e9c1def3 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -33,7 +33,9 @@ struct TransactionState {
33 } else if (static_cast<size_t>(index) < response.channels.size()) { 33 } else if (static_cast<size_t>(index) < response.channels.size()) {
34 auto& channel_info = response.channels[index]; 34 auto& channel_info = response.channels[index];
35 *handle = ChannelManager::Get().CreateHandle( 35 *handle = ChannelManager::Get().CreateHandle(
36 std::move(channel_info.data_fd), std::move(channel_info.event_fd)); 36 std::move(channel_info.data_fd),
37 std::move(channel_info.pollin_event_fd),
38 std::move(channel_info.pollhup_event_fd));
37 } else { 39 } else {
38 return false; 40 return false;
39 } 41 }
@@ -53,9 +55,9 @@ struct TransactionState {
53 55
54 if (auto* channel_data = 56 if (auto* channel_data =
55 ChannelManager::Get().GetChannelData(handle.value())) { 57 ChannelManager::Get().GetChannelData(handle.value())) {
56 ChannelInfo<BorrowedHandle> channel_info; 58 ChannelInfo<BorrowedHandle> channel_info{
57 channel_info.data_fd.Reset(handle.value()); 59 channel_data->data_fd(), channel_data->pollin_event_fd(),
58 channel_info.event_fd = channel_data->event_receiver.event_fd(); 60 channel_data->pollhup_event_fd()};
59 request.channels.push_back(std::move(channel_info)); 61 request.channels.push_back(std::move(channel_info));
60 return request.channels.size() - 1; 62 return request.channels.size() - 1;
61 } else { 63 } else {
diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp
index 433f45976..09dc7beb7 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -139,20 +139,33 @@ Status<std::unique_ptr<pdx::ClientChannel>> ClientChannelFactory::Connect(
139 139
140 RequestHeader<BorrowedHandle> request; 140 RequestHeader<BorrowedHandle> request;
141 InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false); 141 InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false);
142
142 status = SendData(socket_.Borrow(), request); 143 status = SendData(socket_.Borrow(), request);
143 if (!status) 144 if (!status)
144 return status.error_status(); 145 return status.error_status();
146
145 ResponseHeader<LocalHandle> response; 147 ResponseHeader<LocalHandle> response;
146 status = ReceiveData(socket_.Borrow(), &response); 148 status = ReceiveData(socket_.Borrow(), &response);
147 if (!status) 149 if (!status)
148 return status.error_status(); 150 return status.error_status();
149 int ref = response.ret_code; 151 else if (response.ret_code < 0 || response.channels.size() != 1)
150 if (ref < 0 || static_cast<size_t>(ref) > response.file_descriptors.size()) 152 return ErrorStatus(EIO);
153
154 LocalHandle pollin_event_fd = std::move(response.channels[0].pollin_event_fd);
155 LocalHandle pollhup_event_fd =
156 std::move(response.channels[0].pollhup_event_fd);
157
158 if (!pollin_event_fd || !pollhup_event_fd) {
159 ALOGE(
160 "ClientChannelFactory::Connect: Required fd was not returned from the "
161 "service: pollin_event_fd=%d pollhup_event_fd=%d",
162 pollin_event_fd.Get(), pollhup_event_fd.Get());
151 return ErrorStatus(EIO); 163 return ErrorStatus(EIO);
164 }
152 165
153 LocalHandle event_fd = std::move(response.file_descriptors[ref]);
154 return ClientChannel::Create(ChannelManager::Get().CreateHandle( 166 return ClientChannel::Create(ChannelManager::Get().CreateHandle(
155 std::move(socket_), std::move(event_fd))); 167 std::move(socket_), std::move(pollin_event_fd),
168 std::move(pollhup_event_fd)));
156} 169}
157 170
158} // namespace uds 171} // namespace uds
diff --git a/libs/vr/libpdx_uds/private/uds/channel_event_set.h b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
index 1f464d5f9..99e75028d 100644
--- a/libs/vr/libpdx_uds/private/uds/channel_event_set.h
+++ b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
@@ -1,11 +1,9 @@
1#ifndef ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_ 1#ifndef ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_
2#define ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_ 2#define ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_
3 3
4#include <errno.h> 4#include <vector>
5#include <poll.h>
6#include <sys/epoll.h>
7#include <sys/eventfd.h>
8 5
6#include <pdx/client_channel.h>
9#include <pdx/file_handle.h> 7#include <pdx/file_handle.h>
10#include <pdx/status.h> 8#include <pdx/status.h>
11 9
@@ -19,21 +17,20 @@ class ChannelEventSet {
19 ChannelEventSet(ChannelEventSet&&) = default; 17 ChannelEventSet(ChannelEventSet&&) = default;
20 ChannelEventSet& operator=(ChannelEventSet&&) = default; 18 ChannelEventSet& operator=(ChannelEventSet&&) = default;
21 19
22 BorrowedHandle event_fd() const { return epoll_fd_.Borrow(); } 20 BorrowedHandle pollin_event_fd() const { return pollin_event_fd_.Borrow(); }
21 BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); }
23 22
24 explicit operator bool() const { return !!epoll_fd_ && !!event_fd_; } 23 explicit operator bool() const {
24 return !!pollin_event_fd_ && !!pollhup_event_fd_;
25 }
25 26
26 Status<void> AddDataFd(const LocalHandle& data_fd);
27 int ModifyEvents(int clear_mask, int set_mask); 27 int ModifyEvents(int clear_mask, int set_mask);
28 28
29 private: 29 private:
30 LocalHandle epoll_fd_; 30 LocalHandle pollin_event_fd_;
31 LocalHandle event_fd_; 31 LocalHandle pollhup_event_fd_;
32 uint32_t event_bits_ = 0; 32 uint32_t event_bits_ = 0;
33 33
34 static Status<void> SetupHandle(int fd, LocalHandle* handle,
35 const char* error_name);
36
37 ChannelEventSet(const ChannelEventSet&) = delete; 34 ChannelEventSet(const ChannelEventSet&) = delete;
38 void operator=(const ChannelEventSet&) = delete; 35 void operator=(const ChannelEventSet&) = delete;
39}; 36};
@@ -41,14 +38,31 @@ class ChannelEventSet {
41class ChannelEventReceiver { 38class ChannelEventReceiver {
42 public: 39 public:
43 ChannelEventReceiver() = default; 40 ChannelEventReceiver() = default;
44 ChannelEventReceiver(LocalHandle epoll_fd) : epoll_fd_{std::move(epoll_fd)} {} 41 ChannelEventReceiver(LocalHandle data_fd, LocalHandle pollin_event_fd,
42 LocalHandle pollhup_event_fd);
45 ChannelEventReceiver(ChannelEventReceiver&&) = default; 43 ChannelEventReceiver(ChannelEventReceiver&&) = default;
46 ChannelEventReceiver& operator=(ChannelEventReceiver&&) = default; 44 ChannelEventReceiver& operator=(ChannelEventReceiver&&) = default;
47 45
46 explicit operator bool() const {
47 return !!pollin_event_fd_ && !!pollhup_event_fd_ && !!data_fd_ &&
48 !!epoll_fd_;
49 }
50
48 BorrowedHandle event_fd() const { return epoll_fd_.Borrow(); } 51 BorrowedHandle event_fd() const { return epoll_fd_.Borrow(); }
52
53 BorrowedHandle pollin_event_fd() const { return pollin_event_fd_.Borrow(); }
54 BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); }
55 BorrowedHandle data_fd() const { return data_fd_.Borrow(); }
56
49 Status<int> GetPendingEvents() const; 57 Status<int> GetPendingEvents() const;
58 Status<int> PollPendingEvents(int timeout_ms) const;
59
60 std::vector<ClientChannel::EventSource> GetEventSources() const;
50 61
51 private: 62 private:
63 LocalHandle data_fd_;
64 LocalHandle pollin_event_fd_;
65 LocalHandle pollhup_event_fd_;
52 LocalHandle epoll_fd_; 66 LocalHandle epoll_fd_;
53 67
54 ChannelEventReceiver(const ChannelEventReceiver&) = delete; 68 ChannelEventReceiver(const ChannelEventReceiver&) = delete;
diff --git a/libs/vr/libpdx_uds/private/uds/channel_manager.h b/libs/vr/libpdx_uds/private/uds/channel_manager.h
index 2aca41421..5f6a51434 100644
--- a/libs/vr/libpdx_uds/private/uds/channel_manager.h
+++ b/libs/vr/libpdx_uds/private/uds/channel_manager.h
@@ -16,13 +16,11 @@ class ChannelManager : public ChannelManagerInterface {
16 public: 16 public:
17 static ChannelManager& Get(); 17 static ChannelManager& Get();
18 18
19 LocalChannelHandle CreateHandle(LocalHandle data_fd, LocalHandle event_fd); 19 LocalChannelHandle CreateHandle(LocalHandle data_fd,
20 struct ChannelData { 20 LocalHandle pollin_event_fd,
21 LocalHandle data_fd; 21 LocalHandle pollhup_event_fd);
22 ChannelEventReceiver event_receiver;
23 };
24 22
25 ChannelData* GetChannelData(int32_t handle); 23 ChannelEventReceiver* GetChannelData(int32_t handle);
26 24
27 private: 25 private:
28 ChannelManager() = default; 26 ChannelManager() = default;
@@ -30,7 +28,7 @@ class ChannelManager : public ChannelManagerInterface {
30 void CloseHandle(int32_t handle) override; 28 void CloseHandle(int32_t handle) override;
31 29
32 std::mutex mutex_; 30 std::mutex mutex_;
33 std::unordered_map<int32_t, ChannelData> channels_; 31 std::unordered_map<int32_t, ChannelEventReceiver> channels_;
34}; 32};
35 33
36} // namespace uds 34} // namespace uds
diff --git a/libs/vr/libpdx_uds/private/uds/client_channel.h b/libs/vr/libpdx_uds/private/uds/client_channel.h
index 8f607f56a..7a5ddf40e 100644
--- a/libs/vr/libpdx_uds/private/uds/client_channel.h
+++ b/libs/vr/libpdx_uds/private/uds/client_channel.h
@@ -23,11 +23,19 @@ class ClientChannel : public pdx::ClientChannel {
23 uint32_t GetIpcTag() const override { return Endpoint::kIpcTag; } 23 uint32_t GetIpcTag() const override { return Endpoint::kIpcTag; }
24 24
25 int event_fd() const override { 25 int event_fd() const override {
26 return channel_data_ ? channel_data_->event_receiver.event_fd().Get() : -1; 26 return channel_data_ ? channel_data_->event_fd().Get() : -1;
27 } 27 }
28
29 std::vector<EventSource> GetEventSources() const override {
30 if (channel_data_)
31 return channel_data_->GetEventSources();
32 else
33 return {};
34 }
35
28 Status<int> GetEventMask(int /*events*/) override { 36 Status<int> GetEventMask(int /*events*/) override {
29 if (channel_data_) 37 if (channel_data_)
30 return channel_data_->event_receiver.GetPendingEvents(); 38 return channel_data_->GetPendingEvents();
31 else 39 else
32 return ErrorStatus(EINVAL); 40 return ErrorStatus(EINVAL);
33 } 41 }
@@ -74,7 +82,7 @@ class ClientChannel : public pdx::ClientChannel {
74 const iovec* receive_vector, size_t receive_count); 82 const iovec* receive_vector, size_t receive_count);
75 83
76 LocalChannelHandle channel_handle_; 84 LocalChannelHandle channel_handle_;
77 ChannelManager::ChannelData* channel_data_; 85 ChannelEventReceiver* channel_data_;
78 std::mutex socket_mutex_; 86 std::mutex socket_mutex_;
79}; 87};
80 88
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 664a0d1a1..63b5b1078 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -110,10 +110,12 @@ template <typename FileHandleType>
110class ChannelInfo { 110class ChannelInfo {
111 public: 111 public:
112 FileHandleType data_fd; 112 FileHandleType data_fd;
113 FileHandleType event_fd; 113 FileHandleType pollin_event_fd;
114 FileHandleType pollhup_event_fd;
114 115
115 private: 116 private:
116 PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, event_fd); 117 PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, pollin_event_fd,
118 pollhup_event_fd);
117}; 119};
118 120
119template <typename FileHandleType> 121template <typename FileHandleType>
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index a16381270..01ebf6519 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -7,6 +7,7 @@
7#include <mutex> 7#include <mutex>
8#include <string> 8#include <string>
9#include <unordered_map> 9#include <unordered_map>
10#include <utility>
10#include <vector> 11#include <vector>
11 12
12#include <pdx/service.h> 13#include <pdx/service.h>
@@ -139,7 +140,8 @@ class Endpoint : public pdx::Endpoint {
139 Status<void> ReenableEpollEvent(const BorrowedHandle& channel_fd); 140 Status<void> ReenableEpollEvent(const BorrowedHandle& channel_fd);
140 Channel* GetChannelState(int32_t channel_id); 141 Channel* GetChannelState(int32_t channel_id);
141 BorrowedHandle GetChannelSocketFd(int32_t channel_id); 142 BorrowedHandle GetChannelSocketFd(int32_t channel_id);
142 BorrowedHandle GetChannelEventFd(int32_t channel_id); 143 Status<std::pair<BorrowedHandle, BorrowedHandle>> GetChannelEventFd(
144 int32_t channel_id);
143 int32_t GetChannelId(const BorrowedHandle& channel_fd); 145 int32_t GetChannelId(const BorrowedHandle& channel_fd);
144 Status<void> CreateChannelSocketPair(LocalHandle* local_socket, 146 Status<void> CreateChannelSocketPair(LocalHandle* local_socket,
145 LocalHandle* remote_socket); 147 LocalHandle* remote_socket);
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 27a56f9fe..0ee77f43a 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -49,7 +49,9 @@ struct MessageState {
49 } else if (static_cast<size_t>(index) < request.channels.size()) { 49 } else if (static_cast<size_t>(index) < request.channels.size()) {
50 auto& channel_info = request.channels[index]; 50 auto& channel_info = request.channels[index];
51 *handle = ChannelManager::Get().CreateHandle( 51 *handle = ChannelManager::Get().CreateHandle(
52 std::move(channel_info.data_fd), std::move(channel_info.event_fd)); 52 std::move(channel_info.data_fd),
53 std::move(channel_info.pollin_event_fd),
54 std::move(channel_info.pollhup_event_fd));
53 } else { 55 } else {
54 return false; 56 return false;
55 } 57 }
@@ -69,9 +71,9 @@ struct MessageState {
69 71
70 if (auto* channel_data = 72 if (auto* channel_data =
71 ChannelManager::Get().GetChannelData(handle.value())) { 73 ChannelManager::Get().GetChannelData(handle.value())) {
72 ChannelInfo<BorrowedHandle> channel_info; 74 ChannelInfo<BorrowedHandle> channel_info{
73 channel_info.data_fd.Reset(handle.value()); 75 channel_data->data_fd(), channel_data->pollin_event_fd(),
74 channel_info.event_fd = channel_data->event_receiver.event_fd(); 76 channel_data->pollhup_event_fd()};
75 response.channels.push_back(std::move(channel_info)); 77 response.channels.push_back(std::move(channel_info));
76 return response.channels.size() - 1; 78 return response.channels.size() - 1;
77 } else { 79 } else {
@@ -80,12 +82,13 @@ struct MessageState {
80 } 82 }
81 83
82 Status<ChannelReference> PushChannelHandle(BorrowedHandle data_fd, 84 Status<ChannelReference> PushChannelHandle(BorrowedHandle data_fd,
83 BorrowedHandle event_fd) { 85 BorrowedHandle pollin_event_fd,
84 if (!data_fd || !event_fd) 86 BorrowedHandle pollhup_event_fd) {
87 if (!data_fd || !pollin_event_fd || !pollhup_event_fd)
85 return ErrorStatus{EINVAL}; 88 return ErrorStatus{EINVAL};
86 ChannelInfo<BorrowedHandle> channel_info; 89 ChannelInfo<BorrowedHandle> channel_info{std::move(data_fd),
87 channel_info.data_fd = std::move(data_fd); 90 std::move(pollin_event_fd),
88 channel_info.event_fd = std::move(event_fd); 91 std::move(pollhup_event_fd)};
89 response.channels.push_back(std::move(channel_info)); 92 response.channels.push_back(std::move(channel_info));
90 return response.channels.size() - 1; 93 return response.channels.size() - 1;
91 } 94 }
@@ -287,7 +290,6 @@ Status<std::pair<int32_t, Endpoint::ChannelData*>> Endpoint::OnNewChannelLocked(
287 return ErrorStatus(errno); 290 return ErrorStatus(errno);
288 } 291 }
289 ChannelData channel_data; 292 ChannelData channel_data;
290 channel_data.event_set.AddDataFd(channel_fd);
291 channel_data.data_fd = std::move(channel_fd); 293 channel_data.data_fd = std::move(channel_fd);
292 channel_data.channel_state = channel_state; 294 channel_data.channel_state = channel_state;
293 for (;;) { 295 for (;;) {
@@ -431,18 +433,21 @@ Status<RemoteChannelHandle> Endpoint::PushChannel(Message* message,
431 return status.error_status(); 433 return status.error_status();
432 434
433 std::lock_guard<std::mutex> autolock(channel_mutex_); 435 std::lock_guard<std::mutex> autolock(channel_mutex_);
434 auto channel_data = OnNewChannelLocked(std::move(local_socket), channel); 436 auto channel_data_status =
435 if (!channel_data) 437 OnNewChannelLocked(std::move(local_socket), channel);
436 return channel_data.error_status(); 438 if (!channel_data_status)
437 *channel_id = channel_data.get().first; 439 return channel_data_status.error_status();
440
441 ChannelData* channel_data;
442 std::tie(*channel_id, channel_data) = channel_data_status.take();
438 443
439 // Flags are ignored for now. 444 // Flags are ignored for now.
440 // TODO(xiaohuit): Implement those. 445 // TODO(xiaohuit): Implement those.
441 446
442 auto* state = static_cast<MessageState*>(message->GetState()); 447 auto* state = static_cast<MessageState*>(message->GetState());
443 Status<ChannelReference> ref = state->PushChannelHandle( 448 Status<ChannelReference> ref = state->PushChannelHandle(
444 remote_socket.Borrow(), 449 remote_socket.Borrow(), channel_data->event_set.pollin_event_fd(),
445 channel_data.get().second->event_set.event_fd().Borrow()); 450 channel_data->event_set.pollhup_event_fd());
446 if (!ref) 451 if (!ref)
447 return ref.error_status(); 452 return ref.error_status();
448 state->sockets_to_close.push_back(std::move(remote_socket)); 453 state->sockets_to_close.push_back(std::move(remote_socket));
@@ -472,13 +477,15 @@ BorrowedHandle Endpoint::GetChannelSocketFd(int32_t channel_id) {
472 return handle; 477 return handle;
473} 478}
474 479
475BorrowedHandle Endpoint::GetChannelEventFd(int32_t channel_id) { 480Status<std::pair<BorrowedHandle, BorrowedHandle>> Endpoint::GetChannelEventFd(
481 int32_t channel_id) {
476 std::lock_guard<std::mutex> autolock(channel_mutex_); 482 std::lock_guard<std::mutex> autolock(channel_mutex_);
477 BorrowedHandle handle;
478 auto channel_data = channels_.find(channel_id); 483 auto channel_data = channels_.find(channel_id);
479 if (channel_data != channels_.end()) 484 if (channel_data != channels_.end()) {
480 handle = channel_data->second.event_set.event_fd().Borrow(); 485 return {{channel_data->second.event_set.pollin_event_fd(),
481 return handle; 486 channel_data->second.event_set.pollhup_event_fd()}};
487 }
488 return ErrorStatus(ENOENT);
482} 489}
483 490
484int32_t Endpoint::GetChannelId(const BorrowedHandle& channel_fd) { 491int32_t Endpoint::GetChannelId(const BorrowedHandle& channel_fd) {
@@ -593,11 +600,6 @@ Status<void> Endpoint::MessageReceive(Message* message) {
593 } 600 }
594 601
595 BorrowedHandle channel_fd{event.data.fd}; 602 BorrowedHandle channel_fd{event.data.fd};
596 if (event.events & (EPOLLRDHUP | EPOLLHUP)) {
597 BuildCloseMessage(GetChannelId(channel_fd), message);
598 return {};
599 }
600
601 return ReceiveMessageForChannel(channel_fd, message); 603 return ReceiveMessageForChannel(channel_fd, message);
602} 604}
603 605
@@ -616,12 +618,23 @@ Status<void> Endpoint::MessageReply(Message* message, int return_code) {
616 if (return_code < 0) { 618 if (return_code < 0) {
617 return CloseChannel(channel_id); 619 return CloseChannel(channel_id);
618 } else { 620 } else {
619 // Reply with the event fd. 621 // Open messages do not have a payload and may not transfer any channels
620 auto push_status = state->PushFileHandle(GetChannelEventFd(channel_id)); 622 // or file descriptors on behalf of the service.
621 state->response_data.clear(); // Just in case... 623 state->response_data.clear();
622 if (!push_status) 624 state->response.file_descriptors.clear();
623 return push_status.error_status(); 625 state->response.channels.clear();
624 return_code = push_status.get(); 626
627 // Return the channel event-related fds in a single ChannelInfo entry
628 // with an empty data_fd member.
629 auto status = GetChannelEventFd(channel_id);
630 if (!status)
631 return status.error_status();
632
633 auto handles = status.take();
634 state->response.channels.push_back({BorrowedHandle(),
635 std::move(handles.first),
636 std::move(handles.second)});
637 return_code = 0;
625 } 638 }
626 break; 639 break;
627 } 640 }
diff --git a/libs/vr/libpdx_uds/service_framework_tests.cpp b/libs/vr/libpdx_uds/service_framework_tests.cpp
index 5943b0a1b..27427162f 100644
--- a/libs/vr/libpdx_uds/service_framework_tests.cpp
+++ b/libs/vr/libpdx_uds/service_framework_tests.cpp
@@ -1,5 +1,6 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3#include <poll.h>
3#include <sys/epoll.h> 4#include <sys/epoll.h>
4#include <sys/eventfd.h> 5#include <sys/eventfd.h>
5#include <unistd.h> 6#include <unistd.h>
@@ -506,6 +507,37 @@ TEST_F(ServiceFrameworkTest, Impulse) {
506 EXPECT_EQ(-EINVAL, client->SendAsync(invalid_pointer, sizeof(int))); 507 EXPECT_EQ(-EINVAL, client->SendAsync(invalid_pointer, sizeof(int)));
507} 508}
508 509
510// Test impulses.
511TEST_F(ServiceFrameworkTest, ImpulseHangup) {
512 // Create a test service and add it to the dispatcher.
513 auto service = TestService::Create(kTestService1);
514 ASSERT_NE(nullptr, service);
515 ASSERT_EQ(0, dispatcher_->AddService(service));
516
517 auto client = TestClient::Create(kTestService1);
518 ASSERT_NE(nullptr, client);
519
520 const int kMaxIterations = 1000;
521 for (int i = 0; i < kMaxIterations; i++) {
522 auto impulse_client = TestClient::Create(kTestService1);
523 ASSERT_NE(nullptr, impulse_client);
524
525 const uint8_t a = (i >> 0) & 0xff;
526 const uint8_t b = (i >> 8) & 0xff;
527 const uint8_t c = (i >> 16) & 0xff;
528 const uint8_t d = (i >> 24) & 0xff;
529 ImpulsePayload expected_payload = {{a, b, c, d}};
530 EXPECT_EQ(0, impulse_client->SendAsync(expected_payload.data(), 4));
531
532 // Hangup the impulse test client, then send a sync message over client to
533 // make sure the hangup message is handled before checking the impulse
534 // payload.
535 impulse_client = nullptr;
536 client->GetThisChannelId();
537 EXPECT_EQ(expected_payload, service->GetImpulsePayload());
538 }
539}
540
509// Test Message::PushChannel/Service::PushChannel API. 541// Test Message::PushChannel/Service::PushChannel API.
510TEST_F(ServiceFrameworkTest, PushChannel) { 542TEST_F(ServiceFrameworkTest, PushChannel) {
511 // Create a test service and add it to the dispatcher. 543 // Create a test service and add it to the dispatcher.
@@ -574,9 +606,7 @@ TEST_F(ServiceFrameworkTest, Ids) {
574 606
575 pid_t process_id2; 607 pid_t process_id2;
576 608
577 std::thread thread([&]() { 609 std::thread thread([&]() { process_id2 = client->GetThisProcessId(); });
578 process_id2 = client->GetThisProcessId();
579 });
580 thread.join(); 610 thread.join();
581 611
582 EXPECT_LT(2, process_id2); 612 EXPECT_LT(2, process_id2);
@@ -614,15 +644,15 @@ TEST_F(ServiceFrameworkTest, PollIn) {
614 auto client = TestClient::Create(kTestService1); 644 auto client = TestClient::Create(kTestService1);
615 ASSERT_NE(nullptr, client); 645 ASSERT_NE(nullptr, client);
616 646
617 epoll_event event; 647 pollfd pfd{client->event_fd(), POLLIN, 0};
618 int count = epoll_wait(client->event_fd(), &event, 1, 0); 648 int count = poll(&pfd, 1, 0);
619 ASSERT_EQ(0, count); 649 ASSERT_EQ(0, count);
620 650
621 client->SendPollInEvent(); 651 client->SendPollInEvent();
622 652
623 count = epoll_wait(client->event_fd(), &event, 1, -1); 653 count = poll(&pfd, 1, 10000 /*10s*/);
624 ASSERT_EQ(1, count); 654 ASSERT_EQ(1, count);
625 ASSERT_TRUE((EPOLLIN & event.events) != 0); 655 ASSERT_TRUE((POLLIN & pfd.revents) != 0);
626} 656}
627 657
628TEST_F(ServiceFrameworkTest, PollHup) { 658TEST_F(ServiceFrameworkTest, PollHup) {
@@ -635,15 +665,15 @@ TEST_F(ServiceFrameworkTest, PollHup) {
635 auto client = TestClient::Create(kTestService1); 665 auto client = TestClient::Create(kTestService1);
636 ASSERT_NE(nullptr, client); 666 ASSERT_NE(nullptr, client);
637 667
638 epoll_event event; 668 pollfd pfd{client->event_fd(), POLLIN, 0};
639 int count = epoll_wait(client->event_fd(), &event, 1, 0); 669 int count = poll(&pfd, 1, 0);
640 ASSERT_EQ(0, count); 670 ASSERT_EQ(0, count);
641 671
642 client->SendPollHupEvent(); 672 client->SendPollHupEvent();
643 673
644 count = epoll_wait(client->event_fd(), &event, 1, -1); 674 count = poll(&pfd, 1, 10000 /*10s*/);
645 ASSERT_EQ(1, count); 675 ASSERT_EQ(1, count);
646 auto event_status = client->GetEventMask(event.events); 676 auto event_status = client->GetEventMask(pfd.revents);
647 ASSERT_TRUE(event_status.ok()); 677 ASSERT_TRUE(event_status.ok());
648 ASSERT_TRUE((EPOLLHUP & event_status.get()) != 0); 678 ASSERT_TRUE((EPOLLHUP & event_status.get()) != 0);
649} 679}
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index 3d132c95e..87c823e5b 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -213,8 +213,8 @@ Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
213 ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue"); 213 ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
214 ALOGD_IF(TRACE, 214 ALOGD_IF(TRACE,
215 "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, " 215 "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
216 "meta_size_bytes=%zu", 216 "user_metadata_size=%zu",
217 surface_id(), config.meta_size_bytes); 217 surface_id(), config.user_metadata_size);
218 218
219 std::lock_guard<std::mutex> autolock(lock_); 219 std::lock_guard<std::mutex> autolock(lock_);
220 auto producer = ProducerQueue::Create(config, UsagePolicy{}); 220 auto producer = ProducerQueue::Create(config, UsagePolicy{});
@@ -280,10 +280,10 @@ std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const {
280Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue( 280Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
281 Message& /*message*/, const ProducerQueueConfig& config) { 281 Message& /*message*/, const ProducerQueueConfig& config) {
282 ATRACE_NAME("DirectDisplaySurface::OnCreateQueue"); 282 ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
283 ALOGD_IF( 283 ALOGD_IF(TRACE,
284 TRACE, 284 "DirectDisplaySurface::OnCreateQueue: surface_id=%d "
285 "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu", 285 "user_metadata_size=%zu",
286 surface_id(), config.meta_size_bytes); 286 surface_id(), config.user_metadata_size);
287 287
288 std::lock_guard<std::mutex> autolock(lock_); 288 std::lock_guard<std::mutex> autolock(lock_);
289 if (!direct_queue_) { 289 if (!direct_queue_) {
diff --git a/services/vr/bufferhubd/Android.mk b/services/vr/bufferhubd/Android.mk
index 97f0332d7..28cf53dd8 100644
--- a/services/vr/bufferhubd/Android.mk
+++ b/services/vr/bufferhubd/Android.mk
@@ -22,6 +22,9 @@ sourceFiles := \
22 consumer_queue_channel.cpp \ 22 consumer_queue_channel.cpp \
23 producer_queue_channel.cpp \ 23 producer_queue_channel.cpp \
24 24
25headerLibraries := \
26 libdvr_headers
27
25staticLibraries := \ 28staticLibraries := \
26 libperformance \ 29 libperformance \
27 libpdx_default_transport \ 30 libpdx_default_transport \
@@ -41,6 +44,7 @@ LOCAL_SRC_FILES := $(sourceFiles)
41LOCAL_CFLAGS := -DLOG_TAG=\"bufferhubd\" 44LOCAL_CFLAGS := -DLOG_TAG=\"bufferhubd\"
42LOCAL_CFLAGS += -DTRACE=0 45LOCAL_CFLAGS += -DTRACE=0
43LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_GRAPHICS 46LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_GRAPHICS
47LOCAL_HEADER_LIBRARIES := $(headerLibraries)
44LOCAL_STATIC_LIBRARIES := $(staticLibraries) 48LOCAL_STATIC_LIBRARIES := $(staticLibraries)
45LOCAL_SHARED_LIBRARIES := $(sharedLibraries) 49LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
46LOCAL_MODULE := bufferhubd 50LOCAL_MODULE := bufferhubd
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 26843c99c..cdb1f9179 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -20,8 +20,8 @@ using android::pdx::Channel;
20using android::pdx::ErrorStatus; 20using android::pdx::ErrorStatus;
21using android::pdx::Message; 21using android::pdx::Message;
22using android::pdx::Status; 22using android::pdx::Status;
23using android::pdx::rpc::DispatchRemoteMethod;
24using android::pdx::default_transport::Endpoint; 23using android::pdx::default_transport::Endpoint;
24using android::pdx::rpc::DispatchRemoteMethod;
25 25
26namespace android { 26namespace android {
27namespace dvr { 27namespace dvr {
@@ -53,7 +53,15 @@ std::string BufferHubService::DumpState(size_t /*max_length*/) {
53 stream << " "; 53 stream << " ";
54 stream << std::setw(6) << "Format"; 54 stream << std::setw(6) << "Format";
55 stream << " "; 55 stream << " ";
56 stream << std::setw(11) << "Usage"; 56 stream << std::setw(10) << "Usage";
57 stream << " ";
58 stream << std::setw(9) << "Pending";
59 stream << " ";
60 stream << std::setw(18) << "State";
61 stream << " ";
62 stream << std::setw(18) << "Signaled";
63 stream << " ";
64 stream << std::setw(10) << "Index";
57 stream << " "; 65 stream << " ";
58 stream << "Name"; 66 stream << "Name";
59 stream << std::endl; 67 stream << std::endl;
@@ -83,46 +91,15 @@ std::string BufferHubService::DumpState(size_t /*max_length*/) {
83 stream << std::setw(8) << info.usage; 91 stream << std::setw(8) << info.usage;
84 stream << std::dec << std::setfill(' '); 92 stream << std::dec << std::setfill(' ');
85 stream << " "; 93 stream << " ";
86 stream << info.name; 94 stream << std::setw(9) << info.pending_count;
87 stream << std::endl;
88 }
89 }
90
91 stream << "Active Consumer Buffers:\n";
92 stream << std::right;
93 stream << std::setw(6) << "Id";
94 stream << " ";
95 stream << std::setw(14) << "Geometry";
96 stream << " ";
97 stream << "Name";
98 stream << std::endl;
99
100 for (const auto& channel : channels) {
101 if (channel->channel_type() == BufferHubChannel::kConsumerType) {
102 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
103
104 stream << std::right;
105 stream << std::setw(6) << info.id;
106 stream << " "; 95 stream << " ";
107 96 stream << "0x" << std::hex << std::setfill('0');
108 if (info.consumer_count == 0) { 97 stream << std::setw(16) << info.state;
109 // consumer_count is tracked by producer. When it's zero, producer must 98 stream << " ";
110 // have already hung up and the consumer is orphaned. 99 stream << "0x" << std::setw(16) << info.signaled_mask;
111 stream << std::setw(14) << "Orphaned."; 100 stream << std::dec << std::setfill(' ');
112 stream << (" channel_id=" + std::to_string(channel->channel_id())); 101 stream << " ";
113 stream << std::endl; 102 stream << std::setw(8) << info.index;
114 continue;
115 }
116
117 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
118 std::string size = std::to_string(info.width) + " B";
119 stream << std::setw(14) << size;
120 } else {
121 std::string dimensions = std::to_string(info.width) + "x" +
122 std::to_string(info.height) + "x" +
123 std::to_string(info.layer_count);
124 stream << std::setw(14) << dimensions;
125 }
126 stream << " "; 103 stream << " ";
127 stream << info.name; 104 stream << info.name;
128 stream << std::endl; 105 stream << std::endl;
@@ -184,6 +161,32 @@ std::string BufferHubService::DumpState(size_t /*max_length*/) {
184 } 161 }
185 } 162 }
186 163
164 stream << std::endl;
165 stream << "Orphaned Consumer Buffers:\n";
166 stream << std::right;
167 stream << std::setw(6) << "Id";
168 stream << " ";
169 stream << std::setw(14) << "Geometry";
170 stream << " ";
171 stream << "Name";
172 stream << std::endl;
173
174 for (const auto& channel : channels) {
175 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
176 // consumer_count is tracked by producer. When it's zero, producer must have
177 // already hung up and the consumer is orphaned.
178 if (channel->channel_type() == BufferHubChannel::kConsumerType &&
179 info.consumer_count == 0) {
180 stream << std::right;
181 stream << std::setw(6) << info.id;
182 stream << " ";
183
184 stream << std::setw(14) << "Orphaned.";
185 stream << (" channel_id=" + std::to_string(channel->channel_id()));
186 stream << std::endl;
187 }
188 }
189
187 return stream.str(); 190 return stream.str();
188} 191}
189 192
@@ -444,6 +447,7 @@ void BufferHubChannel::SignalAvailable() {
444 "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d", 447 "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
445 channel_id(), buffer_id()); 448 channel_id(), buffer_id());
446 if (!IsDetached()) { 449 if (!IsDetached()) {
450 signaled_ = true;
447 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN); 451 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
448 ALOGE_IF(!status, 452 ALOGE_IF(!status,
449 "BufferHubChannel::SignalAvailable: failed to signal availability " 453 "BufferHubChannel::SignalAvailable: failed to signal availability "
@@ -460,6 +464,7 @@ void BufferHubChannel::ClearAvailable() {
460 "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d", 464 "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
461 channel_id(), buffer_id()); 465 channel_id(), buffer_id());
462 if (!IsDetached()) { 466 if (!IsDetached()) {
467 signaled_ = false;
463 const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0); 468 const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
464 ALOGE_IF(!status, 469 ALOGE_IF(!status,
465 "BufferHubChannel::ClearAvailable: failed to clear availability " 470 "BufferHubChannel::ClearAvailable: failed to clear availability "
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index b0df11f2a..270ac9511 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -53,6 +53,10 @@ class BufferHubChannel : public pdx::Channel {
53 uint32_t layer_count = 0; 53 uint32_t layer_count = 0;
54 uint32_t format = 0; 54 uint32_t format = 0;
55 uint64_t usage = 0; 55 uint64_t usage = 0;
56 size_t pending_count = 0;
57 uint64_t state = 0;
58 uint64_t signaled_mask = 0;
59 uint64_t index = 0;
56 std::string name; 60 std::string name;
57 61
58 // Data filed for producer queue. 62 // Data filed for producer queue.
@@ -60,7 +64,9 @@ class BufferHubChannel : public pdx::Channel {
60 UsagePolicy usage_policy{0, 0, 0, 0}; 64 UsagePolicy usage_policy{0, 0, 0, 0};
61 65
62 BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height, 66 BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
63 uint32_t layer_count, uint32_t format, uint64_t usage, const std::string& name) 67 uint32_t layer_count, uint32_t format, uint64_t usage,
68 size_t pending_count, uint64_t state, uint64_t signaled_mask,
69 uint64_t index, const std::string& name)
64 : id(id), 70 : id(id),
65 type(kProducerType), 71 type(kProducerType),
66 consumer_count(consumer_count), 72 consumer_count(consumer_count),
@@ -69,6 +75,10 @@ class BufferHubChannel : public pdx::Channel {
69 layer_count(layer_count), 75 layer_count(layer_count),
70 format(format), 76 format(format),
71 usage(usage), 77 usage(usage),
78 pending_count(pending_count),
79 state(state),
80 signaled_mask(signaled_mask),
81 index(index),
72 name(name) {} 82 name(name) {}
73 83
74 BufferInfo(int id, size_t consumer_count, size_t capacity, 84 BufferInfo(int id, size_t consumer_count, size_t capacity,
@@ -101,6 +111,8 @@ class BufferHubChannel : public pdx::Channel {
101 int channel_id() const { return channel_id_; } 111 int channel_id() const { return channel_id_; }
102 bool IsDetached() const { return channel_id_ == kDetachedId; } 112 bool IsDetached() const { return channel_id_ == kDetachedId; }
103 113
114 bool signaled() const { return signaled_; }
115
104 void Detach() { 116 void Detach() {
105 if (channel_type_ == kProducerType) 117 if (channel_type_ == kProducerType)
106 channel_id_ = kDetachedId; 118 channel_id_ = kDetachedId;
@@ -124,6 +136,8 @@ class BufferHubChannel : public pdx::Channel {
124 // buffer if it is detached and re-attached to another channel. 136 // buffer if it is detached and re-attached to another channel.
125 int channel_id_; 137 int channel_id_;
126 138
139 bool signaled_;
140
127 ChannelType channel_type_; 141 ChannelType channel_type_;
128 142
129 BufferHubChannel(const BufferHubChannel&) = delete; 143 BufferHubChannel(const BufferHubChannel&) = delete;
diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp
index 161382129..b27f218eb 100644
--- a/services/vr/bufferhubd/bufferhubd.cpp
+++ b/services/vr/bufferhubd/bufferhubd.cpp
@@ -2,6 +2,7 @@
2#include <unistd.h> 2#include <unistd.h>
3 3
4#include <log/log.h> 4#include <log/log.h>
5#include <sys/resource.h>
5 6
6#include <dvr/performance_client_api.h> 7#include <dvr/performance_client_api.h>
7#include <pdx/service_dispatcher.h> 8#include <pdx/service_dispatcher.h>
@@ -16,6 +17,23 @@ int main(int, char**) {
16 // We need to be able to create endpoints with full perms. 17 // We need to be able to create endpoints with full perms.
17 umask(0000); 18 umask(0000);
18 19
20 // Bump up the soft limit of open fd to the hard limit.
21 struct rlimit64 rlim;
22 ret = getrlimit64(RLIMIT_NOFILE, &rlim);
23 LOG_ALWAYS_FATAL_IF(ret != 0, "Failed to get nofile limit.");
24
25 ALOGI("Current nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max);
26 rlim.rlim_cur = rlim.rlim_max;
27 ret = setrlimit64(RLIMIT_NOFILE, &rlim);
28 ALOGE_IF(ret < 0, "Failed to set nofile limit, error=%s", strerror(errno));
29
30 rlim.rlim_cur = -1;
31 rlim.rlim_max = -1;
32 if (getrlimit64(RLIMIT_NOFILE, &rlim) < 0)
33 ALOGE("Failed to get nofile limit.");
34 else
35 ALOGI("New nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max);
36
19 dispatcher = android::pdx::ServiceDispatcher::Create(); 37 dispatcher = android::pdx::ServiceDispatcher::Create();
20 CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher\n"); 38 CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher\n");
21 39
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index ac6896ae8..a6d2dbb60 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -19,9 +19,10 @@ namespace android {
19namespace dvr { 19namespace dvr {
20 20
21ConsumerChannel::ConsumerChannel(BufferHubService* service, int buffer_id, 21ConsumerChannel::ConsumerChannel(BufferHubService* service, int buffer_id,
22 int channel_id, 22 int channel_id, uint64_t consumer_state_bit,
23 const std::shared_ptr<Channel> producer) 23 const std::shared_ptr<Channel> producer)
24 : BufferHubChannel(service, buffer_id, channel_id, kConsumerType), 24 : BufferHubChannel(service, buffer_id, channel_id, kConsumerType),
25 consumer_state_bit_(consumer_state_bit),
25 producer_(producer) { 26 producer_(producer) {
26 GetProducer()->AddConsumer(this); 27 GetProducer()->AddConsumer(this);
27} 28}
@@ -32,8 +33,6 @@ ConsumerChannel::~ConsumerChannel() {
32 channel_id(), buffer_id()); 33 channel_id(), buffer_id());
33 34
34 if (auto producer = GetProducer()) { 35 if (auto producer = GetProducer()) {
35 if (!released_) // Producer is waiting for our Release.
36 producer->OnConsumerIgnored();
37 producer->RemoveConsumer(this); 36 producer->RemoveConsumer(this);
38 } 37 }
39} 38}
@@ -43,6 +42,8 @@ BufferHubChannel::BufferInfo ConsumerChannel::GetBufferInfo() const {
43 if (auto producer = GetProducer()) { 42 if (auto producer = GetProducer()) {
44 // If producer has not hung up, copy most buffer info from the producer. 43 // If producer has not hung up, copy most buffer info from the producer.
45 info = producer->GetBufferInfo(); 44 info = producer->GetBufferInfo();
45 } else {
46 info.signaled_mask = consumer_state_bit();
46 } 47 }
47 info.id = buffer_id(); 48 info.id = buffer_id();
48 return info; 49 return info;
@@ -55,6 +56,9 @@ std::shared_ptr<ProducerChannel> ConsumerChannel::GetProducer() const {
55void ConsumerChannel::HandleImpulse(Message& message) { 56void ConsumerChannel::HandleImpulse(Message& message) {
56 ATRACE_NAME("ConsumerChannel::HandleImpulse"); 57 ATRACE_NAME("ConsumerChannel::HandleImpulse");
57 switch (message.GetOp()) { 58 switch (message.GetOp()) {
59 case BufferHubRPC::ConsumerAcquire::Opcode:
60 OnConsumerAcquire(message);
61 break;
58 case BufferHubRPC::ConsumerRelease::Opcode: 62 case BufferHubRPC::ConsumerRelease::Opcode:
59 OnConsumerRelease(message, {}); 63 OnConsumerRelease(message, {});
60 break; 64 break;
@@ -70,7 +74,7 @@ bool ConsumerChannel::HandleMessage(Message& message) {
70 switch (message.GetOp()) { 74 switch (message.GetOp()) {
71 case BufferHubRPC::GetBuffer::Opcode: 75 case BufferHubRPC::GetBuffer::Opcode:
72 DispatchRemoteMethod<BufferHubRPC::GetBuffer>( 76 DispatchRemoteMethod<BufferHubRPC::GetBuffer>(
73 *producer, &ProducerChannel::OnGetBuffer, message); 77 *this, &ConsumerChannel::OnGetBuffer, message);
74 return true; 78 return true;
75 79
76 case BufferHubRPC::NewConsumer::Opcode: 80 case BufferHubRPC::NewConsumer::Opcode:
@@ -98,9 +102,18 @@ bool ConsumerChannel::HandleMessage(Message& message) {
98 } 102 }
99} 103}
100 104
101Status<std::pair<BorrowedFence, ConsumerChannel::MetaData>> 105Status<BufferDescription<BorrowedHandle>> ConsumerChannel::OnGetBuffer(
102ConsumerChannel::OnConsumerAcquire(Message& message, 106 Message& /*message*/) {
103 std::size_t metadata_size) { 107 ATRACE_NAME("ConsumerChannel::OnGetBuffer");
108 ALOGD_IF(TRACE, "ConsumerChannel::OnGetBuffer: buffer=%d", buffer_id());
109 if (auto producer = GetProducer()) {
110 return {producer->GetBuffer(consumer_state_bit_)};
111 } else {
112 return ErrorStatus(EPIPE);
113 }
114}
115
116Status<LocalFence> ConsumerChannel::OnConsumerAcquire(Message& message) {
104 ATRACE_NAME("ConsumerChannel::OnConsumerAcquire"); 117 ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
105 auto producer = GetProducer(); 118 auto producer = GetProducer();
106 if (!producer) 119 if (!producer)
@@ -114,7 +127,7 @@ ConsumerChannel::OnConsumerAcquire(Message& message,
114 producer->buffer_id()); 127 producer->buffer_id());
115 return ErrorStatus(EBUSY); 128 return ErrorStatus(EBUSY);
116 } else { 129 } else {
117 auto status = producer->OnConsumerAcquire(message, metadata_size); 130 auto status = producer->OnConsumerAcquire(message);
118 if (status) { 131 if (status) {
119 ClearAvailable(); 132 ClearAvailable();
120 acquired_ = true; 133 acquired_ = true;
diff --git a/services/vr/bufferhubd/consumer_channel.h b/services/vr/bufferhubd/consumer_channel.h
index 208a00227..55cf96920 100644
--- a/services/vr/bufferhubd/consumer_channel.h
+++ b/services/vr/bufferhubd/consumer_channel.h
@@ -12,32 +12,35 @@ namespace dvr {
12// Consumer channels are attached to a Producer channel 12// Consumer channels are attached to a Producer channel
13class ConsumerChannel : public BufferHubChannel { 13class ConsumerChannel : public BufferHubChannel {
14 public: 14 public:
15 using BorrowedHandle = pdx::BorrowedHandle;
15 using Channel = pdx::Channel; 16 using Channel = pdx::Channel;
16 using Message = pdx::Message; 17 using Message = pdx::Message;
17 18
18 ConsumerChannel(BufferHubService* service, int buffer_id, int channel_id, 19 ConsumerChannel(BufferHubService* service, int buffer_id, int channel_id,
20 uint64_t consumer_state_bit,
19 const std::shared_ptr<Channel> producer); 21 const std::shared_ptr<Channel> producer);
20 ~ConsumerChannel() override; 22 ~ConsumerChannel() override;
21 23
22 bool HandleMessage(Message& message) override; 24 bool HandleMessage(Message& message) override;
23 void HandleImpulse(Message& message) override; 25 void HandleImpulse(Message& message) override;
24 26
27 uint64_t consumer_state_bit() const { return consumer_state_bit_; }
25 BufferInfo GetBufferInfo() const override; 28 BufferInfo GetBufferInfo() const override;
26 29
27 bool OnProducerPosted(); 30 bool OnProducerPosted();
28 void OnProducerClosed(); 31 void OnProducerClosed();
29 32
30 private: 33 private:
31 using MetaData = pdx::rpc::BufferWrapper<std::uint8_t*>;
32
33 std::shared_ptr<ProducerChannel> GetProducer() const; 34 std::shared_ptr<ProducerChannel> GetProducer() const;
34 35
35 pdx::Status<std::pair<BorrowedFence, MetaData>> OnConsumerAcquire( 36 pdx::Status<BufferDescription<BorrowedHandle>> OnGetBuffer(Message& message);
36 Message& message, std::size_t metadata_size); 37
38 pdx::Status<LocalFence> OnConsumerAcquire(Message& message);
37 pdx::Status<void> OnConsumerRelease(Message& message, 39 pdx::Status<void> OnConsumerRelease(Message& message,
38 LocalFence release_fence); 40 LocalFence release_fence);
39 pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore); 41 pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore);
40 42
43 uint64_t consumer_state_bit_{0};
41 bool acquired_{false}; 44 bool acquired_{false};
42 bool released_{true}; 45 bool released_{true};
43 bool ignored_{false}; // True if we are ignoring events. 46 bool ignored_{false}; // True if we are ignoring events.
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index f447e00c3..4d430012f 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -15,10 +15,11 @@ namespace dvr {
15 15
16ConsumerQueueChannel::ConsumerQueueChannel( 16ConsumerQueueChannel::ConsumerQueueChannel(
17 BufferHubService* service, int buffer_id, int channel_id, 17 BufferHubService* service, int buffer_id, int channel_id,
18 const std::shared_ptr<Channel>& producer) 18 const std::shared_ptr<Channel>& producer, bool silent)
19 : BufferHubChannel(service, buffer_id, channel_id, kConsumerQueueType), 19 : BufferHubChannel(service, buffer_id, channel_id, kConsumerQueueType),
20 producer_(producer), 20 producer_(producer),
21 capacity_(0) { 21 capacity_(0),
22 silent_(silent) {
22 GetProducer()->AddConsumer(this); 23 GetProducer()->AddConsumer(this);
23} 24}
24 25
@@ -83,23 +84,30 @@ BufferHubChannel::BufferInfo ConsumerQueueChannel::GetBufferInfo() const {
83void ConsumerQueueChannel::RegisterNewBuffer( 84void ConsumerQueueChannel::RegisterNewBuffer(
84 const std::shared_ptr<ProducerChannel>& producer_channel, size_t slot) { 85 const std::shared_ptr<ProducerChannel>& producer_channel, size_t slot) {
85 ALOGD_IF(TRACE, 86 ALOGD_IF(TRACE,
86 "ConsumerQueueChannel::RegisterNewBuffer: buffer_id=%d slot=%zu", 87 "ConsumerQueueChannel::RegisterNewBuffer: queue_id=%d buffer_id=%d "
87 producer_channel->buffer_id(), slot); 88 "slot=%zu silent=%d",
88 pending_buffer_slots_.emplace(producer_channel, slot); 89 buffer_id(), producer_channel->buffer_id(), slot, silent_);
89 90 // Only register buffers if the queue is not silent.
90 // Signal the client that there is new buffer available throught POLLIN. 91 if (!silent_) {
91 SignalAvailable(); 92 pending_buffer_slots_.emplace(producer_channel, slot);
93
94 // Signal the client that there is new buffer available.
95 SignalAvailable();
96 }
92} 97}
93 98
94Status<std::vector<std::pair<RemoteChannelHandle, size_t>>> 99Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
95ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) { 100ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) {
96 std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles; 101 std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
97 ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers"); 102 ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers");
98 ALOGD_IF( 103 ALOGD_IF(TRACE,
99 TRACE, 104 "ConsumerQueueChannel::OnConsumerQueueImportBuffers: "
100 "ConsumerQueueChannel::OnConsumerQueueImportBuffers number of buffers to " 105 "pending_buffer_slots=%zu",
101 "import: %zu", 106 pending_buffer_slots_.size());
102 pending_buffer_slots_.size()); 107
108 // Indicate this is a silent queue that will not import buffers.
109 if (silent_)
110 return ErrorStatus(EBADR);
103 111
104 while (!pending_buffer_slots_.empty()) { 112 while (!pending_buffer_slots_.empty()) {
105 auto producer_channel = pending_buffer_slots_.front().first.lock(); 113 auto producer_channel = pending_buffer_slots_.front().first.lock();
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index aa3f531c7..8437c4cd0 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -19,7 +19,7 @@ class ConsumerQueueChannel : public BufferHubChannel {
19 using RemoteChannelHandle = pdx::RemoteChannelHandle; 19 using RemoteChannelHandle = pdx::RemoteChannelHandle;
20 20
21 ConsumerQueueChannel(BufferHubService* service, int buffer_id, int channel_id, 21 ConsumerQueueChannel(BufferHubService* service, int buffer_id, int channel_id,
22 const std::shared_ptr<Channel>& producer); 22 const std::shared_ptr<Channel>& producer, bool silent);
23 ~ConsumerQueueChannel() override; 23 ~ConsumerQueueChannel() override;
24 24
25 bool HandleMessage(Message& message) override; 25 bool HandleMessage(Message& message) override;
@@ -54,6 +54,10 @@ class ConsumerQueueChannel : public BufferHubChannel {
54 // Tracks how many buffers have this queue imported. 54 // Tracks how many buffers have this queue imported.
55 size_t capacity_; 55 size_t capacity_;
56 56
57 // A silent queue does not signal or export buffers. It is only used to spawn
58 // another consumer queue.
59 bool silent_;
60
57 ConsumerQueueChannel(const ConsumerQueueChannel&) = delete; 61 ConsumerQueueChannel(const ConsumerQueueChannel&) = delete;
58 void operator=(const ConsumerQueueChannel&) = delete; 62 void operator=(const ConsumerQueueChannel&) = delete;
59}; 63};
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index b2db79571..716db5eea 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -2,6 +2,8 @@
2 2
3#include <log/log.h> 3#include <log/log.h>
4#include <sync/sync.h> 4#include <sync/sync.h>
5#include <sys/epoll.h>
6#include <sys/eventfd.h>
5#include <sys/poll.h> 7#include <sys/poll.h>
6#include <utils/Trace.h> 8#include <utils/Trace.h>
7 9
@@ -24,24 +26,88 @@ using android::pdx::rpc::WrapBuffer;
24namespace android { 26namespace android {
25namespace dvr { 27namespace dvr {
26 28
29namespace {
30
31static inline uint64_t FindNextClearedBit(uint64_t bits) {
32 return ~bits - (~bits & (~bits - 1));
33}
34
35} // namespace
36
27ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id, 37ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
28 uint32_t width, uint32_t height, 38 uint32_t width, uint32_t height,
29 uint32_t layer_count, uint32_t format, 39 uint32_t layer_count, uint32_t format,
30 uint64_t usage, size_t meta_size_bytes, 40 uint64_t usage, size_t user_metadata_size,
31 int* error) 41 int* error)
32 : BufferHubChannel(service, channel_id, channel_id, kProducerType), 42 : BufferHubChannel(service, channel_id, channel_id, kProducerType),
33 pending_consumers_(0), 43 pending_consumers_(0),
34 producer_owns_(true), 44 producer_owns_(true),
35 meta_size_bytes_(meta_size_bytes), 45 user_metadata_size_(user_metadata_size),
36 meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) { 46 metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize +
37 const int ret = buffer_.Alloc(width, height, layer_count, format, usage); 47 user_metadata_size) {
38 if (ret < 0) { 48 if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
39 ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s", 49 ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
40 strerror(-ret)); 50 strerror(-ret));
41 *error = ret; 51 *error = ret;
42 return; 52 return;
43 } 53 }
44 54
55 if (int ret = metadata_buffer_.Alloc(metadata_buf_size_, /*height=*/1,
56 /*layer_count=*/1,
57 BufferHubDefs::kMetadataFormat,
58 BufferHubDefs::kMetadataUsage)) {
59 ALOGE("ProducerChannel::ProducerChannel: Failed to allocate metadata: %s",
60 strerror(-ret));
61 *error = ret;
62 return;
63 }
64
65 void* metadata_ptr = nullptr;
66 if (int ret = metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
67 /*y=*/0, metadata_buf_size_,
68 /*height=*/1, &metadata_ptr)) {
69 ALOGE("ProducerChannel::ProducerChannel: Failed to lock metadata.");
70 *error = -ret;
71 return;
72 }
73 metadata_header_ =
74 reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
75
76 // Using placement new here to reuse shared memory instead of new allocation
77 // and also initialize the value to zero.
78 buffer_state_ =
79 new (&metadata_header_->buffer_state) std::atomic<uint64_t>(0);
80 fence_state_ =
81 new (&metadata_header_->fence_state) std::atomic<uint64_t>(0);
82
83 acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
84 release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
85 if (!acquire_fence_fd_ || !release_fence_fd_) {
86 ALOGE("ProducerChannel::ProducerChannel: Failed to create shared fences.");
87 *error = -EIO;
88 return;
89 }
90
91 dummy_fence_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
92 if (!dummy_fence_fd_) {
93 ALOGE("ProducerChannel::ProducerChannel: Failed to create dummy fences.");
94 *error = -EIO;
95 return;
96 }
97
98 epoll_event event;
99 event.events = 0;
100 event.data.u64 = 0ULL;
101 if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_ADD, dummy_fence_fd_.Get(),
102 &event) < 0) {
103 ALOGE(
104 "ProducerChannel::ProducerChannel: Failed to modify the shared "
105 "release fence to include the dummy fence: %s",
106 strerror(errno));
107 *error = -EIO;
108 return;
109 }
110
45 // Success. 111 // Success.
46 *error = 0; 112 *error = 0;
47} 113}
@@ -49,11 +115,11 @@ ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
49Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create( 115Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
50 BufferHubService* service, int channel_id, uint32_t width, uint32_t height, 116 BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
51 uint32_t layer_count, uint32_t format, uint64_t usage, 117 uint32_t layer_count, uint32_t format, uint64_t usage,
52 size_t meta_size_bytes) { 118 size_t user_metadata_size) {
53 int error; 119 int error;
54 std::shared_ptr<ProducerChannel> producer( 120 std::shared_ptr<ProducerChannel> producer(
55 new ProducerChannel(service, channel_id, width, height, layer_count, 121 new ProducerChannel(service, channel_id, width, height, layer_count,
56 format, usage, meta_size_bytes, &error)); 122 format, usage, user_metadata_size, &error));
57 if (error < 0) 123 if (error < 0)
58 return ErrorStatus(-error); 124 return ErrorStatus(-error);
59 else 125 else
@@ -62,16 +128,24 @@ Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
62 128
63ProducerChannel::~ProducerChannel() { 129ProducerChannel::~ProducerChannel() {
64 ALOGD_IF(TRACE, 130 ALOGD_IF(TRACE,
65 "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d", 131 "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d "
66 channel_id(), buffer_id()); 132 "state=%" PRIx64 ".",
133 channel_id(), buffer_id(), buffer_state_->load());
67 for (auto consumer : consumer_channels_) 134 for (auto consumer : consumer_channels_)
68 consumer->OnProducerClosed(); 135 consumer->OnProducerClosed();
69} 136}
70 137
71BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const { 138BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
139 // Derive the mask of signaled buffers in this producer / consumer set.
140 uint64_t signaled_mask = signaled() ? BufferHubDefs::kProducerStateBit : 0;
141 for (const ConsumerChannel* consumer : consumer_channels_) {
142 signaled_mask |= consumer->signaled() ? consumer->consumer_state_bit() : 0;
143 }
144
72 return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(), 145 return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(),
73 buffer_.height(), buffer_.layer_count(), buffer_.format(), 146 buffer_.height(), buffer_.layer_count(), buffer_.format(),
74 buffer_.usage(), name_); 147 buffer_.usage(), pending_consumers_, buffer_state_->load(),
148 signaled_mask, metadata_header_->queue_index, name_);
75} 149}
76 150
77void ProducerChannel::HandleImpulse(Message& message) { 151void ProducerChannel::HandleImpulse(Message& message) {
@@ -80,6 +154,9 @@ void ProducerChannel::HandleImpulse(Message& message) {
80 case BufferHubRPC::ProducerGain::Opcode: 154 case BufferHubRPC::ProducerGain::Opcode:
81 OnProducerGain(message); 155 OnProducerGain(message);
82 break; 156 break;
157 case BufferHubRPC::ProducerPost::Opcode:
158 OnProducerPost(message, {});
159 break;
83 } 160 }
84} 161}
85 162
@@ -121,16 +198,26 @@ bool ProducerChannel::HandleMessage(Message& message) {
121 } 198 }
122} 199}
123 200
124Status<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffer( 201BufferDescription<BorrowedHandle> ProducerChannel::GetBuffer(
202 uint64_t buffer_state_bit) {
203 return {
204 buffer_, metadata_buffer_, buffer_id(),
205 buffer_state_bit, acquire_fence_fd_.Borrow(), release_fence_fd_.Borrow()};
206}
207
208Status<BufferDescription<BorrowedHandle>> ProducerChannel::OnGetBuffer(
125 Message& /*message*/) { 209 Message& /*message*/) {
126 ATRACE_NAME("ProducerChannel::OnGetBuffer"); 210 ATRACE_NAME("ProducerChannel::OnGetBuffer");
127 ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d", buffer_id()); 211 ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d, state=%" PRIx64 ".",
128 return {NativeBufferHandle<BorrowedHandle>(buffer_, buffer_id())}; 212 buffer_id(), buffer_state_->load());
213 return {GetBuffer(BufferHubDefs::kProducerStateBit)};
129} 214}
130 215
131Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) { 216Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
132 ATRACE_NAME("ProducerChannel::CreateConsumer"); 217 ATRACE_NAME("ProducerChannel::CreateConsumer");
133 ALOGD_IF(TRACE, "ProducerChannel::CreateConsumer: buffer_id=%d", buffer_id()); 218 ALOGD_IF(TRACE,
219 "ProducerChannel::CreateConsumer: buffer_id=%d, producer_owns=%d",
220 buffer_id(), producer_owns_);
134 221
135 int channel_id; 222 int channel_id;
136 auto status = message.PushChannel(0, nullptr, &channel_id); 223 auto status = message.PushChannel(0, nullptr, &channel_id);
@@ -141,8 +228,21 @@ Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
141 return ErrorStatus(ENOMEM); 228 return ErrorStatus(ENOMEM);
142 } 229 }
143 230
144 auto consumer = std::make_shared<ConsumerChannel>( 231 // Try find the next consumer state bit which has not been claimed by any
145 service(), buffer_id(), channel_id, shared_from_this()); 232 // consumer yet.
233 uint64_t consumer_state_bit = FindNextClearedBit(
234 active_consumer_bit_mask_ | orphaned_consumer_bit_mask_ |
235 BufferHubDefs::kProducerStateBit);
236 if (consumer_state_bit == 0ULL) {
237 ALOGE(
238 "ProducerChannel::CreateConsumer: reached the maximum mumber of "
239 "consumers per producer: 63.");
240 return ErrorStatus(E2BIG);
241 }
242
243 auto consumer =
244 std::make_shared<ConsumerChannel>(service(), buffer_id(), channel_id,
245 consumer_state_bit, shared_from_this());
146 const auto channel_status = service()->SetChannel(channel_id, consumer); 246 const auto channel_status = service()->SetChannel(channel_id, consumer);
147 if (!channel_status) { 247 if (!channel_status) {
148 ALOGE( 248 ALOGE(
@@ -152,12 +252,14 @@ Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
152 return ErrorStatus(ENOMEM); 252 return ErrorStatus(ENOMEM);
153 } 253 }
154 254
155 if (!producer_owns_) { 255 if (!producer_owns_ &&
256 !BufferHubDefs::IsBufferReleased(buffer_state_->load())) {
156 // Signal the new consumer when adding it to a posted producer. 257 // Signal the new consumer when adding it to a posted producer.
157 if (consumer->OnProducerPosted()) 258 if (consumer->OnProducerPosted())
158 pending_consumers_++; 259 pending_consumers_++;
159 } 260 }
160 261
262 active_consumer_bit_mask_ |= consumer_state_bit;
161 return {status.take()}; 263 return {status.take()};
162} 264}
163 265
@@ -168,8 +270,7 @@ Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
168} 270}
169 271
170Status<void> ProducerChannel::OnProducerPost( 272Status<void> ProducerChannel::OnProducerPost(
171 Message&, LocalFence acquire_fence, 273 Message&, LocalFence acquire_fence) {
172 BufferWrapper<std::vector<std::uint8_t>> metadata) {
173 ATRACE_NAME("ProducerChannel::OnProducerPost"); 274 ATRACE_NAME("ProducerChannel::OnProducerPost");
174 ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id()); 275 ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
175 if (!producer_owns_) { 276 if (!producer_owns_) {
@@ -177,27 +278,45 @@ Status<void> ProducerChannel::OnProducerPost(
177 return ErrorStatus(EBUSY); 278 return ErrorStatus(EBUSY);
178 } 279 }
179 280
180 if (meta_size_bytes_ != metadata.size()) { 281 epoll_event event;
181 ALOGD_IF(TRACE, 282 event.events = 0;
182 "ProducerChannel::OnProducerPost: Expected meta_size_bytes=%zu " 283 event.data.u64 = 0ULL;
183 "got size=%zu", 284 int ret = epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
184 meta_size_bytes_, metadata.size()); 285 dummy_fence_fd_.Get(), &event);
185 return ErrorStatus(EINVAL); 286 ALOGE_IF(ret < 0,
287 "ProducerChannel::OnProducerPost: Failed to modify the shared "
288 "release fence to include the dummy fence: %s",
289 strerror(errno));
290
291 eventfd_t dummy_fence_count = 0ULL;
292 if (eventfd_read(dummy_fence_fd_.Get(), &dummy_fence_count) < 0) {
293 const int error = errno;
294 if (error != EAGAIN) {
295 ALOGE(
296 "ProducerChannel::ProducerChannel: Failed to read dummy fence, "
297 "error: %s",
298 strerror(error));
299 return ErrorStatus(error);
300 }
186 } 301 }
187 302
188 std::copy(metadata.begin(), metadata.end(), meta_.get()); 303 ALOGW_IF(dummy_fence_count > 0,
304 "ProducerChannel::ProducerChannel: %" PRIu64
305 " dummy fence(s) was signaled during last release/gain cycle "
306 "buffer_id=%d.",
307 dummy_fence_count, buffer_id());
308
189 post_fence_ = std::move(acquire_fence); 309 post_fence_ = std::move(acquire_fence);
190 producer_owns_ = false; 310 producer_owns_ = false;
191 311
192 // Signal any interested consumers. If there are none, automatically release 312 // Signal any interested consumers. If there are none, the buffer will stay
193 // the buffer. 313 // in posted state until a consumer comes online. This behavior guarantees
314 // that no frame is silently dropped.
194 pending_consumers_ = 0; 315 pending_consumers_ = 0;
195 for (auto consumer : consumer_channels_) { 316 for (auto consumer : consumer_channels_) {
196 if (consumer->OnProducerPosted()) 317 if (consumer->OnProducerPosted())
197 pending_consumers_++; 318 pending_consumers_++;
198 } 319 }
199 if (pending_consumers_ == 0)
200 SignalAvailable();
201 ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: %d pending consumers", 320 ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: %d pending consumers",
202 pending_consumers_); 321 pending_consumers_);
203 322
@@ -214,8 +333,13 @@ Status<LocalFence> ProducerChannel::OnProducerGain(Message& /*message*/) {
214 } 333 }
215 334
216 // There are still pending consumers, return busy. 335 // There are still pending consumers, return busy.
217 if (pending_consumers_ > 0) 336 if (pending_consumers_ > 0) {
337 ALOGE(
338 "ProducerChannel::OnGain: Producer (id=%d) is gaining a buffer that "
339 "still has %d pending consumer(s).",
340 buffer_id(), pending_consumers_);
218 return ErrorStatus(EBUSY); 341 return ErrorStatus(EBUSY);
342 }
219 343
220 ClearAvailable(); 344 ClearAvailable();
221 producer_owns_ = true; 345 producer_owns_ = true;
@@ -223,9 +347,7 @@ Status<LocalFence> ProducerChannel::OnProducerGain(Message& /*message*/) {
223 return {std::move(returned_fence_)}; 347 return {std::move(returned_fence_)};
224} 348}
225 349
226Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>> 350Status<LocalFence> ProducerChannel::OnConsumerAcquire(Message& /*message*/) {
227ProducerChannel::OnConsumerAcquire(Message& /*message*/,
228 std::size_t metadata_size) {
229 ATRACE_NAME("ProducerChannel::OnConsumerAcquire"); 351 ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
230 ALOGD_IF(TRACE, "ProducerChannel::OnConsumerAcquire: buffer_id=%d", 352 ALOGD_IF(TRACE, "ProducerChannel::OnConsumerAcquire: buffer_id=%d",
231 buffer_id()); 353 buffer_id());
@@ -236,12 +358,7 @@ ProducerChannel::OnConsumerAcquire(Message& /*message*/,
236 358
237 // Return a borrowed fd to avoid unnecessary duplication of the underlying fd. 359 // Return a borrowed fd to avoid unnecessary duplication of the underlying fd.
238 // Serialization just needs to read the handle. 360 // Serialization just needs to read the handle.
239 if (metadata_size == 0) 361 return {std::move(post_fence_)};
240 return {std::make_pair(post_fence_.borrow(),
241 WrapBuffer<std::uint8_t>(nullptr, 0))};
242 else
243 return {std::make_pair(post_fence_.borrow(),
244 WrapBuffer(meta_.get(), meta_size_bytes_))};
245} 362}
246 363
247Status<void> ProducerChannel::OnConsumerRelease(Message&, 364Status<void> ProducerChannel::OnConsumerRelease(Message&,
@@ -273,17 +390,75 @@ Status<void> ProducerChannel::OnConsumerRelease(Message&,
273 } 390 }
274 391
275 OnConsumerIgnored(); 392 OnConsumerIgnored();
393 if (pending_consumers_ == 0) {
394 // Clear the producer bit atomically to transit into released state. This
395 // has to done by BufferHub as it requries synchronization among all
396 // consumers.
397 BufferHubDefs::ModifyBufferState(buffer_state_,
398 BufferHubDefs::kProducerStateBit, 0ULL);
399 ALOGD_IF(TRACE,
400 "ProducerChannel::OnConsumerRelease: releasing last consumer: "
401 "buffer_id=%d state=%" PRIx64 ".",
402 buffer_id(), buffer_state_->load());
403
404 if (orphaned_consumer_bit_mask_) {
405 ALOGW(
406 "ProducerChannel::OnConsumerRelease: orphaned buffer detected "
407 "during the this acquire/release cycle: id=%d orphaned=0x%" PRIx64
408 " queue_index=%" PRIu64 ".",
409 buffer_id(), orphaned_consumer_bit_mask_,
410 metadata_header_->queue_index);
411 orphaned_consumer_bit_mask_ = 0;
412 }
413
414 SignalAvailable();
415 }
416
417 ALOGE_IF(pending_consumers_ &&
418 BufferHubDefs::IsBufferReleased(buffer_state_->load()),
419 "ProducerChannel::OnConsumerRelease: buffer state inconsistent: "
420 "pending_consumers=%d, buffer buffer is in releaed state.",
421 pending_consumers_);
276 return {}; 422 return {};
277} 423}
278 424
279void ProducerChannel::OnConsumerIgnored() { 425void ProducerChannel::OnConsumerIgnored() {
280 if (!--pending_consumers_) 426 if (pending_consumers_ == 0) {
281 SignalAvailable(); 427 ALOGE("ProducerChannel::OnConsumerIgnored: no pending consumer.");
428 return;
429 }
430
431 --pending_consumers_;
282 ALOGD_IF(TRACE, 432 ALOGD_IF(TRACE,
283 "ProducerChannel::OnConsumerIgnored: buffer_id=%d %d consumers left", 433 "ProducerChannel::OnConsumerIgnored: buffer_id=%d %d consumers left",
284 buffer_id(), pending_consumers_); 434 buffer_id(), pending_consumers_);
285} 435}
286 436
437void ProducerChannel::OnConsumerOrphaned(ConsumerChannel* channel) {
438 // Ignore the orphaned consumer.
439 OnConsumerIgnored();
440
441 const uint64_t consumer_state_bit = channel->consumer_state_bit();
442 ALOGE_IF(orphaned_consumer_bit_mask_ & consumer_state_bit,
443 "ProducerChannel::OnConsumerOrphaned: Consumer "
444 "(consumer_state_bit=%" PRIx64 ") is already orphaned.",
445 consumer_state_bit);
446 orphaned_consumer_bit_mask_ |= consumer_state_bit;
447
448 // Atomically clear the fence state bit as an orphaned consumer will never
449 // signal a release fence. Also clear the buffer state as it won't be released
450 // as well.
451 fence_state_->fetch_and(~consumer_state_bit);
452 BufferHubDefs::ModifyBufferState(buffer_state_, consumer_state_bit, 0ULL);
453
454 ALOGW(
455 "ProducerChannel::OnConsumerOrphaned: detected new orphaned consumer "
456 "buffer_id=%d consumer_state_bit=%" PRIx64 " queue_index=%" PRIu64
457 " buffer_state=%" PRIx64 " fence_state=%" PRIx64 ".",
458 buffer_id(), consumer_state_bit, metadata_header_->queue_index,
459 buffer_state_->load(), fence_state_->load());
460}
461
287Status<void> ProducerChannel::OnProducerMakePersistent(Message& message, 462Status<void> ProducerChannel::OnProducerMakePersistent(Message& message,
288 const std::string& name, 463 const std::string& name,
289 int user_id, 464 int user_id,
@@ -335,6 +510,40 @@ void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
335void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) { 510void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) {
336 consumer_channels_.erase( 511 consumer_channels_.erase(
337 std::find(consumer_channels_.begin(), consumer_channels_.end(), channel)); 512 std::find(consumer_channels_.begin(), consumer_channels_.end(), channel));
513 active_consumer_bit_mask_ &= ~channel->consumer_state_bit();
514
515 const uint64_t buffer_state = buffer_state_->load();
516 if (BufferHubDefs::IsBufferPosted(buffer_state) ||
517 BufferHubDefs::IsBufferAcquired(buffer_state)) {
518 // The consumer client is being destoryed without releasing. This could
519 // happen in corner cases when the consumer crashes. Here we mark it
520 // orphaned before remove it from producer.
521 OnConsumerOrphaned(channel);
522 }
523
524 if (BufferHubDefs::IsBufferReleased(buffer_state) ||
525 BufferHubDefs::IsBufferGained(buffer_state)) {
526 // The consumer is being close while it is suppose to signal a release
527 // fence. Signal the dummy fence here.
528 if (fence_state_->load() & channel->consumer_state_bit()) {
529 epoll_event event;
530 event.events = EPOLLIN;
531 event.data.u64 = channel->consumer_state_bit();
532 if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
533 dummy_fence_fd_.Get(), &event) < 0) {
534 ALOGE(
535 "ProducerChannel::RemoveConsumer: Failed to modify the shared "
536 "release fence to include the dummy fence: %s",
537 strerror(errno));
538 return;
539 }
540 ALOGW(
541 "ProducerChannel::RemoveConsumer: signal dummy release fence "
542 "buffer_id=%d",
543 buffer_id());
544 eventfd_write(dummy_fence_fd_.Get(), 1);
545 }
546 }
338} 547}
339 548
340// Returns true if either the user or group ids match the owning ids or both 549// Returns true if either the user or group ids match the owning ids or both
@@ -350,10 +559,12 @@ bool ProducerChannel::CheckAccess(int euid, int egid) {
350// Returns true if the given parameters match the underlying buffer parameters. 559// Returns true if the given parameters match the underlying buffer parameters.
351bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height, 560bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
352 uint32_t layer_count, uint32_t format, 561 uint32_t layer_count, uint32_t format,
353 uint64_t usage, size_t meta_size_bytes) { 562 uint64_t usage,
354 return meta_size_bytes == meta_size_bytes_ && buffer_.width() == width && 563 size_t user_metadata_size) {
355 buffer_.height() == height && buffer_.layer_count() == layer_count && 564 return user_metadata_size == user_metadata_size_ &&
356 buffer_.format() == format && buffer_.usage() == usage; 565 buffer_.width() == width && buffer_.height() == height &&
566 buffer_.layer_count() == layer_count && buffer_.format() == format &&
567 buffer_.usage() == usage;
357} 568}
358 569
359} // namespace dvr 570} // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index 5ada47880..e280f4de8 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -33,7 +33,7 @@ class ProducerChannel : public BufferHubChannel {
33 static pdx::Status<std::shared_ptr<ProducerChannel>> Create( 33 static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
34 BufferHubService* service, int channel_id, uint32_t width, 34 BufferHubService* service, int channel_id, uint32_t width,
35 uint32_t height, uint32_t layer_count, uint32_t format, uint64_t usage, 35 uint32_t height, uint32_t layer_count, uint32_t format, uint64_t usage,
36 size_t meta_size_bytes); 36 size_t user_metadata_size);
37 37
38 ~ProducerChannel() override; 38 ~ProducerChannel() override;
39 39
@@ -42,24 +42,25 @@ class ProducerChannel : public BufferHubChannel {
42 42
43 BufferInfo GetBufferInfo() const override; 43 BufferInfo GetBufferInfo() const override;
44 44
45 pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message); 45 BufferDescription<BorrowedHandle> GetBuffer(uint64_t buffer_state_bit);
46 46
47 pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message); 47 pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message);
48 pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message); 48 pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message);
49 49
50 pdx::Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>> 50 pdx::Status<LocalFence> OnConsumerAcquire(Message& message);
51 OnConsumerAcquire(Message& message, std::size_t metadata_size);
52 pdx::Status<void> OnConsumerRelease(Message& message, 51 pdx::Status<void> OnConsumerRelease(Message& message,
53 LocalFence release_fence); 52 LocalFence release_fence);
54 53
55 void OnConsumerIgnored(); 54 void OnConsumerIgnored();
55 void OnConsumerOrphaned(ConsumerChannel* channel);
56 56
57 void AddConsumer(ConsumerChannel* channel); 57 void AddConsumer(ConsumerChannel* channel);
58 void RemoveConsumer(ConsumerChannel* channel); 58 void RemoveConsumer(ConsumerChannel* channel);
59 59
60 bool CheckAccess(int euid, int egid); 60 bool CheckAccess(int euid, int egid);
61 bool CheckParameters(uint32_t width, uint32_t height, uint32_t layer_count, 61 bool CheckParameters(uint32_t width, uint32_t height, uint32_t layer_count,
62 uint32_t format, uint64_t usage, size_t meta_size_bytes); 62 uint32_t format, uint64_t usage,
63 size_t user_metadata_size);
63 64
64 pdx::Status<void> OnProducerMakePersistent(Message& message, 65 pdx::Status<void> OnProducerMakePersistent(Message& message,
65 const std::string& name, 66 const std::string& name,
@@ -74,11 +75,28 @@ class ProducerChannel : public BufferHubChannel {
74 75
75 IonBuffer buffer_; 76 IonBuffer buffer_;
76 77
78 // IonBuffer that is shared between bufferhubd, producer, and consumers.
79 IonBuffer metadata_buffer_;
80 BufferHubDefs::MetadataHeader* metadata_header_ = nullptr;
81 std::atomic<uint64_t>* buffer_state_ = nullptr;
82 std::atomic<uint64_t>* fence_state_ = nullptr;
83
84 // All active consumer bits. Valid bits are the lower 63 bits, while the
85 // highest bit is reserved for the producer and should not be set.
86 uint64_t active_consumer_bit_mask_{0ULL};
87 // All orphaned consumer bits. Valid bits are the lower 63 bits, while the
88 // highest bit is reserved for the producer and should not be set.
89 uint64_t orphaned_consumer_bit_mask_{0ULL};
90
77 bool producer_owns_; 91 bool producer_owns_;
78 LocalFence post_fence_; 92 LocalFence post_fence_;
79 LocalFence returned_fence_; 93 LocalFence returned_fence_;
80 size_t meta_size_bytes_; 94 size_t user_metadata_size_; // size of user requested buffer buffer size.
81 std::unique_ptr<uint8_t[]> meta_; 95 size_t metadata_buf_size_; // size of the ion buffer that holds metadata.
96
97 pdx::LocalHandle acquire_fence_fd_;
98 pdx::LocalHandle release_fence_fd_;
99 pdx::LocalHandle dummy_fence_fd_;
82 100
83 static constexpr int kNoCheckId = -1; 101 static constexpr int kNoCheckId = -1;
84 static constexpr int kUseCallerId = 0; 102 static constexpr int kUseCallerId = 0;
@@ -92,11 +110,10 @@ class ProducerChannel : public BufferHubChannel {
92 110
93 ProducerChannel(BufferHubService* service, int channel, uint32_t width, 111 ProducerChannel(BufferHubService* service, int channel, uint32_t width,
94 uint32_t height, uint32_t layer_count, uint32_t format, 112 uint32_t height, uint32_t layer_count, uint32_t format,
95 uint64_t usage, size_t meta_size_bytes, int* error); 113 uint64_t usage, size_t user_metadata_size, int* error);
96 114
97 pdx::Status<void> OnProducerPost( 115 pdx::Status<BufferDescription<BorrowedHandle>> OnGetBuffer(Message& message);
98 Message& message, LocalFence acquire_fence, 116 pdx::Status<void> OnProducerPost(Message& message, LocalFence acquire_fence);
99 BufferWrapper<std::vector<std::uint8_t>> metadata);
100 pdx::Status<LocalFence> OnProducerGain(Message& message); 117 pdx::Status<LocalFence> OnProducerGain(Message& message);
101 118
102 ProducerChannel(const ProducerChannel&) = delete; 119 ProducerChannel(const ProducerChannel&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index b8bb728b7..c0c48c2dc 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -7,8 +7,8 @@
7 7
8using android::pdx::ErrorStatus; 8using android::pdx::ErrorStatus;
9using android::pdx::Message; 9using android::pdx::Message;
10using android::pdx::Status;
11using android::pdx::RemoteChannelHandle; 10using android::pdx::RemoteChannelHandle;
11using android::pdx::Status;
12using android::pdx::rpc::DispatchRemoteMethod; 12using android::pdx::rpc::DispatchRemoteMethod;
13 13
14namespace android { 14namespace android {
@@ -96,10 +96,12 @@ BufferHubChannel::BufferInfo ProducerQueueChannel::GetBufferInfo() const {
96} 96}
97 97
98Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue( 98Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue(
99 Message& message) { 99 Message& message, bool silent) {
100 ATRACE_NAME("ProducerQueueChannel::OnCreateConsumerQueue"); 100 ATRACE_NAME("ProducerQueueChannel::OnCreateConsumerQueue");
101 ALOGD_IF(TRACE, "ProducerQueueChannel::OnCreateConsumerQueue: channel_id=%d", 101 ALOGD_IF(
102 channel_id()); 102 TRACE,
103 "ProducerQueueChannel::OnCreateConsumerQueue: channel_id=%d slient=%d",
104 channel_id(), silent);
103 105
104 int channel_id; 106 int channel_id;
105 auto status = message.PushChannel(0, nullptr, &channel_id); 107 auto status = message.PushChannel(0, nullptr, &channel_id);
@@ -112,7 +114,7 @@ Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue(
112 } 114 }
113 115
114 auto consumer_queue_channel = std::make_shared<ConsumerQueueChannel>( 116 auto consumer_queue_channel = std::make_shared<ConsumerQueueChannel>(
115 service(), buffer_id(), channel_id, shared_from_this()); 117 service(), buffer_id(), channel_id, shared_from_this(), silent);
116 118
117 // Register the existing buffers with the new consumer queue. 119 // Register the existing buffers with the new consumer queue.
118 for (size_t slot = 0; slot < BufferHubRPC::kMaxQueueCapacity; slot++) { 120 for (size_t slot = 0; slot < BufferHubRPC::kMaxQueueCapacity; slot++) {
@@ -222,7 +224,7 @@ ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width,
222 224
223 auto producer_channel_status = 225 auto producer_channel_status =
224 ProducerChannel::Create(service(), buffer_id, width, height, layer_count, 226 ProducerChannel::Create(service(), buffer_id, width, height, layer_count,
225 format, usage, config_.meta_size_bytes); 227 format, usage, config_.user_metadata_size);
226 if (!producer_channel_status) { 228 if (!producer_channel_status) {
227 ALOGE( 229 ALOGE(
228 "ProducerQueueChannel::AllocateBuffer: Failed to create producer " 230 "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index fd519c55e..e825f4777 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -26,7 +26,7 @@ class ProducerQueueChannel : public BufferHubChannel {
26 // Returns a handle for the service channel, as well as the size of the 26 // Returns a handle for the service channel, as well as the size of the
27 // metadata associated with the queue. 27 // metadata associated with the queue.
28 pdx::Status<pdx::RemoteChannelHandle> OnCreateConsumerQueue( 28 pdx::Status<pdx::RemoteChannelHandle> OnCreateConsumerQueue(
29 pdx::Message& message); 29 pdx::Message& message, bool silent);
30 30
31 pdx::Status<QueueInfo> OnGetQueueInfo(pdx::Message& message); 31 pdx::Status<QueueInfo> OnGetQueueInfo(pdx::Message& message);
32 32