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 <memory>
10 #include <sstream>
11 #include <string>
12 #include <thread>
13 
14 #include <pdx/default_transport/service_endpoint.h>
15 #include <private/dvr/bufferhub_rpc.h>
16 #include "consumer_channel.h"
17 #include "detached_buffer_channel.h"
18 #include "producer_channel.h"
19 #include "producer_queue_channel.h"
20 
21 using android::pdx::Channel;
22 using android::pdx::ErrorStatus;
23 using android::pdx::Message;
24 using android::pdx::Status;
25 using android::pdx::default_transport::Endpoint;
26 using android::pdx::rpc::DispatchRemoteMethod;
27 
28 namespace android {
29 namespace dvr {
30 
BufferHubService()31 BufferHubService::BufferHubService()
32     : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {}
33 
~BufferHubService()34 BufferHubService::~BufferHubService() {}
35 
IsInitialized() const36 bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); }
37 
DumpState(size_t)38 std::string BufferHubService::DumpState(size_t /*max_length*/) {
39   std::ostringstream stream;
40   auto channels = GetChannels<BufferHubChannel>();
41 
42   std::sort(channels.begin(), channels.end(),
43             [](const std::shared_ptr<BufferHubChannel>& a,
44                const std::shared_ptr<BufferHubChannel>& b) {
45               return a->buffer_id() < b->buffer_id();
46             });
47 
48   stream << "Active Producer Buffers:\n";
49   stream << std::right;
50   stream << std::setw(6) << "Id";
51   stream << " ";
52   stream << std::setw(9) << "Consumers";
53   stream << " ";
54   stream << std::setw(14) << "Geometry";
55   stream << " ";
56   stream << std::setw(6) << "Format";
57   stream << " ";
58   stream << std::setw(10) << "Usage";
59   stream << " ";
60   stream << std::setw(9) << "Pending";
61   stream << " ";
62   stream << std::setw(18) << "State";
63   stream << " ";
64   stream << std::setw(18) << "Signaled";
65   stream << " ";
66   stream << std::setw(10) << "Index";
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 << std::endl;
104     }
105 
106     if (channel->channel_type() == BufferHubChannel::kDetachedBufferType) {
107       BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
108 
109       stream << std::right;
110       stream << std::setw(6) << info.id;
111       stream << " ";
112       stream << std::setw(9) << "N/A";
113       stream << " ";
114       if (info.format == HAL_PIXEL_FORMAT_BLOB) {
115         std::string size = std::to_string(info.width) + " B";
116         stream << std::setw(14) << size;
117       } else {
118         std::string dimensions = std::to_string(info.width) + "x" +
119                                  std::to_string(info.height) + "x" +
120                                  std::to_string(info.layer_count);
121         stream << std::setw(14) << dimensions;
122       }
123       stream << " ";
124       stream << std::setw(6) << info.format;
125       stream << " ";
126       stream << "0x" << std::hex << std::setfill('0');
127       stream << std::setw(8) << info.usage;
128       stream << std::dec << std::setfill(' ');
129       stream << " ";
130       stream << std::setw(9) << "N/A";
131       stream << " ";
132       stream << std::hex << std::setfill(' ');
133       stream << std::setw(18) << "Detached";
134       stream << " ";
135       stream << std::setw(18) << "N/A";
136       stream << " ";
137       stream << std::setw(10) << "N/A";
138       stream << std::endl;
139     }
140   }
141 
142   stream << std::endl;
143   stream << "Active Producer Queues:\n";
144   stream << std::right << std::setw(6) << "Id";
145   stream << std::right << std::setw(12) << " Capacity";
146   stream << std::right << std::setw(12) << " Consumers";
147   stream << " UsageSetMask";
148   stream << " UsageClearMask";
149   stream << " UsageDenySetMask";
150   stream << " UsageDenyClearMask";
151   stream << " ";
152   stream << std::endl;
153 
154   for (const auto& channel : channels) {
155     if (channel->channel_type() == BufferHubChannel::kProducerQueueType) {
156       BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
157 
158       stream << std::dec << std::setfill(' ');
159       stream << std::right << std::setw(6) << info.id;
160       stream << std::right << std::setw(12) << info.capacity;
161       stream << std::right << std::setw(12) << info.consumer_count;
162       stream << std::setw(5) << std::setfill(' ') << "0x";
163       stream << std::hex << std::setfill('0');
164       stream << std::setw(8) << info.usage_policy.usage_set_mask;
165       stream << std::setw(7) << std::setfill(' ') << "0x";
166       stream << std::hex << std::setfill('0');
167       stream << std::setw(8) << info.usage_policy.usage_clear_mask;
168       stream << std::setw(9) << std::setfill(' ') << "0x";
169       stream << std::hex << std::setfill('0');
170       stream << std::setw(8) << info.usage_policy.usage_deny_set_mask;
171       stream << std::setw(11) << std::setfill(' ') << "0x";
172       stream << std::hex << std::setfill('0');
173       stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask;
174       stream << std::hex << std::setfill('0');
175       stream << std::endl;
176     }
177   }
178 
179   stream << std::endl;
180   stream << "Active Consumer Queues:\n";
181   stream << std::dec << std::setfill(' ');
182   stream << std::right << std::setw(6) << "Id";
183   stream << std::right << std::setw(12) << " Imported";
184   stream << " ";
185   stream << std::endl;
186 
187   for (const auto& channel : channels) {
188     if (channel->channel_type() == BufferHubChannel::kConsumerQueueType) {
189       BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
190 
191       stream << std::right << std::setw(6) << info.id;
192       stream << std::right << std::setw(12) << info.capacity;
193       stream << std::endl;
194     }
195   }
196 
197   stream << std::endl;
198   stream << "Orphaned Consumer Buffers:\n";
199   stream << std::right;
200   stream << std::setw(6) << "Id";
201   stream << " ";
202   stream << std::setw(14) << "Info";
203   stream << std::endl;
204 
205   for (const auto& channel : channels) {
206     BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
207     // consumer_count is tracked by producer. When it's zero, producer must have
208     // already hung up and the consumer is orphaned.
209     if (channel->channel_type() == BufferHubChannel::kConsumerType &&
210         info.consumer_count == 0) {
211       stream << std::right;
212       stream << std::setw(6) << info.id;
213       stream << " ";
214 
215       stream << std::setw(14) << "Orphaned.";
216       stream << (" channel_id=" + std::to_string(channel->channel_id()));
217       stream << std::endl;
218     }
219   }
220 
221   return stream.str();
222 }
223 
HandleImpulse(Message & message)224 void BufferHubService::HandleImpulse(Message& message) {
225   ATRACE_NAME("BufferHubService::HandleImpulse");
226   if (auto channel = message.GetChannel<BufferHubChannel>())
227     channel->HandleImpulse(message);
228 }
229 
HandleMessage(Message & message)230 pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
231   ATRACE_NAME("BufferHubService::HandleMessage");
232   auto channel = message.GetChannel<BufferHubChannel>();
233 
234   ALOGD_IF(
235       TRACE,
236       "BufferHubService::HandleMessage: channel=%p channel_id=%d opcode=%d",
237       channel.get(), message.GetChannelId(), message.GetOp());
238 
239   // If the channel is already set up, let it handle the message.
240   if (channel && !channel->HandleMessage(message))
241     return DefaultHandleMessage(message);
242 
243   // This channel has not been set up yet, the following are valid operations.
244   switch (message.GetOp()) {
245     case BufferHubRPC::CreateBuffer::Opcode:
246       DispatchRemoteMethod<BufferHubRPC::CreateBuffer>(
247           *this, &BufferHubService::OnCreateBuffer, message);
248       return {};
249 
250     case DetachedBufferRPC::Create::Opcode:
251       DispatchRemoteMethod<DetachedBufferRPC::Create>(
252           *this, &BufferHubService::OnCreateDetachedBuffer, message);
253       return {};
254 
255     case BufferHubRPC::CreateProducerQueue::Opcode:
256       DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
257           *this, &BufferHubService::OnCreateProducerQueue, message);
258       return {};
259 
260     case BufferHubRPC::ProducerBufferDetach::Opcode:
261       // In addition to the message handler in the ProducerChannel's
262       // HandleMessage method, we also need to invalid the producer channel (and
263       // all associated consumer channels). Note that this has to be done after
264       // HandleMessage returns to make sure the IPC request has went back to the
265       // client first.
266       SetChannel(channel->channel_id(), nullptr);
267       return {};
268 
269     case DetachedBufferRPC::Promote::Opcode:
270       // In addition to the message handler in the DetachedBufferChannel's
271       // HandleMessage method, we also need to invalid the channel. Note that
272       // this has to be done after HandleMessage returns to make sure the IPC
273       // request has went back to the client first.
274       SetChannel(channel->channel_id(), nullptr);
275       return {};
276 
277     default:
278       return DefaultHandleMessage(message);
279   }
280 }
281 
OnCreateBuffer(Message & message,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,size_t meta_size_bytes)282 Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
283                                               uint32_t height, uint32_t format,
284                                               uint64_t usage,
285                                               size_t meta_size_bytes) {
286   // Use the producer channel id as the global buffer id.
287   const int buffer_id = message.GetChannelId();
288   ALOGD_IF(TRACE,
289            "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
290            "format=%u usage=%" PRIx64 " meta_size_bytes=%zu",
291            buffer_id, width, height, format, usage, meta_size_bytes);
292 
293   // See if this channel is already attached to a buffer.
294   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
295     ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
296           buffer_id);
297     return ErrorStatus(EALREADY);
298   }
299   const uint32_t kDefaultLayerCount = 1;
300   auto status = ProducerChannel::Create(this, buffer_id, width, height,
301                                         kDefaultLayerCount, format, usage,
302                                         meta_size_bytes);
303   if (status) {
304     message.SetChannel(status.take());
305     return {};
306   } else {
307     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
308           status.GetErrorMessage().c_str());
309     return status.error_status();
310   }
311 }
312 
OnCreateDetachedBuffer(pdx::Message & message,uint32_t width,uint32_t height,uint32_t layer_count,uint32_t format,uint64_t usage,size_t user_metadata_size)313 pdx::Status<void> BufferHubService::OnCreateDetachedBuffer(
314     pdx::Message& message, uint32_t width, uint32_t height,
315     uint32_t layer_count, uint32_t format, uint64_t usage,
316     size_t user_metadata_size) {
317   // Use the producer channel id as the global buffer id.
318   const int buffer_id = message.GetChannelId();
319   ALOGD_IF(TRACE,
320            "BufferHubService::OnCreateDetachedBuffer: buffer_id=%d width=%u "
321            "height=%u layer_count=%u format=%u usage=%" PRIx64
322            " user_metadata_size=%zu",
323            buffer_id, width, height, layer_count, format, usage,
324            user_metadata_size);
325 
326   // See if this channel is already attached to a buffer.
327   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
328     ALOGE(
329         "BufferHubService::OnCreateDetachedBuffer: Buffer already created: "
330         "buffer=%d",
331         buffer_id);
332     return ErrorStatus(EALREADY);
333   }
334 
335   std::unique_ptr<DetachedBufferChannel> channel =
336       DetachedBufferChannel::Create(this, buffer_id, width, height, layer_count,
337                                     format, usage, user_metadata_size);
338   if (!channel) {
339     ALOGE(
340         "BufferHubService::OnCreateDetachedBuffer: Failed to allocate buffer, "
341         "buffer=%d.",
342         buffer_id);
343     return ErrorStatus(ENOMEM);
344   }
345 
346   message.SetChannel(std::move(channel));
347   return {};
348 }
349 
OnCreateProducerQueue(pdx::Message & message,const ProducerQueueConfig & producer_config,const UsagePolicy & usage_policy)350 Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
351     pdx::Message& message, const ProducerQueueConfig& producer_config,
352     const UsagePolicy& usage_policy) {
353   // Use the producer channel id as the global queue id.
354   const int queue_id = message.GetChannelId();
355   ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
356            queue_id);
357 
358   // See if this channel is already attached to another object.
359   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
360     ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d",
361           queue_id);
362     return ErrorStatus(EALREADY);
363   }
364 
365   auto status = ProducerQueueChannel::Create(this, queue_id, producer_config,
366                                              usage_policy);
367   if (status) {
368     message.SetChannel(status.take());
369     return {{producer_config, queue_id}};
370   } else {
371     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
372     return status.error_status();
373   }
374 }
375 
SignalAvailable()376 void BufferHubChannel::SignalAvailable() {
377   ATRACE_NAME("BufferHubChannel::SignalAvailable");
378   ALOGD_IF(TRACE,
379            "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
380            channel_id(), buffer_id());
381   signaled_ = true;
382   const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
383   ALOGE_IF(!status,
384            "BufferHubChannel::SignalAvailable: failed to signal availability "
385            "channel_id=%d: %s",
386            channel_id_, status.GetErrorMessage().c_str());
387 }
388 
ClearAvailable()389 void BufferHubChannel::ClearAvailable() {
390   ATRACE_NAME("BufferHubChannel::ClearAvailable");
391   ALOGD_IF(TRACE,
392            "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
393            channel_id(), buffer_id());
394   signaled_ = false;
395   const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
396   ALOGE_IF(!status,
397            "BufferHubChannel::ClearAvailable: failed to clear availability "
398            "channel_id=%d: %s",
399            channel_id_, status.GetErrorMessage().c_str());
400 }
401 
Hangup()402 void BufferHubChannel::Hangup() {
403   ATRACE_NAME("BufferHubChannel::Hangup");
404   ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d",
405            channel_id(), buffer_id());
406   const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP);
407   ALOGE_IF(
408       !status,
409       "BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s",
410       channel_id_, status.GetErrorMessage().c_str());
411 }
412 
413 }  // namespace dvr
414 }  // namespace android
415