buffer_hub_client.cpp revision 10e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848
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
133void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
134                                 size_t max_fds_count) const {
135  size_t numFds = static_cast<size_t>(native_handle()->numFds);
136  *fds_count = std::min(max_fds_count, numFds);
137  std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
138}
139
140BufferConsumer::BufferConsumer(LocalChannelHandle channel)
141    : BASE(std::move(channel)) {
142  const int ret = ImportBuffer();
143  if (ret < 0) {
144    ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s",
145          strerror(-ret));
146    Close(ret);
147  }
148}
149
150std::unique_ptr<BufferConsumer> BufferConsumer::Import(
151    LocalChannelHandle channel) {
152  ATRACE_NAME("BufferConsumer::Import");
153  ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value());
154  return BufferConsumer::Create(std::move(channel));
155}
156
157std::unique_ptr<BufferConsumer> BufferConsumer::Import(
158    Status<LocalChannelHandle> status) {
159  return Import(status ? status.take()
160                       : LocalChannelHandle{nullptr, -status.error()});
161}
162
163int BufferConsumer::Acquire(LocalHandle* ready_fence) {
164  return Acquire(ready_fence, nullptr, 0);
165}
166
167int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
168                            size_t meta_size_bytes) {
169  ATRACE_NAME("BufferConsumer::Acquire");
170  LocalFence fence;
171  auto return_value =
172      std::make_pair(std::ref(fence), WrapBuffer(meta, meta_size_bytes));
173  auto status = InvokeRemoteMethodInPlace<BufferHubRPC::ConsumerAcquire>(
174      &return_value, meta_size_bytes);
175  if (status && ready_fence)
176    *ready_fence = fence.take();
177  return status ? 0 : -status.error();
178}
179
180int BufferConsumer::Release(const LocalHandle& release_fence) {
181  ATRACE_NAME("BufferConsumer::Release");
182  return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
183      BorrowedFence(release_fence.Borrow())));
184}
185
186int BufferConsumer::ReleaseAsync() {
187  ATRACE_NAME("BufferConsumer::ReleaseAsync");
188  return ReturnStatusOrError(
189      SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
190}
191
192int BufferConsumer::Discard() { return Release(LocalHandle()); }
193
194int BufferConsumer::SetIgnore(bool ignore) {
195  return ReturnStatusOrError(
196      InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
197}
198
199BufferProducer::BufferProducer(int width, int height, int format, int usage,
200                               size_t metadata_size, size_t slice_count)
201    : BASE(BufferHubRPC::kClientPath) {
202  ATRACE_NAME("BufferProducer::BufferProducer");
203  ALOGD_IF(TRACE,
204           "BufferProducer::BufferProducer: fd=%d width=%d height=%d format=%d "
205           "usage=%d, metadata_size=%zu, slice_count=%zu",
206           event_fd(), width, height, format, usage, metadata_size,
207           slice_count);
208
209  auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
210      width, height, format, usage, metadata_size, slice_count);
211  if (!status) {
212    ALOGE(
213        "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
214        status.GetErrorMessage().c_str());
215    Close(-status.error());
216    return;
217  }
218
219  const int ret = ImportBuffer();
220  if (ret < 0) {
221    ALOGE(
222        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
223        strerror(-ret));
224    Close(ret);
225  }
226}
227
228BufferProducer::BufferProducer(const std::string& name, int user_id,
229                               int group_id, int width, int height, int format,
230                               int usage, size_t meta_size_bytes,
231                               size_t slice_count)
232    : BASE(BufferHubRPC::kClientPath) {
233  ATRACE_NAME("BufferProducer::BufferProducer");
234  ALOGD_IF(TRACE,
235           "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
236           "group_id=%d width=%d height=%d format=%d usage=%d, "
237           "meta_size_bytes=%zu, slice_count=%zu",
238           event_fd(), name.c_str(), user_id, group_id, width, height, format,
239           usage, meta_size_bytes, slice_count);
240
241  auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
242      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
243      slice_count);
244  if (!status) {
245    ALOGE(
246        "BufferProducer::BufferProducer: Failed to create/get persistent "
247        "buffer \"%s\": %s",
248        name.c_str(), status.GetErrorMessage().c_str());
249    Close(-status.error());
250    return;
251  }
252
253  const int ret = ImportBuffer();
254  if (ret < 0) {
255    ALOGE(
256        "BufferProducer::BufferProducer: Failed to import producer buffer "
257        "\"%s\": %s",
258        name.c_str(), strerror(-ret));
259    Close(ret);
260  }
261}
262
263BufferProducer::BufferProducer(int usage, size_t size)
264    : BASE(BufferHubRPC::kClientPath) {
265  ATRACE_NAME("BufferProducer::BufferProducer");
266  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%d size=%zu", usage,
267           size);
268  const int width = static_cast<int>(size);
269  const int height = 1;
270  const int format = HAL_PIXEL_FORMAT_BLOB;
271  const size_t meta_size_bytes = 0;
272  const size_t slice_count = 1;
273  auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
274      width, height, format, usage, meta_size_bytes, slice_count);
275  if (!status) {
276    ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
277          status.GetErrorMessage().c_str());
278    Close(-status.error());
279    return;
280  }
281
282  const int ret = ImportBuffer();
283  if (ret < 0) {
284    ALOGE(
285        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
286        strerror(-ret));
287    Close(ret);
288  }
289}
290
291BufferProducer::BufferProducer(const std::string& name, int user_id,
292                               int group_id, int usage, size_t size)
293    : BASE(BufferHubRPC::kClientPath) {
294  ATRACE_NAME("BufferProducer::BufferProducer");
295  ALOGD_IF(TRACE,
296           "BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
297           "usage=%d size=%zu",
298           name.c_str(), user_id, group_id, usage, size);
299  const int width = static_cast<int>(size);
300  const int height = 1;
301  const int format = HAL_PIXEL_FORMAT_BLOB;
302  const size_t meta_size_bytes = 0;
303  const size_t slice_count = 1;
304  auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
305      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
306      slice_count);
307  if (!status) {
308    ALOGE(
309        "BufferProducer::BufferProducer: Failed to create persistent "
310        "buffer \"%s\": %s",
311        name.c_str(), status.GetErrorMessage().c_str());
312    Close(-status.error());
313    return;
314  }
315
316  const int ret = ImportBuffer();
317  if (ret < 0) {
318    ALOGE(
319        "BufferProducer::BufferProducer: Failed to import producer buffer "
320        "\"%s\": %s",
321        name.c_str(), strerror(-ret));
322    Close(ret);
323  }
324}
325
326BufferProducer::BufferProducer(const std::string& name)
327    : BASE(BufferHubRPC::kClientPath) {
328  ATRACE_NAME("BufferProducer::BufferProducer");
329  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: name=%s", name.c_str());
330
331  auto status = InvokeRemoteMethod<BufferHubRPC::GetPersistentBuffer>(name);
332  if (!status) {
333    ALOGE(
334        "BufferProducer::BufferProducer: Failed to get producer buffer by name "
335        "\"%s\": %s",
336        name.c_str(), status.GetErrorMessage().c_str());
337    Close(-status.error());
338    return;
339  }
340
341  const int ret = ImportBuffer();
342  if (ret < 0) {
343    ALOGE(
344        "BufferProducer::BufferProducer: Failed to import producer buffer "
345        "\"%s\": %s",
346        name.c_str(), strerror(-ret));
347    Close(ret);
348  }
349}
350
351BufferProducer::BufferProducer(LocalChannelHandle channel)
352    : BASE(std::move(channel)) {
353  const int ret = ImportBuffer();
354  if (ret < 0) {
355    ALOGE(
356        "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
357        strerror(-ret));
358    Close(ret);
359  }
360}
361
362int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
363                         size_t meta_size_bytes) {
364  ATRACE_NAME("BufferProducer::Post");
365  return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
366      BorrowedFence(ready_fence.Borrow()), WrapBuffer(meta, meta_size_bytes)));
367}
368
369int BufferProducer::Gain(LocalHandle* release_fence) {
370  ATRACE_NAME("BufferProducer::Gain");
371  auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
372  if (!status)
373    return -status.error();
374  if (release_fence)
375    *release_fence = status.take().take();
376  return 0;
377}
378
379int BufferProducer::GainAsync() {
380  ATRACE_NAME("BufferProducer::GainAsync");
381  return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
382}
383
384std::unique_ptr<BufferProducer> BufferProducer::Import(
385    LocalChannelHandle channel) {
386  ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
387  return BufferProducer::Create(std::move(channel));
388}
389
390std::unique_ptr<BufferProducer> BufferProducer::Import(
391    Status<LocalChannelHandle> status) {
392  return Import(status ? status.take()
393                       : LocalChannelHandle{nullptr, -status.error()});
394}
395
396int BufferProducer::MakePersistent(const std::string& name, int user_id,
397                                   int group_id) {
398  ATRACE_NAME("BufferProducer::MakePersistent");
399  return ReturnStatusOrError(
400      InvokeRemoteMethod<BufferHubRPC::ProducerMakePersistent>(name, user_id,
401                                                               group_id));
402}
403
404int BufferProducer::RemovePersistence() {
405  ATRACE_NAME("BufferProducer::RemovePersistence");
406  return ReturnStatusOrError(
407      InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>());
408}
409
410std::unique_ptr<BufferProducer> BufferProducer::CreateUncachedBlob(
411    size_t size) {
412  return BufferProducer::Create(kUncachedBlobUsageFlags, size);
413}
414
415std::unique_ptr<BufferProducer> BufferProducer::CreatePersistentUncachedBlob(
416    const std::string& name, int user_id, int group_id, size_t size) {
417  return BufferProducer::Create(name, user_id, group_id,
418                                kUncachedBlobUsageFlags, size);
419}
420
421}  // namespace dvr
422}  // namespace android
423