• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 namespace android {
28 
29 /**
30  * InputEvent represents an event from the kernel. The fields largely mirror
31  * those found in linux/input.h.
32  */
33 struct 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. */
42 struct 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  */
57 class InputDeviceNode {
58 public:
59     virtual const std::string& getPath() const = 0;
60 
61     virtual const std::string& getName() const = 0;
62     virtual const std::string& getLocation() const = 0;
63     virtual const std::string& getUniqueId() const = 0;
64 
65     virtual uint16_t getBusType() const = 0;
66     virtual uint16_t getVendorId() const = 0;
67     virtual uint16_t getProductId() const = 0;
68     virtual uint16_t getVersion() const = 0;
69 
70     virtual bool hasKey(int32_t key) const = 0;
71     virtual bool hasRelativeAxis(int axis) const = 0;
72     virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0;
73     virtual bool hasInputProperty(int property) const = 0;
74 
75     virtual int32_t getKeyState(int32_t key) const = 0;
76     virtual int32_t getSwitchState(int32_t sw) const = 0;
77     virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const = 0;
78 
79     virtual void vibrate(nsecs_t duration) = 0;
80     virtual void cancelVibrate(int32_t deviceId) = 0;
81 
82     virtual void disableDriverKeyRepeat() = 0;
83 
84 protected:
85     InputDeviceNode() = default;
86     virtual ~InputDeviceNode() = default;
87 };
88 
89 /** Callback interface for receiving input events, including device changes. */
90 class InputCallbackInterface {
91 public:
92     virtual void onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event,
93             nsecs_t event_time) = 0;
94     virtual void onDeviceAdded(std::shared_ptr<InputDeviceNode> node) = 0;
95     virtual void onDeviceRemoved(std::shared_ptr<InputDeviceNode> node) = 0;
96 
97 protected:
98     InputCallbackInterface() = default;
99     virtual ~InputCallbackInterface() = default;
100 };
101 
102 /**
103  * InputHubInterface is responsible for monitoring a set of device paths and
104  * executing callbacks when events occur. Before calling poll(), you should set
105  * the device and input callbacks, and register your device path(s).
106  */
107 class InputHubInterface {
108 public:
109     virtual status_t registerDevicePath(const std::string& path) = 0;
110     virtual status_t unregisterDevicePath(const std::string& path) = 0;
111 
112     virtual status_t poll() = 0;
113     virtual status_t wake() = 0;
114 
115     virtual void dump(String8& dump) = 0;
116 
117 protected:
118     InputHubInterface() = default;
119     virtual ~InputHubInterface() = default;
120 };
121 
122 /**
123  * An implementation of InputHubInterface that uses epoll to wait for events.
124  *
125  * This class is not threadsafe. Any functions called on the InputHub should be
126  * called on the same thread that is used to call poll(). The only exception is
127  * wake(), which may be used to return from poll() before an input or device
128  * event occurs.
129  */
130 class InputHub : public InputHubInterface {
131 public:
132     explicit InputHub(std::shared_ptr<InputCallbackInterface> cb);
133     virtual ~InputHub() override;
134 
135     virtual status_t registerDevicePath(const std::string& path) override;
136     virtual status_t unregisterDevicePath(const std::string& path) override;
137 
138     virtual status_t poll() override;
139     virtual status_t wake() override;
140 
141     virtual void dump(String8& dump) override;
142 
143 private:
144     status_t readNotify();
145     status_t scanDir(const std::string& path);
146     status_t openNode(const std::string& path, std::shared_ptr<InputDeviceNode>* outNode);
147     status_t closeNode(const std::shared_ptr<InputDeviceNode>& node);
148     status_t closeNodeByFd(int fd);
149     std::shared_ptr<InputDeviceNode> findNodeByPath(const std::string& path);
150 
151     enum class WakeMechanism {
152         /**
153          * The kernel supports the EPOLLWAKEUP flag for epoll_ctl.
154          *
155          * When using this mechanism, epoll_wait will internally acquire a wake
156          * lock whenever one of the FDs it is monitoring becomes ready. The wake
157          * lock is held automatically by the kernel until the next call to
158          * epoll_wait.
159          *
160          * This mechanism only exists in Linux kernel 3.5+.
161          */
162         EPOLL_WAKEUP,
163         /**
164          * The kernel evdev driver supports the EVIOCSSUSPENDBLOCK ioctl.
165          *
166          * When using this mechanism, the InputHub asks evdev to acquire and
167          * hold a wake lock whenever its buffer is non-empty. We must take care
168          * to acquire our own userspace wake lock before draining the buffer to
169          * prevent actually going back into suspend before we have fully
170          * processed all of the events.
171          *
172          * This mechanism only exists in older Android Linux kernels.
173          */
174         LEGACY_EVDEV_SUSPENDBLOCK_IOCTL,
175         /**
176          * The kernel doesn't seem to support any special wake mechanism.
177          *
178          * We explicitly acquire and release wake locks when processing input
179          * events.
180          */
181         LEGACY_EVDEV_EXPLICIT_WAKE_LOCKS,
182     };
183     WakeMechanism mWakeupMechanism = WakeMechanism::LEGACY_EVDEV_EXPLICIT_WAKE_LOCKS;
184     bool manageWakeLocks() const;
185     bool mNeedToCheckSuspendBlockIoctl = true;
186 
187     int mEpollFd;
188     int mINotifyFd;
189     int mWakeEventFd;
190     int mWakeReadPipeFd;
191     int mWakeWritePipeFd;
192 
193     // Callback for input events
194     std::shared_ptr<InputCallbackInterface> mInputCallback;
195 
196     // Map from watch descriptors to watched paths
197     std::unordered_map<int, std::string> mWatchedPaths;
198     // Map from file descriptors to InputDeviceNodes
199     std::unordered_map<int, std::shared_ptr<InputDeviceNode>> mDeviceNodes;
200 };
201 
202 }  // namespace android
203 
204 #endif  // ANDROID_INPUT_HUB_H_
205