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 <memory> 10#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" 17#include "detached_buffer_channel.h" 18#include "producer_channel.h" 19#include "producer_queue_channel.h" 20 21using android::pdx::Channel; 22using android::pdx::ErrorStatus; 23using android::pdx::Message; 24using android::pdx::Status; 25using android::pdx::default_transport::Endpoint; 26using android::pdx::rpc::DispatchRemoteMethod; 27 28namespace android { 29namespace dvr { 30 31BufferHubService::BufferHubService() 32 : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {} 33 34BufferHubService::~BufferHubService() {} 35 36bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); } 37 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 << " "; 58 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"; 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 << std::endl; 104 } 105 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 } 140 } 141 142 stream << std::endl; 143 stream << "Active Producer Queues:\n"; 144 stream << std::right << std::setw(6) << "Id"; 145 stream << std::right << std::setw(12) << " Capacity"; 146 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'); 164 stream << std::setw(8) << info.usage_policy.usage_set_mask; 165 stream << std::setw(7) << std::setfill(' ') << "0x"; 166 stream << std::hex << std::setfill('0'); 167 stream << std::setw(8) << info.usage_policy.usage_clear_mask; 168 stream << std::setw(9) << std::setfill(' ') << "0x"; 169 stream << std::hex << std::setfill('0'); 170 stream << std::setw(8) << info.usage_policy.usage_deny_set_mask; 171 stream << std::setw(11) << std::setfill(' ') << "0x"; 172 stream << std::hex << std::setfill('0'); 173 stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask; 174 stream << std::hex << std::setfill('0'); 175 stream << std::endl; 176 } 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; 193 stream << std::endl; 194 } 195 } 196 197 stream << std::endl; 198 stream << "Orphaned Consumer Buffers:\n"; 199 stream << std::right; 200 stream << std::setw(6) << "Id"; 201 stream << " "; 202 stream << std::setw(14) << "Info"; 203 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 221 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 230pdx::Status<void> BufferHubService::HandleMessage(Message& message) { 231 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); 248 return {}; 249 250 case DetachedBufferRPC::Create::Opcode: 251 DispatchRemoteMethod<DetachedBufferRPC::Create>( 252 *this, &BufferHubService::OnCreateDetachedBuffer, message); 253 return {}; 254 255 case BufferHubRPC::CreateProducerQueue::Opcode: 256 DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>( 257 *this, &BufferHubService::OnCreateProducerQueue, message); 258 return {}; 259 260 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 269 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 277 default: 278 return DefaultHandleMessage(message); 279 } 280} 281 282Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width, 283 uint32_t height, uint32_t format, 284 uint64_t usage, 285 size_t meta_size_bytes) { 286 // Use the producer channel id as the global buffer id. 287 const int buffer_id = message.GetChannelId(); 288 ALOGD_IF(TRACE, 289 "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u " 290 "format=%u usage=%" PRIx64 " meta_size_bytes=%zu", 291 buffer_id, width, height, format, usage, meta_size_bytes); 292 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); 297 return ErrorStatus(EALREADY); 298 } 299 const uint32_t kDefaultLayerCount = 1; 300 auto status = ProducerChannel::Create(this, buffer_id, width, height, 301 kDefaultLayerCount, format, usage, 302 meta_size_bytes); 303 if (status) { 304 message.SetChannel(status.take()); 305 return {}; 306 } else { 307 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s", 308 status.GetErrorMessage().c_str()); 309 return status.error_status(); 310 } 311} 312 313pdx::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 350Status<QueueInfo> BufferHubService::OnCreateProducerQueue( 351 pdx::Message& message, const ProducerQueueConfig& producer_config, 352 const UsagePolicy& usage_policy) { 353 // 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); 362 return ErrorStatus(EALREADY); 363 } 364 365 auto status = ProducerQueueChannel::Create(this, queue_id, producer_config, 366 usage_policy); 367 if (status) { 368 message.SetChannel(status.take()); 369 return {{producer_config, queue_id}}; 370 } else { 371 ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!"); 372 return status.error_status(); 373 } 374} 375 376void BufferHubChannel::SignalAvailable() { 377 ATRACE_NAME("BufferHubChannel::SignalAvailable"); 378 ALOGD_IF(TRACE, 379 "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d", 380 channel_id(), buffer_id()); 381 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()); 387} 388 389void BufferHubChannel::ClearAvailable() { 390 ATRACE_NAME("BufferHubChannel::ClearAvailable"); 391 ALOGD_IF(TRACE, 392 "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d", 393 channel_id(), buffer_id()); 394 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()); 400} 401 402void BufferHubChannel::Hangup() { 403 ATRACE_NAME("BufferHubChannel::Hangup"); 404 ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d", 405 channel_id(), buffer_id()); 406 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()); 411} 412 413} // namespace dvr 414} // namespace android 415