buffer_hub_client.cpp revision 108e84f7e6a9117b66dba000dcf16c6d8c862e16
1#include <private/dvr/buffer_hub_client.h>
2
3#include <log/log.h>
4#include <poll.h>
5#define ATRACE_TAG ATRACE_TAG_GRAPHICS
6#include <utils/Trace.h>
7
8#include <mutex>
9
10#include <pdx/default_transport/client_channel.h>
11#include <pdx/default_transport/client_channel_factory.h>
12#include <private/dvr/platform_defines.h>
13
14#include "include/private/dvr/bufferhub_rpc.h"
15
16using android::pdx::LocalHandle;
17using android::pdx::LocalChannelHandle;
18using android::pdx::rpc::WrapBuffer;
19using android::pdx::Status;
20
21namespace {
22
23// TODO(hendrikw): These flags can not be hard coded.
24constexpr int kUncachedBlobUsageFlags = GRALLOC_USAGE_SW_READ_RARELY |
25                                        GRALLOC_USAGE_SW_WRITE_RARELY |
26                                        GRALLOC_USAGE_PRIVATE_UNCACHED;
27
28}  // anonymous namespace
29
30namespace android {
31namespace dvr {
32
33BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
34    : Client{pdx::default_transport::ClientChannel::Create(
35          std::move(channel_handle))},
36      id_(-1) {}
37BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
38    : Client{pdx::default_transport::ClientChannelFactory::Create(
39          endpoint_path)},
40      id_(-1) {}
41
42BufferHubBuffer::~BufferHubBuffer() {}
43
44Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
45  Status<LocalChannelHandle> status =
46      InvokeRemoteMethod<BufferHubRPC::NewConsumer>();
47  ALOGE_IF(!status,
48           "BufferHub::CreateConsumer: Failed to create consumer channel: %s",
49           status.GetErrorMessage().c_str());
50  return status;
51}
52
53int BufferHubBuffer::ImportBuffer() {
54  ATRACE_NAME("BufferHubBuffer::ImportBuffer");
55
56  Status<NativeBufferHandle<LocalHandle>> status =
57      InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
58  if (!status) {
59    ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
60          status.GetErrorMessage().c_str());
61    return -status.error();
62  } else if (status.get().id() < 0) {
63    ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!");
64    return -EIO;
65  }
66
67  auto buffer_handle = status.take();
68
69  // Stash the buffer id to replace the value in id_.
70  const int new_id = buffer_handle.id();
71
72  // Import the buffer.
73  IonBuffer ion_buffer;
74  ALOGD_IF(
75      TRACE, "BufferHubBuffer::ImportBuffer: id=%d FdCount=%zu IntCount=%zu",
76      buffer_handle.id(), buffer_handle.FdCount(), buffer_handle.IntCount());
77
78  const int ret = buffer_handle.Import(&ion_buffer);
79  if (ret < 0)
80    return ret;
81
82  // If the import succeeds, replace the previous buffer and id.
83  buffer_ = std::move(ion_buffer);
84  id_ = new_id;
85  return 0;
86}
87
88int BufferHubBuffer::Poll(int timeout_ms) {
89  ATRACE_NAME("BufferHubBuffer::Poll");
90  pollfd p = {event_fd(), POLLIN, 0};
91  return poll(&p, 1, timeout_ms);
92}
93
94int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height,
95                          void** address) {
96  return buffer_.Lock(usage, x, y, width, height, address);
97}
98
99int BufferHubBuffer::Unlock() { return buffer_.Unlock(); }
100
101int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
102  int width = static_cast<int>(size);
103  int height = 1;
104  // TODO(hendrikw): These flags can not be hard coded.
105  constexpr int usage = GRALLOC_USAGE_SW_READ_RARELY |
106                        GRALLOC_USAGE_SW_WRITE_RARELY |
107                        GRALLOC_USAGE_PRIVATE_UNCACHED;
108  int ret = Lock(usage, 0, 0, width, height, addr);
109  if (ret == 0)
110    Unlock();
111  return ret;
112}
113
114int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) {
115  int width = static_cast<int>(size);
116  int height = 1;
117  constexpr int usage =
118      GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_PRIVATE_UNCACHED;
119  int ret = Lock(usage, 0, 0, width, height, addr);
120  if (ret == 0)
121    Unlock();
122  return ret;
123}
124
125void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
126                                 size_t max_fds_count) const {
127  size_t numFds = static_cast<size_t>(native_handle()->numFds);
128  *fds_count = std::min(max_fds_count, numFds);
129  std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
130}
131
132BufferConsumer::BufferConsumer(LocalChannelHandle channel)
133    : BASE(std::move(channel)) {
134  const int ret = ImportBuffer();
135  if (ret < 0) {
136    ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s",
137          strerror(-ret));
138    Close(ret);
139  }
140}
141
142std::unique_ptr<BufferConsumer> BufferConsumer::Import(
143    LocalChannelHandle channel) {
144  ATRACE_NAME("BufferConsumer::Import");
145  ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value());
146  return BufferConsumer::Create(std::move(channel));
147}
148
149std::unique_ptr<BufferConsumer> BufferConsumer::Import(
150    Status<LocalChannelHandle> status) {
151  return Import(status ? status.take()
152                       : LocalChannelHandle{nullptr, -status.error()});
153}
154
155int BufferConsumer::Acquire(LocalHandle* ready_fence) {
156  return Acquire(ready_fence, nullptr, 0);
157}
158
159int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
160                            size_t meta_size_bytes) {
161  ATRACE_NAME("BufferConsumer::Acquire");
162  LocalFence fence;
163  auto return_value =
164      std::make_pair(std::ref(fence), WrapBuffer(meta, meta_size_bytes));
165  auto status = InvokeRemoteMethodInPlace<BufferHubRPC::ConsumerAcquire>(
166      &return_value, meta_size_bytes);
167  if (status && ready_fence)
168    *ready_fence = fence.take();
169  return status ? 0 : -status.error();
170}
171
172int BufferConsumer::Release(const LocalHandle& release_fence) {
173  ATRACE_NAME("BufferConsumer::Release");
174  return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
175      BorrowedFence(release_fence.Borrow())));
176}
177
178int BufferConsumer::ReleaseAsync() {
179  ATRACE_NAME("BufferConsumer::ReleaseAsync");
180  return ReturnStatusOrError(
181      SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
182}
183
184int BufferConsumer::Discard() { return Release(LocalHandle()); }
185
186int BufferConsumer::SetIgnore(bool ignore) {
187  return ReturnStatusOrError(
188      InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
189}
190
191BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
192                               uint32_t usage, size_t metadata_size)
193    : BufferProducer(width, height, format, usage, usage, metadata_size) {}
194
195BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
196                               uint64_t producer_usage, uint64_t consumer_usage,
197                               size_t metadata_size)
198    : BASE(BufferHubRPC::kClientPath) {
199  ATRACE_NAME("BufferProducer::BufferProducer");
200  ALOGD_IF(TRACE,
201           "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
202           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
203           " metadata_size=%zu",
204           event_fd(), width, height, format, producer_usage, consumer_usage,
205           metadata_size);
206
207  // (b/37881101) Deprecate producer/consumer usage
208  auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
209      width, height, format, (producer_usage | consumer_usage), metadata_size);
210  if (!status) {
211    ALOGE(
212        "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
213        status.GetErrorMessage().c_str());
214    Close(-status.error());
215    return;
216  }
217
218  const int ret = ImportBuffer();
219  if (ret < 0) {
220    ALOGE(
221        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
222        strerror(-ret));
223    Close(ret);
224  }
225}
226
227BufferProducer::BufferProducer(const std::string& name, int user_id,
228                               int group_id, uint32_t width, uint32_t height,
229                               uint32_t format, uint32_t usage,
230                               size_t meta_size_bytes)
231    : BufferProducer(name, user_id, group_id, width, height, format, usage,
232                     usage, meta_size_bytes) {}
233
234BufferProducer::BufferProducer(const std::string& name, int user_id,
235                               int group_id, uint32_t width, uint32_t height,
236                               uint32_t format, uint64_t producer_usage,
237                               uint64_t consumer_usage, size_t meta_size_bytes)
238    : BASE(BufferHubRPC::kClientPath) {
239  ATRACE_NAME("BufferProducer::BufferProducer");
240  ALOGD_IF(TRACE,
241           "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
242           "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
243           " consumer_usage=%" PRIx64 " meta_size_bytes=%zu",
244           event_fd(), name.c_str(), user_id, group_id, width, height, format,
245           producer_usage, consumer_usage, meta_size_bytes);
246
247  // (b/37881101) Deprecate producer/consumer usage
248  auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
249      name, user_id, group_id, width, height, format,
250      (producer_usage | consumer_usage), meta_size_bytes);
251  if (!status) {
252    ALOGE(
253        "BufferProducer::BufferProducer: Failed to create/get persistent "
254        "buffer \"%s\": %s",
255        name.c_str(), status.GetErrorMessage().c_str());
256    Close(-status.error());
257    return;
258  }
259
260  const int ret = ImportBuffer();
261  if (ret < 0) {
262    ALOGE(
263        "BufferProducer::BufferProducer: Failed to import producer buffer "
264        "\"%s\": %s",
265        name.c_str(), strerror(-ret));
266    Close(ret);
267  }
268}
269
270BufferProducer::BufferProducer(uint32_t usage, size_t size)
271    : BufferProducer(usage, usage, size) {}
272
273BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
274                               size_t size)
275    : BASE(BufferHubRPC::kClientPath) {
276  ATRACE_NAME("BufferProducer::BufferProducer");
277  ALOGD_IF(TRACE,
278           "BufferProducer::BufferProducer: producer_usage=%" PRIx64
279           " consumer_usage=%" PRIx64 " size=%zu",
280           producer_usage, consumer_usage, size);
281  const int width = static_cast<int>(size);
282  const int height = 1;
283  const int format = HAL_PIXEL_FORMAT_BLOB;
284  const size_t meta_size_bytes = 0;
285
286  // (b/37881101) Deprecate producer/consumer usage
287  auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
288      width, height, format, (producer_usage | consumer_usage),
289      meta_size_bytes);
290  if (!status) {
291    ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
292          status.GetErrorMessage().c_str());
293    Close(-status.error());
294    return;
295  }
296
297  const int ret = ImportBuffer();
298  if (ret < 0) {
299    ALOGE(
300        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
301        strerror(-ret));
302    Close(ret);
303  }
304}
305
306BufferProducer::BufferProducer(const std::string& name, int user_id,
307                               int group_id, uint32_t usage, size_t size)
308    : BufferProducer(name, user_id, group_id, usage, usage, size) {}
309
310BufferProducer::BufferProducer(const std::string& name, int user_id,
311                               int group_id, uint64_t producer_usage,
312                               uint64_t consumer_usage, size_t size)
313    : BASE(BufferHubRPC::kClientPath) {
314  ATRACE_NAME("BufferProducer::BufferProducer");
315  ALOGD_IF(TRACE,
316           "BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
317           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu",
318           name.c_str(), user_id, group_id, producer_usage, consumer_usage,
319           size);
320  const int width = static_cast<int>(size);
321  const int height = 1;
322  const int format = HAL_PIXEL_FORMAT_BLOB;
323  const size_t meta_size_bytes = 0;
324
325  // (b/37881101) Deprecate producer/consumer usage
326  auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
327      name, user_id, group_id, width, height, format,
328      (producer_usage | consumer_usage), meta_size_bytes);
329  if (!status) {
330    ALOGE(
331        "BufferProducer::BufferProducer: Failed to create persistent "
332        "buffer \"%s\": %s",
333        name.c_str(), status.GetErrorMessage().c_str());
334    Close(-status.error());
335    return;
336  }
337
338  const int ret = ImportBuffer();
339  if (ret < 0) {
340    ALOGE(
341        "BufferProducer::BufferProducer: Failed to import producer buffer "
342        "\"%s\": %s",
343        name.c_str(), strerror(-ret));
344    Close(ret);
345  }
346}
347
348BufferProducer::BufferProducer(const std::string& name)
349    : BASE(BufferHubRPC::kClientPath) {
350  ATRACE_NAME("BufferProducer::BufferProducer");
351  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: name=%s", name.c_str());
352
353  auto status = InvokeRemoteMethod<BufferHubRPC::GetPersistentBuffer>(name);
354  if (!status) {
355    ALOGE(
356        "BufferProducer::BufferProducer: Failed to get producer buffer by name "
357        "\"%s\": %s",
358        name.c_str(), status.GetErrorMessage().c_str());
359    Close(-status.error());
360    return;
361  }
362
363  const int ret = ImportBuffer();
364  if (ret < 0) {
365    ALOGE(
366        "BufferProducer::BufferProducer: Failed to import producer buffer "
367        "\"%s\": %s",
368        name.c_str(), strerror(-ret));
369    Close(ret);
370  }
371}
372
373BufferProducer::BufferProducer(LocalChannelHandle channel)
374    : BASE(std::move(channel)) {
375  const int ret = ImportBuffer();
376  if (ret < 0) {
377    ALOGE(
378        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
379        strerror(-ret));
380    Close(ret);
381  }
382}
383
384int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
385                         size_t meta_size_bytes) {
386  ATRACE_NAME("BufferProducer::Post");
387  return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
388      BorrowedFence(ready_fence.Borrow()), WrapBuffer(meta, meta_size_bytes)));
389}
390
391int BufferProducer::Gain(LocalHandle* release_fence) {
392  ATRACE_NAME("BufferProducer::Gain");
393  auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
394  if (!status)
395    return -status.error();
396  if (release_fence)
397    *release_fence = status.take().take();
398  return 0;
399}
400
401int BufferProducer::GainAsync() {
402  ATRACE_NAME("BufferProducer::GainAsync");
403  return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
404}
405
406std::unique_ptr<BufferProducer> BufferProducer::Import(
407    LocalChannelHandle channel) {
408  ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
409  return BufferProducer::Create(std::move(channel));
410}
411
412std::unique_ptr<BufferProducer> BufferProducer::Import(
413    Status<LocalChannelHandle> status) {
414  return Import(status ? status.take()
415                       : LocalChannelHandle{nullptr, -status.error()});
416}
417
418int BufferProducer::MakePersistent(const std::string& name, int user_id,
419                                   int group_id) {
420  ATRACE_NAME("BufferProducer::MakePersistent");
421  return ReturnStatusOrError(
422      InvokeRemoteMethod<BufferHubRPC::ProducerMakePersistent>(name, user_id,
423                                                               group_id));
424}
425
426int BufferProducer::RemovePersistence() {
427  ATRACE_NAME("BufferProducer::RemovePersistence");
428  return ReturnStatusOrError(
429      InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>());
430}
431
432std::unique_ptr<BufferProducer> BufferProducer::CreateUncachedBlob(
433    size_t size) {
434  return BufferProducer::Create(kUncachedBlobUsageFlags, size);
435}
436
437std::unique_ptr<BufferProducer> BufferProducer::CreatePersistentUncachedBlob(
438    const std::string& name, int user_id, int group_id, size_t size) {
439  return BufferProducer::Create(name, user_id, group_id,
440                                kUncachedBlobUsageFlags, size);
441}
442
443}  // namespace dvr
444}  // namespace android
445