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::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