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>
SetupHandle(int fd,FileHandleType * handle,const char * error_name)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 
ChannelEventSet()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 
ModifyEvents(int clear_mask,int set_mask)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 
ChannelEventReceiver(LocalHandle data_fd,LocalHandle pollin_event_fd,LocalHandle pollhup_event_fd)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 
PollPendingEvents(int timeout_ms) const116 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 
GetPendingEvents() const136 Status<int> ChannelEventReceiver::GetPendingEvents() const {
137   constexpr long kTimeoutMs = 0;
138   return PollPendingEvents(kTimeoutMs);
139 }
140 
GetEventSources() const141 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