blob: 12243dc779bf8dcbe5ed69df53455f0def5c6c9b [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "buffer_hub.h"
2
Alex Vakulenko4fe60582017-02-02 11:35:59 -08003#include <log/log.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08004#include <poll.h>
5#include <utils/Trace.h>
6
7#include <iomanip>
8#include <sstream>
9#include <string>
10#include <thread>
11
12#include <pdx/default_transport/service_endpoint.h>
13#include <private/dvr/bufferhub_rpc.h>
14#include "consumer_channel.h"
15#include "producer_channel.h"
16#include "producer_queue_channel.h"
17
18using android::pdx::Channel;
19using android::pdx::Message;
20using android::pdx::rpc::DispatchRemoteMethod;
21using android::pdx::default_transport::Endpoint;
22
23namespace android {
24namespace dvr {
25
26BufferHubService::BufferHubService()
27 : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {}
28
29BufferHubService::~BufferHubService() {}
30
31bool BufferHubService::IsInitialized() const {
32 return BASE::IsInitialized() && IonBuffer::GetGrallocModule();
33}
34
35std::string BufferHubService::DumpState(size_t /*max_length*/) {
36 std::ostringstream stream;
37 auto channels = GetChannels<BufferHubChannel>();
38
39 std::sort(channels.begin(), channels.end(),
40 [](const std::shared_ptr<BufferHubChannel>& a,
41 const std::shared_ptr<BufferHubChannel>& b) {
42 return a->buffer_id() < b->buffer_id();
43 });
44
45 stream << "Active Producer Buffers:\n";
46 stream << std::right;
47 stream << std::setw(6) << "Id";
48 stream << " ";
49 stream << std::setw(9) << "Consumers";
50 stream << " ";
51 stream << std::setw(14) << "Geometry";
52 stream << " ";
53 stream << std::setw(6) << "Format";
54 stream << " ";
55 stream << std::setw(10) << "Usage";
56 stream << " ";
57 stream << "Name";
58 stream << std::endl;
59
60 for (const auto& channel : channels) {
61 if (channel->channel_type() == BufferHubChannel::kProducerType) {
62 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
63
64 stream << std::right;
65 stream << std::setw(6) << info.id;
66 stream << " ";
67 stream << std::setw(9) << info.consumer_count;
68 stream << " ";
69 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
70 std::string size = std::to_string(info.width) + " B";
71 stream << std::setw(14) << size;
72 } else {
73 std::string dimensions = std::to_string(info.width) + "x" +
74 std::to_string(info.height) + "x" +
75 std::to_string(info.slice_count);
76 stream << std::setw(14) << dimensions;
77 }
78 stream << " ";
79 stream << std::setw(6) << info.format;
80 stream << " ";
81 stream << "0x" << std::hex << std::setfill('0');
82 stream << std::setw(8) << info.usage;
83 stream << std::dec << std::setfill(' ');
84 stream << " ";
85 stream << info.name;
86 stream << std::endl;
87 }
88 }
89
90 stream << "Active Consumer Buffers:\n";
91 stream << std::right;
92 stream << std::setw(6) << "Id";
93 stream << " ";
94 stream << std::setw(14) << "Geometry";
95 stream << " ";
96 stream << "Name";
97 stream << std::endl;
98
99 for (const auto& channel : channels) {
100 if (channel->channel_type() == BufferHubChannel::kConsumerType) {
101 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
102
103 stream << std::right;
104 stream << std::setw(6) << info.id;
105 stream << " ";
106
107 if (info.consumer_count == 0) {
108 // consumer_count is tracked by producer. When it's zero, producer must
109 // have already hung up and the consumer is orphaned.
110 stream << std::setw(14) << "Orphaned.";
111 stream << std::endl;
112 continue;
113 }
114
115 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
116 std::string size = std::to_string(info.width) + " B";
117 stream << std::setw(14) << size;
118 } else {
119 std::string dimensions = std::to_string(info.width) + "x" +
120 std::to_string(info.height) + "x" +
121 std::to_string(info.slice_count);
122 stream << std::setw(14) << dimensions;
123 }
124 stream << " ";
125 stream << info.name;
126 stream << std::endl;
127 }
128 }
129
130 stream << std::endl;
131 stream << "Active Producer Queues:\n";
132 stream << std::right << std::setw(6) << "Id";
133 stream << std::right << std::setw(12) << " Allocated";
134 stream << std::right << std::setw(12) << " Consumers";
135 stream << " UsageSetMask";
136 stream << " UsageClearMask";
137 stream << " UsageDenySetMask";
138 stream << " UsageDenyClearMask";
139 stream << " ";
140 stream << std::endl;
141
142 for (const auto& channel : channels) {
143 if (channel->channel_type() == BufferHubChannel::kProducerQueueType) {
144 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
145
146 stream << std::dec << std::setfill(' ');
147 stream << std::right << std::setw(6) << info.id;
148 stream << std::right << std::setw(12) << info.capacity;
149 stream << std::right << std::setw(12) << info.consumer_count;
150 stream << std::setw(5) << std::setfill(' ') << "0x";
151 stream << std::hex << std::setfill('0');
152 stream << std::setw(8) << info.usage_set_mask;
153 stream << std::setw(7) << std::setfill(' ') << "0x";
154 stream << std::hex << std::setfill('0');
155 stream << std::setw(8) << info.usage_clear_mask;
156 stream << std::setw(9) << std::setfill(' ') << "0x";
157 stream << std::hex << std::setfill('0');
158 stream << std::setw(8) << info.usage_deny_set_mask;
159 stream << std::setw(11) << std::setfill(' ') << "0x";
160 stream << std::hex << std::setfill('0');
161 stream << std::setw(8) << info.usage_deny_clear_mask;
162 }
163 }
164
165 stream << std::endl;
166 stream << "Active Consumer Queues:\n";
167 stream << std::dec << std::setfill(' ');
168 stream << std::right << std::setw(6) << "Id";
169 stream << std::right << std::setw(12) << " Imported";
170 stream << " ";
171 stream << std::endl;
172
173 for (const auto& channel : channels) {
174 if (channel->channel_type() == BufferHubChannel::kConsumerQueueType) {
175 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
176
177 stream << std::right << std::setw(6) << info.id;
178 stream << std::right << std::setw(12) << info.capacity;
179 }
180 }
181
182 return stream.str();
183}
184
185void BufferHubService::HandleImpulse(Message& message) {
186 ATRACE_NAME("BufferHubService::HandleImpulse");
187 if (auto channel = message.GetChannel<BufferHubChannel>())
188 channel->HandleImpulse(message);
189}
190
191int BufferHubService::HandleMessage(Message& message) {
192 ATRACE_NAME("BufferHubService::HandleMessage");
193 auto channel = message.GetChannel<BufferHubChannel>();
194
195 ALOGD_IF(
196 TRACE,
197 "BufferHubService::HandleMessage: channel=%p channel_id=%d opcode=%d",
198 channel.get(), message.GetChannelId(), message.GetOp());
199
200 // If the channel is already set up, let it handle the message.
201 if (channel && !channel->HandleMessage(message))
202 return DefaultHandleMessage(message);
203
204 // This channel has not been set up yet, the following are valid operations.
205 switch (message.GetOp()) {
206 case BufferHubRPC::CreateBuffer::Opcode:
207 DispatchRemoteMethod<BufferHubRPC::CreateBuffer>(
208 *this, &BufferHubService::OnCreateBuffer, message);
209 return 0;
210
211 case BufferHubRPC::CreatePersistentBuffer::Opcode:
212 DispatchRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
213 *this, &BufferHubService::OnCreatePersistentBuffer, message);
214 return 0;
215
216 case BufferHubRPC::GetPersistentBuffer::Opcode:
217 DispatchRemoteMethod<BufferHubRPC::GetPersistentBuffer>(
218 *this, &BufferHubService::OnGetPersistentBuffer, message);
219 return 0;
220
221 case BufferHubRPC::CreateProducerQueue::Opcode:
222 DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
223 *this, &BufferHubService::OnCreateProducerQueue, message);
224 return 0;
225
226 default:
227 return DefaultHandleMessage(message);
228 }
229}
230
231void BufferHubService::OnChannelClose(Message&,
232 const std::shared_ptr<Channel>& channel) {
233 if (auto buffer = std::static_pointer_cast<BufferHubChannel>(channel))
234 buffer->Detach();
235}
236
237int BufferHubService::OnCreateBuffer(Message& message, int width, int height,
238 int format, int usage,
239 size_t meta_size_bytes,
240 size_t slice_count) {
241 // Use the producer channel id as the global buffer id.
242 const int buffer_id = message.GetChannelId();
243 ALOGD_IF(TRACE,
244 "BufferHubService::OnCreateBuffer: buffer_id=%d width=%d height=%d "
245 "format=%d usage=%d meta_size_bytes=%zu slice_count=%zu",
246 buffer_id, width, height, format, usage, meta_size_bytes,
247 slice_count);
248
249 // See if this channel is already attached to a buffer.
250 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
251 ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
252 buffer_id);
253 return -EALREADY;
254 }
255
256 int error;
257 if (const auto producer_channel =
258 ProducerChannel::Create(this, buffer_id, width, height, format, usage,
259 meta_size_bytes, slice_count, &error)) {
260 message.SetChannel(producer_channel);
261 return 0;
262 } else {
263 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
264 return error;
265 }
266}
267
268int BufferHubService::OnCreatePersistentBuffer(
269 Message& message, const std::string& name, int user_id, int group_id,
270 int width, int height, int format, int usage, size_t meta_size_bytes,
271 size_t slice_count) {
272 const int channel_id = message.GetChannelId();
273 ALOGD_IF(TRACE,
274 "BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
275 "user_id=%d group_id=%d width=%d height=%d format=%d usage=%d "
276 "meta_size_bytes=%zu slice_count=%zu",
277 channel_id, name.c_str(), user_id, group_id, width, height, format,
278 usage, meta_size_bytes, slice_count);
279
280 // See if this channel is already attached to a buffer.
281 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
282 ALOGE(
283 "BufferHubService::OnCreatePersistentBuffer: Channel already attached "
284 "to buffer: channel_id=%d buffer_id=%d",
285 channel_id, channel->buffer_id());
286 return -EALREADY;
287 }
288
289 const int euid = message.GetEffectiveUserId();
290 const int egid = message.GetEffectiveGroupId();
291 int error;
292
293 if (auto buffer = GetNamedBuffer(name)) {
294 if (!buffer->CheckAccess(euid, egid)) {
295 ALOGE(
296 "BufferHubService::OnCreatePersistentBuffer: Requesting process does "
297 "not have permission to access named buffer: name=%s euid=%d egid=%d",
298 name.c_str(), euid, euid);
299 return -EPERM;
300 } else if (!buffer->CheckParameters(width, height, format, usage,
301 meta_size_bytes, slice_count)) {
302 ALOGE(
303 "BufferHubService::OnCreatePersistentBuffer: Requested an existing "
304 "buffer with different parameters: name=%s",
305 name.c_str());
306 return -EINVAL;
307 } else if (!buffer->IsDetached()) {
308 ALOGE(
309 "BufferHubService::OnCreatePersistentBuffer: Requesting a persistent "
310 "buffer that is already attached to a channel: name=%s",
311 name.c_str());
312 return -EINVAL;
313 } else {
314 buffer->Attach(channel_id);
315 message.SetChannel(buffer);
316 return 0;
317 }
318 } else if (auto buffer = ProducerChannel::Create(
319 this, channel_id, width, height, format, usage,
320 meta_size_bytes, slice_count, &error)) {
321 const int ret =
322 buffer->OnProducerMakePersistent(message, name, user_id, group_id);
323 if (!ret)
324 message.SetChannel(buffer);
325 return ret;
326 } else {
327 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
328 return error;
329 }
330}
331
332int BufferHubService::OnGetPersistentBuffer(Message& message,
333 const std::string& name) {
334 const int channel_id = message.GetChannelId();
335 ALOGD_IF(TRACE,
336 "BufferHubService::OnGetPersistentBuffer: channel_id=%d name=%s",
337 channel_id, name.c_str());
338
339 // See if this channel is already attached to a buffer.
340 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
341 ALOGE(
342 "BufferHubService::OnGetPersistentBuffer: Channel already attached to "
343 "buffer: channel_id=%d buffer_id=%d",
344 channel_id, channel->buffer_id());
345 return -EALREADY;
346 }
347
348 const int euid = message.GetEffectiveUserId();
349 const int egid = message.GetEffectiveGroupId();
350
351 if (auto buffer = GetNamedBuffer(name)) {
352 if (!buffer->CheckAccess(euid, egid)) {
353 ALOGE(
354 "BufferHubService::OnGetPersistentBuffer: Requesting process does "
355 "not have permission to access named buffer: name=%s euid=%d egid=%d",
356 name.c_str(), euid, egid);
357 return -EPERM;
358 } else if (!buffer->IsDetached()) {
359 ALOGE(
360 "BufferHubService::OnGetPersistentBuffer: Requesting a persistent "
361 "buffer that is already attached to a channel: name=%s",
362 name.c_str());
363 return -EINVAL;
364 } else {
365 buffer->Attach(channel_id);
366 message.SetChannel(buffer);
367 return 0;
368 }
369 } else {
370 ALOGE("BufferHubService::OnGetPersistentBuffer: Buffer \"%s\" not found!",
371 name.c_str());
372 return -ENOENT;
373 }
374}
375
376int BufferHubService::OnCreateProducerQueue(
377 pdx::Message& message, size_t meta_size_bytes, int usage_set_mask,
378 int usage_clear_mask, int usage_deny_set_mask, int usage_deny_clear_mask) {
379 // Use the producer channel id as the global queue id.
380 const int queue_id = message.GetChannelId();
381 ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
382 queue_id);
383
384 // See if this channel is already attached to another object.
385 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
386 ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d",
387 queue_id);
388 return -EALREADY;
389 }
390
391 int error;
392 if (const auto producer_channel = ProducerQueueChannel::Create(
393 this, queue_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
394 usage_deny_set_mask, usage_deny_clear_mask, &error)) {
395 message.SetChannel(producer_channel);
396 return 0;
397 } else {
398 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
399 return error;
400 }
401}
402
403bool BufferHubService::AddNamedBuffer(
404 const std::string& name, const std::shared_ptr<ProducerChannel>& buffer) {
405 auto search = named_buffers_.find(name);
406 if (search == named_buffers_.end()) {
407 named_buffers_.emplace(name, buffer);
408 return true;
409 } else {
410 return false;
411 }
412}
413
414std::shared_ptr<ProducerChannel> BufferHubService::GetNamedBuffer(
415 const std::string& name) {
416 auto search = named_buffers_.find(name);
417 if (search != named_buffers_.end())
418 return search->second;
419 else
420 return nullptr;
421}
422
423bool BufferHubService::RemoveNamedBuffer(const ProducerChannel& buffer) {
424 for (auto it = named_buffers_.begin(); it != named_buffers_.end();) {
425 if (it->second.get() == &buffer) {
426 named_buffers_.erase(it);
427 return true;
428 }
429 ++it;
430 }
431 return false;
432}
433
434void BufferHubChannel::SignalAvailable() {
435 ATRACE_NAME("BufferHubChannel::SignalAvailable");
436 if (!IsDetached()) {
437 const int ret = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
438 ALOGE_IF(ret < 0,
439 "BufferHubChannel::SignalAvailable: failed to signal availability "
440 "channel_id=%d: %s",
441 channel_id_, strerror(-ret));
442 } else {
443 ALOGD_IF(TRACE, "BufferHubChannel::SignalAvailable: detached buffer.");
444 }
445}
446
447void BufferHubChannel::ClearAvailable() {
448 ATRACE_NAME("BufferHubChannel::ClearAvailable");
449 if (!IsDetached()) {
450 const int ret = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
451 ALOGE_IF(ret < 0,
452 "BufferHubChannel::ClearAvailable: failed to clear availability "
453 "channel_id=%d: %s",
454 channel_id_, strerror(-ret));
455 } else {
456 ALOGD_IF(TRACE, "BufferHubChannel::ClearAvailable: detached buffer.");
457 }
458}
459
460void BufferHubChannel::Hangup() {
461 ATRACE_NAME("BufferHubChannel::Hangup");
462 if (!IsDetached()) {
463 const int ret = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP);
464 ALOGE_IF(
465 ret < 0,
466 "BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s",
467 channel_id_, strerror(-ret));
468 } else {
469 ALOGD_IF(TRACE, "BufferHubChannel::Hangup: detached buffer.");
470 }
471}
472
473} // namespace dvr
474} // namespace android