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