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