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
21using android::pdx::Channel;
22using android::pdx::ErrorStatus;
23using android::pdx::Message;
24using android::pdx::Status;
25using android::pdx::default_transport::Endpoint;
26using android::pdx::rpc::DispatchRemoteMethod;
27
28namespace android {
29namespace dvr {
30
31BufferHubService::BufferHubService()
32    : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {}
33
34BufferHubService::~BufferHubService() {}
35
36bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); }
37
38std::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
224void BufferHubService::HandleImpulse(Message& message) {
225  ATRACE_NAME("BufferHubService::HandleImpulse");
226  if (auto channel = message.GetChannel<BufferHubChannel>())
227    channel->HandleImpulse(message);
228}
229
230pdx::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
282Status<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
313pdx::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
350Status<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
376void 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
389void 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
402void 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