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