1/*
2 * Copyright (C) 2015 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#ifndef ANDROID_INPUT_HUB_H_
18#define ANDROID_INPUT_HUB_H_
19
20#include <memory>
21#include <string>
22#include <unordered_map>
23
24#include <utils/String8.h>
25#include <utils/Timers.h>
26
27namespace android {
28
29/**
30 * InputEvent represents an event from the kernel. The fields largely mirror
31 * those found in linux/input.h.
32 */
33struct InputEvent {
34    nsecs_t when;
35
36    int32_t type;
37    int32_t code;
38    int32_t value;
39};
40
41/** Describes an absolute axis. */
42struct AbsoluteAxisInfo {
43    int32_t minValue = 0;   // minimum value
44    int32_t maxValue = 0;   // maximum value
45    int32_t flat = 0;       // center flat position, e.g. flat == 8 means center is between -8 and 8
46    int32_t fuzz = 0;       // error tolerance, e.g. fuzz == 4 means value is +/- 4 due to noise
47    int32_t resolution = 0; // resolution in units per mm or radians per mm
48};
49
50/**
51 * An InputDeviceNode represents a device node in the Linux system. It can be
52 * used to interact with the device, setting and getting property values.
53 *
54 * An InputDeviceNode should only be used on the same thread that is polling for
55 * input events.
56 */
57class InputDeviceNode {
58public:
59    /** Get the Linux device path for the node. */
60    virtual const std::string& getPath() const = 0;
61
62    /** Get the name of the device returned by the driver. */
63    virtual const std::string& getName() const = 0;
64    /** Get the location of the device returned by the driver. */
65    virtual const std::string& getLocation() const = 0;
66    /** Get the unique id of the device returned by the driver. */
67    virtual const std::string& getUniqueId() const = 0;
68
69    /** Get the bus type of the device returned by the driver. */
70    virtual uint16_t getBusType() const = 0;
71    /** Get the vendor id of the device returned by the driver. */
72    virtual uint16_t getVendorId() const = 0;
73    /** Get the product id of the device returned by the driver. */
74    virtual uint16_t getProductId() const = 0;
75    /** Get the version of the device driver. */
76    virtual uint16_t getVersion() const = 0;
77
78    /** Returns true if the device has the key. */
79    virtual bool hasKey(int32_t key) const = 0;
80    /** Returns true if the device has a key in the range [startKey, endKey). */
81    virtual bool hasKeyInRange(int32_t startKey, int32_t endKey) const = 0;
82    /** Returns true if the device has the relative axis. */
83    virtual bool hasRelativeAxis(int32_t axis) const = 0;
84    /** Returns true if the device has the absolute axis. */
85    virtual bool hasAbsoluteAxis(int32_t axis) const = 0;
86    /** Returns true if the device has the switch. */
87    virtual bool hasSwitch(int32_t sw) const = 0;
88    /** Returns true if the device has the force feedback method. */
89    virtual bool hasForceFeedback(int32_t ff) const = 0;
90    /** Returns true if the device has the input property. */
91    virtual bool hasInputProperty(int property) const = 0;
92
93    /** Returns the state of the key. */
94    virtual int32_t getKeyState(int32_t key) const = 0;
95    /** Returns the state of the switch. */
96    virtual int32_t getSwitchState(int32_t sw) const = 0;
97    /** Returns information about the absolute axis. */
98    virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0;
99    /** Returns the value of the absolute axis. */
100    virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const = 0;
101
102    /** Vibrate the device for duration ns. */
103    virtual void vibrate(nsecs_t duration) = 0;
104    /** Stop vibration on the device. */
105    virtual void cancelVibrate() = 0;
106
107    /** Disable key repeat for the device in the driver. */
108    virtual void disableDriverKeyRepeat() = 0;
109
110protected:
111    InputDeviceNode() = default;
112    virtual ~InputDeviceNode() = default;
113};
114
115/** Callback interface for receiving input events, including device changes. */
116class InputCallbackInterface {
117public:
118    virtual void onInputEvent(const std::shared_ptr<InputDeviceNode>& node, InputEvent& event,
119            nsecs_t event_time) = 0;
120    virtual void onDeviceAdded(const std::shared_ptr<InputDeviceNode>& node) = 0;
121    virtual void onDeviceRemoved(const std::shared_ptr<InputDeviceNode>& node) = 0;
122
123protected:
124    InputCallbackInterface() = default;
125    virtual ~InputCallbackInterface() = default;
126};
127
128/**
129 * InputHubInterface is responsible for monitoring a set of device paths and
130 * executing callbacks when events occur. Before calling poll(), you should set
131 * the device and input callbacks, and register your device path(s).
132 */
133class InputHubInterface {
134public:
135    virtual status_t registerDevicePath(const std::string& path) = 0;
136    virtual status_t unregisterDevicePath(const std::string& path) = 0;
137
138    virtual status_t poll() = 0;
139    virtual status_t wake() = 0;
140
141    virtual void dump(String8& dump) = 0;
142
143protected:
144    InputHubInterface() = default;
145    virtual ~InputHubInterface() = default;
146};
147
148/**
149 * An implementation of InputHubInterface that uses epoll to wait for events.
150 *
151 * This class is not threadsafe. Any functions called on the InputHub should be
152 * called on the same thread that is used to call poll(). The only exception is
153 * wake(), which may be used to return from poll() before an input or device
154 * event occurs.
155 */
156class InputHub : public InputHubInterface {
157public:
158    explicit InputHub(const std::shared_ptr<InputCallbackInterface>& cb);
159    virtual ~InputHub() override;
160
161    virtual status_t registerDevicePath(const std::string& path) override;
162    virtual status_t unregisterDevicePath(const std::string& path) override;
163
164    virtual status_t poll() override;
165    virtual status_t wake() override;
166
167    virtual void dump(String8& dump) override;
168
169private:
170    status_t readNotify();
171    status_t scanDir(const std::string& path);
172    std::shared_ptr<InputDeviceNode> openNode(const std::string& path);
173    status_t closeNode(const InputDeviceNode* node);
174    status_t closeNodeByFd(int fd);
175    std::shared_ptr<InputDeviceNode> findNodeByPath(const std::string& path);
176
177    enum class WakeMechanism {
178        /**
179         * The kernel supports the EPOLLWAKEUP flag for epoll_ctl.
180         *
181         * When using this mechanism, epoll_wait will internally acquire a wake
182         * lock whenever one of the FDs it is monitoring becomes ready. The wake
183         * lock is held automatically by the kernel until the next call to
184         * epoll_wait.
185         *
186         * This mechanism only exists in Linux kernel 3.5+.
187         */
188        EPOLL_WAKEUP,
189        /**
190         * The kernel evdev driver supports the EVIOCSSUSPENDBLOCK ioctl.
191         *
192         * When using this mechanism, the InputHub asks evdev to acquire and
193         * hold a wake lock whenever its buffer is non-empty. We must take care
194         * to acquire our own userspace wake lock before draining the buffer to
195         * prevent actually going back into suspend before we have fully
196         * processed all of the events.
197         *
198         * This mechanism only exists in older Android Linux kernels.
199         */
200        LEGACY_EVDEV_SUSPENDBLOCK_IOCTL,
201        /**
202         * The kernel doesn't seem to support any special wake mechanism.
203         *
204         * We explicitly acquire and release wake locks when processing input
205         * events.
206         */
207        LEGACY_EVDEV_EXPLICIT_WAKE_LOCKS,
208    };
209    WakeMechanism mWakeupMechanism = WakeMechanism::LEGACY_EVDEV_EXPLICIT_WAKE_LOCKS;
210    bool manageWakeLocks() const;
211    bool mNeedToCheckSuspendBlockIoctl = true;
212
213    int mEpollFd;
214    int mINotifyFd;
215    int mWakeEventFd;
216    int mWakeReadPipeFd;
217    int mWakeWritePipeFd;
218
219    // Callback for input events
220    std::shared_ptr<InputCallbackInterface> mInputCallback;
221
222    // Map from watch descriptors to watched paths
223    std::unordered_map<int, std::string> mWatchedPaths;
224    // Map from file descriptors to InputDeviceNodes
225    std::unordered_map<int, std::shared_ptr<InputDeviceNode>> mDeviceNodes;
226};
227
228}  // namespace android
229
230#endif  // ANDROID_INPUT_HUB_H_
231