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