blob: 15391da9531e823a07a7fffaa79a481e39204a6f [file] [log] [blame]
Corey Tabakacd52dd92017-04-07 18:03:57 -07001#include <inttypes.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08002#include <poll.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08003
4#include <iomanip>
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -07005#include <memory>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08006#include <sstream>
7#include <string>
8#include <thread>
9
Fan Xu74df4902018-09-20 16:40:51 -070010#include <log/log.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080011#include <pdx/default_transport/service_endpoint.h>
12#include <private/dvr/bufferhub_rpc.h>
Fan Xu74df4902018-09-20 16:40:51 -070013#include <private/dvr/buffer_channel.h>
14#include <private/dvr/buffer_hub.h>
15#include <private/dvr/consumer_channel.h>
16#include <private/dvr/producer_channel.h>
17#include <private/dvr/producer_queue_channel.h>
18#include <utils/Trace.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080019
20using android::pdx::Channel;
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070021using android::pdx::ErrorStatus;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080022using android::pdx::Message;
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070023using android::pdx::Status;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080024using android::pdx::default_transport::Endpoint;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070025using android::pdx::rpc::DispatchRemoteMethod;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080026
27namespace android {
28namespace dvr {
29
30BufferHubService::BufferHubService()
31 : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {}
32
33BufferHubService::~BufferHubService() {}
34
Corey Tabaka1db8a5d2017-03-22 02:12:52 -070035bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080036
37std::string BufferHubService::DumpState(size_t /*max_length*/) {
38 std::ostringstream stream;
39 auto channels = GetChannels<BufferHubChannel>();
40
41 std::sort(channels.begin(), channels.end(),
42 [](const std::shared_ptr<BufferHubChannel>& a,
43 const std::shared_ptr<BufferHubChannel>& b) {
44 return a->buffer_id() < b->buffer_id();
45 });
46
47 stream << "Active Producer Buffers:\n";
48 stream << std::right;
49 stream << std::setw(6) << "Id";
50 stream << " ";
51 stream << std::setw(9) << "Consumers";
52 stream << " ";
53 stream << std::setw(14) << "Geometry";
54 stream << " ";
55 stream << std::setw(6) << "Format";
56 stream << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070057 stream << std::setw(10) << "Usage";
58 stream << " ";
59 stream << std::setw(9) << "Pending";
60 stream << " ";
61 stream << std::setw(18) << "State";
62 stream << " ";
63 stream << std::setw(18) << "Signaled";
64 stream << " ";
65 stream << std::setw(10) << "Index";
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080066 stream << std::endl;
67
68 for (const auto& channel : channels) {
69 if (channel->channel_type() == BufferHubChannel::kProducerType) {
70 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
71
72 stream << std::right;
73 stream << std::setw(6) << info.id;
74 stream << " ";
75 stream << std::setw(9) << info.consumer_count;
76 stream << " ";
77 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
78 std::string size = std::to_string(info.width) + " B";
79 stream << std::setw(14) << size;
80 } else {
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -070081 std::string dimensions = std::to_string(info.width) + "x" +
82 std::to_string(info.height) + "x" +
83 std::to_string(info.layer_count);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080084 stream << std::setw(14) << dimensions;
85 }
86 stream << " ";
87 stream << std::setw(6) << info.format;
88 stream << " ";
89 stream << "0x" << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -070090 stream << std::setw(8) << info.usage;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080091 stream << std::dec << std::setfill(' ');
92 stream << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070093 stream << std::setw(9) << info.pending_count;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080094 stream << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070095 stream << "0x" << std::hex << std::setfill('0');
96 stream << std::setw(16) << info.state;
97 stream << " ";
98 stream << "0x" << std::setw(16) << info.signaled_mask;
99 stream << std::dec << std::setfill(' ');
100 stream << " ";
101 stream << std::setw(8) << info.index;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800102 stream << std::endl;
103 }
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700104
105 if (channel->channel_type() == BufferHubChannel::kDetachedBufferType) {
106 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
107
108 stream << std::right;
109 stream << std::setw(6) << info.id;
110 stream << " ";
111 stream << std::setw(9) << "N/A";
112 stream << " ";
113 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
114 std::string size = std::to_string(info.width) + " B";
115 stream << std::setw(14) << size;
116 } else {
117 std::string dimensions = std::to_string(info.width) + "x" +
118 std::to_string(info.height) + "x" +
119 std::to_string(info.layer_count);
120 stream << std::setw(14) << dimensions;
121 }
122 stream << " ";
123 stream << std::setw(6) << info.format;
124 stream << " ";
125 stream << "0x" << std::hex << std::setfill('0');
126 stream << std::setw(8) << info.usage;
127 stream << std::dec << std::setfill(' ');
128 stream << " ";
129 stream << std::setw(9) << "N/A";
130 stream << " ";
131 stream << std::hex << std::setfill(' ');
132 stream << std::setw(18) << "Detached";
133 stream << " ";
134 stream << std::setw(18) << "N/A";
135 stream << " ";
136 stream << std::setw(10) << "N/A";
137 stream << std::endl;
138 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800139 }
140
141 stream << std::endl;
142 stream << "Active Producer Queues:\n";
143 stream << std::right << std::setw(6) << "Id";
Corey Tabaka8a4e6a92017-04-20 13:42:02 -0700144 stream << std::right << std::setw(12) << " Capacity";
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800145 stream << std::right << std::setw(12) << " Consumers";
146 stream << " UsageSetMask";
147 stream << " UsageClearMask";
148 stream << " UsageDenySetMask";
149 stream << " UsageDenyClearMask";
150 stream << " ";
151 stream << std::endl;
152
153 for (const auto& channel : channels) {
154 if (channel->channel_type() == BufferHubChannel::kProducerQueueType) {
155 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
156
157 stream << std::dec << std::setfill(' ');
158 stream << std::right << std::setw(6) << info.id;
159 stream << std::right << std::setw(12) << info.capacity;
160 stream << std::right << std::setw(12) << info.consumer_count;
161 stream << std::setw(5) << std::setfill(' ') << "0x";
162 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700163 stream << std::setw(8) << info.usage_policy.usage_set_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800164 stream << std::setw(7) << std::setfill(' ') << "0x";
165 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700166 stream << std::setw(8) << info.usage_policy.usage_clear_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800167 stream << std::setw(9) << std::setfill(' ') << "0x";
168 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700169 stream << std::setw(8) << info.usage_policy.usage_deny_set_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800170 stream << std::setw(11) << std::setfill(' ') << "0x";
171 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700172 stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700173 stream << std::hex << std::setfill('0');
174 stream << std::endl;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800175 }
176 }
177
178 stream << std::endl;
179 stream << "Active Consumer Queues:\n";
180 stream << std::dec << std::setfill(' ');
181 stream << std::right << std::setw(6) << "Id";
182 stream << std::right << std::setw(12) << " Imported";
183 stream << " ";
184 stream << std::endl;
185
186 for (const auto& channel : channels) {
187 if (channel->channel_type() == BufferHubChannel::kConsumerQueueType) {
188 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
189
190 stream << std::right << std::setw(6) << info.id;
191 stream << std::right << std::setw(12) << info.capacity;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700192 stream << std::endl;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800193 }
194 }
195
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700196 stream << std::endl;
197 stream << "Orphaned Consumer Buffers:\n";
198 stream << std::right;
199 stream << std::setw(6) << "Id";
200 stream << " ";
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800201 stream << std::setw(14) << "Info";
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700202 stream << std::endl;
203
204 for (const auto& channel : channels) {
205 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
206 // consumer_count is tracked by producer. When it's zero, producer must have
207 // already hung up and the consumer is orphaned.
208 if (channel->channel_type() == BufferHubChannel::kConsumerType &&
209 info.consumer_count == 0) {
210 stream << std::right;
211 stream << std::setw(6) << info.id;
212 stream << " ";
213
214 stream << std::setw(14) << "Orphaned.";
215 stream << (" channel_id=" + std::to_string(channel->channel_id()));
216 stream << std::endl;
217 }
218 }
219
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800220 return stream.str();
221}
222
223void BufferHubService::HandleImpulse(Message& message) {
224 ATRACE_NAME("BufferHubService::HandleImpulse");
225 if (auto channel = message.GetChannel<BufferHubChannel>())
226 channel->HandleImpulse(message);
227}
228
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700229pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800230 ATRACE_NAME("BufferHubService::HandleMessage");
231 auto channel = message.GetChannel<BufferHubChannel>();
232
233 ALOGD_IF(
234 TRACE,
235 "BufferHubService::HandleMessage: channel=%p channel_id=%d opcode=%d",
236 channel.get(), message.GetChannelId(), message.GetOp());
237
238 // If the channel is already set up, let it handle the message.
239 if (channel && !channel->HandleMessage(message))
240 return DefaultHandleMessage(message);
241
242 // This channel has not been set up yet, the following are valid operations.
243 switch (message.GetOp()) {
244 case BufferHubRPC::CreateBuffer::Opcode:
245 DispatchRemoteMethod<BufferHubRPC::CreateBuffer>(
246 *this, &BufferHubService::OnCreateBuffer, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700247 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800248
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700249 case DetachedBufferRPC::Create::Opcode:
250 DispatchRemoteMethod<DetachedBufferRPC::Create>(
251 *this, &BufferHubService::OnCreateDetachedBuffer, message);
252 return {};
253
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800254 case BufferHubRPC::CreateProducerQueue::Opcode:
255 DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
256 *this, &BufferHubService::OnCreateProducerQueue, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700257 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800258
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700259 case BufferHubRPC::ProducerBufferDetach::Opcode:
260 // In addition to the message handler in the ProducerChannel's
261 // HandleMessage method, we also need to invalid the producer channel (and
262 // all associated consumer channels). Note that this has to be done after
263 // HandleMessage returns to make sure the IPC request has went back to the
264 // client first.
265 SetChannel(channel->channel_id(), nullptr);
266 return {};
267
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700268 case DetachedBufferRPC::Promote::Opcode:
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -0700269 // In addition to the message handler in the BufferChannel's
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700270 // HandleMessage method, we also need to invalid the channel. Note that
271 // this has to be done after HandleMessage returns to make sure the IPC
272 // request has went back to the client first.
273 SetChannel(channel->channel_id(), nullptr);
274 return {};
275
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800276 default:
277 return DefaultHandleMessage(message);
278 }
279}
280
Corey Tabakacd52dd92017-04-07 18:03:57 -0700281Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
282 uint32_t height, uint32_t format,
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700283 uint64_t usage,
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700284 size_t meta_size_bytes) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800285 // Use the producer channel id as the global buffer id.
286 const int buffer_id = message.GetChannelId();
287 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700288 "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700289 "format=%u usage=%" PRIx64 " meta_size_bytes=%zu",
290 buffer_id, width, height, format, usage, meta_size_bytes);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800291
292 // See if this channel is already attached to a buffer.
293 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
294 ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
295 buffer_id);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700296 return ErrorStatus(EALREADY);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800297 }
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700298 const uint32_t kDefaultLayerCount = 1;
299 auto status = ProducerChannel::Create(this, buffer_id, width, height,
300 kDefaultLayerCount, format, usage,
301 meta_size_bytes);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700302 if (status) {
303 message.SetChannel(status.take());
304 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800305 } else {
Corey Tabakacd52dd92017-04-07 18:03:57 -0700306 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
307 status.GetErrorMessage().c_str());
308 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800309 }
310}
311
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700312pdx::Status<void> BufferHubService::OnCreateDetachedBuffer(
313 pdx::Message& message, uint32_t width, uint32_t height,
314 uint32_t layer_count, uint32_t format, uint64_t usage,
315 size_t user_metadata_size) {
316 // Use the producer channel id as the global buffer id.
317 const int buffer_id = message.GetChannelId();
318 ALOGD_IF(TRACE,
319 "BufferHubService::OnCreateDetachedBuffer: buffer_id=%d width=%u "
320 "height=%u layer_count=%u format=%u usage=%" PRIx64
321 " user_metadata_size=%zu",
322 buffer_id, width, height, layer_count, format, usage,
323 user_metadata_size);
324
325 // See if this channel is already attached to a buffer.
326 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
327 ALOGE(
328 "BufferHubService::OnCreateDetachedBuffer: Buffer already created: "
329 "buffer=%d",
330 buffer_id);
331 return ErrorStatus(EALREADY);
332 }
333
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -0700334 std::unique_ptr<BufferChannel> channel =
335 BufferChannel::Create(this, buffer_id, width, height, layer_count, format,
336 usage, user_metadata_size);
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700337 if (!channel) {
338 ALOGE(
339 "BufferHubService::OnCreateDetachedBuffer: Failed to allocate buffer, "
340 "buffer=%d.",
341 buffer_id);
342 return ErrorStatus(ENOMEM);
343 }
344
345 message.SetChannel(std::move(channel));
346 return {};
347}
348
Corey Tabaka1db8a5d2017-03-22 02:12:52 -0700349Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700350 pdx::Message& message, const ProducerQueueConfig& producer_config,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700351 const UsagePolicy& usage_policy) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800352 // Use the producer channel id as the global queue id.
353 const int queue_id = message.GetChannelId();
354 ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
355 queue_id);
356
357 // See if this channel is already attached to another object.
358 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
359 ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d",
360 queue_id);
Corey Tabaka1db8a5d2017-03-22 02:12:52 -0700361 return ErrorStatus(EALREADY);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800362 }
363
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700364 auto status = ProducerQueueChannel::Create(this, queue_id, producer_config,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700365 usage_policy);
366 if (status) {
367 message.SetChannel(status.take());
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700368 return {{producer_config, queue_id}};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800369 } else {
370 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
Corey Tabakacd52dd92017-04-07 18:03:57 -0700371 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800372 }
373}
374
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800375void BufferHubChannel::SignalAvailable() {
376 ATRACE_NAME("BufferHubChannel::SignalAvailable");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800377 ALOGD_IF(TRACE,
378 "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
379 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800380 signaled_ = true;
381 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
382 ALOGE_IF(!status,
383 "BufferHubChannel::SignalAvailable: failed to signal availability "
384 "channel_id=%d: %s",
385 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800386}
387
388void BufferHubChannel::ClearAvailable() {
389 ATRACE_NAME("BufferHubChannel::ClearAvailable");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800390 ALOGD_IF(TRACE,
391 "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
392 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800393 signaled_ = false;
394 const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
395 ALOGE_IF(!status,
396 "BufferHubChannel::ClearAvailable: failed to clear availability "
397 "channel_id=%d: %s",
398 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800399}
400
401void BufferHubChannel::Hangup() {
402 ATRACE_NAME("BufferHubChannel::Hangup");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800403 ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d",
404 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800405 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP);
406 ALOGE_IF(
407 !status,
408 "BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s",
409 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800410}
411
412} // namespace dvr
413} // namespace android