summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot2017-10-11 02:21:48 -0500
committerandroid-build-team Robot2017-10-11 02:21:48 -0500
commitdcdc77c87e2c777fc8f5cb9672b4706d5dad3b36 (patch)
tree6595f49407fbe45702f943d913a1d34bd1910fb8
parent666e90ffc939a27db63bd7c031fe70ebc8676b73 (diff)
parent52ea25cf06cef250ec73052611b48556b3fce4d5 (diff)
downloadframeworks-native-dcdc77c87e2c777fc8f5cb9672b4706d5dad3b36.tar.gz
frameworks-native-dcdc77c87e2c777fc8f5cb9672b4706d5dad3b36.tar.xz
frameworks-native-dcdc77c87e2c777fc8f5cb9672b4706d5dad3b36.zip
Snap for 4388906 from 52ea25cf06cef250ec73052611b48556b3fce4d5 to oc-mr1-release
Change-Id: I8be8e1ad05e7445a5c03a3f6009b5e1e30171a59
-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