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