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 
15 using android::pdx::LocalHandle;
16 using android::pdx::LocalChannelHandle;
17 using android::pdx::rpc::WrapBuffer;
18 using android::pdx::Status;
19 
20 namespace android {
21 namespace dvr {
22 
BufferHubBuffer(LocalChannelHandle channel_handle)23 BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
24     : Client{pdx::default_transport::ClientChannel::Create(
25           std::move(channel_handle))},
26       id_(-1) {}
BufferHubBuffer(const std::string & endpoint_path)27 BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
28     : Client{pdx::default_transport::ClientChannelFactory::Create(
29           endpoint_path)},
30       id_(-1) {}
31 
~BufferHubBuffer()32 BufferHubBuffer::~BufferHubBuffer() {}
33 
CreateConsumer()34 Status<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 
ImportBuffer()43 int 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 
Poll(int timeout_ms)78 int 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 
Lock(int usage,int x,int y,int width,int height,void ** address)84 int 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 
Unlock()89 int BufferHubBuffer::Unlock() { return buffer_.Unlock(); }
90 
GetBlobReadWritePointer(size_t size,void ** addr)91 int 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 
GetBlobReadOnlyPointer(size_t size,void ** addr)100 int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) {
101   return GetBlobReadWritePointer(size, addr);
102 }
103 
GetBlobFds(int * fds,size_t * fds_count,size_t max_fds_count) const104 void 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 
BufferConsumer(LocalChannelHandle channel)111 BufferConsumer::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 
Import(LocalChannelHandle channel)121 std::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 
Import(Status<LocalChannelHandle> status)128 std::unique_ptr<BufferConsumer> BufferConsumer::Import(
129     Status<LocalChannelHandle> status) {
130   return Import(status ? status.take()
131                        : LocalChannelHandle{nullptr, -status.error()});
132 }
133 
Acquire(LocalHandle * ready_fence)134 int BufferConsumer::Acquire(LocalHandle* ready_fence) {
135   return Acquire(ready_fence, nullptr, 0);
136 }
137 
Acquire(LocalHandle * ready_fence,void * meta,size_t meta_size_bytes)138 int 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 
Release(const LocalHandle & release_fence)151 int BufferConsumer::Release(const LocalHandle& release_fence) {
152   ATRACE_NAME("BufferConsumer::Release");
153   return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
154       BorrowedFence(release_fence.Borrow())));
155 }
156 
ReleaseAsync()157 int BufferConsumer::ReleaseAsync() {
158   ATRACE_NAME("BufferConsumer::ReleaseAsync");
159   return ReturnStatusOrError(
160       SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
161 }
162 
Discard()163 int BufferConsumer::Discard() { return Release(LocalHandle()); }
164 
SetIgnore(bool ignore)165 int BufferConsumer::SetIgnore(bool ignore) {
166   return ReturnStatusOrError(
167       InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
168 }
169 
BufferProducer(uint32_t width,uint32_t height,uint32_t format,uint32_t usage,size_t metadata_size)170 BufferProducer::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 
BufferProducer(uint32_t width,uint32_t height,uint32_t format,uint64_t producer_usage,uint64_t consumer_usage,size_t metadata_size)174 BufferProducer::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 
BufferProducer(const std::string & name,int user_id,int group_id,uint32_t width,uint32_t height,uint32_t format,uint32_t usage,size_t meta_size_bytes)206 BufferProducer::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 
BufferProducer(const std::string & name,int user_id,int group_id,uint32_t width,uint32_t height,uint32_t format,uint64_t producer_usage,uint64_t consumer_usage,size_t meta_size_bytes)213 BufferProducer::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 
BufferProducer(uint32_t usage,size_t size)249 BufferProducer::BufferProducer(uint32_t usage, size_t size)
250     : BufferProducer(usage, usage, size) {}
251 
BufferProducer(uint64_t producer_usage,uint64_t consumer_usage,size_t size)252 BufferProducer::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 
BufferProducer(const std::string & name,int user_id,int group_id,uint32_t usage,size_t size)285 BufferProducer::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 
BufferProducer(const std::string & name,int user_id,int group_id,uint64_t producer_usage,uint64_t consumer_usage,size_t size)289 BufferProducer::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 
BufferProducer(const std::string & name)327 BufferProducer::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 
BufferProducer(LocalChannelHandle channel)352 BufferProducer::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 
Post(const LocalHandle & ready_fence,const void * meta,size_t meta_size_bytes)363 int 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 
Gain(LocalHandle * release_fence)370 int 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 
GainAsync()380 int BufferProducer::GainAsync() {
381   ATRACE_NAME("BufferProducer::GainAsync");
382   return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
383 }
384 
Import(LocalChannelHandle channel)385 std::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 
Import(Status<LocalChannelHandle> status)391 std::unique_ptr<BufferProducer> BufferProducer::Import(
392     Status<LocalChannelHandle> status) {
393   return Import(status ? status.take()
394                        : LocalChannelHandle{nullptr, -status.error()});
395 }
396 
MakePersistent(const std::string & name,int user_id,int group_id)397 int 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 
RemovePersistence()405 int BufferProducer::RemovePersistence() {
406   ATRACE_NAME("BufferProducer::RemovePersistence");
407   return ReturnStatusOrError(
408       InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>());
409 }
410 
411 }  // namespace dvr
412 }  // namespace android
413