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