Home | History | Annotate | Download | only in evdev
      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