blob: 64092656e382a986f1238dc9e8889496c8ee70f4 [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_hub.h>
14#include <private/dvr/consumer_channel.h>
15#include <private/dvr/producer_channel.h>
16#include <private/dvr/producer_queue_channel.h>
17#include <utils/Trace.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080018
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 << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070058 stream << std::setw(18) << "State";
59 stream << " ";
60 stream << std::setw(18) << "Signaled";
61 stream << " ";
62 stream << std::setw(10) << "Index";
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080063 stream << std::endl;
64
65 for (const auto& channel : channels) {
66 if (channel->channel_type() == BufferHubChannel::kProducerType) {
67 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
68
69 stream << std::right;
70 stream << std::setw(6) << info.id;
71 stream << " ";
72 stream << std::setw(9) << info.consumer_count;
73 stream << " ";
74 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
75 std::string size = std::to_string(info.width) + " B";
76 stream << std::setw(14) << size;
77 } else {
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -070078 std::string dimensions = std::to_string(info.width) + "x" +
79 std::to_string(info.height) + "x" +
80 std::to_string(info.layer_count);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080081 stream << std::setw(14) << dimensions;
82 }
83 stream << " ";
84 stream << std::setw(6) << info.format;
85 stream << " ";
86 stream << "0x" << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -070087 stream << std::setw(8) << info.usage;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080088 stream << std::dec << std::setfill(' ');
89 stream << " ";
Corey Tabaka52ea25c2017-09-13 18:02:48 -070090 stream << "0x" << std::hex << std::setfill('0');
91 stream << std::setw(16) << info.state;
92 stream << " ";
93 stream << "0x" << std::setw(16) << info.signaled_mask;
94 stream << std::dec << std::setfill(' ');
95 stream << " ";
96 stream << std::setw(8) << info.index;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080097 stream << std::endl;
98 }
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -070099
100 if (channel->channel_type() == BufferHubChannel::kDetachedBufferType) {
101 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
102
103 stream << std::right;
104 stream << std::setw(6) << info.id;
105 stream << " ";
106 stream << std::setw(9) << "N/A";
107 stream << " ";
108 if (info.format == HAL_PIXEL_FORMAT_BLOB) {
109 std::string size = std::to_string(info.width) + " B";
110 stream << std::setw(14) << size;
111 } else {
112 std::string dimensions = std::to_string(info.width) + "x" +
113 std::to_string(info.height) + "x" +
114 std::to_string(info.layer_count);
115 stream << std::setw(14) << dimensions;
116 }
117 stream << " ";
118 stream << std::setw(6) << info.format;
119 stream << " ";
120 stream << "0x" << std::hex << std::setfill('0');
121 stream << std::setw(8) << info.usage;
122 stream << std::dec << std::setfill(' ');
123 stream << " ";
124 stream << std::setw(9) << "N/A";
125 stream << " ";
126 stream << std::hex << std::setfill(' ');
127 stream << std::setw(18) << "Detached";
128 stream << " ";
129 stream << std::setw(18) << "N/A";
130 stream << " ";
131 stream << std::setw(10) << "N/A";
132 stream << std::endl;
133 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800134 }
135
136 stream << std::endl;
137 stream << "Active Producer Queues:\n";
138 stream << std::right << std::setw(6) << "Id";
Corey Tabaka8a4e6a92017-04-20 13:42:02 -0700139 stream << std::right << std::setw(12) << " Capacity";
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800140 stream << std::right << std::setw(12) << " Consumers";
141 stream << " UsageSetMask";
142 stream << " UsageClearMask";
143 stream << " UsageDenySetMask";
144 stream << " UsageDenyClearMask";
145 stream << " ";
146 stream << std::endl;
147
148 for (const auto& channel : channels) {
149 if (channel->channel_type() == BufferHubChannel::kProducerQueueType) {
150 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
151
152 stream << std::dec << std::setfill(' ');
153 stream << std::right << std::setw(6) << info.id;
154 stream << std::right << std::setw(12) << info.capacity;
155 stream << std::right << std::setw(12) << info.consumer_count;
156 stream << std::setw(5) << std::setfill(' ') << "0x";
157 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700158 stream << std::setw(8) << info.usage_policy.usage_set_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800159 stream << std::setw(7) << std::setfill(' ') << "0x";
160 stream << std::hex << std::setfill('0');
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700161 stream << std::setw(8) << info.usage_policy.usage_clear_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800162 stream << std::setw(9) << 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_deny_set_mask;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800165 stream << std::setw(11) << 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_deny_clear_mask;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700168 stream << std::hex << std::setfill('0');
169 stream << std::endl;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800170 }
171 }
172
173 stream << std::endl;
174 stream << "Active Consumer Queues:\n";
175 stream << std::dec << std::setfill(' ');
176 stream << std::right << std::setw(6) << "Id";
177 stream << std::right << std::setw(12) << " Imported";
178 stream << " ";
179 stream << std::endl;
180
181 for (const auto& channel : channels) {
182 if (channel->channel_type() == BufferHubChannel::kConsumerQueueType) {
183 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
184
185 stream << std::right << std::setw(6) << info.id;
186 stream << std::right << std::setw(12) << info.capacity;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700187 stream << std::endl;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800188 }
189 }
190
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700191 stream << std::endl;
192 stream << "Orphaned Consumer Buffers:\n";
193 stream << std::right;
194 stream << std::setw(6) << "Id";
195 stream << " ";
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800196 stream << std::setw(14) << "Info";
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700197 stream << std::endl;
198
199 for (const auto& channel : channels) {
200 BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
201 // consumer_count is tracked by producer. When it's zero, producer must have
202 // already hung up and the consumer is orphaned.
203 if (channel->channel_type() == BufferHubChannel::kConsumerType &&
204 info.consumer_count == 0) {
205 stream << std::right;
206 stream << std::setw(6) << info.id;
207 stream << " ";
208
209 stream << std::setw(14) << "Orphaned.";
210 stream << (" channel_id=" + std::to_string(channel->channel_id()));
211 stream << std::endl;
212 }
213 }
214
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800215 return stream.str();
216}
217
218void BufferHubService::HandleImpulse(Message& message) {
219 ATRACE_NAME("BufferHubService::HandleImpulse");
220 if (auto channel = message.GetChannel<BufferHubChannel>())
221 channel->HandleImpulse(message);
222}
223
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700224pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800225 ATRACE_NAME("BufferHubService::HandleMessage");
226 auto channel = message.GetChannel<BufferHubChannel>();
227
228 ALOGD_IF(
229 TRACE,
230 "BufferHubService::HandleMessage: channel=%p channel_id=%d opcode=%d",
231 channel.get(), message.GetChannelId(), message.GetOp());
232
233 // If the channel is already set up, let it handle the message.
234 if (channel && !channel->HandleMessage(message))
235 return DefaultHandleMessage(message);
236
237 // This channel has not been set up yet, the following are valid operations.
238 switch (message.GetOp()) {
239 case BufferHubRPC::CreateBuffer::Opcode:
240 DispatchRemoteMethod<BufferHubRPC::CreateBuffer>(
241 *this, &BufferHubService::OnCreateBuffer, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700242 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800243
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800244 case BufferHubRPC::CreateProducerQueue::Opcode:
245 DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
246 *this, &BufferHubService::OnCreateProducerQueue, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700247 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800248
249 default:
250 return DefaultHandleMessage(message);
251 }
252}
253
Corey Tabakacd52dd92017-04-07 18:03:57 -0700254Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
255 uint32_t height, uint32_t format,
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700256 uint64_t usage,
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700257 size_t meta_size_bytes) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800258 // Use the producer channel id as the global buffer id.
259 const int buffer_id = message.GetChannelId();
260 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700261 "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700262 "format=%u usage=%" PRIx64 " meta_size_bytes=%zu",
263 buffer_id, width, height, format, usage, meta_size_bytes);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800264
265 // See if this channel is already attached to a buffer.
266 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
267 ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
268 buffer_id);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700269 return ErrorStatus(EALREADY);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800270 }
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700271 const uint32_t kDefaultLayerCount = 1;
272 auto status = ProducerChannel::Create(this, buffer_id, width, height,
273 kDefaultLayerCount, format, usage,
274 meta_size_bytes);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700275 if (status) {
276 message.SetChannel(status.take());
277 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800278 } else {
Corey Tabakacd52dd92017-04-07 18:03:57 -0700279 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
280 status.GetErrorMessage().c_str());
281 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800282 }
283}
284
Corey Tabaka1db8a5d2017-03-22 02:12:52 -0700285Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700286 pdx::Message& message, const ProducerQueueConfig& producer_config,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700287 const UsagePolicy& usage_policy) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800288 // Use the producer channel id as the global queue id.
289 const int queue_id = message.GetChannelId();
290 ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
291 queue_id);
292
293 // See if this channel is already attached to another object.
294 if (const auto channel = message.GetChannel<BufferHubChannel>()) {
295 ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d",
296 queue_id);
Corey Tabaka1db8a5d2017-03-22 02:12:52 -0700297 return ErrorStatus(EALREADY);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800298 }
299
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700300 auto status = ProducerQueueChannel::Create(this, queue_id, producer_config,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700301 usage_policy);
302 if (status) {
303 message.SetChannel(status.take());
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -0700304 return {{producer_config, queue_id}};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800305 } else {
306 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
Corey Tabakacd52dd92017-04-07 18:03:57 -0700307 return status.error_status();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800308 }
309}
310
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800311void BufferHubChannel::SignalAvailable() {
312 ATRACE_NAME("BufferHubChannel::SignalAvailable");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800313 ALOGD_IF(TRACE,
314 "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
315 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800316 signaled_ = true;
317 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
318 ALOGE_IF(!status,
319 "BufferHubChannel::SignalAvailable: failed to signal availability "
320 "channel_id=%d: %s",
321 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800322}
323
324void BufferHubChannel::ClearAvailable() {
325 ATRACE_NAME("BufferHubChannel::ClearAvailable");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800326 ALOGD_IF(TRACE,
327 "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
328 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800329 signaled_ = false;
330 const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
331 ALOGE_IF(!status,
332 "BufferHubChannel::ClearAvailable: failed to clear availability "
333 "channel_id=%d: %s",
334 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800335}
336
337void BufferHubChannel::Hangup() {
338 ATRACE_NAME("BufferHubChannel::Hangup");
Corey Tabaka3079cb72017-01-19 15:07:26 -0800339 ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d",
340 channel_id(), buffer_id());
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800341 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP);
342 ALOGE_IF(
343 !status,
344 "BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s",
345 channel_id_, status.GetErrorMessage().c_str());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800346}
347
348} // namespace dvr
349} // namespace android