blob: 827cbdefdbe9b8ecacca46adc1c3da5f51d4e852 [file] [log] [blame]
Tim Kilbourn73475a42015-02-13 10:35:20 -08001/*
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:
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070059 /** Get the Linux device path for the node. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080060 virtual const std::string& getPath() const = 0;
61
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070062 /** Get the name of the device returned by the driver. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080063 virtual const std::string& getName() const = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070064 /** Get the location of the device returned by the driver. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080065 virtual const std::string& getLocation() const = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070066 /** Get the unique id of the device returned by the driver. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080067 virtual const std::string& getUniqueId() const = 0;
68
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070069 /** Get the bus type of the device returned by the driver. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080070 virtual uint16_t getBusType() const = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070071 /** Get the vendor id of the device returned by the driver. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080072 virtual uint16_t getVendorId() const = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070073 /** Get the product id of the device returned by the driver. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080074 virtual uint16_t getProductId() const = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070075 /** Get the version of the device driver. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080076 virtual uint16_t getVersion() const = 0;
77
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070078 /** Returns true if the device has the key. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080079 virtual bool hasKey(int32_t key) const = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070080 /** 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. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080091 virtual bool hasInputProperty(int property) const = 0;
92
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070093 /** Returns the state of the key. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080094 virtual int32_t getKeyState(int32_t key) const = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070095 /** Returns the state of the switch. */
Tim Kilbourn73475a42015-02-13 10:35:20 -080096 virtual int32_t getSwitchState(int32_t sw) const = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070097 /** Returns information about the absolute axis. */
98 virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0;
99 /** Returns the value of the absolute axis. */
Tim Kilbourn73475a42015-02-13 10:35:20 -0800100 virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const = 0;
101
Tim Kilbourn3186e7b2015-04-16 15:32:08 -0700102 /** Vibrate the device for duration ns. */
Tim Kilbourn73475a42015-02-13 10:35:20 -0800103 virtual void vibrate(nsecs_t duration) = 0;
Tim Kilbourn3186e7b2015-04-16 15:32:08 -0700104 /** Stop vibration on the device. */
105 virtual void cancelVibrate() = 0;
Tim Kilbourn73475a42015-02-13 10:35:20 -0800106
Tim Kilbourn3186e7b2015-04-16 15:32:08 -0700107 /** Disable key repeat for the device in the driver. */
Tim Kilbourn73475a42015-02-13 10:35:20 -0800108 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:
Tim Kilbournc929d252015-04-29 13:50:17 -0700118 virtual void onInputEvent(const std::shared_ptr<InputDeviceNode>& node, InputEvent& event,
Tim Kilbourn73475a42015-02-13 10:35:20 -0800119 nsecs_t event_time) = 0;
Tim Kilbournc929d252015-04-29 13:50:17 -0700120 virtual void onDeviceAdded(const std::shared_ptr<InputDeviceNode>& node) = 0;
121 virtual void onDeviceRemoved(const std::shared_ptr<InputDeviceNode>& node) = 0;
Tim Kilbourn73475a42015-02-13 10:35:20 -0800122
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:
Tim Kilbournc929d252015-04-29 13:50:17 -0700158 explicit InputHub(const std::shared_ptr<InputCallbackInterface>& cb);
Tim Kilbourn73475a42015-02-13 10:35:20 -0800159 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);
Tim Kilbournc929d252015-04-29 13:50:17 -0700172 std::shared_ptr<InputDeviceNode> openNode(const std::string& path);
173 status_t closeNode(const InputDeviceNode* node);
Tim Kilbourn73475a42015-02-13 10:35:20 -0800174 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;
Tim Kilbourn73475a42015-02-13 10:35:20 -0800216
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_