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