blob: e4e19c7518492e9134ae1d028137fcbb8f8f6623 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "buffer_hub.h"
2
Corey Tabakacd52dd92017-04-07 18:03:57 -07003#include <inttypes.h>
Alex Vakulenko4fe60582017-02-02 11:35:59 -08004#include <log/log.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08005#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
19using android::pdx::Channel;
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070020using android::pdx::ErrorStatus;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080021using android::pdx::Message;
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070022using android::pdx::Status;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080023using android::pdx::default_transport::Endpoint;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070024using android::pdx::rpc::DispatchRemoteMethod;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080025
26namespace android {
27namespace dvr {
28
29BufferHubService::BufferHubService()
30 : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {}
31
32BufferHubService::~BufferHubService() {}
33
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070034bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080035
36std::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 << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070056 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";
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080065 stream << std::endl;
66
67 for (const auto& channel : channels) {
68 if (channel->channel_type() == BufferHubChannel::kProducerType) {
69 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
70
71 stream << std::right;
72 stream << std::setw(6) << info.id;
73 stream << " ";
74 stream << std::setw(9) << info.consumer_count;
75 stream << " ";
76 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
77 std::string size = std::to_string(info.width) + " B";
78 stream << std::setw(14) << size;
79 } else {
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -070080 std::string dimensions = std::to_string(info.width) + "x" +
81 std::to_string(info.height) + "x" +
82 std::to_string(info.layer_count);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080083 stream << std::setw(14) << dimensions;
84 }
85 stream << " ";
86 stream << std::setw(6) << info.format;
87 stream << " ";
88 stream << "0x" << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -070089 stream << std::setw(8) << info.usage;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080090 stream << std::dec << std::setfill(' ');
91 stream << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070092 stream << std::setw(9) << info.pending_count;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080093 stream << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070094 stream << "0x" << std::hex << std::setfill('0');
95 stream << std::setw(16) << info.state;
96 stream << " ";
97 stream << "0x" << std::setw(16) << info.signaled_mask;
98 stream << std::dec << std::setfill(' ');
99 stream << " ";
100 stream << std::setw(8) << info.index;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800101 stream << std::endl;
102 }
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700103
104 if (channel->channel_type() == BufferHubChannel::kDetachedBufferType) {
105 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
106
107 stream << std::right;
108 stream << std::setw(6) << info.id;
109 stream << " ";
110 stream << std::setw(9) << "N/A";
111 stream << " ";
112 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
113 std::string size = std::to_string(info.width) + " B";
114 stream << std::setw(14) << size;
115 } else {
116 std::string dimensions = std::to_string(info.width) + "x" +
117 std::to_string(info.height) + "x" +
118 std::to_string(info.layer_count);
119 stream << std::setw(14) << dimensions;
120 }
121 stream << " ";
122 stream << std::setw(6) << info.format;
123 stream << " ";
124 stream << "0x" << std::hex << std::setfill('0');
125 stream << std::setw(8) << info.usage;
126 stream << std::dec << std::setfill(' ');
127 stream << " ";
128 stream << std::setw(9) << "N/A";
129 stream << " ";
130 stream << std::hex << std::setfill(' ');
131 stream << std::setw(18) << "Detached";
132 stream << " ";
133 stream << std::setw(18) << "N/A";
134 stream << " ";
135 stream << std::setw(10) << "N/A";
136 stream << std::endl;
137 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800138 }
139
140 stream << std::endl;
141 stream << "Active Producer Queues:\n";
142 stream << std::right << std::setw(6) << "Id";
Corey Tabaka8a4e6a92017-04-20 13:42:02 -0700143 stream << std::right << std::setw(12) << " Capacity";
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800144 stream << std::right << std::setw(12) << " Consumers";
145 stream << " UsageSetMask";
146 stream << " UsageClearMask";
147 stream << " UsageDenySetMask";
148 stream << " UsageDenyClearMask";
149 stream << " ";
150 stream << std::endl;
151
152 for (const auto& channel : channels) {
153 if (channel->channel_type() == BufferHubChannel::kProducerQueueType) {
154 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
155
156 stream << std::dec << std::setfill(' ');
157 stream << std::right << std::setw(6) << info.id;
158 stream << std::right << std::setw(12) << info.capacity;
159 stream << std::right << std::setw(12) << info.consumer_count;
160 stream << std::setw(5) << std::setfill(' ') << "0x";
161 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700162 stream << std::setw(8) << info.usage_policy.usage_set_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800163 stream << std::setw(7) << std::setfill(' ') << "0x";
164 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700165 stream << std::setw(8) << info.usage_policy.usage_clear_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800166 stream << std::setw(9) << std::setfill(' ') << "0x";
167 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700168 stream << std::setw(8) << info.usage_policy.usage_deny_set_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800169 stream << std::setw(11) << std::setfill(' ') << "0x";
170 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700171 stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700172 stream << std::hex << std::setfill('0');
173 stream << std::endl;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800174 }
175 }
176
177 stream << std::endl;
178 stream << "Active Consumer Queues:\n";
179 stream << std::dec << std::setfill(' ');
180 stream << std::right << std::setw(6) << "Id";
181 stream << std::right << std::setw(12) << " Imported";
182 stream << " ";
183 stream << std::endl;
184
185 for (const auto& channel : channels) {
186 if (channel->channel_type() == BufferHubChannel::kConsumerQueueType) {
187 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
188
189 stream << std::right << std::setw(6) << info.id;
190 stream << std::right << std::setw(12) << info.capacity;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700191 stream << std::endl;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800192 }
193 }
194
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700195 stream << std::endl;
196 stream << "Orphaned Consumer Buffers:\n";
197 stream << std::right;
198 stream << std::setw(6) << "Id";
199 stream << " ";
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800200 stream << std::setw(14) << "Info";
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700201 stream << std::endl;
202
203 for (const auto& channel : channels) {
204 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
205 // consumer_count is tracked by producer. When it's zero, producer must have
206 // already hung up and the consumer is orphaned.
207 if (channel->channel_type() == BufferHubChannel::kConsumerType &&
208 info.consumer_count == 0) {
209 stream << std::right;
210 stream << std::setw(6) << info.id;
211 stream << " ";
212
213 stream << std::setw(14) << "Orphaned.";
214 stream << (" channel_id=" + std::to_string(channel->channel_id()));
215 stream << std::endl;
216 }
217 }
218
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800219 return stream.str();
220}
221
222void BufferHubService::HandleImpulse(Message& message) {
223 ATRACE_NAME("BufferHubService::HandleImpulse");
224 if (auto channel = message.GetChannel<BufferHubChannel>())
225 channel->HandleImpulse(message);
226}
227
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700228pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800229 ATRACE_NAME("BufferHubService::HandleMessage");
230 auto channel = message.GetChannel<BufferHubChannel>();
231
232 ALOGD_IF(
233 TRACE,
234 "BufferHubService::HandleMessage: channel=%p channel_id=%d opcode=%d",
235 channel.get(), message.GetChannelId(), message.GetOp());
236
237 // If the channel is already set up, let it handle the message.
238 if (channel && !channel->HandleMessage(message))
239 return DefaultHandleMessage(message);
240
241 // This channel has not been set up yet, the following are valid operations.
242 switch (message.GetOp()) {
243 case BufferHubRPC::CreateBuffer::Opcode:
244 DispatchRemoteMethod<BufferHubRPC::CreateBuffer>(
245 *this, &BufferHubService::OnCreateBuffer, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700246 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800247
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800248 case BufferHubRPC::CreateProducerQueue::Opcode:
249 DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
250 *this, &BufferHubService::OnCreateProducerQueue, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700251 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800252
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700253 case BufferHubRPC::ProducerBufferDetach::Opcode:
254 // In addition to the message handler in the ProducerChannel's
255 // HandleMessage method, we also need to invalid the producer channel (and
256 // all associated consumer channels). Note that this has to be done after
257 // HandleMessage returns to make sure the IPC request has went back to the
258 // client first.
259 SetChannel(channel->channel_id(), nullptr);
260 return {};
261
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800262 default:
263 return DefaultHandleMessage(message);
264 }
265}
266
Corey Tabakacd52dd92017-04-07 18:03:57 -0700267Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
268 uint32_t height, uint32_t format,
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700269 uint64_t usage,
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700270 size_t meta_size_bytes) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800271 // Use the producer channel id as the global buffer id.
272 const int buffer_id = message.GetChannelId();
273 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700274 "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700275 "format=%u usage=%" PRIx64 " meta_size_bytes=%zu",
276 buffer_id, width, height, format, usage, meta_size_bytes);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800277
278 // See if this channel is already attached to a buffer.
279 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
280 ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
281 buffer_id);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700282 return ErrorStatus(EALREADY);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800283 }
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700284 const uint32_t kDefaultLayerCount = 1;
285 auto status = ProducerChannel::Create(this, buffer_id, width, height,
286 kDefaultLayerCount, format, usage,
287 meta_size_bytes);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700288 if (status) {
289 message.SetChannel(status.take());
290 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800291 } else {
Corey Tabakacd52dd92017-04-07 18:03:57 -0700292 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
293 status.GetErrorMessage().c_str());
294 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800295 }
296}
297
Corey Tabaka1db8a5d2017-03-22 02:12:52 -0700298Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700299 pdx::Message& message, const ProducerQueueConfig& producer_config,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700300 const UsagePolicy& usage_policy) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800301 // Use the producer channel id as the global queue id.
302 const int queue_id = message.GetChannelId();
303 ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
304 queue_id);
305
306 // See if this channel is already attached to another object.
307 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
308 ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d",
309 queue_id);
Corey Tabaka1db8a5d2017-03-22 02:12:52 -0700310 return ErrorStatus(EALREADY);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800311 }
312
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700313 auto status = ProducerQueueChannel::Create(this, queue_id, producer_config,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700314 usage_policy);
315 if (status) {
316 message.SetChannel(status.take());
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700317 return {{producer_config, queue_id}};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800318 } else {
319 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
Corey Tabakacd52dd92017-04-07 18:03:57 -0700320 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800321 }
322}
323
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800324void BufferHubChannel::SignalAvailable() {
325 ATRACE_NAME("BufferHubChannel::SignalAvailable");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800326 ALOGD_IF(TRACE,
327 "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
328 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800329 signaled_ = true;
330 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
331 ALOGE_IF(!status,
332 "BufferHubChannel::SignalAvailable: failed to signal availability "
333 "channel_id=%d: %s",
334 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800335}
336
337void BufferHubChannel::ClearAvailable() {
338 ATRACE_NAME("BufferHubChannel::ClearAvailable");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800339 ALOGD_IF(TRACE,
340 "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
341 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800342 signaled_ = false;
343 const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
344 ALOGE_IF(!status,
345 "BufferHubChannel::ClearAvailable: failed to clear availability "
346 "channel_id=%d: %s",
347 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800348}
349
350void BufferHubChannel::Hangup() {
351 ATRACE_NAME("BufferHubChannel::Hangup");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800352 ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d",
353 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800354 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP);
355 ALOGE_IF(
356 !status,
357 "BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s",
358 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800359}
360
361} // namespace dvr
362} // namespace android