blob: e57c8edfe337033927b952e4dd371a3da1b948be [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>
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -07009#include <memory>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080010#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"
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070017#include "detached_buffer_channel.h"
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080018#include "producer_channel.h"
19#include "producer_queue_channel.h"
20
21using android::pdx::Channel;
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070022using android::pdx::ErrorStatus;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080023using android::pdx::Message;
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070024using android::pdx::Status;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080025using android::pdx::default_transport::Endpoint;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070026using android::pdx::rpc::DispatchRemoteMethod;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080027
28namespace android {
29namespace dvr {
30
31BufferHubService::BufferHubService()
32 : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {}
33
34BufferHubService::~BufferHubService() {}
35
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070036bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080037
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 << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070058 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";
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080067 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 {
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -070082 std::string dimensions = std::to_string(info.width) + "x" +
83 std::to_string(info.height) + "x" +
84 std::to_string(info.layer_count);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080085 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');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -070091 stream << std::setw(8) << info.usage;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080092 stream << std::dec << std::setfill(' ');
93 stream << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070094 stream << std::setw(9) << info.pending_count;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080095 stream << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070096 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;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800103 stream << std::endl;
104 }
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700105
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 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800140 }
141
142 stream << std::endl;
143 stream << "Active Producer Queues:\n";
144 stream << std::right << std::setw(6) << "Id";
Corey Tabaka8a4e6a92017-04-20 13:42:02 -0700145 stream << std::right << std::setw(12) << " Capacity";
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800146 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');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700164 stream << std::setw(8) << info.usage_policy.usage_set_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800165 stream << std::setw(7) << std::setfill(' ') << "0x";
166 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700167 stream << std::setw(8) << info.usage_policy.usage_clear_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800168 stream << std::setw(9) << std::setfill(' ') << "0x";
169 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700170 stream << std::setw(8) << info.usage_policy.usage_deny_set_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800171 stream << std::setw(11) << std::setfill(' ') << "0x";
172 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700173 stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700174 stream << std::hex << std::setfill('0');
175 stream << std::endl;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800176 }
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;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700193 stream << std::endl;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800194 }
195 }
196
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700197 stream << std::endl;
198 stream << "Orphaned Consumer Buffers:\n";
199 stream << std::right;
200 stream << std::setw(6) << "Id";
201 stream << " ";
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800202 stream << std::setw(14) << "Info";
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700203 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
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800221 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
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700230pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800231 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);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700248 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800249
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700250 case DetachedBufferRPC::Create::Opcode:
251 DispatchRemoteMethod<DetachedBufferRPC::Create>(
252 *this, &BufferHubService::OnCreateDetachedBuffer, message);
253 return {};
254
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800255 case BufferHubRPC::CreateProducerQueue::Opcode:
256 DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
257 *this, &BufferHubService::OnCreateProducerQueue, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700258 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800259
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700260 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
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700269 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
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800277 default:
278 return DefaultHandleMessage(message);
279 }
280}
281
Corey Tabakacd52dd92017-04-07 18:03:57 -0700282Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
283 uint32_t height, uint32_t format,
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700284 uint64_t usage,
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700285 size_t meta_size_bytes) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800286 // Use the producer channel id as the global buffer id.
287 const int buffer_id = message.GetChannelId();
288 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700289 "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700290 "format=%u usage=%" PRIx64 " meta_size_bytes=%zu",
291 buffer_id, width, height, format, usage, meta_size_bytes);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800292
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);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700297 return ErrorStatus(EALREADY);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800298 }
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700299 const uint32_t kDefaultLayerCount = 1;
300 auto status = ProducerChannel::Create(this, buffer_id, width, height,
301 kDefaultLayerCount, format, usage,
302 meta_size_bytes);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700303 if (status) {
304 message.SetChannel(status.take());
305 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800306 } else {
Corey Tabakacd52dd92017-04-07 18:03:57 -0700307 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
308 status.GetErrorMessage().c_str());
309 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800310 }
311}
312
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700313pdx::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
Corey Tabaka1db8a5d2017-03-22 02:12:52 -0700350Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700351 pdx::Message& message, const ProducerQueueConfig& producer_config,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700352 const UsagePolicy& usage_policy) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800353 // 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);
Corey Tabaka1db8a5d2017-03-22 02:12:52 -0700362 return ErrorStatus(EALREADY);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800363 }
364
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700365 auto status = ProducerQueueChannel::Create(this, queue_id, producer_config,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700366 usage_policy);
367 if (status) {
368 message.SetChannel(status.take());
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700369 return {{producer_config, queue_id}};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800370 } else {
371 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
Corey Tabakacd52dd92017-04-07 18:03:57 -0700372 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800373 }
374}
375
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800376void BufferHubChannel::SignalAvailable() {
377 ATRACE_NAME("BufferHubChannel::SignalAvailable");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800378 ALOGD_IF(TRACE,
379 "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
380 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800381 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());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800387}
388
389void BufferHubChannel::ClearAvailable() {
390 ATRACE_NAME("BufferHubChannel::ClearAvailable");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800391 ALOGD_IF(TRACE,
392 "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
393 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800394 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());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800400}
401
402void BufferHubChannel::Hangup() {
403 ATRACE_NAME("BufferHubChannel::Hangup");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800404 ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d",
405 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800406 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());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800411}
412
413} // namespace dvr
414} // namespace android