You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
4.7 KiB

/*
*
* Copyright 2018, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CONFIRMATIONUI_EVDEV_H_
#define CONFIRMATIONUI_EVDEV_H_
#include <linux/input.h>
#include <poll.h>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <list>
#include <mutex>
#include <string>
#include <thread>
#include <tuple>
#include <vector>
namespace secure_input {
template <typename Fn> class NonCopyableFunction;
template <typename Ret, typename... Args> class NonCopyableFunction<Ret(Args...)> {
class NonCopyableFunctionBase {
public:
NonCopyableFunctionBase() = default;
virtual ~NonCopyableFunctionBase() {}
virtual Ret operator()(Args... args) = 0;
NonCopyableFunctionBase(const NonCopyableFunctionBase&) = delete;
NonCopyableFunctionBase& operator=(const NonCopyableFunctionBase&) = delete;
};
template <typename Fn> class NonCopyableFunctionTypeEraser : public NonCopyableFunctionBase {
private:
Fn f_;
public:
NonCopyableFunctionTypeEraser() = default;
explicit NonCopyableFunctionTypeEraser(Fn f) : f_(std::move(f)) {}
Ret operator()(Args... args) override { return f_(std::move(args)...); }
};
private:
std::unique_ptr<NonCopyableFunctionBase> f_;
public:
NonCopyableFunction() = default;
template <typename F> NonCopyableFunction(F f) {
f_ = std::make_unique<NonCopyableFunctionTypeEraser<F>>(std::move(f));
}
NonCopyableFunction(NonCopyableFunction&& other) = default;
NonCopyableFunction& operator=(NonCopyableFunction&& other) = default;
NonCopyableFunction(const NonCopyableFunction& other) = delete;
NonCopyableFunction& operator=(const NonCopyableFunction& other) = delete;
Ret operator()(Args... args) {
if (f_) return (*f_)(std::move(args)...);
}
};
class EventLoop {
private:
enum class ThreadState : long {
STARTING,
RUNNING,
STOP_REQUESTED,
JOINED,
TERMINATING,
};
std::thread thread_;
int eventFd_ = -1;
volatile ThreadState state_ = ThreadState::JOINED;
std::mutex mutex_;
std::condition_variable condVar_;
struct EventReceiver {
EventReceiver(int fd, short flags, NonCopyableFunction<void(short)> handle)
: eventFd(fd), eventFlags(flags), handleEvent(std::move(handle)) {}
int eventFd;
short eventFlags;
NonCopyableFunction<void(short)> handleEvent;
};
std::vector<EventReceiver> receivers_;
std::list<EventReceiver> newReceivers_;
struct Timer {
Timer(std::chrono::steady_clock::time_point _next,
std::chrono::steady_clock::duration _duration, NonCopyableFunction<void()> handle,
bool _oneShot)
: next(_next), duration(_duration), handleTimer(std::move(handle)), oneShot(_oneShot) {}
std::chrono::steady_clock::time_point next;
std::chrono::steady_clock::duration duration;
NonCopyableFunction<void()> handleTimer;
bool oneShot;
};
std::vector<Timer> timers_;
std::list<Timer> newTimers_;
static bool timerOrder(const Timer& a, const Timer& b);
void processNewTimers();
int runTimers();
void processNewReceivers();
public:
~EventLoop();
void addEventReceiver(NonCopyableFunction<void(short)> handler, int eventFd,
short flags = POLLIN);
void addTimer(NonCopyableFunction<void()> handler, std::chrono::steady_clock::duration duration,
bool oneShot = true);
bool start();
void stop();
};
class EventDev {
private:
int fd_ = -1;
std::string path_;
public:
EventDev();
EventDev(const std::string& path);
EventDev(const EventDev&) = delete;
EventDev(EventDev&& other);
EventDev& operator=(EventDev&& other);
~EventDev() { ungrab(); }
bool grab();
void ungrab();
std::tuple<bool, input_event> readEvent() const;
int fd() const;
};
bool grabAllEvDevsAndRegisterCallbacks(EventLoop* eventloop,
std::function<void(short, const EventDev&)> handler);
} // namespace secure_input
#endif // CONFIRMATIONUI_EVDEV_H_