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 <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 19 using android::pdx::Channel; 20 using android::pdx::ErrorStatus; 21 using android::pdx::Message; 22 using android::pdx::Status; 23 using android::pdx::default_transport::Endpoint; 24 using android::pdx::rpc::DispatchRemoteMethod; 25 26 namespace android { 27 namespace dvr { 28 29 BufferHubService::BufferHubService() 30 : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {} 31 32 BufferHubService::~BufferHubService() {} 33 34 bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); } 35 36 std::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 << " "; 56 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"; 65 stream << " "; 66 stream << "Name"; 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 << " "; 104 stream << info.name; 105 stream << std::endl; 106 } 107 } 108 109 stream << std::endl; 110 stream << "Active Producer Queues:\n"; 111 stream << std::right << std::setw(6) << "Id"; 112 stream << std::right << std::setw(12) << " Capacity"; 113 stream << std::right << std::setw(12) << " Consumers"; 114 stream << " UsageSetMask"; 115 stream << " UsageClearMask"; 116 stream << " UsageDenySetMask"; 117 stream << " UsageDenyClearMask"; 118 stream << " "; 119 stream << std::endl; 120 121 for (const auto& channel : channels) { 122 if (channel->channel_type() == BufferHubChannel::kProducerQueueType) { 123 BufferHubChannel::BufferInfo info = channel->GetBufferInfo(); 124 125 stream << std::dec << std::setfill(' '); 126 stream << std::right << std::setw(6) << info.id; 127 stream << std::right << std::setw(12) << info.capacity; 128 stream << std::right << std::setw(12) << info.consumer_count; 129 stream << std::setw(5) << std::setfill(' ') << "0x"; 130 stream << std::hex << std::setfill('0'); 131 stream << std::setw(8) << info.usage_policy.usage_set_mask; 132 stream << std::setw(7) << std::setfill(' ') << "0x"; 133 stream << std::hex << std::setfill('0'); 134 stream << std::setw(8) << info.usage_policy.usage_clear_mask; 135 stream << std::setw(9) << std::setfill(' ') << "0x"; 136 stream << std::hex << std::setfill('0'); 137 stream << std::setw(8) << info.usage_policy.usage_deny_set_mask; 138 stream << std::setw(11) << std::setfill(' ') << "0x"; 139 stream << std::hex << std::setfill('0'); 140 stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask; 141 stream << std::hex << std::setfill('0'); 142 stream << std::endl; 143 } 144 } 145 146 stream << std::endl; 147 stream << "Active Consumer Queues:\n"; 148 stream << std::dec << std::setfill(' '); 149 stream << std::right << std::setw(6) << "Id"; 150 stream << std::right << std::setw(12) << " Imported"; 151 stream << " "; 152 stream << std::endl; 153 154 for (const auto& channel : channels) { 155 if (channel->channel_type() == BufferHubChannel::kConsumerQueueType) { 156 BufferHubChannel::BufferInfo info = channel->GetBufferInfo(); 157 158 stream << std::right << std::setw(6) << info.id; 159 stream << std::right << std::setw(12) << info.capacity; 160 stream << std::endl; 161 } 162 } 163 164 stream << std::endl; 165 stream << "Orphaned Consumer Buffers:\n"; 166 stream << std::right; 167 stream << std::setw(6) << "Id"; 168 stream << " "; 169 stream << std::setw(14) << "Geometry"; 170 stream << " "; 171 stream << "Name"; 172 stream << std::endl; 173 174 for (const auto& channel : channels) { 175 BufferHubChannel::BufferInfo info = channel->GetBufferInfo(); 176 // consumer_count is tracked by producer. When it's zero, producer must have 177 // already hung up and the consumer is orphaned. 178 if (channel->channel_type() == BufferHubChannel::kConsumerType && 179 info.consumer_count == 0) { 180 stream << std::right; 181 stream << std::setw(6) << info.id; 182 stream << " "; 183 184 stream << std::setw(14) << "Orphaned."; 185 stream << (" channel_id=" + std::to_string(channel->channel_id())); 186 stream << std::endl; 187 } 188 } 189 190 return stream.str(); 191 } 192 193 void BufferHubService::HandleImpulse(Message& message) { 194 ATRACE_NAME("BufferHubService::HandleImpulse"); 195 if (auto channel = message.GetChannel<BufferHubChannel>()) 196 channel->HandleImpulse(message); 197 } 198 199 pdx::Status<void> BufferHubService::HandleMessage(Message& message) { 200 ATRACE_NAME("BufferHubService::HandleMessage"); 201 auto channel = message.GetChannel<BufferHubChannel>(); 202 203 ALOGD_IF( 204 TRACE, 205 "BufferHubService::HandleMessage: channel=%p channel_id=%d opcode=%d", 206 channel.get(), message.GetChannelId(), message.GetOp()); 207 208 // If the channel is already set up, let it handle the message. 209 if (channel && !channel->HandleMessage(message)) 210 return DefaultHandleMessage(message); 211 212 // This channel has not been set up yet, the following are valid operations. 213 switch (message.GetOp()) { 214 case BufferHubRPC::CreateBuffer::Opcode: 215 DispatchRemoteMethod<BufferHubRPC::CreateBuffer>( 216 *this, &BufferHubService::OnCreateBuffer, message); 217 return {}; 218 219 case BufferHubRPC::CreatePersistentBuffer::Opcode: 220 DispatchRemoteMethod<BufferHubRPC::CreatePersistentBuffer>( 221 *this, &BufferHubService::OnCreatePersistentBuffer, message); 222 return {}; 223 224 case BufferHubRPC::GetPersistentBuffer::Opcode: 225 DispatchRemoteMethod<BufferHubRPC::GetPersistentBuffer>( 226 *this, &BufferHubService::OnGetPersistentBuffer, message); 227 return {}; 228 229 case BufferHubRPC::CreateProducerQueue::Opcode: 230 DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>( 231 *this, &BufferHubService::OnCreateProducerQueue, message); 232 return {}; 233 234 default: 235 return DefaultHandleMessage(message); 236 } 237 } 238 239 void BufferHubService::OnChannelClose(Message&, 240 const std::shared_ptr<Channel>& channel) { 241 if (auto buffer = std::static_pointer_cast<BufferHubChannel>(channel)) 242 buffer->Detach(); 243 } 244 245 Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width, 246 uint32_t height, uint32_t format, 247 uint64_t usage, 248 size_t meta_size_bytes) { 249 // Use the producer channel id as the global buffer id. 250 const int buffer_id = message.GetChannelId(); 251 ALOGD_IF(TRACE, 252 "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u " 253 "format=%u usage=%" PRIx64 " meta_size_bytes=%zu", 254 buffer_id, width, height, format, usage, meta_size_bytes); 255 256 // See if this channel is already attached to a buffer. 257 if (const auto channel = message.GetChannel<BufferHubChannel>()) { 258 ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d", 259 buffer_id); 260 return ErrorStatus(EALREADY); 261 } 262 const uint32_t kDefaultLayerCount = 1; 263 auto status = ProducerChannel::Create(this, buffer_id, width, height, 264 kDefaultLayerCount, format, usage, 265 meta_size_bytes); 266 if (status) { 267 message.SetChannel(status.take()); 268 return {}; 269 } else { 270 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s", 271 status.GetErrorMessage().c_str()); 272 return status.error_status(); 273 } 274 } 275 276 Status<void> BufferHubService::OnCreatePersistentBuffer( 277 Message& message, const std::string& name, int user_id, int group_id, 278 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, 279 size_t meta_size_bytes) { 280 const uint32_t kDefaultLayerCount = 1; 281 const int channel_id = message.GetChannelId(); 282 ALOGD_IF(TRACE, 283 "BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s " 284 "user_id=%d group_id=%d width=%u height=%u format=%u " 285 "usage=%" PRIx64 " meta_size_bytes=%zu", 286 channel_id, name.c_str(), user_id, group_id, width, height, format, 287 usage, meta_size_bytes); 288 289 // See if this channel is already attached to a buffer. 290 if (const auto channel = message.GetChannel<BufferHubChannel>()) { 291 ALOGE( 292 "BufferHubService::OnCreatePersistentBuffer: Channel already attached " 293 "to buffer: channel_id=%d buffer_id=%d", 294 channel_id, channel->buffer_id()); 295 return ErrorStatus(EALREADY); 296 } 297 298 const int euid = message.GetEffectiveUserId(); 299 const int egid = message.GetEffectiveGroupId(); 300 301 if (auto buffer = GetNamedBuffer(name)) { 302 if (!buffer->CheckAccess(euid, egid)) { 303 ALOGE( 304 "BufferHubService::OnCreatePersistentBuffer: Requesting process does " 305 "not have permission to access named buffer: name=%s euid=%d egid=%d", 306 name.c_str(), euid, euid); 307 return ErrorStatus(EPERM); 308 } else if (!buffer->CheckParameters(width, height, kDefaultLayerCount, 309 format, usage, meta_size_bytes)) { 310 ALOGE( 311 "BufferHubService::OnCreatePersistentBuffer: Requested an existing " 312 "buffer with different parameters: name=%s", 313 name.c_str()); 314 return ErrorStatus(EINVAL); 315 } else if (!buffer->IsDetached()) { 316 ALOGE( 317 "BufferHubService::OnCreatePersistentBuffer: Requesting a persistent " 318 "buffer that is already attached to a channel: name=%s", 319 name.c_str()); 320 return ErrorStatus(EINVAL); 321 } else { 322 buffer->Attach(channel_id); 323 message.SetChannel(buffer); 324 return {}; 325 } 326 } else { 327 auto status = ProducerChannel::Create(this, channel_id, width, height, 328 kDefaultLayerCount, format, usage, 329 meta_size_bytes); 330 if (!status) { 331 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!"); 332 return status.error_status(); 333 } 334 auto persistent_buffer = status.take(); 335 auto make_persistent_status = persistent_buffer->OnProducerMakePersistent( 336 message, name, user_id, group_id); 337 if (make_persistent_status) 338 message.SetChannel(persistent_buffer); 339 return make_persistent_status; 340 } 341 } 342 343 Status<void> BufferHubService::OnGetPersistentBuffer(Message& message, 344 const std::string& name) { 345 const int channel_id = message.GetChannelId(); 346 ALOGD_IF(TRACE, 347 "BufferHubService::OnGetPersistentBuffer: channel_id=%d name=%s", 348 channel_id, name.c_str()); 349 350 // See if this channel is already attached to a buffer. 351 if (const auto channel = message.GetChannel<BufferHubChannel>()) { 352 ALOGE( 353 "BufferHubService::OnGetPersistentBuffer: Channel already attached to " 354 "buffer: channel_id=%d buffer_id=%d", 355 channel_id, channel->buffer_id()); 356 return ErrorStatus(EALREADY); 357 } 358 359 const int euid = message.GetEffectiveUserId(); 360 const int egid = message.GetEffectiveGroupId(); 361 362 if (auto buffer = GetNamedBuffer(name)) { 363 if (!buffer->CheckAccess(euid, egid)) { 364 ALOGE( 365 "BufferHubService::OnGetPersistentBuffer: Requesting process does " 366 "not have permission to access named buffer: name=%s euid=%d egid=%d", 367 name.c_str(), euid, egid); 368 return ErrorStatus(EPERM); 369 } else if (!buffer->IsDetached()) { 370 ALOGE( 371 "BufferHubService::OnGetPersistentBuffer: Requesting a persistent " 372 "buffer that is already attached to a channel: name=%s", 373 name.c_str()); 374 return ErrorStatus(EINVAL); 375 } else { 376 buffer->Attach(channel_id); 377 message.SetChannel(buffer); 378 return {}; 379 } 380 } else { 381 ALOGE("BufferHubService::OnGetPersistentBuffer: Buffer \"%s\" not found!", 382 name.c_str()); 383 return ErrorStatus(ENOENT); 384 } 385 } 386 387 Status<QueueInfo> BufferHubService::OnCreateProducerQueue( 388 pdx::Message& message, const ProducerQueueConfig& producer_config, 389 const UsagePolicy& usage_policy) { 390 // Use the producer channel id as the global queue id. 391 const int queue_id = message.GetChannelId(); 392 ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d", 393 queue_id); 394 395 // See if this channel is already attached to another object. 396 if (const auto channel = message.GetChannel<BufferHubChannel>()) { 397 ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d", 398 queue_id); 399 return ErrorStatus(EALREADY); 400 } 401 402 auto status = ProducerQueueChannel::Create(this, queue_id, producer_config, 403 usage_policy); 404 if (status) { 405 message.SetChannel(status.take()); 406 return {{producer_config, queue_id}}; 407 } else { 408 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!"); 409 return status.error_status(); 410 } 411 } 412 413 bool BufferHubService::AddNamedBuffer( 414 const std::string& name, const std::shared_ptr<ProducerChannel>& buffer) { 415 auto search = named_buffers_.find(name); 416 if (search == named_buffers_.end()) { 417 named_buffers_.emplace(name, buffer); 418 return true; 419 } else { 420 return false; 421 } 422 } 423 424 std::shared_ptr<ProducerChannel> BufferHubService::GetNamedBuffer( 425 const std::string& name) { 426 auto search = named_buffers_.find(name); 427 if (search != named_buffers_.end()) 428 return search->second; 429 else 430 return nullptr; 431 } 432 433 bool BufferHubService::RemoveNamedBuffer(const ProducerChannel& buffer) { 434 for (auto it = named_buffers_.begin(); it != named_buffers_.end();) { 435 if (it->second.get() == &buffer) { 436 named_buffers_.erase(it); 437 return true; 438 } 439 ++it; 440 } 441 return false; 442 } 443 444 void BufferHubChannel::SignalAvailable() { 445 ATRACE_NAME("BufferHubChannel::SignalAvailable"); 446 ALOGD_IF(TRACE, 447 "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d", 448 channel_id(), buffer_id()); 449 if (!IsDetached()) { 450 signaled_ = true; 451 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN); 452 ALOGE_IF(!status, 453 "BufferHubChannel::SignalAvailable: failed to signal availability " 454 "channel_id=%d: %s", 455 channel_id_, status.GetErrorMessage().c_str()); 456 } else { 457 ALOGD_IF(TRACE, "BufferHubChannel::SignalAvailable: detached buffer."); 458 } 459 } 460 461 void BufferHubChannel::ClearAvailable() { 462 ATRACE_NAME("BufferHubChannel::ClearAvailable"); 463 ALOGD_IF(TRACE, 464 "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d", 465 channel_id(), buffer_id()); 466 if (!IsDetached()) { 467 signaled_ = false; 468 const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0); 469 ALOGE_IF(!status, 470 "BufferHubChannel::ClearAvailable: failed to clear availability " 471 "channel_id=%d: %s", 472 channel_id_, status.GetErrorMessage().c_str()); 473 } else { 474 ALOGD_IF(TRACE, "BufferHubChannel::ClearAvailable: detached buffer."); 475 } 476 } 477 478 void BufferHubChannel::Hangup() { 479 ATRACE_NAME("BufferHubChannel::Hangup"); 480 ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d", 481 channel_id(), buffer_id()); 482 if (!IsDetached()) { 483 const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP); 484 ALOGE_IF( 485 !status, 486 "BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s", 487 channel_id_, status.GetErrorMessage().c_str()); 488 } else { 489 ALOGD_IF(TRACE, "BufferHubChannel::Hangup: detached buffer."); 490 } 491 } 492 493 } // namespace dvr 494 } // namespace android 495