• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2018, The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <secure_input/evdev.h>
19 
20 #include <android-base/logging.h>
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <linux/input.h>
24 #include <poll.h>
25 #include <signal.h>
26 #include <sys/eventfd.h>
27 #include <sys/ioctl.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <teeui/msg_formatting.h>
31 #include <time.h>
32 
33 #include <algorithm>
34 #include <atomic>
35 #include <chrono>
36 #include <condition_variable>
37 #include <list>
38 #include <mutex>
39 #include <string>
40 #include <thread>
41 #include <tuple>
42 
43 namespace secure_input {
44 
timerOrder(const Timer & a,const Timer & b)45 bool EventLoop::timerOrder(const Timer& a, const Timer& b) {
46     return a.next > b.next;
47 }
48 
processNewTimers()49 void EventLoop::processNewTimers() {
50     for (auto& timer : newTimers_) {
51         timers_.push_back(std::move(timer));
52         std::push_heap(timers_.begin(), timers_.end(), timerOrder);
53     }
54     newTimers_.clear();
55 }
56 
runTimers()57 int EventLoop::runTimers() {
58     using namespace std::chrono_literals;
59     auto now = std::chrono::steady_clock::now();
60     while (!timers_.empty() && timers_[0].next <= now) {
61         std::pop_heap(timers_.begin(), timers_.end(), timerOrder);
62         auto& current = *timers_.rbegin();
63         current.handleTimer();
64         if (!current.oneShot) {
65             auto diff = now - current.next;
66             current.next += ((diff / current.duration) + 1) * current.duration;
67             std::push_heap(timers_.begin(), timers_.end(), timerOrder);
68         } else {
69             timers_.pop_back();
70         }
71     }
72     if (timers_.empty()) return -1;
73     auto& next = *timers_.begin();
74     auto diff = next.next - now;
75     if (diff > 60s) {
76         return 60000;
77     } else {
78         return std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();
79     }
80 }
81 
processNewReceivers()82 void EventLoop::processNewReceivers() {
83     for (auto& receiver : newReceivers_) {
84         receivers_.push_back(std::move(receiver));
85     }
86     newReceivers_.clear();
87 }
88 
addEventReceiver(NonCopyableFunction<void (short)> handler,int eventFd,short flags)89 void EventLoop::addEventReceiver(NonCopyableFunction<void(short)> handler, int eventFd,
90                                  short flags) {
91     std::unique_lock<std::mutex> lock(mutex_);
92     newReceivers_.emplace_back(eventFd, flags, std::move(handler));
93     if (eventFd_ != -1) {
94         eventfd_write(eventFd_, 1);
95     }
96 }
97 
addTimer(NonCopyableFunction<void ()> handler,std::chrono::steady_clock::duration duration,bool oneShot)98 void EventLoop::addTimer(NonCopyableFunction<void()> handler,
99                          std::chrono::steady_clock::duration duration, bool oneShot) {
100     std::unique_lock<std::mutex> lock(mutex_);
101     std::chrono::steady_clock::time_point next = std::chrono::steady_clock::now() + duration;
102     newTimers_.emplace_back(next, duration, std::move(handler), oneShot);
103     if (eventFd_ != -1) {
104         eventfd_write(eventFd_, 1);
105     }
106 }
107 
start()108 bool EventLoop::start() {
109     std::unique_lock<std::mutex> lock(mutex_);
110     if (state_ != ThreadState::JOINED) return false;
111     eventFd_ = eventfd(0, EFD_CLOEXEC);
112     if (eventFd_ == -1) return false;
113     state_ = ThreadState::STARTING;
114 
115     thread_ = std::thread([this]() {
116         std::unique_lock<std::mutex> lock(mutex_);
117         state_ = ThreadState::RUNNING;
118         lock.unlock();
119         condVar_.notify_all();
120         lock.lock();
121         while (state_ == ThreadState::RUNNING) {
122             processNewTimers();
123             processNewReceivers();  // must be called while locked
124             lock.unlock();
125             std::vector<pollfd> fds(receivers_.size() + 1);
126             fds[0] = {eventFd_, POLLIN, 0};
127             unsigned i = 1;
128             for (auto& receiver : receivers_) {
129                 fds[i] = {receiver.eventFd, receiver.eventFlags, 0};
130                 ++i;
131             }
132             auto rc = poll(fds.data(), fds.size(), runTimers());
133             if (state_ != ThreadState::RUNNING) {
134                 lock.lock();
135                 break;
136             }
137             if (rc > 0) {
138                 // don't handle eventFd_ explicitly
139                 i = 1;
140                 for (auto& receiver : receivers_) {
141                     if (fds[i].revents & receiver.eventFlags) {
142                         receiver.handleEvent(fds[i].revents);
143                     }
144                     ++i;
145                 }
146             } else if (rc < 0) {
147                 LOG(ERROR) << __func__ << " poll failed with errno: " << strerror(errno);
148             }
149             lock.lock();
150         }
151         state_ = ThreadState::TERMINATING;
152         lock.unlock();
153         condVar_.notify_all();
154     });
155     condVar_.wait(lock, [this]() -> bool { return state_ != ThreadState::STARTING; });
156     return state_ == ThreadState::RUNNING;
157 }
158 
stop()159 void EventLoop::stop() {
160     std::unique_lock<std::mutex> lock(mutex_);
161     if (state_ == ThreadState::JOINED) return;
162     if (state_ == ThreadState::RUNNING) {
163         state_ = ThreadState::STOP_REQUESTED;
164         eventfd_write(eventFd_, 1);
165     }
166     condVar_.wait(lock, [this]() -> bool { return state_ == ThreadState::TERMINATING; });
167     thread_.join();
168     close(eventFd_);
169     state_ = ThreadState::JOINED;
170     LOG(DEBUG) << "Done ending event polling";
171 }
172 
~EventLoop()173 EventLoop::~EventLoop() {
174     stop();
175 }
176 
EventDev()177 EventDev::EventDev() : fd_(-1), path_("") {}
EventDev(const std::string & path)178 EventDev::EventDev(const std::string& path) : fd_(-1), path_(path) {}
EventDev(EventDev && other)179 EventDev::EventDev(EventDev&& other) : fd_(other.fd_), path_(std::move(other.path_)) {
180     other.fd_ = -1;
181 }
operator =(EventDev && other)182 EventDev& EventDev::operator=(EventDev&& other) {
183     if (&other == this) return *this;
184     fd_ = other.fd_;
185     path_ = std::move(other.path_);
186     other.fd_ = -1;
187     return *this;
188 }
grab()189 bool EventDev::grab() {
190     if (fd_ >= 0) {
191         return true;
192     }
193     fd_ = TEMP_FAILURE_RETRY(open(path_.c_str(), O_RDWR | O_NONBLOCK));
194     if (fd_ < 0) {
195         LOG(ERROR) << "failed to open event device \"" << path_ << "\"";
196         return false;
197     }
198     int error = ioctl(fd_, EVIOCGRAB, 1);
199     if (error) {
200         LOG(ERROR) << "failed to grab event device " << path_ << " exclusively EVIOCGRAB returned "
201                    << error << " " << strerror(errno);
202         close(fd_);
203         fd_ = -1;
204         return false;
205     }
206     return true;
207 }
208 
ungrab()209 void EventDev::ungrab() {
210     if (fd_ < 0) {
211         return;
212     }
213     int error = ioctl(fd_, EVIOCGRAB, 0);
214     if (error) {
215         LOG(ERROR) << "failed to ungrab \"" << path_ << "\" EVIOCGRAB returned " << error;
216     }
217     close(fd_);
218     fd_ = -1;
219 }
220 
readEvent() const221 std::tuple<bool, input_event> EventDev::readEvent() const {
222     std::tuple<bool, input_event> result{false, {}};
223     ssize_t rc;
224     rc = TEMP_FAILURE_RETRY(read(fd_, &std::get<1>(result), sizeof std::get<1>(result)));
225     std::get<0>(result) = rc == sizeof std::get<1>(result);
226     return result;
227 }
228 
fd() const229 int EventDev::fd() const {
230     return fd_;
231 }
232 
grabAllEvDevsAndRegisterCallbacks(EventLoop * eventloop,std::function<void (short,const EventDev &)> handler)233 bool grabAllEvDevsAndRegisterCallbacks(EventLoop* eventloop,
234                                        std::function<void(short, const EventDev&)> handler) {
235     if (!eventloop) return false;
236     dirent** dirs = nullptr;
237     int n = scandir(
238         "/dev/input", &dirs,
239         [](const dirent* dir) -> int {
240             return (dir->d_type & DT_CHR) && !strncmp("event", dir->d_name, 5);
241         },
242         alphasort);
243     if (n < 0) {
244         LOG(WARNING) << "Unable to enumerate input devices " << strerror(errno);
245         return true;
246     }
247 
248     bool result = true;
249     for (int i = 0; i < n; ++i) {
250         EventDev evDev(std::string("/dev/input/") + dirs[i]->d_name);
251         result = result && evDev.grab();
252         int fd = evDev.fd();
253         eventloop->addEventReceiver(
254             [&, handler, evDev = std::move(evDev)](short flags) { handler(flags, evDev); }, fd,
255             POLLIN);
256         free(dirs[i]);
257     }
258     free(dirs);
259     // true if all devices where grabbed successfully
260     return result;
261 }
262 
263 }  // namespace secure_input
264