buffer_hub_client.cpp revision e4eec20f6263f4a42ae462456f60ea6c4518bb0a
1#include <private/dvr/buffer_hub_client.h>
2
3#include <cutils/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
23constexpr int kUncachedBlobUsageFlags = GRALLOC_USAGE_SW_READ_RARELY |
24                                        GRALLOC_USAGE_SW_WRITE_RARELY |
25                                        GRALLOC_USAGE_PRIVATE_UNCACHED;
26
27}  // anonymous namespace
28
29namespace android {
30namespace dvr {
31
32BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
33    : Client{pdx::default_transport::ClientChannel::Create(
34          std::move(channel_handle))},
35      id_(-1) {}
36BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
37    : Client{pdx::default_transport::ClientChannelFactory::Create(
38          endpoint_path)},
39      id_(-1) {}
40
41BufferHubBuffer::~BufferHubBuffer() {}
42
43Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
44  Status<LocalChannelHandle> status =
45      InvokeRemoteMethod<BufferHubRPC::NewConsumer>();
46  ALOGE_IF(!status,
47           "BufferHub::CreateConsumer: Failed to create consumer channel: %s",
48           status.GetErrorMessage().c_str());
49  return status;
50}
51
52int BufferHubBuffer::ImportBuffer() {
53  ATRACE_NAME("BufferHubBuffer::ImportBuffer");
54  if (!IonBuffer::GetGrallocModule())
55    return -EIO;
56
57  Status<std::vector<NativeBufferHandle<LocalHandle>>> status =
58      InvokeRemoteMethod<BufferHubRPC::GetBuffers>();
59  if (!status) {
60    ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffers: %s",
61          status.GetErrorMessage().c_str());
62    return -status.error();
63  } else if (status.get().empty()) {
64    ALOGE(
65        "BufferHubBuffer::ImportBuffer: Expected to receive at least one "
66        "buffer handle but got zero!");
67    return -EIO;
68  }
69
70  auto buffer_handles = status.take();
71
72  // Stash the buffer id to replace the value in id_. All sub-buffers of a
73  // buffer hub buffer have the same id.
74  const int new_id = buffer_handles[0].id();
75
76  // Import all of the buffers.
77  std::vector<IonBuffer> ion_buffers;
78  for (auto& handle : buffer_handles) {
79    const size_t i = &handle - buffer_handles.data();
80    ALOGD_IF(
81        TRACE,
82        "BufferHubBuffer::ImportBuffer: i=%zu id=%d FdCount=%zu IntCount=%zu",
83        i, handle.id(), handle.FdCount(), handle.IntCount());
84
85    IonBuffer buffer;
86    const int ret = handle.Import(&buffer);
87    if (ret < 0)
88      return ret;
89
90    ion_buffers.emplace_back(std::move(buffer));
91  }
92
93  // If all imports succeed, replace the previous buffers and id.
94  slices_ = std::move(ion_buffers);
95  id_ = new_id;
96  return 0;
97}
98
99int BufferHubBuffer::Poll(int timeout_ms) {
100  ATRACE_NAME("BufferHubBuffer::Poll");
101  pollfd p = {event_fd(), POLLIN, 0};
102  return poll(&p, 1, timeout_ms);
103}
104
105int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height,
106                          void** address, size_t index) {
107  return slices_[index].Lock(usage, x, y, width, height, address);
108}
109
110int BufferHubBuffer::Unlock(size_t index) { return slices_[index].Unlock(); }
111
112int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
113  int width = static_cast<int>(size);
114  int height = 1;
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
135BufferConsumer::BufferConsumer(LocalChannelHandle channel)
136    : BASE(std::move(channel)) {
137  const int ret = ImportBuffer();
138  if (ret < 0) {
139    ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s",
140          strerror(-ret));
141    Close(ret);
142  }
143}
144
145std::unique_ptr<BufferConsumer> BufferConsumer::Import(
146    LocalChannelHandle channel) {
147  ATRACE_NAME("BufferConsumer::Import");
148  ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value());
149  return BufferConsumer::Create(std::move(channel));
150}
151
152std::unique_ptr<BufferConsumer> BufferConsumer::Import(
153    Status<LocalChannelHandle> status) {
154  return Import(status ? status.take()
155                       : LocalChannelHandle{nullptr, -status.error()});
156}
157
158int BufferConsumer::Acquire(LocalHandle* ready_fence) {
159  return Acquire(ready_fence, nullptr, 0);
160}
161
162int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
163                            size_t meta_size_bytes) {
164  ATRACE_NAME("BufferConsumer::Acquire");
165  LocalFence fence;
166  auto return_value =
167      std::make_pair(std::ref(fence), WrapBuffer(meta, meta_size_bytes));
168  auto status = InvokeRemoteMethodInPlace<BufferHubRPC::ConsumerAcquire>(
169      &return_value, meta_size_bytes);
170  if (status && ready_fence)
171    *ready_fence = fence.take();
172  return status ? 0 : -status.error();
173}
174
175int BufferConsumer::Release(const LocalHandle& release_fence) {
176  ATRACE_NAME("BufferConsumer::Release");
177  return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
178      BorrowedFence(release_fence.Borrow())));
179}
180
181int BufferConsumer::ReleaseAsync() {
182  ATRACE_NAME("BufferConsumer::ReleaseAsync");
183  return ReturnStatusOrError(
184      SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
185}
186
187int BufferConsumer::Discard() { return Release(LocalHandle()); }
188
189int BufferConsumer::SetIgnore(bool ignore) {
190  return ReturnStatusOrError(
191      InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
192}
193
194BufferProducer::BufferProducer(int width, int height, int format, int usage,
195                               size_t metadata_size, size_t slice_count)
196    : BASE(BufferHubRPC::kClientPath) {
197  ATRACE_NAME("BufferProducer::BufferProducer");
198  ALOGD_IF(TRACE,
199           "BufferProducer::BufferProducer: fd=%d width=%d height=%d format=%d "
200           "usage=%d, metadata_size=%zu, slice_count=%zu",
201           event_fd(), width, height, format, usage, metadata_size,
202           slice_count);
203
204  auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
205      width, height, format, usage, metadata_size, slice_count);
206  if (!status) {
207    ALOGE(
208        "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
209        status.GetErrorMessage().c_str());
210    Close(-status.error());
211    return;
212  }
213
214  const int ret = ImportBuffer();
215  if (ret < 0) {
216    ALOGE(
217        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
218        strerror(-ret));
219    Close(ret);
220  }
221}
222
223BufferProducer::BufferProducer(const std::string& name, int user_id,
224                               int group_id, int width, int height, int format,
225                               int usage, size_t meta_size_bytes,
226                               size_t slice_count)
227    : BASE(BufferHubRPC::kClientPath) {
228  ATRACE_NAME("BufferProducer::BufferProducer");
229  ALOGD_IF(TRACE,
230           "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
231           "group_id=%d width=%d height=%d format=%d usage=%d, "
232           "meta_size_bytes=%zu, slice_count=%zu",
233           event_fd(), name.c_str(), user_id, group_id, width, height, format,
234           usage, meta_size_bytes, slice_count);
235
236  auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
237      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
238      slice_count);
239  if (!status) {
240    ALOGE(
241        "BufferProducer::BufferProducer: Failed to create/get persistent "
242        "buffer \"%s\": %s",
243        name.c_str(), status.GetErrorMessage().c_str());
244    Close(-status.error());
245    return;
246  }
247
248  const int ret = ImportBuffer();
249  if (ret < 0) {
250    ALOGE(
251        "BufferProducer::BufferProducer: Failed to import producer buffer "
252        "\"%s\": %s",
253        name.c_str(), strerror(-ret));
254    Close(ret);
255  }
256}
257
258BufferProducer::BufferProducer(int usage, size_t size)
259    : BASE(BufferHubRPC::kClientPath) {
260  ATRACE_NAME("BufferProducer::BufferProducer");
261  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%d size=%zu", usage,
262           size);
263  const int width = static_cast<int>(size);
264  const int height = 1;
265  const int format = HAL_PIXEL_FORMAT_BLOB;
266  const size_t meta_size_bytes = 0;
267  const size_t slice_count = 1;
268  auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
269      width, height, format, usage, meta_size_bytes, slice_count);
270  if (!status) {
271    ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
272          status.GetErrorMessage().c_str());
273    Close(-status.error());
274    return;
275  }
276
277  const int ret = ImportBuffer();
278  if (ret < 0) {
279    ALOGE(
280        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
281        strerror(-ret));
282    Close(ret);
283  }
284}
285
286BufferProducer::BufferProducer(const std::string& name, int user_id,
287                               int group_id, int usage, size_t size)
288    : BASE(BufferHubRPC::kClientPath) {
289  ATRACE_NAME("BufferProducer::BufferProducer");
290  ALOGD_IF(TRACE,
291           "BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
292           "usage=%d size=%zu",
293           name.c_str(), user_id, group_id, usage, size);
294  const int width = static_cast<int>(size);
295  const int height = 1;
296  const int format = HAL_PIXEL_FORMAT_BLOB;
297  const size_t meta_size_bytes = 0;
298  const size_t slice_count = 1;
299  auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
300      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
301      slice_count);
302  if (!status) {
303    ALOGE(
304        "BufferProducer::BufferProducer: Failed to create persistent "
305        "buffer \"%s\": %s",
306        name.c_str(), status.GetErrorMessage().c_str());
307    Close(-status.error());
308    return;
309  }
310
311  const int ret = ImportBuffer();
312  if (ret < 0) {
313    ALOGE(
314        "BufferProducer::BufferProducer: Failed to import producer buffer "
315        "\"%s\": %s",
316        name.c_str(), strerror(-ret));
317    Close(ret);
318  }
319}
320
321BufferProducer::BufferProducer(const std::string& name)
322    : BASE(BufferHubRPC::kClientPath) {
323  ATRACE_NAME("BufferProducer::BufferProducer");
324  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: name=%s", name.c_str());
325
326  auto status = InvokeRemoteMethod<BufferHubRPC::GetPersistentBuffer>(name);
327  if (!status) {
328    ALOGE(
329        "BufferProducer::BufferProducer: Failed to get producer buffer by name "
330        "\"%s\": %s",
331        name.c_str(), status.GetErrorMessage().c_str());
332    Close(-status.error());
333    return;
334  }
335
336  const int ret = ImportBuffer();
337  if (ret < 0) {
338    ALOGE(
339        "BufferProducer::BufferProducer: Failed to import producer buffer "
340        "\"%s\": %s",
341        name.c_str(), strerror(-ret));
342    Close(ret);
343  }
344}
345
346BufferProducer::BufferProducer(LocalChannelHandle channel)
347    : BASE(std::move(channel)) {
348  const int ret = ImportBuffer();
349  if (ret < 0) {
350    ALOGE(
351        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
352        strerror(-ret));
353    Close(ret);
354  }
355}
356
357int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
358                         size_t meta_size_bytes) {
359  ATRACE_NAME("BufferProducer::Post");
360  return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
361      BorrowedFence(ready_fence.Borrow()), WrapBuffer(meta, meta_size_bytes)));
362}
363
364int BufferProducer::Gain(LocalHandle* release_fence) {
365  ATRACE_NAME("BufferProducer::Gain");
366  auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
367  if (!status)
368    return -status.error();
369  if (release_fence)
370    *release_fence = status.take().take();
371  return 0;
372}
373
374int BufferProducer::GainAsync() {
375  ATRACE_NAME("BufferProducer::GainAsync");
376  return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
377}
378
379std::unique_ptr<BufferProducer> BufferProducer::Import(
380    LocalChannelHandle channel) {
381  ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
382  return BufferProducer::Create(std::move(channel));
383}
384
385std::unique_ptr<BufferProducer> BufferProducer::Import(
386    Status<LocalChannelHandle> status) {
387  return Import(status ? status.take()
388                       : LocalChannelHandle{nullptr, -status.error()});
389}
390
391int BufferProducer::MakePersistent(const std::string& name, int user_id,
392                                   int group_id) {
393  ATRACE_NAME("BufferProducer::MakePersistent");
394  return ReturnStatusOrError(
395      InvokeRemoteMethod<BufferHubRPC::ProducerMakePersistent>(name, user_id,
396                                                               group_id));
397}
398
399int BufferProducer::RemovePersistence() {
400  ATRACE_NAME("BufferProducer::RemovePersistence");
401  return ReturnStatusOrError(
402      InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>());
403}
404
405std::unique_ptr<BufferProducer> BufferProducer::CreateUncachedBlob(
406    size_t size) {
407  return BufferProducer::Create(kUncachedBlobUsageFlags, size);
408}
409
410std::unique_ptr<BufferProducer> BufferProducer::CreatePersistentUncachedBlob(
411    const std::string& name, int user_id, int group_id, size_t size) {
412  return BufferProducer::Create(name, user_id, group_id,
413                                kUncachedBlobUsageFlags, size);
414}
415
416}  // namespace dvr
417}  // namespace android
418