• 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     /** 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 
110 protected:
111     InputDeviceNode() = default;
112     virtual ~InputDeviceNode() = default;
113 };
114 
115 /** Callback interface for receiving input events, including device changes. */
116 class InputCallbackInterface {
117 public:
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 
123 protected:
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  */
133 class InputHubInterface {
134 public:
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 
143 protected:
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  */
156 class InputHub : public InputHubInterface {
157 public:
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 
169 private:
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 
217     // Callback for input events
218     std::shared_ptr<InputCallbackInterface> mInputCallback;
219 
220     // Map from watch descriptors to watched paths
221     std::unordered_map<int, std::string> mWatchedPaths;
222     // Map from file descriptors to InputDeviceNodes
223     std::unordered_map<int, std::shared_ptr<InputDeviceNode>> mDeviceNodes;
224 };
225 
226 }  // namespace android
227 
228 #endif  // ANDROID_INPUT_HUB_H_
229