#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