1 /**
2  * Copyright (c) 2021, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "libsysfsmonitor"
18 #define DEBUG false
19 
20 #include "SysfsMonitor.h"
21 
22 #include <android-base/stringprintf.h>
23 #include <log/log.h>
24 
25 #include <sys/epoll.h>
26 
27 namespace {
28 
29 using ::android::base::Error;
30 using ::android::base::Result;
31 using ::android::base::StringPrintf;
32 
33 // The maximum number of sysfs files to monitor.
34 constexpr int32_t EPOLL_MAX_EVENTS = 10;
35 
36 }  // namespace
37 
38 namespace android {
39 namespace automotive {
40 
init(CallbackFunc callback)41 Result<void> SysfsMonitor::init(CallbackFunc callback) {
42     if (mEpollFd >= 0) {
43         return Error() << "Epoll instance was already created";
44     }
45     if (mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC)); mEpollFd < 0) {
46         return Error() << "Cannot create epoll instance: errno = " << errno;
47     }
48     mCallback = callback;
49     return {};
50 }
51 
release()52 Result<void> SysfsMonitor::release() {
53     if (mEpollFd < 0) {
54         return Error() << "Epoll instance wasn't created";
55     }
56     for (const int32_t fd : mMonitoringFds) {
57         if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, /*event=*/nullptr)) {
58             ALOGW("Failed to deregister fd(%d) from epoll instance: errno = %d", fd, errno);
59         }
60     }
61     mMonitoringFds.clear();
62     mEpollFd.reset();
63     mCallback = nullptr;
64     return {};
65 }
66 
registerFd(int32_t fd)67 Result<void> SysfsMonitor::registerFd(int32_t fd) {
68     if (fd < 0) {
69         return Error() << StringPrintf("fd(%d) is invalid", fd);
70     }
71     if (mMonitoringFds.count(fd) > 0) {
72         return Error() << StringPrintf("fd(%d) is already being monitored", fd);
73     }
74     if (mMonitoringFds.size() == EPOLL_MAX_EVENTS) {
75         return Error() << "Cannot monitor more than " << EPOLL_MAX_EVENTS << " sysfs files";
76     }
77     struct epoll_event eventItem = {};
78     eventItem.events = EPOLLIN | EPOLLPRI | EPOLLET;
79     eventItem.data.fd = fd;
80     if (int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem); result != 0) {
81         return Error() << StringPrintf("Failed to add fd(%d) to epoll instance: errno = %d", fd,
82                                        errno);
83     }
84     mMonitoringFds.insert(fd);
85     return {};
86 }
87 
unregisterFd(int32_t fd)88 Result<void> SysfsMonitor::unregisterFd(int32_t fd) {
89     if (fd < 0) {
90         return Error() << StringPrintf("fd(%d) is invalid", fd);
91     }
92     if (mMonitoringFds.count(fd) == 0) {
93         return Error() << StringPrintf("fd(%d) is not being monitored", fd);
94     }
95     // Even when epoll_ctl() fails, we proceed to handle the request.
96     if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, /*event=*/nullptr)) {
97         ALOGW("Failed to deregister fd(%d) from epoll instance: errno = %d", fd, errno);
98     }
99     mMonitoringFds.erase(fd);
100     return {};
101 }
102 
observe()103 Result<void> SysfsMonitor::observe() {
104     if (mEpollFd < 0) {
105         return Error() << "Epoll instance is not initialized";
106     }
107 
108     struct epoll_event events[EPOLL_MAX_EVENTS];
109     while (true) {
110         int pollResult = epoll_wait(mEpollFd, events, EPOLL_MAX_EVENTS, /*timeout=*/-1);
111         if (pollResult < 0) {
112             ALOGW("Polling sysfs failed, but continue polling: errno = %d", errno);
113             continue;
114         }
115         std::vector<int32_t> fds;
116         for (int i = 0; i < pollResult; i++) {
117             int fd = events[i].data.fd;
118             if (mMonitoringFds.count(fd) == 0) {
119                 continue;
120             }
121             if (events[i].events & EPOLLIN) {
122                 fds.push_back(fd);
123             } else if (events[i].events & EPOLLERR) {
124                 ALOGW("An error occurred when polling fd(%d)", fd);
125             }
126         }
127         if (mCallback && fds.size() > 0) {
128             mCallback(fds);
129         }
130     }
131     return {};
132 }
133 
134 }  // namespace automotive
135 }  // namespace android
136