Home | History | Annotate | Download | only in bufferhubd
      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