1 #include "private/uds/channel_event_set.h"
2 
3 #include <log/log.h>
4 
5 #include <uds/ipc_helper.h>
6 
7 namespace android {
8 namespace pdx {
9 namespace uds {
10 
ChannelEventSet()11 ChannelEventSet::ChannelEventSet() {
12   const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
13   LocalHandle epoll_fd, event_fd;
14 
15   if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll") ||
16       !SetupHandle(eventfd(0, flags), &event_fd, "event")) {
17     return;
18   }
19 
20   epoll_event event;
21   event.events = 0;
22   event.data.u32 = 0;
23   if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_fd.Get(), &event) < 0) {
24     const int error = errno;
25     ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s",
26           strerror(error));
27     return;
28   }
29 
30   epoll_fd_ = std::move(epoll_fd);
31   event_fd_ = std::move(event_fd);
32 }
33 
AddDataFd(const LocalHandle & data_fd)34 Status<void> ChannelEventSet::AddDataFd(const LocalHandle& data_fd) {
35   epoll_event event;
36   event.events = EPOLLHUP | EPOLLRDHUP;
37   event.data.u32 = event.events;
38   if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) {
39     const int error = errno;
40     ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s",
41           strerror(error));
42     return ErrorStatus{error};
43   } else {
44     return {};
45   }
46 }
47 
ModifyEvents(int clear_mask,int set_mask)48 int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) {
49   ALOGD_IF(TRACE, "ChannelEventSet::ModifyEvents: clear_mask=%x set_mask=%x",
50            clear_mask, set_mask);
51   const int old_bits = event_bits_;
52   const int new_bits = (event_bits_ & ~clear_mask) | set_mask;
53   event_bits_ = new_bits;
54 
55   // If anything changed clear the event and update the event mask.
56   if (old_bits != new_bits) {
57     eventfd_t value;
58     eventfd_read(event_fd_.Get(), &value);
59 
60     epoll_event event;
61     event.events = POLLIN;
62     event.data.u32 = event_bits_;
63     if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, event_fd_.Get(), &event) <
64         0) {
65       const int error = errno;
66       ALOGE("ChannelEventSet::AddEventHandle: Failed to update event: %s",
67             strerror(error));
68       return -error;
69     }
70   }
71 
72   // If there are any bits set, re-trigger the eventfd.
73   if (new_bits)
74     eventfd_write(event_fd_.Get(), 1);
75 
76   return 0;
77 }
78 
SetupHandle(int fd,LocalHandle * handle,const char * error_name)79 Status<void> ChannelEventSet::SetupHandle(int fd, LocalHandle* handle,
80                                           const char* error_name) {
81   const int error = errno;
82   handle->Reset(fd);
83   if (!*handle) {
84     ALOGE("ChannelEventSet::SetupHandle: Failed to setup %s handle: %s",
85           error_name, strerror(error));
86     return ErrorStatus{error};
87   }
88   return {};
89 }
90 
GetPendingEvents() const91 Status<int> ChannelEventReceiver::GetPendingEvents() const {
92   constexpr long kTimeoutMs = 0;
93   epoll_event event;
94   const int count =
95       RETRY_EINTR(epoll_wait(epoll_fd_.Get(), &event, 1, kTimeoutMs));
96 
97   Status<int> status;
98   if (count < 0) {
99     status.SetError(errno);
100     ALOGE("ChannelEventReceiver::GetPendingEvents: Failed to get events: %s",
101           status.GetErrorMessage().c_str());
102     return status;
103   }
104 
105   const int mask_out = event.data.u32;
106   ALOGD_IF(TRACE, "ChannelEventReceiver::GetPendingEvents: mask_out=%x",
107            mask_out);
108 
109   status.SetValue(mask_out);
110   return status;
111 }
112 
113 }  // namespace uds
114 }  // namespace pdx
115 }  // namespace android
116