#include "private/uds/channel_event_set.h" #include <log/log.h> #include <uds/ipc_helper.h> namespace android { namespace pdx { namespace uds { ChannelEventSet::ChannelEventSet() { const int flags = EFD_CLOEXEC | EFD_NONBLOCK; LocalHandle epoll_fd, event_fd; if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll") || !SetupHandle(eventfd(0, flags), &event_fd, "event")) { return; } epoll_event event; event.events = 0; event.data.u32 = 0; if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_fd.Get(), &event) < 0) { const int error = errno; ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s", strerror(error)); return; } epoll_fd_ = std::move(epoll_fd); event_fd_ = std::move(event_fd); } Status<void> ChannelEventSet::AddDataFd(const LocalHandle& data_fd) { epoll_event event; event.events = EPOLLHUP | EPOLLRDHUP; event.data.u32 = event.events; if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) { const int error = errno; ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s", strerror(error)); return ErrorStatus{error}; } else { return {}; } } int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) { ALOGD_IF(TRACE, "ChannelEventSet::ModifyEvents: clear_mask=%x set_mask=%x", clear_mask, set_mask); const int old_bits = event_bits_; const int new_bits = (event_bits_ & ~clear_mask) | set_mask; event_bits_ = new_bits; // If anything changed clear the event and update the event mask. if (old_bits != new_bits) { eventfd_t value; eventfd_read(event_fd_.Get(), &value); epoll_event event; event.events = POLLIN; event.data.u32 = event_bits_; if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, event_fd_.Get(), &event) < 0) { const int error = errno; ALOGE("ChannelEventSet::AddEventHandle: Failed to update event: %s", strerror(error)); return -error; } } // If there are any bits set, re-trigger the eventfd. if (new_bits) eventfd_write(event_fd_.Get(), 1); return 0; } Status<void> ChannelEventSet::SetupHandle(int fd, LocalHandle* handle, const char* error_name) { const int error = errno; handle->Reset(fd); if (!*handle) { ALOGE("ChannelEventSet::SetupHandle: Failed to setup %s handle: %s", error_name, strerror(error)); return ErrorStatus{error}; } return {}; } Status<int> ChannelEventReceiver::GetPendingEvents() const { constexpr long kTimeoutMs = 0; epoll_event event; const int count = RETRY_EINTR(epoll_wait(epoll_fd_.Get(), &event, 1, kTimeoutMs)); Status<int> status; if (count < 0) { status.SetError(errno); ALOGE("ChannelEventReceiver::GetPendingEvents: Failed to get events: %s", status.GetErrorMessage().c_str()); return status; } const int mask_out = event.data.u32; ALOGD_IF(TRACE, "ChannelEventReceiver::GetPendingEvents: mask_out=%x", mask_out); status.SetValue(mask_out); return status; } } // namespace uds } // namespace pdx } // namespace android