Home | History | Annotate | Download | only in libpdx_uds
      1 #include "private/uds/channel_event_set.h"
      2 
      3 #include <errno.h>
      4 #include <log/log.h>
      5 #include <poll.h>
      6 #include <sys/epoll.h>
      7 #include <sys/eventfd.h>
      8 
      9 #include <uds/ipc_helper.h>
     10 
     11 namespace android {
     12 namespace pdx {
     13 namespace uds {
     14 
     15 namespace {
     16 
     17 template <typename FileHandleType>
     18 Status<void> SetupHandle(int fd, FileHandleType* handle,
     19                          const char* error_name) {
     20   const int error = errno;
     21   handle->Reset(fd);
     22   if (!*handle) {
     23     ALOGE("SetupHandle: Failed to setup %s handle: %s", error_name,
     24           strerror(error));
     25     return ErrorStatus{error};
     26   }
     27   return {};
     28 }
     29 
     30 }  // anonymous namespace
     31 
     32 ChannelEventSet::ChannelEventSet() {
     33   const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
     34   LocalHandle pollin_event_fd, pollhup_event_fd;
     35 
     36   if (!SetupHandle(eventfd(0, flags), &pollin_event_fd, "pollin_event") ||
     37       !SetupHandle(eventfd(0, flags), &pollhup_event_fd, "pollhup_event")) {
     38     return;
     39   }
     40 
     41   pollin_event_fd_ = std::move(pollin_event_fd);
     42   pollhup_event_fd_ = std::move(pollhup_event_fd);
     43 }
     44 
     45 int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) {
     46   ALOGD_IF(TRACE, "ChannelEventSet::ModifyEvents: clear_mask=%x set_mask=%x",
     47            clear_mask, set_mask);
     48   const int old_bits = event_bits_;
     49   const int new_bits = (event_bits_ & ~clear_mask) | set_mask;
     50   event_bits_ = new_bits;
     51   eventfd_t value;
     52 
     53   // Calculate which bits changed and how. Bits that haven't changed since last
     54   // modification will not change the state of an eventfd.
     55   const int set_bits = new_bits & ~old_bits;
     56   const int clear_bits = ~new_bits & old_bits;
     57 
     58   if (set_bits & EPOLLIN)
     59     eventfd_write(pollin_event_fd_.Get(), 1);
     60   else if (clear_bits & EPOLLIN)
     61     eventfd_read(pollin_event_fd_.Get(), &value);
     62 
     63   if (set_bits & EPOLLHUP)
     64     eventfd_write(pollhup_event_fd_.Get(), 1);
     65   else if (clear_bits & EPOLLHUP)
     66     eventfd_read(pollhup_event_fd_.Get(), &value);
     67 
     68   return 0;
     69 }
     70 
     71 ChannelEventReceiver::ChannelEventReceiver(LocalHandle data_fd,
     72                                            LocalHandle pollin_event_fd,
     73                                            LocalHandle pollhup_event_fd) {
     74   LocalHandle epoll_fd;
     75   if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll")) {
     76     return;
     77   }
     78 
     79   epoll_event event;
     80   event.events = EPOLLHUP | EPOLLRDHUP;
     81   event.data.u32 = 0;
     82   if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) {
     83     const int error = errno;
     84     ALOGE("ChannelEventSet::ChannelEventSet: Failed to add data_fd: %s",
     85           strerror(error));
     86     return;
     87   }
     88 
     89   event.events = EPOLLIN;
     90   event.data.u32 = 0;
     91   if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollin_event_fd.Get(), &event) <
     92       0) {
     93     const int error = errno;
     94     ALOGE("ChannelEventSet::ChannelEventSet: Failed to add pollin_event_fd: %s",
     95           strerror(error));
     96     return;
     97   }
     98 
     99   event.events = EPOLLIN;
    100   event.data.u32 = 0;
    101   if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollhup_event_fd.Get(), &event) <
    102       0) {
    103     const int error = errno;
    104     ALOGE(
    105         "ChannelEventSet::ChannelEventSet: Failed to add pollhup_event_fd: %s",
    106         strerror(error));
    107     return;
    108   }
    109 
    110   pollin_event_fd_ = std::move(pollin_event_fd);
    111   pollhup_event_fd_ = std::move(pollhup_event_fd);
    112   data_fd_ = std::move(data_fd);
    113   epoll_fd_ = std::move(epoll_fd);
    114 }
    115 
    116 Status<int> ChannelEventReceiver::PollPendingEvents(int timeout_ms) const {
    117   std::array<pollfd, 3> pfds = {{{pollin_event_fd_.Get(), POLLIN, 0},
    118                                  {pollhup_event_fd_.Get(), POLLIN, 0},
    119                                  {data_fd_.Get(), POLLHUP | POLLRDHUP, 0}}};
    120   if (RETRY_EINTR(poll(pfds.data(), pfds.size(), timeout_ms)) < 0) {
    121     const int error = errno;
    122     ALOGE(
    123         "ChannelEventReceiver::PollPendingEvents: Failed to poll for events: "
    124         "%s",
    125         strerror(error));
    126     return ErrorStatus{error};
    127   }
    128 
    129   const int event_mask =
    130       ((pfds[0].revents & POLLIN) ? EPOLLIN : 0) |
    131       ((pfds[1].revents & POLLIN) ? EPOLLHUP : 0) |
    132       ((pfds[2].revents & (POLLHUP | POLLRDHUP)) ? EPOLLHUP : 0);
    133   return {event_mask};
    134 }
    135 
    136 Status<int> ChannelEventReceiver::GetPendingEvents() const {
    137   constexpr long kTimeoutMs = 0;
    138   return PollPendingEvents(kTimeoutMs);
    139 }
    140 
    141 std::vector<ClientChannel::EventSource> ChannelEventReceiver::GetEventSources()
    142     const {
    143   return {{data_fd_.Get(), EPOLLHUP | EPOLLRDHUP},
    144           {pollin_event_fd_.Get(), EPOLLIN},
    145           {pollhup_event_fd_.Get(), POLLIN}};
    146 }
    147 
    148 }  // namespace uds
    149 }  // namespace pdx
    150 }  // namespace android
    151