Home | History | Annotate | Download | only in libpdx_uds
      1 #include "private/uds/channel_event_set.h"
      2 
      3 #include <log/log.h>
      4 
      5 #include <uds/ipc_helper.h>
      6 
      7 namespace android {
      8 namespace pdx {
      9 namespace uds {
     10 
     11 ChannelEventSet::ChannelEventSet() {
     12   const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
     13   LocalHandle epoll_fd, event_fd;
     14 
     15   if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll") ||
     16       !SetupHandle(eventfd(0, flags), &event_fd, "event")) {
     17     return;
     18   }
     19 
     20   epoll_event event;
     21   event.events = 0;
     22   event.data.u32 = 0;
     23   if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_fd.Get(), &event) < 0) {
     24     const int error = errno;
     25     ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s",
     26           strerror(error));
     27     return;
     28   }
     29 
     30   epoll_fd_ = std::move(epoll_fd);
     31   event_fd_ = std::move(event_fd);
     32 }
     33 
     34 Status<void> ChannelEventSet::AddDataFd(const LocalHandle& data_fd) {
     35   epoll_event event;
     36   event.events = EPOLLHUP | EPOLLRDHUP;
     37   event.data.u32 = event.events;
     38   if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) {
     39     const int error = errno;
     40     ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s",
     41           strerror(error));
     42     return ErrorStatus{error};
     43   } else {
     44     return {};
     45   }
     46 }
     47 
     48 int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) {
     49   ALOGD_IF(TRACE, "ChannelEventSet::ModifyEvents: clear_mask=%x set_mask=%x",
     50            clear_mask, set_mask);
     51   const int old_bits = event_bits_;
     52   const int new_bits = (event_bits_ & ~clear_mask) | set_mask;
     53   event_bits_ = new_bits;
     54 
     55   // If anything changed clear the event and update the event mask.
     56   if (old_bits != new_bits) {
     57     eventfd_t value;
     58     eventfd_read(event_fd_.Get(), &value);
     59 
     60     epoll_event event;
     61     event.events = POLLIN;
     62     event.data.u32 = event_bits_;
     63     if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, event_fd_.Get(), &event) <
     64         0) {
     65       const int error = errno;
     66       ALOGE("ChannelEventSet::AddEventHandle: Failed to update event: %s",
     67             strerror(error));
     68       return -error;
     69     }
     70   }
     71 
     72   // If there are any bits set, re-trigger the eventfd.
     73   if (new_bits)
     74     eventfd_write(event_fd_.Get(), 1);
     75 
     76   return 0;
     77 }
     78 
     79 Status<void> ChannelEventSet::SetupHandle(int fd, LocalHandle* handle,
     80                                           const char* error_name) {
     81   const int error = errno;
     82   handle->Reset(fd);
     83   if (!*handle) {
     84     ALOGE("ChannelEventSet::SetupHandle: Failed to setup %s handle: %s",
     85           error_name, strerror(error));
     86     return ErrorStatus{error};
     87   }
     88   return {};
     89 }
     90 
     91 Status<int> ChannelEventReceiver::GetPendingEvents() const {
     92   constexpr long kTimeoutMs = 0;
     93   epoll_event event;
     94   const int count =
     95       RETRY_EINTR(epoll_wait(epoll_fd_.Get(), &event, 1, kTimeoutMs));
     96 
     97   Status<int> status;
     98   if (count < 0) {
     99     status.SetError(errno);
    100     ALOGE("ChannelEventReceiver::GetPendingEvents: Failed to get events: %s",
    101           status.GetErrorMessage().c_str());
    102     return status;
    103   }
    104 
    105   const int mask_out = event.data.u32;
    106   ALOGD_IF(TRACE, "ChannelEventReceiver::GetPendingEvents: mask_out=%x",
    107            mask_out);
    108 
    109   status.SetValue(mask_out);
    110   return status;
    111 }
    112 
    113 }  // namespace uds
    114 }  // namespace pdx
    115 }  // namespace android
    116