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
11namespace android {
12namespace pdx {
13namespace uds {
14
15namespace {
16
17template <typename FileHandleType>
18Status<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
32ChannelEventSet::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
45int 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
71ChannelEventReceiver::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
116Status<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
136Status<int> ChannelEventReceiver::GetPendingEvents() const {
137  constexpr long kTimeoutMs = 0;
138  return PollPendingEvents(kTimeoutMs);
139}
140
141std::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