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