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