xref: /aosp_15_r20/hardware/libhardware/modules/input/evdev/InputHub.cpp (revision e01b6f769022e40d0923dee176e8dc7cd1d52984)
1*e01b6f76SAndroid Build Coastguard Worker /*
2*e01b6f76SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*e01b6f76SAndroid Build Coastguard Worker  *
4*e01b6f76SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e01b6f76SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e01b6f76SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e01b6f76SAndroid Build Coastguard Worker  *
8*e01b6f76SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e01b6f76SAndroid Build Coastguard Worker  *
10*e01b6f76SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e01b6f76SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e01b6f76SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e01b6f76SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e01b6f76SAndroid Build Coastguard Worker  * limitations under the License.
15*e01b6f76SAndroid Build Coastguard Worker  */
16*e01b6f76SAndroid Build Coastguard Worker 
17*e01b6f76SAndroid Build Coastguard Worker #define LOG_TAG "InputHub"
18*e01b6f76SAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*e01b6f76SAndroid Build Coastguard Worker 
20*e01b6f76SAndroid Build Coastguard Worker #include "InputHub.h"
21*e01b6f76SAndroid Build Coastguard Worker 
22*e01b6f76SAndroid Build Coastguard Worker #include <dirent.h>
23*e01b6f76SAndroid Build Coastguard Worker #include <errno.h>
24*e01b6f76SAndroid Build Coastguard Worker #include <fcntl.h>
25*e01b6f76SAndroid Build Coastguard Worker #include <string.h>
26*e01b6f76SAndroid Build Coastguard Worker #include <sys/capability.h>
27*e01b6f76SAndroid Build Coastguard Worker #include <sys/epoll.h>
28*e01b6f76SAndroid Build Coastguard Worker #include <sys/eventfd.h>
29*e01b6f76SAndroid Build Coastguard Worker #include <sys/inotify.h>
30*e01b6f76SAndroid Build Coastguard Worker #include <sys/ioctl.h>
31*e01b6f76SAndroid Build Coastguard Worker #include <sys/stat.h>
32*e01b6f76SAndroid Build Coastguard Worker #include <sys/types.h>
33*e01b6f76SAndroid Build Coastguard Worker #include <sys/utsname.h>
34*e01b6f76SAndroid Build Coastguard Worker #include <unistd.h>
35*e01b6f76SAndroid Build Coastguard Worker 
36*e01b6f76SAndroid Build Coastguard Worker #include <vector>
37*e01b6f76SAndroid Build Coastguard Worker 
38*e01b6f76SAndroid Build Coastguard Worker #include <android/input.h>
39*e01b6f76SAndroid Build Coastguard Worker #include <hardware_legacy/power.h>
40*e01b6f76SAndroid Build Coastguard Worker #include <linux/input.h>
41*e01b6f76SAndroid Build Coastguard Worker 
42*e01b6f76SAndroid Build Coastguard Worker #include <utils/Log.h>
43*e01b6f76SAndroid Build Coastguard Worker 
44*e01b6f76SAndroid Build Coastguard Worker #include "BitUtils.h"
45*e01b6f76SAndroid Build Coastguard Worker 
46*e01b6f76SAndroid Build Coastguard Worker namespace android {
47*e01b6f76SAndroid Build Coastguard Worker 
48*e01b6f76SAndroid Build Coastguard Worker static const char WAKE_LOCK_ID[] = "KeyEvents";
49*e01b6f76SAndroid Build Coastguard Worker static const int NO_TIMEOUT = -1;
50*e01b6f76SAndroid Build Coastguard Worker static const int EPOLL_MAX_EVENTS = 16;
51*e01b6f76SAndroid Build Coastguard Worker static const int INPUT_MAX_EVENTS = 128;
52*e01b6f76SAndroid Build Coastguard Worker 
testBit(int bit,const uint8_t arr[])53*e01b6f76SAndroid Build Coastguard Worker static constexpr bool testBit(int bit, const uint8_t arr[]) {
54*e01b6f76SAndroid Build Coastguard Worker     return arr[bit / 8] & (1 << (bit % 8));
55*e01b6f76SAndroid Build Coastguard Worker }
56*e01b6f76SAndroid Build Coastguard Worker 
sizeofBitArray(size_t bits)57*e01b6f76SAndroid Build Coastguard Worker static constexpr size_t sizeofBitArray(size_t bits) {
58*e01b6f76SAndroid Build Coastguard Worker     return (bits + 7) / 8;
59*e01b6f76SAndroid Build Coastguard Worker }
60*e01b6f76SAndroid Build Coastguard Worker 
getLinuxRelease(int * major,int * minor)61*e01b6f76SAndroid Build Coastguard Worker static void getLinuxRelease(int* major, int* minor) {
62*e01b6f76SAndroid Build Coastguard Worker     struct utsname info;
63*e01b6f76SAndroid Build Coastguard Worker     if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) {
64*e01b6f76SAndroid Build Coastguard Worker         *major = 0, *minor = 0;
65*e01b6f76SAndroid Build Coastguard Worker         ALOGE("Could not get linux version: %s", strerror(errno));
66*e01b6f76SAndroid Build Coastguard Worker     }
67*e01b6f76SAndroid Build Coastguard Worker }
68*e01b6f76SAndroid Build Coastguard Worker 
69*e01b6f76SAndroid Build Coastguard Worker class EvdevDeviceNode : public InputDeviceNode {
70*e01b6f76SAndroid Build Coastguard Worker public:
71*e01b6f76SAndroid Build Coastguard Worker     static EvdevDeviceNode* openDeviceNode(const std::string& path);
72*e01b6f76SAndroid Build Coastguard Worker 
~EvdevDeviceNode()73*e01b6f76SAndroid Build Coastguard Worker     virtual ~EvdevDeviceNode() {
74*e01b6f76SAndroid Build Coastguard Worker         ALOGV("closing %s (fd=%d)", mPath.c_str(), mFd);
75*e01b6f76SAndroid Build Coastguard Worker         if (mFd >= 0) {
76*e01b6f76SAndroid Build Coastguard Worker             ::close(mFd);
77*e01b6f76SAndroid Build Coastguard Worker         }
78*e01b6f76SAndroid Build Coastguard Worker     }
79*e01b6f76SAndroid Build Coastguard Worker 
getFd() const80*e01b6f76SAndroid Build Coastguard Worker     virtual int getFd() const { return mFd; }
getPath() const81*e01b6f76SAndroid Build Coastguard Worker     virtual const std::string& getPath() const override { return mPath; }
getName() const82*e01b6f76SAndroid Build Coastguard Worker     virtual const std::string& getName() const override { return mName; }
getLocation() const83*e01b6f76SAndroid Build Coastguard Worker     virtual const std::string& getLocation() const override { return mLocation; }
getUniqueId() const84*e01b6f76SAndroid Build Coastguard Worker     virtual const std::string& getUniqueId() const override { return mUniqueId; }
85*e01b6f76SAndroid Build Coastguard Worker 
getBusType() const86*e01b6f76SAndroid Build Coastguard Worker     virtual uint16_t getBusType() const override { return mBusType; }
getVendorId() const87*e01b6f76SAndroid Build Coastguard Worker     virtual uint16_t getVendorId() const override { return mVendorId; }
getProductId() const88*e01b6f76SAndroid Build Coastguard Worker     virtual uint16_t getProductId() const override { return mProductId; }
getVersion() const89*e01b6f76SAndroid Build Coastguard Worker     virtual uint16_t getVersion() const override { return mVersion; }
90*e01b6f76SAndroid Build Coastguard Worker 
91*e01b6f76SAndroid Build Coastguard Worker     virtual bool hasKey(int32_t key) const override;
92*e01b6f76SAndroid Build Coastguard Worker     virtual bool hasKeyInRange(int32_t start, int32_t end) const override;
93*e01b6f76SAndroid Build Coastguard Worker     virtual bool hasRelativeAxis(int32_t axis) const override;
94*e01b6f76SAndroid Build Coastguard Worker     virtual bool hasAbsoluteAxis(int32_t axis) const override;
95*e01b6f76SAndroid Build Coastguard Worker     virtual bool hasSwitch(int32_t sw) const override;
96*e01b6f76SAndroid Build Coastguard Worker     virtual bool hasForceFeedback(int32_t ff) const override;
97*e01b6f76SAndroid Build Coastguard Worker     virtual bool hasInputProperty(int property) const override;
98*e01b6f76SAndroid Build Coastguard Worker 
99*e01b6f76SAndroid Build Coastguard Worker     virtual int32_t getKeyState(int32_t key) const override;
100*e01b6f76SAndroid Build Coastguard Worker     virtual int32_t getSwitchState(int32_t sw) const override;
101*e01b6f76SAndroid Build Coastguard Worker     virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const override;
102*e01b6f76SAndroid Build Coastguard Worker     virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const override;
103*e01b6f76SAndroid Build Coastguard Worker 
104*e01b6f76SAndroid Build Coastguard Worker     virtual void vibrate(nsecs_t duration) override;
105*e01b6f76SAndroid Build Coastguard Worker     virtual void cancelVibrate() override;
106*e01b6f76SAndroid Build Coastguard Worker 
107*e01b6f76SAndroid Build Coastguard Worker     virtual void disableDriverKeyRepeat() override;
108*e01b6f76SAndroid Build Coastguard Worker 
109*e01b6f76SAndroid Build Coastguard Worker private:
EvdevDeviceNode(const std::string & path,int fd)110*e01b6f76SAndroid Build Coastguard Worker     EvdevDeviceNode(const std::string& path, int fd) :
111*e01b6f76SAndroid Build Coastguard Worker         mFd(fd), mPath(path) {}
112*e01b6f76SAndroid Build Coastguard Worker 
113*e01b6f76SAndroid Build Coastguard Worker     status_t queryProperties();
114*e01b6f76SAndroid Build Coastguard Worker     void queryAxisInfo();
115*e01b6f76SAndroid Build Coastguard Worker 
116*e01b6f76SAndroid Build Coastguard Worker     int mFd;
117*e01b6f76SAndroid Build Coastguard Worker     std::string mPath;
118*e01b6f76SAndroid Build Coastguard Worker 
119*e01b6f76SAndroid Build Coastguard Worker     std::string mName;
120*e01b6f76SAndroid Build Coastguard Worker     std::string mLocation;
121*e01b6f76SAndroid Build Coastguard Worker     std::string mUniqueId;
122*e01b6f76SAndroid Build Coastguard Worker 
123*e01b6f76SAndroid Build Coastguard Worker     uint16_t mBusType;
124*e01b6f76SAndroid Build Coastguard Worker     uint16_t mVendorId;
125*e01b6f76SAndroid Build Coastguard Worker     uint16_t mProductId;
126*e01b6f76SAndroid Build Coastguard Worker     uint16_t mVersion;
127*e01b6f76SAndroid Build Coastguard Worker 
128*e01b6f76SAndroid Build Coastguard Worker     uint8_t mKeyBitmask[KEY_CNT / 8];
129*e01b6f76SAndroid Build Coastguard Worker     uint8_t mAbsBitmask[ABS_CNT / 8];
130*e01b6f76SAndroid Build Coastguard Worker     uint8_t mRelBitmask[REL_CNT / 8];
131*e01b6f76SAndroid Build Coastguard Worker     uint8_t mSwBitmask[SW_CNT / 8];
132*e01b6f76SAndroid Build Coastguard Worker     uint8_t mLedBitmask[LED_CNT / 8];
133*e01b6f76SAndroid Build Coastguard Worker     uint8_t mFfBitmask[FF_CNT / 8];
134*e01b6f76SAndroid Build Coastguard Worker     uint8_t mPropBitmask[INPUT_PROP_CNT / 8];
135*e01b6f76SAndroid Build Coastguard Worker 
136*e01b6f76SAndroid Build Coastguard Worker     std::unordered_map<uint32_t, std::unique_ptr<AbsoluteAxisInfo>> mAbsInfo;
137*e01b6f76SAndroid Build Coastguard Worker 
138*e01b6f76SAndroid Build Coastguard Worker     bool mFfEffectPlaying = false;
139*e01b6f76SAndroid Build Coastguard Worker     int16_t mFfEffectId = -1;
140*e01b6f76SAndroid Build Coastguard Worker };
141*e01b6f76SAndroid Build Coastguard Worker 
openDeviceNode(const std::string & path)142*e01b6f76SAndroid Build Coastguard Worker EvdevDeviceNode* EvdevDeviceNode::openDeviceNode(const std::string& path) {
143*e01b6f76SAndroid Build Coastguard Worker     auto fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC));
144*e01b6f76SAndroid Build Coastguard Worker     if (fd < 0) {
145*e01b6f76SAndroid Build Coastguard Worker         ALOGE("could not open evdev device %s. err=%d", path.c_str(), errno);
146*e01b6f76SAndroid Build Coastguard Worker         return nullptr;
147*e01b6f76SAndroid Build Coastguard Worker     }
148*e01b6f76SAndroid Build Coastguard Worker 
149*e01b6f76SAndroid Build Coastguard Worker     // Tell the kernel that we want to use the monotonic clock for reporting
150*e01b6f76SAndroid Build Coastguard Worker     // timestamps associated with input events. This is important because the
151*e01b6f76SAndroid Build Coastguard Worker     // input system uses the timestamps extensively and assumes they were
152*e01b6f76SAndroid Build Coastguard Worker     // recorded using the monotonic clock.
153*e01b6f76SAndroid Build Coastguard Worker     //
154*e01b6f76SAndroid Build Coastguard Worker     // The EVIOCSCLOCKID ioctl was introduced in Linux 3.4.
155*e01b6f76SAndroid Build Coastguard Worker     int clockId = CLOCK_MONOTONIC;
156*e01b6f76SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(ioctl(fd, EVIOCSCLOCKID, &clockId)) < 0) {
157*e01b6f76SAndroid Build Coastguard Worker         ALOGW("Could not set input clock id to CLOCK_MONOTONIC. errno=%d", errno);
158*e01b6f76SAndroid Build Coastguard Worker     }
159*e01b6f76SAndroid Build Coastguard Worker 
160*e01b6f76SAndroid Build Coastguard Worker     auto node = new EvdevDeviceNode(path, fd);
161*e01b6f76SAndroid Build Coastguard Worker     status_t ret = node->queryProperties();
162*e01b6f76SAndroid Build Coastguard Worker     if (ret != OK) {
163*e01b6f76SAndroid Build Coastguard Worker         ALOGE("could not open evdev device %s: failed to read properties. errno=%d",
164*e01b6f76SAndroid Build Coastguard Worker                 path.c_str(), ret);
165*e01b6f76SAndroid Build Coastguard Worker         delete node;
166*e01b6f76SAndroid Build Coastguard Worker         return nullptr;
167*e01b6f76SAndroid Build Coastguard Worker     }
168*e01b6f76SAndroid Build Coastguard Worker     return node;
169*e01b6f76SAndroid Build Coastguard Worker }
170*e01b6f76SAndroid Build Coastguard Worker 
queryProperties()171*e01b6f76SAndroid Build Coastguard Worker status_t EvdevDeviceNode::queryProperties() {
172*e01b6f76SAndroid Build Coastguard Worker     char buffer[80];
173*e01b6f76SAndroid Build Coastguard Worker 
174*e01b6f76SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGNAME(sizeof(buffer) - 1), buffer)) < 1) {
175*e01b6f76SAndroid Build Coastguard Worker         ALOGV("could not get device name for %s.", mPath.c_str());
176*e01b6f76SAndroid Build Coastguard Worker     } else {
177*e01b6f76SAndroid Build Coastguard Worker         buffer[sizeof(buffer) - 1] = '\0';
178*e01b6f76SAndroid Build Coastguard Worker         mName = buffer;
179*e01b6f76SAndroid Build Coastguard Worker     }
180*e01b6f76SAndroid Build Coastguard Worker 
181*e01b6f76SAndroid Build Coastguard Worker     int driverVersion;
182*e01b6f76SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGVERSION, &driverVersion))) {
183*e01b6f76SAndroid Build Coastguard Worker         ALOGE("could not get driver version for %s. err=%d", mPath.c_str(), errno);
184*e01b6f76SAndroid Build Coastguard Worker         return -errno;
185*e01b6f76SAndroid Build Coastguard Worker     }
186*e01b6f76SAndroid Build Coastguard Worker 
187*e01b6f76SAndroid Build Coastguard Worker     struct input_id inputId;
188*e01b6f76SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGID, &inputId))) {
189*e01b6f76SAndroid Build Coastguard Worker         ALOGE("could not get device input id for %s. err=%d", mPath.c_str(), errno);
190*e01b6f76SAndroid Build Coastguard Worker         return -errno;
191*e01b6f76SAndroid Build Coastguard Worker     }
192*e01b6f76SAndroid Build Coastguard Worker     mBusType = inputId.bustype;
193*e01b6f76SAndroid Build Coastguard Worker     mVendorId = inputId.vendor;
194*e01b6f76SAndroid Build Coastguard Worker     mProductId = inputId.product;
195*e01b6f76SAndroid Build Coastguard Worker     mVersion = inputId.version;
196*e01b6f76SAndroid Build Coastguard Worker 
197*e01b6f76SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGPHYS(sizeof(buffer) - 1), buffer)) < 1) {
198*e01b6f76SAndroid Build Coastguard Worker         ALOGV("could not get location for %s.", mPath.c_str());
199*e01b6f76SAndroid Build Coastguard Worker     } else {
200*e01b6f76SAndroid Build Coastguard Worker         buffer[sizeof(buffer) - 1] = '\0';
201*e01b6f76SAndroid Build Coastguard Worker         mLocation = buffer;
202*e01b6f76SAndroid Build Coastguard Worker     }
203*e01b6f76SAndroid Build Coastguard Worker 
204*e01b6f76SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGUNIQ(sizeof(buffer) - 1), buffer)) < 1) {
205*e01b6f76SAndroid Build Coastguard Worker         ALOGV("could not get unique id for %s.", mPath.c_str());
206*e01b6f76SAndroid Build Coastguard Worker     } else {
207*e01b6f76SAndroid Build Coastguard Worker         buffer[sizeof(buffer) - 1] = '\0';
208*e01b6f76SAndroid Build Coastguard Worker         mUniqueId = buffer;
209*e01b6f76SAndroid Build Coastguard Worker     }
210*e01b6f76SAndroid Build Coastguard Worker 
211*e01b6f76SAndroid Build Coastguard Worker     ALOGV("add device %s", mPath.c_str());
212*e01b6f76SAndroid Build Coastguard Worker     ALOGV("  bus:        %04x\n"
213*e01b6f76SAndroid Build Coastguard Worker           "  vendor:     %04x\n"
214*e01b6f76SAndroid Build Coastguard Worker           "  product:    %04x\n"
215*e01b6f76SAndroid Build Coastguard Worker           "  version:    %04x\n",
216*e01b6f76SAndroid Build Coastguard Worker         mBusType, mVendorId, mProductId, mVersion);
217*e01b6f76SAndroid Build Coastguard Worker     ALOGV("  name:       \"%s\"\n"
218*e01b6f76SAndroid Build Coastguard Worker           "  location:   \"%s\"\n"
219*e01b6f76SAndroid Build Coastguard Worker           "  unique_id:  \"%s\"\n"
220*e01b6f76SAndroid Build Coastguard Worker           "  descriptor: (TODO)\n"
221*e01b6f76SAndroid Build Coastguard Worker           "  driver:     v%d.%d.%d",
222*e01b6f76SAndroid Build Coastguard Worker         mName.c_str(), mLocation.c_str(), mUniqueId.c_str(),
223*e01b6f76SAndroid Build Coastguard Worker         driverVersion >> 16, (driverVersion >> 8) & 0xff, (driverVersion >> 16) & 0xff);
224*e01b6f76SAndroid Build Coastguard Worker 
225*e01b6f76SAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_KEY, sizeof(mKeyBitmask)), mKeyBitmask));
226*e01b6f76SAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_ABS, sizeof(mAbsBitmask)), mAbsBitmask));
227*e01b6f76SAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_REL, sizeof(mRelBitmask)), mRelBitmask));
228*e01b6f76SAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_SW,  sizeof(mSwBitmask)),  mSwBitmask));
229*e01b6f76SAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_LED, sizeof(mLedBitmask)), mLedBitmask));
230*e01b6f76SAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_FF,  sizeof(mFfBitmask)),  mFfBitmask));
231*e01b6f76SAndroid Build Coastguard Worker     TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGPROP(sizeof(mPropBitmask)), mPropBitmask));
232*e01b6f76SAndroid Build Coastguard Worker 
233*e01b6f76SAndroid Build Coastguard Worker     queryAxisInfo();
234*e01b6f76SAndroid Build Coastguard Worker 
235*e01b6f76SAndroid Build Coastguard Worker     return OK;
236*e01b6f76SAndroid Build Coastguard Worker }
237*e01b6f76SAndroid Build Coastguard Worker 
queryAxisInfo()238*e01b6f76SAndroid Build Coastguard Worker void EvdevDeviceNode::queryAxisInfo() {
239*e01b6f76SAndroid Build Coastguard Worker     for (int32_t axis = 0; axis < ABS_MAX; ++axis) {
240*e01b6f76SAndroid Build Coastguard Worker         if (testBit(axis, mAbsBitmask)) {
241*e01b6f76SAndroid Build Coastguard Worker             struct input_absinfo info;
242*e01b6f76SAndroid Build Coastguard Worker             if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGABS(axis), &info))) {
243*e01b6f76SAndroid Build Coastguard Worker                 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
244*e01b6f76SAndroid Build Coastguard Worker                         axis, mPath.c_str(), mFd, errno);
245*e01b6f76SAndroid Build Coastguard Worker                 continue;
246*e01b6f76SAndroid Build Coastguard Worker             }
247*e01b6f76SAndroid Build Coastguard Worker 
248*e01b6f76SAndroid Build Coastguard Worker             mAbsInfo[axis] = std::unique_ptr<AbsoluteAxisInfo>(new AbsoluteAxisInfo{
249*e01b6f76SAndroid Build Coastguard Worker                     .minValue = info.minimum,
250*e01b6f76SAndroid Build Coastguard Worker                     .maxValue = info.maximum,
251*e01b6f76SAndroid Build Coastguard Worker                     .flat = info.flat,
252*e01b6f76SAndroid Build Coastguard Worker                     .fuzz = info.fuzz,
253*e01b6f76SAndroid Build Coastguard Worker                     .resolution = info.resolution
254*e01b6f76SAndroid Build Coastguard Worker                     });
255*e01b6f76SAndroid Build Coastguard Worker         }
256*e01b6f76SAndroid Build Coastguard Worker     }
257*e01b6f76SAndroid Build Coastguard Worker }
258*e01b6f76SAndroid Build Coastguard Worker 
hasKey(int32_t key) const259*e01b6f76SAndroid Build Coastguard Worker bool EvdevDeviceNode::hasKey(int32_t key) const {
260*e01b6f76SAndroid Build Coastguard Worker     if (key >= 0 && key <= KEY_MAX) {
261*e01b6f76SAndroid Build Coastguard Worker         return testBit(key, mKeyBitmask);
262*e01b6f76SAndroid Build Coastguard Worker     }
263*e01b6f76SAndroid Build Coastguard Worker     return false;
264*e01b6f76SAndroid Build Coastguard Worker }
265*e01b6f76SAndroid Build Coastguard Worker 
hasKeyInRange(int32_t startKey,int32_t endKey) const266*e01b6f76SAndroid Build Coastguard Worker bool EvdevDeviceNode::hasKeyInRange(int32_t startKey, int32_t endKey) const {
267*e01b6f76SAndroid Build Coastguard Worker     return testBitInRange(mKeyBitmask, startKey, endKey);
268*e01b6f76SAndroid Build Coastguard Worker }
269*e01b6f76SAndroid Build Coastguard Worker 
hasRelativeAxis(int axis) const270*e01b6f76SAndroid Build Coastguard Worker bool EvdevDeviceNode::hasRelativeAxis(int axis) const {
271*e01b6f76SAndroid Build Coastguard Worker     if (axis >= 0 && axis <= REL_MAX) {
272*e01b6f76SAndroid Build Coastguard Worker         return testBit(axis, mRelBitmask);
273*e01b6f76SAndroid Build Coastguard Worker     }
274*e01b6f76SAndroid Build Coastguard Worker     return false;
275*e01b6f76SAndroid Build Coastguard Worker }
276*e01b6f76SAndroid Build Coastguard Worker 
hasAbsoluteAxis(int axis) const277*e01b6f76SAndroid Build Coastguard Worker bool EvdevDeviceNode::hasAbsoluteAxis(int axis) const {
278*e01b6f76SAndroid Build Coastguard Worker     if (axis >= 0 && axis <= ABS_MAX) {
279*e01b6f76SAndroid Build Coastguard Worker         return getAbsoluteAxisInfo(axis) != nullptr;
280*e01b6f76SAndroid Build Coastguard Worker     }
281*e01b6f76SAndroid Build Coastguard Worker     return false;
282*e01b6f76SAndroid Build Coastguard Worker }
283*e01b6f76SAndroid Build Coastguard Worker 
getAbsoluteAxisInfo(int32_t axis) const284*e01b6f76SAndroid Build Coastguard Worker const AbsoluteAxisInfo* EvdevDeviceNode::getAbsoluteAxisInfo(int32_t axis) const {
285*e01b6f76SAndroid Build Coastguard Worker     if (axis < 0 || axis > ABS_MAX) {
286*e01b6f76SAndroid Build Coastguard Worker         return nullptr;
287*e01b6f76SAndroid Build Coastguard Worker     }
288*e01b6f76SAndroid Build Coastguard Worker 
289*e01b6f76SAndroid Build Coastguard Worker     const auto absInfo = mAbsInfo.find(axis);
290*e01b6f76SAndroid Build Coastguard Worker     if (absInfo != mAbsInfo.end()) {
291*e01b6f76SAndroid Build Coastguard Worker         return absInfo->second.get();
292*e01b6f76SAndroid Build Coastguard Worker     }
293*e01b6f76SAndroid Build Coastguard Worker     return nullptr;
294*e01b6f76SAndroid Build Coastguard Worker }
295*e01b6f76SAndroid Build Coastguard Worker 
hasSwitch(int32_t sw) const296*e01b6f76SAndroid Build Coastguard Worker bool EvdevDeviceNode::hasSwitch(int32_t sw) const {
297*e01b6f76SAndroid Build Coastguard Worker     if (sw >= 0 && sw <= SW_MAX) {
298*e01b6f76SAndroid Build Coastguard Worker         return testBit(sw, mSwBitmask);
299*e01b6f76SAndroid Build Coastguard Worker     }
300*e01b6f76SAndroid Build Coastguard Worker     return false;
301*e01b6f76SAndroid Build Coastguard Worker }
302*e01b6f76SAndroid Build Coastguard Worker 
hasForceFeedback(int32_t ff) const303*e01b6f76SAndroid Build Coastguard Worker bool EvdevDeviceNode::hasForceFeedback(int32_t ff) const {
304*e01b6f76SAndroid Build Coastguard Worker     if (ff >= 0 && ff <= FF_MAX) {
305*e01b6f76SAndroid Build Coastguard Worker         return testBit(ff, mFfBitmask);
306*e01b6f76SAndroid Build Coastguard Worker     }
307*e01b6f76SAndroid Build Coastguard Worker     return false;
308*e01b6f76SAndroid Build Coastguard Worker }
309*e01b6f76SAndroid Build Coastguard Worker 
hasInputProperty(int property) const310*e01b6f76SAndroid Build Coastguard Worker bool EvdevDeviceNode::hasInputProperty(int property) const {
311*e01b6f76SAndroid Build Coastguard Worker     if (property >= 0 && property <= INPUT_PROP_MAX) {
312*e01b6f76SAndroid Build Coastguard Worker         return testBit(property, mPropBitmask);
313*e01b6f76SAndroid Build Coastguard Worker     }
314*e01b6f76SAndroid Build Coastguard Worker     return false;
315*e01b6f76SAndroid Build Coastguard Worker }
316*e01b6f76SAndroid Build Coastguard Worker 
getKeyState(int32_t key) const317*e01b6f76SAndroid Build Coastguard Worker int32_t EvdevDeviceNode::getKeyState(int32_t key) const {
318*e01b6f76SAndroid Build Coastguard Worker     if (key >= 0 && key <= KEY_MAX) {
319*e01b6f76SAndroid Build Coastguard Worker         if (testBit(key, mKeyBitmask)) {
320*e01b6f76SAndroid Build Coastguard Worker             uint8_t keyState[sizeofBitArray(KEY_CNT)];
321*e01b6f76SAndroid Build Coastguard Worker             memset(keyState, 0, sizeof(keyState));
322*e01b6f76SAndroid Build Coastguard Worker             if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGKEY(sizeof(keyState)), keyState)) >= 0) {
323*e01b6f76SAndroid Build Coastguard Worker                 return testBit(key, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
324*e01b6f76SAndroid Build Coastguard Worker             }
325*e01b6f76SAndroid Build Coastguard Worker         }
326*e01b6f76SAndroid Build Coastguard Worker     }
327*e01b6f76SAndroid Build Coastguard Worker     return AKEY_STATE_UNKNOWN;
328*e01b6f76SAndroid Build Coastguard Worker }
329*e01b6f76SAndroid Build Coastguard Worker 
getSwitchState(int32_t sw) const330*e01b6f76SAndroid Build Coastguard Worker int32_t EvdevDeviceNode::getSwitchState(int32_t sw) const {
331*e01b6f76SAndroid Build Coastguard Worker     if (sw >= 0 && sw <= SW_MAX) {
332*e01b6f76SAndroid Build Coastguard Worker         if (testBit(sw, mSwBitmask)) {
333*e01b6f76SAndroid Build Coastguard Worker             uint8_t swState[sizeofBitArray(SW_CNT)];
334*e01b6f76SAndroid Build Coastguard Worker             memset(swState, 0, sizeof(swState));
335*e01b6f76SAndroid Build Coastguard Worker             if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGSW(sizeof(swState)), swState)) >= 0) {
336*e01b6f76SAndroid Build Coastguard Worker                 return testBit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
337*e01b6f76SAndroid Build Coastguard Worker             }
338*e01b6f76SAndroid Build Coastguard Worker         }
339*e01b6f76SAndroid Build Coastguard Worker     }
340*e01b6f76SAndroid Build Coastguard Worker     return AKEY_STATE_UNKNOWN;
341*e01b6f76SAndroid Build Coastguard Worker }
342*e01b6f76SAndroid Build Coastguard Worker 
getAbsoluteAxisValue(int32_t axis,int32_t * outValue) const343*e01b6f76SAndroid Build Coastguard Worker status_t EvdevDeviceNode::getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const {
344*e01b6f76SAndroid Build Coastguard Worker     *outValue = 0;
345*e01b6f76SAndroid Build Coastguard Worker 
346*e01b6f76SAndroid Build Coastguard Worker     if (axis >= 0 && axis <= ABS_MAX) {
347*e01b6f76SAndroid Build Coastguard Worker         if (testBit(axis, mAbsBitmask)) {
348*e01b6f76SAndroid Build Coastguard Worker             struct input_absinfo info;
349*e01b6f76SAndroid Build Coastguard Worker             if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGABS(axis), &info))) {
350*e01b6f76SAndroid Build Coastguard Worker                 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
351*e01b6f76SAndroid Build Coastguard Worker                         axis, mPath.c_str(), mFd, errno);
352*e01b6f76SAndroid Build Coastguard Worker                 return -errno;
353*e01b6f76SAndroid Build Coastguard Worker             }
354*e01b6f76SAndroid Build Coastguard Worker 
355*e01b6f76SAndroid Build Coastguard Worker             *outValue = info.value;
356*e01b6f76SAndroid Build Coastguard Worker             return OK;
357*e01b6f76SAndroid Build Coastguard Worker         }
358*e01b6f76SAndroid Build Coastguard Worker     }
359*e01b6f76SAndroid Build Coastguard Worker     return -1;
360*e01b6f76SAndroid Build Coastguard Worker }
361*e01b6f76SAndroid Build Coastguard Worker 
vibrate(nsecs_t duration)362*e01b6f76SAndroid Build Coastguard Worker void EvdevDeviceNode::vibrate(nsecs_t duration) {
363*e01b6f76SAndroid Build Coastguard Worker     ff_effect effect{};
364*e01b6f76SAndroid Build Coastguard Worker     effect.type = FF_RUMBLE;
365*e01b6f76SAndroid Build Coastguard Worker     effect.id = mFfEffectId;
366*e01b6f76SAndroid Build Coastguard Worker     effect.u.rumble.strong_magnitude = 0xc000;
367*e01b6f76SAndroid Build Coastguard Worker     effect.u.rumble.weak_magnitude = 0xc000;
368*e01b6f76SAndroid Build Coastguard Worker     effect.replay.length = (duration + 999'999LL) / 1'000'000LL;
369*e01b6f76SAndroid Build Coastguard Worker     effect.replay.delay = 0;
370*e01b6f76SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCSFF, &effect))) {
371*e01b6f76SAndroid Build Coastguard Worker         ALOGW("Could not upload force feedback effect to device %s due to error %d.",
372*e01b6f76SAndroid Build Coastguard Worker                 mPath.c_str(), errno);
373*e01b6f76SAndroid Build Coastguard Worker         return;
374*e01b6f76SAndroid Build Coastguard Worker     }
375*e01b6f76SAndroid Build Coastguard Worker     mFfEffectId = effect.id;
376*e01b6f76SAndroid Build Coastguard Worker 
377*e01b6f76SAndroid Build Coastguard Worker     struct input_event ev{};
378*e01b6f76SAndroid Build Coastguard Worker     ev.type = EV_FF;
379*e01b6f76SAndroid Build Coastguard Worker     ev.code = mFfEffectId;
380*e01b6f76SAndroid Build Coastguard Worker     ev.value = 1;
381*e01b6f76SAndroid Build Coastguard Worker     size_t written = TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(ev)));
382*e01b6f76SAndroid Build Coastguard Worker     if (written != sizeof(ev)) {
383*e01b6f76SAndroid Build Coastguard Worker         ALOGW("Could not start force feedback effect on device %s due to error %d.",
384*e01b6f76SAndroid Build Coastguard Worker                 mPath.c_str(), errno);
385*e01b6f76SAndroid Build Coastguard Worker         return;
386*e01b6f76SAndroid Build Coastguard Worker     }
387*e01b6f76SAndroid Build Coastguard Worker     mFfEffectPlaying = true;
388*e01b6f76SAndroid Build Coastguard Worker }
389*e01b6f76SAndroid Build Coastguard Worker 
cancelVibrate()390*e01b6f76SAndroid Build Coastguard Worker void EvdevDeviceNode::cancelVibrate() {
391*e01b6f76SAndroid Build Coastguard Worker     if (mFfEffectPlaying) {
392*e01b6f76SAndroid Build Coastguard Worker         mFfEffectPlaying = false;
393*e01b6f76SAndroid Build Coastguard Worker 
394*e01b6f76SAndroid Build Coastguard Worker         struct input_event ev{};
395*e01b6f76SAndroid Build Coastguard Worker         ev.type = EV_FF;
396*e01b6f76SAndroid Build Coastguard Worker         ev.code = mFfEffectId;
397*e01b6f76SAndroid Build Coastguard Worker         ev.value = 0;
398*e01b6f76SAndroid Build Coastguard Worker         size_t written = TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(ev)));
399*e01b6f76SAndroid Build Coastguard Worker         if (written != sizeof(ev)) {
400*e01b6f76SAndroid Build Coastguard Worker             ALOGW("Could not stop force feedback effect on device %s due to error %d.",
401*e01b6f76SAndroid Build Coastguard Worker                     mPath.c_str(), errno);
402*e01b6f76SAndroid Build Coastguard Worker             return;
403*e01b6f76SAndroid Build Coastguard Worker         }
404*e01b6f76SAndroid Build Coastguard Worker     }
405*e01b6f76SAndroid Build Coastguard Worker }
406*e01b6f76SAndroid Build Coastguard Worker 
disableDriverKeyRepeat()407*e01b6f76SAndroid Build Coastguard Worker void EvdevDeviceNode::disableDriverKeyRepeat() {
408*e01b6f76SAndroid Build Coastguard Worker     unsigned int repeatRate[] = {0, 0};
409*e01b6f76SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCSREP, repeatRate))) {
410*e01b6f76SAndroid Build Coastguard Worker         ALOGW("Unable to disable kernel key repeat for %s due to error %d.",
411*e01b6f76SAndroid Build Coastguard Worker                 mPath.c_str(), errno);
412*e01b6f76SAndroid Build Coastguard Worker     }
413*e01b6f76SAndroid Build Coastguard Worker }
414*e01b6f76SAndroid Build Coastguard Worker 
InputHub(const std::shared_ptr<InputCallbackInterface> & cb)415*e01b6f76SAndroid Build Coastguard Worker InputHub::InputHub(const std::shared_ptr<InputCallbackInterface>& cb) :
416*e01b6f76SAndroid Build Coastguard Worker     mInputCallback(cb) {
417*e01b6f76SAndroid Build Coastguard Worker     // Determine the type of suspend blocking we can do on this device. There
418*e01b6f76SAndroid Build Coastguard Worker     // are 3 options, in decreasing order of preference:
419*e01b6f76SAndroid Build Coastguard Worker     //   1) EPOLLWAKEUP: introduced in Linux kernel 3.5, this flag can be set on
420*e01b6f76SAndroid Build Coastguard Worker     //   an epoll event to indicate that a wake lock should be held from the
421*e01b6f76SAndroid Build Coastguard Worker     //   time an fd has data until the next epoll_wait (or the epoll fd is
422*e01b6f76SAndroid Build Coastguard Worker     //   closed).
423*e01b6f76SAndroid Build Coastguard Worker     //   2) EVIOCSSUSPENDBLOCK: introduced into the Android kernel's evdev
424*e01b6f76SAndroid Build Coastguard Worker     //   driver, this ioctl blocks suspend while the event queue for the fd is
425*e01b6f76SAndroid Build Coastguard Worker     //   not empty. This was never accepted into the mainline kernel, and it was
426*e01b6f76SAndroid Build Coastguard Worker     //   replaced by EPOLLWAKEUP.
427*e01b6f76SAndroid Build Coastguard Worker     //   3) explicit wake locks: use acquire_wake_lock to manage suspend
428*e01b6f76SAndroid Build Coastguard Worker     //   blocking explicitly in the InputHub code.
429*e01b6f76SAndroid Build Coastguard Worker     //
430*e01b6f76SAndroid Build Coastguard Worker     // (1) can be checked by simply observing the Linux kernel version. (2)
431*e01b6f76SAndroid Build Coastguard Worker     // requires an fd from an evdev node, which cannot be done in the InputHub
432*e01b6f76SAndroid Build Coastguard Worker     // constructor. So we assume (3) unless (1) is true, and we can verify
433*e01b6f76SAndroid Build Coastguard Worker     // whether (2) is true once we have an evdev fd (and we're not in (1)).
434*e01b6f76SAndroid Build Coastguard Worker     int major, minor;
435*e01b6f76SAndroid Build Coastguard Worker     getLinuxRelease(&major, &minor);
436*e01b6f76SAndroid Build Coastguard Worker     if (major > 3 || (major == 3 && minor >= 5)) {
437*e01b6f76SAndroid Build Coastguard Worker         ALOGI("Using EPOLLWAKEUP to block suspend while processing input events.");
438*e01b6f76SAndroid Build Coastguard Worker         mWakeupMechanism = WakeMechanism::EPOLL_WAKEUP;
439*e01b6f76SAndroid Build Coastguard Worker         mNeedToCheckSuspendBlockIoctl = false;
440*e01b6f76SAndroid Build Coastguard Worker     }
441*e01b6f76SAndroid Build Coastguard Worker     if (manageWakeLocks()) {
442*e01b6f76SAndroid Build Coastguard Worker         acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
443*e01b6f76SAndroid Build Coastguard Worker     }
444*e01b6f76SAndroid Build Coastguard Worker 
445*e01b6f76SAndroid Build Coastguard Worker     // epoll_create argument is ignored, but it must be > 0.
446*e01b6f76SAndroid Build Coastguard Worker     mEpollFd = epoll_create(1);
447*e01b6f76SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
448*e01b6f76SAndroid Build Coastguard Worker 
449*e01b6f76SAndroid Build Coastguard Worker     mINotifyFd = inotify_init();
450*e01b6f76SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(mINotifyFd < 0, "Could not create inotify instance. errno=%d", errno);
451*e01b6f76SAndroid Build Coastguard Worker 
452*e01b6f76SAndroid Build Coastguard Worker     struct epoll_event eventItem;
453*e01b6f76SAndroid Build Coastguard Worker     memset(&eventItem, 0, sizeof(eventItem));
454*e01b6f76SAndroid Build Coastguard Worker     eventItem.events = EPOLLIN;
455*e01b6f76SAndroid Build Coastguard Worker     if (mWakeupMechanism == WakeMechanism::EPOLL_WAKEUP) {
456*e01b6f76SAndroid Build Coastguard Worker         eventItem.events |= EPOLLWAKEUP;
457*e01b6f76SAndroid Build Coastguard Worker     }
458*e01b6f76SAndroid Build Coastguard Worker     eventItem.data.u32 = mINotifyFd;
459*e01b6f76SAndroid Build Coastguard Worker     int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
460*e01b6f76SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
461*e01b6f76SAndroid Build Coastguard Worker 
462*e01b6f76SAndroid Build Coastguard Worker     int wakeFds[2];
463*e01b6f76SAndroid Build Coastguard Worker     result = pipe(wakeFds);
464*e01b6f76SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
465*e01b6f76SAndroid Build Coastguard Worker 
466*e01b6f76SAndroid Build Coastguard Worker     mWakeEventFd = eventfd(0, EFD_NONBLOCK);
467*e01b6f76SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(mWakeEventFd == -1, "Could not create wake event fd. errno=%d", errno);
468*e01b6f76SAndroid Build Coastguard Worker 
469*e01b6f76SAndroid Build Coastguard Worker     eventItem.data.u32 = mWakeEventFd;
470*e01b6f76SAndroid Build Coastguard Worker     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, &eventItem);
471*e01b6f76SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance. errno=%d", errno);
472*e01b6f76SAndroid Build Coastguard Worker }
473*e01b6f76SAndroid Build Coastguard Worker 
~InputHub()474*e01b6f76SAndroid Build Coastguard Worker InputHub::~InputHub() {
475*e01b6f76SAndroid Build Coastguard Worker     ::close(mEpollFd);
476*e01b6f76SAndroid Build Coastguard Worker     ::close(mINotifyFd);
477*e01b6f76SAndroid Build Coastguard Worker     ::close(mWakeEventFd);
478*e01b6f76SAndroid Build Coastguard Worker 
479*e01b6f76SAndroid Build Coastguard Worker     if (manageWakeLocks()) {
480*e01b6f76SAndroid Build Coastguard Worker         release_wake_lock(WAKE_LOCK_ID);
481*e01b6f76SAndroid Build Coastguard Worker     }
482*e01b6f76SAndroid Build Coastguard Worker }
483*e01b6f76SAndroid Build Coastguard Worker 
registerDevicePath(const std::string & path)484*e01b6f76SAndroid Build Coastguard Worker status_t InputHub::registerDevicePath(const std::string& path) {
485*e01b6f76SAndroid Build Coastguard Worker     ALOGV("registering device path %s", path.c_str());
486*e01b6f76SAndroid Build Coastguard Worker     int wd = inotify_add_watch(mINotifyFd, path.c_str(), IN_DELETE | IN_CREATE);
487*e01b6f76SAndroid Build Coastguard Worker     if (wd < 0) {
488*e01b6f76SAndroid Build Coastguard Worker         ALOGE("Could not add %s to INotify watch. errno=%d", path.c_str(), errno);
489*e01b6f76SAndroid Build Coastguard Worker         return -errno;
490*e01b6f76SAndroid Build Coastguard Worker     }
491*e01b6f76SAndroid Build Coastguard Worker     mWatchedPaths[wd] = path;
492*e01b6f76SAndroid Build Coastguard Worker     scanDir(path);
493*e01b6f76SAndroid Build Coastguard Worker     return OK;
494*e01b6f76SAndroid Build Coastguard Worker }
495*e01b6f76SAndroid Build Coastguard Worker 
unregisterDevicePath(const std::string & path)496*e01b6f76SAndroid Build Coastguard Worker status_t InputHub::unregisterDevicePath(const std::string& path) {
497*e01b6f76SAndroid Build Coastguard Worker     int wd = -1;
498*e01b6f76SAndroid Build Coastguard Worker     for (const auto& pair : mWatchedPaths) {
499*e01b6f76SAndroid Build Coastguard Worker         if (pair.second == path) {
500*e01b6f76SAndroid Build Coastguard Worker             wd = pair.first;
501*e01b6f76SAndroid Build Coastguard Worker             break;
502*e01b6f76SAndroid Build Coastguard Worker         }
503*e01b6f76SAndroid Build Coastguard Worker     }
504*e01b6f76SAndroid Build Coastguard Worker 
505*e01b6f76SAndroid Build Coastguard Worker     if (wd == -1) {
506*e01b6f76SAndroid Build Coastguard Worker         return BAD_VALUE;
507*e01b6f76SAndroid Build Coastguard Worker     }
508*e01b6f76SAndroid Build Coastguard Worker     mWatchedPaths.erase(wd);
509*e01b6f76SAndroid Build Coastguard Worker     if (inotify_rm_watch(mINotifyFd, wd) != 0) {
510*e01b6f76SAndroid Build Coastguard Worker         return -errno;
511*e01b6f76SAndroid Build Coastguard Worker     }
512*e01b6f76SAndroid Build Coastguard Worker     return OK;
513*e01b6f76SAndroid Build Coastguard Worker }
514*e01b6f76SAndroid Build Coastguard Worker 
poll()515*e01b6f76SAndroid Build Coastguard Worker status_t InputHub::poll() {
516*e01b6f76SAndroid Build Coastguard Worker     bool deviceChange = false;
517*e01b6f76SAndroid Build Coastguard Worker 
518*e01b6f76SAndroid Build Coastguard Worker     if (manageWakeLocks()) {
519*e01b6f76SAndroid Build Coastguard Worker         // Mind the wake lock dance!
520*e01b6f76SAndroid Build Coastguard Worker         // If we're relying on wake locks, we hold a wake lock at all times
521*e01b6f76SAndroid Build Coastguard Worker         // except during epoll_wait(). This works due to some subtle
522*e01b6f76SAndroid Build Coastguard Worker         // choreography. When a device driver has pending (unread) events, it
523*e01b6f76SAndroid Build Coastguard Worker         // acquires a kernel wake lock. However, once the last pending event
524*e01b6f76SAndroid Build Coastguard Worker         // has been read, the device driver will release the kernel wake lock.
525*e01b6f76SAndroid Build Coastguard Worker         // To prevent the system from going to sleep when this happens, the
526*e01b6f76SAndroid Build Coastguard Worker         // InputHub holds onto its own user wake lock while the client is
527*e01b6f76SAndroid Build Coastguard Worker         // processing events. Thus the system can only sleep if there are no
528*e01b6f76SAndroid Build Coastguard Worker         // events pending or currently being processed.
529*e01b6f76SAndroid Build Coastguard Worker         release_wake_lock(WAKE_LOCK_ID);
530*e01b6f76SAndroid Build Coastguard Worker     }
531*e01b6f76SAndroid Build Coastguard Worker 
532*e01b6f76SAndroid Build Coastguard Worker     struct epoll_event pendingEventItems[EPOLL_MAX_EVENTS];
533*e01b6f76SAndroid Build Coastguard Worker     int pollResult = epoll_wait(mEpollFd, pendingEventItems, EPOLL_MAX_EVENTS, NO_TIMEOUT);
534*e01b6f76SAndroid Build Coastguard Worker 
535*e01b6f76SAndroid Build Coastguard Worker     if (manageWakeLocks()) {
536*e01b6f76SAndroid Build Coastguard Worker         acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
537*e01b6f76SAndroid Build Coastguard Worker     }
538*e01b6f76SAndroid Build Coastguard Worker 
539*e01b6f76SAndroid Build Coastguard Worker     if (pollResult == 0) {
540*e01b6f76SAndroid Build Coastguard Worker         ALOGW("epoll_wait should not return 0 with no timeout");
541*e01b6f76SAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
542*e01b6f76SAndroid Build Coastguard Worker     }
543*e01b6f76SAndroid Build Coastguard Worker     if (pollResult < 0) {
544*e01b6f76SAndroid Build Coastguard Worker         // An error occurred. Return even if it's EINTR, and let the caller
545*e01b6f76SAndroid Build Coastguard Worker         // restart the poll.
546*e01b6f76SAndroid Build Coastguard Worker         ALOGE("epoll_wait returned with errno=%d", errno);
547*e01b6f76SAndroid Build Coastguard Worker         return -errno;
548*e01b6f76SAndroid Build Coastguard Worker     }
549*e01b6f76SAndroid Build Coastguard Worker 
550*e01b6f76SAndroid Build Coastguard Worker     // pollResult > 0: there are events to process
551*e01b6f76SAndroid Build Coastguard Worker     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
552*e01b6f76SAndroid Build Coastguard Worker     std::vector<int> removedDeviceFds;
553*e01b6f76SAndroid Build Coastguard Worker     int inputFd = -1;
554*e01b6f76SAndroid Build Coastguard Worker     std::shared_ptr<InputDeviceNode> deviceNode;
555*e01b6f76SAndroid Build Coastguard Worker     for (int i = 0; i < pollResult; ++i) {
556*e01b6f76SAndroid Build Coastguard Worker         const struct epoll_event& eventItem = pendingEventItems[i];
557*e01b6f76SAndroid Build Coastguard Worker 
558*e01b6f76SAndroid Build Coastguard Worker         int dataFd = static_cast<int>(eventItem.data.u32);
559*e01b6f76SAndroid Build Coastguard Worker         if (dataFd == mINotifyFd) {
560*e01b6f76SAndroid Build Coastguard Worker             if (eventItem.events & EPOLLIN) {
561*e01b6f76SAndroid Build Coastguard Worker                 deviceChange = true;
562*e01b6f76SAndroid Build Coastguard Worker             } else {
563*e01b6f76SAndroid Build Coastguard Worker                 ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
564*e01b6f76SAndroid Build Coastguard Worker             }
565*e01b6f76SAndroid Build Coastguard Worker             continue;
566*e01b6f76SAndroid Build Coastguard Worker         }
567*e01b6f76SAndroid Build Coastguard Worker 
568*e01b6f76SAndroid Build Coastguard Worker         if (dataFd == mWakeEventFd) {
569*e01b6f76SAndroid Build Coastguard Worker             if (eventItem.events & EPOLLIN) {
570*e01b6f76SAndroid Build Coastguard Worker                 ALOGV("awoken after wake()");
571*e01b6f76SAndroid Build Coastguard Worker                 uint64_t u;
572*e01b6f76SAndroid Build Coastguard Worker                 ssize_t nRead = TEMP_FAILURE_RETRY(read(mWakeEventFd, &u, sizeof(uint64_t)));
573*e01b6f76SAndroid Build Coastguard Worker                 if (nRead != sizeof(uint64_t)) {
574*e01b6f76SAndroid Build Coastguard Worker                     ALOGW("Could not read event fd; waking anyway.");
575*e01b6f76SAndroid Build Coastguard Worker                 }
576*e01b6f76SAndroid Build Coastguard Worker             } else {
577*e01b6f76SAndroid Build Coastguard Worker                 ALOGW("Received unexpected epoll event 0x%08x for wake event.",
578*e01b6f76SAndroid Build Coastguard Worker                         eventItem.events);
579*e01b6f76SAndroid Build Coastguard Worker             }
580*e01b6f76SAndroid Build Coastguard Worker             continue;
581*e01b6f76SAndroid Build Coastguard Worker         }
582*e01b6f76SAndroid Build Coastguard Worker 
583*e01b6f76SAndroid Build Coastguard Worker         // Update the fd and device node when the fd changes. When several
584*e01b6f76SAndroid Build Coastguard Worker         // events are read back-to-back with the same fd, this saves many reads
585*e01b6f76SAndroid Build Coastguard Worker         // from the hash table.
586*e01b6f76SAndroid Build Coastguard Worker         if (inputFd != dataFd) {
587*e01b6f76SAndroid Build Coastguard Worker             inputFd = dataFd;
588*e01b6f76SAndroid Build Coastguard Worker             deviceNode = mDeviceNodes[inputFd];
589*e01b6f76SAndroid Build Coastguard Worker         }
590*e01b6f76SAndroid Build Coastguard Worker         if (deviceNode == nullptr) {
591*e01b6f76SAndroid Build Coastguard Worker             ALOGE("could not find device node for fd %d", inputFd);
592*e01b6f76SAndroid Build Coastguard Worker             continue;
593*e01b6f76SAndroid Build Coastguard Worker         }
594*e01b6f76SAndroid Build Coastguard Worker         if (eventItem.events & EPOLLIN) {
595*e01b6f76SAndroid Build Coastguard Worker             struct input_event ievs[INPUT_MAX_EVENTS];
596*e01b6f76SAndroid Build Coastguard Worker             for (;;) {
597*e01b6f76SAndroid Build Coastguard Worker                 ssize_t readSize = TEMP_FAILURE_RETRY(read(inputFd, ievs, sizeof(ievs)));
598*e01b6f76SAndroid Build Coastguard Worker                 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
599*e01b6f76SAndroid Build Coastguard Worker                     ALOGW("could not get event, removed? (fd: %d, size: %zd errno: %d)",
600*e01b6f76SAndroid Build Coastguard Worker                             inputFd, readSize, errno);
601*e01b6f76SAndroid Build Coastguard Worker 
602*e01b6f76SAndroid Build Coastguard Worker                     removedDeviceFds.push_back(inputFd);
603*e01b6f76SAndroid Build Coastguard Worker                     break;
604*e01b6f76SAndroid Build Coastguard Worker                 } else if (readSize < 0) {
605*e01b6f76SAndroid Build Coastguard Worker                     if (errno != EAGAIN && errno != EINTR) {
606*e01b6f76SAndroid Build Coastguard Worker                         ALOGW("could not get event. errno=%d", errno);
607*e01b6f76SAndroid Build Coastguard Worker                     }
608*e01b6f76SAndroid Build Coastguard Worker                     break;
609*e01b6f76SAndroid Build Coastguard Worker                 } else if (readSize % sizeof(input_event) != 0) {
610*e01b6f76SAndroid Build Coastguard Worker                     ALOGE("could not get event. wrong size=%zd", readSize);
611*e01b6f76SAndroid Build Coastguard Worker                     break;
612*e01b6f76SAndroid Build Coastguard Worker                 } else {
613*e01b6f76SAndroid Build Coastguard Worker                     size_t count = static_cast<size_t>(readSize) / sizeof(struct input_event);
614*e01b6f76SAndroid Build Coastguard Worker                     for (size_t i = 0; i < count; ++i) {
615*e01b6f76SAndroid Build Coastguard Worker                         auto& iev = ievs[i];
616*e01b6f76SAndroid Build Coastguard Worker                         auto when = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec);
617*e01b6f76SAndroid Build Coastguard Worker                         InputEvent inputEvent = { when, iev.type, iev.code, iev.value };
618*e01b6f76SAndroid Build Coastguard Worker                         mInputCallback->onInputEvent(deviceNode, inputEvent, now);
619*e01b6f76SAndroid Build Coastguard Worker                     }
620*e01b6f76SAndroid Build Coastguard Worker                 }
621*e01b6f76SAndroid Build Coastguard Worker             }
622*e01b6f76SAndroid Build Coastguard Worker         } else if (eventItem.events & EPOLLHUP) {
623*e01b6f76SAndroid Build Coastguard Worker             ALOGI("Removing device fd %d due to epoll hangup event.", inputFd);
624*e01b6f76SAndroid Build Coastguard Worker             removedDeviceFds.push_back(inputFd);
625*e01b6f76SAndroid Build Coastguard Worker         } else {
626*e01b6f76SAndroid Build Coastguard Worker             ALOGW("Received unexpected epoll event 0x%08x for device fd %d",
627*e01b6f76SAndroid Build Coastguard Worker                     eventItem.events, inputFd);
628*e01b6f76SAndroid Build Coastguard Worker         }
629*e01b6f76SAndroid Build Coastguard Worker     }
630*e01b6f76SAndroid Build Coastguard Worker 
631*e01b6f76SAndroid Build Coastguard Worker     if (removedDeviceFds.size()) {
632*e01b6f76SAndroid Build Coastguard Worker         for (auto deviceFd : removedDeviceFds) {
633*e01b6f76SAndroid Build Coastguard Worker             auto deviceNode = mDeviceNodes[deviceFd];
634*e01b6f76SAndroid Build Coastguard Worker             if (deviceNode != nullptr) {
635*e01b6f76SAndroid Build Coastguard Worker                 status_t ret = closeNodeByFd(deviceFd);
636*e01b6f76SAndroid Build Coastguard Worker                 if (ret != OK) {
637*e01b6f76SAndroid Build Coastguard Worker                     ALOGW("Could not close device with fd %d. errno=%d", deviceFd, ret);
638*e01b6f76SAndroid Build Coastguard Worker                 } else {
639*e01b6f76SAndroid Build Coastguard Worker                     mInputCallback->onDeviceRemoved(deviceNode);
640*e01b6f76SAndroid Build Coastguard Worker                 }
641*e01b6f76SAndroid Build Coastguard Worker             }
642*e01b6f76SAndroid Build Coastguard Worker         }
643*e01b6f76SAndroid Build Coastguard Worker     }
644*e01b6f76SAndroid Build Coastguard Worker 
645*e01b6f76SAndroid Build Coastguard Worker     if (deviceChange) {
646*e01b6f76SAndroid Build Coastguard Worker         readNotify();
647*e01b6f76SAndroid Build Coastguard Worker     }
648*e01b6f76SAndroid Build Coastguard Worker 
649*e01b6f76SAndroid Build Coastguard Worker     return OK;
650*e01b6f76SAndroid Build Coastguard Worker }
651*e01b6f76SAndroid Build Coastguard Worker 
wake()652*e01b6f76SAndroid Build Coastguard Worker status_t InputHub::wake() {
653*e01b6f76SAndroid Build Coastguard Worker     ALOGV("wake() called");
654*e01b6f76SAndroid Build Coastguard Worker 
655*e01b6f76SAndroid Build Coastguard Worker     uint64_t u = 1;
656*e01b6f76SAndroid Build Coastguard Worker     ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &u, sizeof(uint64_t)));
657*e01b6f76SAndroid Build Coastguard Worker 
658*e01b6f76SAndroid Build Coastguard Worker     if (nWrite != sizeof(uint64_t) && errno != EAGAIN) {
659*e01b6f76SAndroid Build Coastguard Worker         ALOGW("Could not write wake signal, errno=%d", errno);
660*e01b6f76SAndroid Build Coastguard Worker         return -errno;
661*e01b6f76SAndroid Build Coastguard Worker     }
662*e01b6f76SAndroid Build Coastguard Worker     return OK;
663*e01b6f76SAndroid Build Coastguard Worker }
664*e01b6f76SAndroid Build Coastguard Worker 
dump(String8 & dump)665*e01b6f76SAndroid Build Coastguard Worker void InputHub::dump(String8& dump) {
666*e01b6f76SAndroid Build Coastguard Worker     // TODO
667*e01b6f76SAndroid Build Coastguard Worker }
668*e01b6f76SAndroid Build Coastguard Worker 
readNotify()669*e01b6f76SAndroid Build Coastguard Worker status_t InputHub::readNotify() {
670*e01b6f76SAndroid Build Coastguard Worker     char event_buf[512];
671*e01b6f76SAndroid Build Coastguard Worker     struct inotify_event* event;
672*e01b6f76SAndroid Build Coastguard Worker 
673*e01b6f76SAndroid Build Coastguard Worker     ssize_t res = TEMP_FAILURE_RETRY(read(mINotifyFd, event_buf, sizeof(event_buf)));
674*e01b6f76SAndroid Build Coastguard Worker     if (res < static_cast<int>(sizeof(*event))) {
675*e01b6f76SAndroid Build Coastguard Worker         ALOGW("could not get inotify event, %s\n", strerror(errno));
676*e01b6f76SAndroid Build Coastguard Worker         return -errno;
677*e01b6f76SAndroid Build Coastguard Worker     }
678*e01b6f76SAndroid Build Coastguard Worker 
679*e01b6f76SAndroid Build Coastguard Worker     size_t event_pos = 0;
680*e01b6f76SAndroid Build Coastguard Worker     while (res >= static_cast<int>(sizeof(*event))) {
681*e01b6f76SAndroid Build Coastguard Worker         event = reinterpret_cast<struct inotify_event*>(event_buf + event_pos);
682*e01b6f76SAndroid Build Coastguard Worker         if (event->len) {
683*e01b6f76SAndroid Build Coastguard Worker             std::string path = mWatchedPaths[event->wd];
684*e01b6f76SAndroid Build Coastguard Worker             path.append("/").append(event->name);
685*e01b6f76SAndroid Build Coastguard Worker             ALOGV("inotify event for path %s", path.c_str());
686*e01b6f76SAndroid Build Coastguard Worker 
687*e01b6f76SAndroid Build Coastguard Worker             if (event->mask & IN_CREATE) {
688*e01b6f76SAndroid Build Coastguard Worker                 auto deviceNode = openNode(path);
689*e01b6f76SAndroid Build Coastguard Worker                 if (deviceNode == nullptr) {
690*e01b6f76SAndroid Build Coastguard Worker                     ALOGE("could not open device node %s. err=%zd", path.c_str(), res);
691*e01b6f76SAndroid Build Coastguard Worker                 } else {
692*e01b6f76SAndroid Build Coastguard Worker                     mInputCallback->onDeviceAdded(deviceNode);
693*e01b6f76SAndroid Build Coastguard Worker                 }
694*e01b6f76SAndroid Build Coastguard Worker             } else {
695*e01b6f76SAndroid Build Coastguard Worker                 auto deviceNode = findNodeByPath(path);
696*e01b6f76SAndroid Build Coastguard Worker                 if (deviceNode != nullptr) {
697*e01b6f76SAndroid Build Coastguard Worker                     status_t ret = closeNode(deviceNode.get());
698*e01b6f76SAndroid Build Coastguard Worker                     if (ret != OK) {
699*e01b6f76SAndroid Build Coastguard Worker                         ALOGW("Could not close device %s. errno=%d", path.c_str(), ret);
700*e01b6f76SAndroid Build Coastguard Worker                     } else {
701*e01b6f76SAndroid Build Coastguard Worker                         mInputCallback->onDeviceRemoved(deviceNode);
702*e01b6f76SAndroid Build Coastguard Worker                     }
703*e01b6f76SAndroid Build Coastguard Worker                 } else {
704*e01b6f76SAndroid Build Coastguard Worker                     ALOGW("could not find device node for %s", path.c_str());
705*e01b6f76SAndroid Build Coastguard Worker                 }
706*e01b6f76SAndroid Build Coastguard Worker             }
707*e01b6f76SAndroid Build Coastguard Worker         }
708*e01b6f76SAndroid Build Coastguard Worker         int event_size = sizeof(*event) + event->len;
709*e01b6f76SAndroid Build Coastguard Worker         res -= event_size;
710*e01b6f76SAndroid Build Coastguard Worker         event_pos += event_size;
711*e01b6f76SAndroid Build Coastguard Worker     }
712*e01b6f76SAndroid Build Coastguard Worker 
713*e01b6f76SAndroid Build Coastguard Worker     return OK;
714*e01b6f76SAndroid Build Coastguard Worker }
715*e01b6f76SAndroid Build Coastguard Worker 
scanDir(const std::string & path)716*e01b6f76SAndroid Build Coastguard Worker status_t InputHub::scanDir(const std::string& path) {
717*e01b6f76SAndroid Build Coastguard Worker     auto dir = ::opendir(path.c_str());
718*e01b6f76SAndroid Build Coastguard Worker     if (dir == nullptr) {
719*e01b6f76SAndroid Build Coastguard Worker         ALOGE("could not open device path %s to scan for devices. err=%d", path.c_str(), errno);
720*e01b6f76SAndroid Build Coastguard Worker         return -errno;
721*e01b6f76SAndroid Build Coastguard Worker     }
722*e01b6f76SAndroid Build Coastguard Worker 
723*e01b6f76SAndroid Build Coastguard Worker     while (auto dirent = readdir(dir)) {
724*e01b6f76SAndroid Build Coastguard Worker         if (strcmp(dirent->d_name, ".") == 0 ||
725*e01b6f76SAndroid Build Coastguard Worker             strcmp(dirent->d_name, "..") == 0) {
726*e01b6f76SAndroid Build Coastguard Worker             continue;
727*e01b6f76SAndroid Build Coastguard Worker         }
728*e01b6f76SAndroid Build Coastguard Worker         std::string filename = path + "/" + dirent->d_name;
729*e01b6f76SAndroid Build Coastguard Worker         auto node = openNode(filename);
730*e01b6f76SAndroid Build Coastguard Worker         if (node == nullptr) {
731*e01b6f76SAndroid Build Coastguard Worker             ALOGE("could not open device node %s", filename.c_str());
732*e01b6f76SAndroid Build Coastguard Worker         } else {
733*e01b6f76SAndroid Build Coastguard Worker             mInputCallback->onDeviceAdded(node);
734*e01b6f76SAndroid Build Coastguard Worker         }
735*e01b6f76SAndroid Build Coastguard Worker     }
736*e01b6f76SAndroid Build Coastguard Worker     ::closedir(dir);
737*e01b6f76SAndroid Build Coastguard Worker     return OK;
738*e01b6f76SAndroid Build Coastguard Worker }
739*e01b6f76SAndroid Build Coastguard Worker 
openNode(const std::string & path)740*e01b6f76SAndroid Build Coastguard Worker std::shared_ptr<InputDeviceNode> InputHub::openNode(const std::string& path) {
741*e01b6f76SAndroid Build Coastguard Worker     ALOGV("opening %s...", path.c_str());
742*e01b6f76SAndroid Build Coastguard Worker     auto evdevNode = std::shared_ptr<EvdevDeviceNode>(EvdevDeviceNode::openDeviceNode(path));
743*e01b6f76SAndroid Build Coastguard Worker     if (evdevNode == nullptr) {
744*e01b6f76SAndroid Build Coastguard Worker         return nullptr;
745*e01b6f76SAndroid Build Coastguard Worker     }
746*e01b6f76SAndroid Build Coastguard Worker 
747*e01b6f76SAndroid Build Coastguard Worker     auto fd = evdevNode->getFd();
748*e01b6f76SAndroid Build Coastguard Worker     ALOGV("opened %s with fd %d", path.c_str(), fd);
749*e01b6f76SAndroid Build Coastguard Worker     mDeviceNodes[fd] = evdevNode;
750*e01b6f76SAndroid Build Coastguard Worker     struct epoll_event eventItem{};
751*e01b6f76SAndroid Build Coastguard Worker     eventItem.events = EPOLLIN;
752*e01b6f76SAndroid Build Coastguard Worker     if (mWakeupMechanism == WakeMechanism::EPOLL_WAKEUP) {
753*e01b6f76SAndroid Build Coastguard Worker         eventItem.events |= EPOLLWAKEUP;
754*e01b6f76SAndroid Build Coastguard Worker     }
755*e01b6f76SAndroid Build Coastguard Worker     eventItem.data.u32 = fd;
756*e01b6f76SAndroid Build Coastguard Worker     if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
757*e01b6f76SAndroid Build Coastguard Worker         ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
758*e01b6f76SAndroid Build Coastguard Worker         return nullptr;
759*e01b6f76SAndroid Build Coastguard Worker     }
760*e01b6f76SAndroid Build Coastguard Worker 
761*e01b6f76SAndroid Build Coastguard Worker     if (mNeedToCheckSuspendBlockIoctl) {
762*e01b6f76SAndroid Build Coastguard Worker #ifndef EVIOCSSUSPENDBLOCK
763*e01b6f76SAndroid Build Coastguard Worker         // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
764*e01b6f76SAndroid Build Coastguard Worker         // will use an epoll flag instead, so as long as we want to support this
765*e01b6f76SAndroid Build Coastguard Worker         // feature, we need to be prepared to define the ioctl ourselves.
766*e01b6f76SAndroid Build Coastguard Worker #define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
767*e01b6f76SAndroid Build Coastguard Worker #endif
768*e01b6f76SAndroid Build Coastguard Worker         if (TEMP_FAILURE_RETRY(ioctl(fd, EVIOCSSUSPENDBLOCK, 1))) {
769*e01b6f76SAndroid Build Coastguard Worker             // no wake mechanism, continue using explicit wake locks
770*e01b6f76SAndroid Build Coastguard Worker             ALOGI("Using explicit wakelocks to block suspend while processing input events.");
771*e01b6f76SAndroid Build Coastguard Worker         } else {
772*e01b6f76SAndroid Build Coastguard Worker             mWakeupMechanism = WakeMechanism::LEGACY_EVDEV_SUSPENDBLOCK_IOCTL;
773*e01b6f76SAndroid Build Coastguard Worker             // release any held wakelocks since we won't need them anymore
774*e01b6f76SAndroid Build Coastguard Worker             release_wake_lock(WAKE_LOCK_ID);
775*e01b6f76SAndroid Build Coastguard Worker             ALOGI("Using EVIOCSSUSPENDBLOCK to block suspend while processing input events.");
776*e01b6f76SAndroid Build Coastguard Worker         }
777*e01b6f76SAndroid Build Coastguard Worker         mNeedToCheckSuspendBlockIoctl = false;
778*e01b6f76SAndroid Build Coastguard Worker     }
779*e01b6f76SAndroid Build Coastguard Worker 
780*e01b6f76SAndroid Build Coastguard Worker     return evdevNode;
781*e01b6f76SAndroid Build Coastguard Worker }
782*e01b6f76SAndroid Build Coastguard Worker 
closeNode(const InputDeviceNode * node)783*e01b6f76SAndroid Build Coastguard Worker status_t InputHub::closeNode(const InputDeviceNode* node) {
784*e01b6f76SAndroid Build Coastguard Worker     for (const auto& pair : mDeviceNodes) {
785*e01b6f76SAndroid Build Coastguard Worker         if (pair.second.get() == node) {
786*e01b6f76SAndroid Build Coastguard Worker             return closeNodeByFd(pair.first);
787*e01b6f76SAndroid Build Coastguard Worker         }
788*e01b6f76SAndroid Build Coastguard Worker     }
789*e01b6f76SAndroid Build Coastguard Worker     return BAD_VALUE;
790*e01b6f76SAndroid Build Coastguard Worker }
791*e01b6f76SAndroid Build Coastguard Worker 
closeNodeByFd(int fd)792*e01b6f76SAndroid Build Coastguard Worker status_t InputHub::closeNodeByFd(int fd) {
793*e01b6f76SAndroid Build Coastguard Worker     status_t ret = OK;
794*e01b6f76SAndroid Build Coastguard Worker     if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL)) {
795*e01b6f76SAndroid Build Coastguard Worker         ALOGW("Could not remove device fd from epoll instance. errno=%d", errno);
796*e01b6f76SAndroid Build Coastguard Worker         ret = -errno;
797*e01b6f76SAndroid Build Coastguard Worker     }
798*e01b6f76SAndroid Build Coastguard Worker     mDeviceNodes.erase(fd);
799*e01b6f76SAndroid Build Coastguard Worker     ::close(fd);
800*e01b6f76SAndroid Build Coastguard Worker     return ret;
801*e01b6f76SAndroid Build Coastguard Worker }
802*e01b6f76SAndroid Build Coastguard Worker 
findNodeByPath(const std::string & path)803*e01b6f76SAndroid Build Coastguard Worker std::shared_ptr<InputDeviceNode> InputHub::findNodeByPath(const std::string& path) {
804*e01b6f76SAndroid Build Coastguard Worker     for (const auto& pair : mDeviceNodes) {
805*e01b6f76SAndroid Build Coastguard Worker         if (pair.second->getPath() == path) return pair.second;
806*e01b6f76SAndroid Build Coastguard Worker     }
807*e01b6f76SAndroid Build Coastguard Worker     return nullptr;
808*e01b6f76SAndroid Build Coastguard Worker }
809*e01b6f76SAndroid Build Coastguard Worker 
manageWakeLocks() const810*e01b6f76SAndroid Build Coastguard Worker bool InputHub::manageWakeLocks() const {
811*e01b6f76SAndroid Build Coastguard Worker     return mWakeupMechanism != WakeMechanism::EPOLL_WAKEUP;
812*e01b6f76SAndroid Build Coastguard Worker }
813*e01b6f76SAndroid Build Coastguard Worker 
814*e01b6f76SAndroid Build Coastguard Worker }  // namespace android
815