1 /*
2  * Copyright (C) 2020 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 #include <log/log.h>
18 #include <sys/epoll.h>
19 #include "multihal_sensors.h"
20 
21 namespace goldfish {
22 
23 namespace {
epollCtlAdd(int epollFd,int fd)24 int epollCtlAdd(int epollFd, int fd) {
25     struct epoll_event ev;
26     ev.events  = EPOLLIN;
27     ev.data.fd = fd;
28     return TEMP_FAILURE_RETRY(epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &ev));
29 }
30 
qemuSensortThreadRcvCommand(const int fd)31 int qemuSensortThreadRcvCommand(const int fd) {
32     char buf;
33     if (TEMP_FAILURE_RETRY(read(fd, &buf, 1)) == 1) {
34         return buf;
35     } else {
36         return -1;
37     }
38 }
39 }  // namespace
40 
qemuSensorListenerThread()41 void MultihalSensors::qemuSensorListenerThread() {
42     const unique_fd epollFd(epoll_create1(0));
43     if (!epollFd.ok()) {
44         ALOGE("%s:%d: epoll_create1 failed", __func__, __LINE__);
45         ::abort();
46     }
47 
48     epollCtlAdd(epollFd.get(), m_qemuSensorsFd.get());
49     epollCtlAdd(epollFd.get(), m_sensorThreadFd.get());
50 
51     QemuSensorsProtocolState protocolState;
52 
53     while (true) {
54         struct epoll_event events[2];
55         const int kTimeoutMs = 60000;
56         const int n = TEMP_FAILURE_RETRY(epoll_wait(epollFd.get(),
57                                                     events, 2,
58                                                     kTimeoutMs));
59         if (n < 0) {
60             ALOGE("%s:%d: epoll_wait failed with '%s'",
61                   __func__, __LINE__, strerror(errno));
62             continue;
63         }
64 
65         for (int i = 0; i < n; ++i) {
66             const struct epoll_event* ev = &events[i];
67             const int fd = ev->data.fd;
68             const int ev_events = ev->events;
69 
70             if (fd == m_qemuSensorsFd.get()) {
71                 if (ev_events & (EPOLLERR | EPOLLHUP)) {
72                     ALOGE("%s:%d: epoll_wait: devFd has an error, ev_events=%x",
73                           __func__, __LINE__, ev_events);
74                     ::abort();
75                 } else if (ev_events & EPOLLIN) {
76                     parseQemuSensorEvent(m_qemuSensorsFd.get(), &protocolState);
77                 }
78             } else if (fd == m_sensorThreadFd.get()) {
79                 if (ev_events & (EPOLLERR | EPOLLHUP)) {
80                     ALOGE("%s:%d: epoll_wait: threadsFd has an error, ev_events=%x",
81                           __func__, __LINE__, ev_events);
82                     ::abort();
83                 } else if (ev_events & EPOLLIN) {
84                     const int cmd = qemuSensortThreadRcvCommand(fd);
85                     if (cmd == kCMD_QUIT) {
86                         return;
87                     } else {
88                         ALOGE("%s:%d: qemuSensortThreadRcvCommand returned unexpected command, cmd=%d",
89                               __func__, __LINE__, cmd);
90                         ::abort();
91                     }
92                 }
93             } else {
94                 ALOGE("%s:%d: epoll_wait() returned unexpected fd",
95                       __func__, __LINE__);
96             }
97         }
98     }
99 }
100 
101 }  // namespace goldfish
102