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 
qemuSensorListenerThreadStart(MultihalSensors * that)41 void MultihalSensors::qemuSensorListenerThreadStart(MultihalSensors* that) {
42     that->qemuSensorListenerThread();
43 }
44 
qemuSensorListenerThread()45 void MultihalSensors::qemuSensorListenerThread() {
46     const unique_fd epollFd(epoll_create1(0));
47     if (!epollFd.ok()) {
48         ALOGE("%s:%d: epoll_create1 failed", __func__, __LINE__);
49         ::abort();
50     }
51 
52     epollCtlAdd(epollFd.get(), m_qemuSensorsFd.get());
53     epollCtlAdd(epollFd.get(), m_sensorThreadFd.get());
54 
55     QemuSensorsProtocolState protocolState;
56 
57     while (true) {
58         struct epoll_event events[2];
59         const int kTimeoutMs = 60000;
60         const int n = TEMP_FAILURE_RETRY(epoll_wait(epollFd.get(),
61                                                     events, 2,
62                                                     kTimeoutMs));
63         if (n < 0) {
64             ALOGE("%s:%d: epoll_wait failed with '%s'",
65                   __func__, __LINE__, strerror(errno));
66             continue;
67         }
68 
69         for (int i = 0; i < n; ++i) {
70             const struct epoll_event* ev = &events[i];
71             const int fd = ev->data.fd;
72             const int ev_events = ev->events;
73 
74             if (fd == m_qemuSensorsFd.get()) {
75                 if (ev_events & (EPOLLERR | EPOLLHUP)) {
76                     ALOGE("%s:%d: epoll_wait: devFd has an error, ev_events=%x",
77                           __func__, __LINE__, ev_events);
78                     ::abort();
79                 } else if (ev_events & EPOLLIN) {
80                     parseQemuSensorEvent(m_qemuSensorsFd.get(), &protocolState);
81                 }
82             } else if (fd == m_sensorThreadFd.get()) {
83                 if (ev_events & (EPOLLERR | EPOLLHUP)) {
84                     ALOGE("%s:%d: epoll_wait: threadsFd has an error, ev_events=%x",
85                           __func__, __LINE__, ev_events);
86                     ::abort();
87                 } else if (ev_events & EPOLLIN) {
88                     const int cmd = qemuSensortThreadRcvCommand(fd);
89                     if (cmd == kCMD_QUIT) {
90                         return;
91                     } else {
92                         ALOGE("%s:%d: qemuSensortThreadRcvCommand returned unexpected command, cmd=%d",
93                               __func__, __LINE__, cmd);
94                         ::abort();
95                     }
96                 }
97             } else {
98                 ALOGE("%s:%d: epoll_wait() returned unexpected fd",
99                       __func__, __LINE__);
100             }
101         }
102     }
103 }
104 
105 }  // namespace goldfish
106