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