blob: 8f34e8afcdd3a112bef05f88328d661e9fef4024 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2005 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
Mark Salyzyn5aa26b22014-06-10 13:07:44 -070017#include <assert.h>
18#include <dirent.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <inttypes.h>
22#include <memory.h>
23#include <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Siarhei Vishniakou7a522bf2019-09-24 12:46:29 +010027#include <sys/capability.h>
Mark Salyzyn5aa26b22014-06-10 13:07:44 -070028#include <sys/epoll.h>
Mark Salyzyn5aa26b22014-06-10 13:07:44 -070029#include <sys/inotify.h>
30#include <sys/ioctl.h>
Prabir Pradhanda7c00c2019-08-29 14:12:42 -070031#include <sys/limits.h>
Mark Salyzyn5aa26b22014-06-10 13:07:44 -070032#include <unistd.h>
33
Michael Wrightd02c5b62014-02-10 15:10:22 -080034#define LOG_TAG "EventHub"
35
36// #define LOG_NDEBUG 0
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -080037#include <android-base/stringprintf.h>
Philip Quinn39b81682019-01-09 22:20:39 -080038#include <cutils/properties.h>
Chris Ye8594e192020-07-14 10:34:06 -070039#include <input/KeyCharacterMap.h>
40#include <input/KeyLayoutMap.h>
41#include <input/VirtualKeyMap.h>
Dan Albert677d87e2014-06-16 17:31:28 -070042#include <openssl/sha.h>
Prabir Pradhanda7c00c2019-08-29 14:12:42 -070043#include <utils/Errors.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080044#include <utils/Log.h>
45#include <utils/Timers.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080046
Chris Ye8594e192020-07-14 10:34:06 -070047#include <filesystem>
48
49#include "EventHub.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080050
Michael Wrightd02c5b62014-02-10 15:10:22 -080051#define INDENT " "
52#define INDENT2 " "
53#define INDENT3 " "
54
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -080055using android::base::StringPrintf;
Chris Ye1b0c7342020-07-28 21:57:03 -070056using namespace android::flag_operators;
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -080057
Michael Wrightd02c5b62014-02-10 15:10:22 -080058namespace android {
59
Prabir Pradhanda7c00c2019-08-29 14:12:42 -070060static const char* DEVICE_PATH = "/dev/input";
Siarhei Vishniakou951f3622018-12-12 19:45:42 -080061// v4l2 devices go directly into /dev
Prabir Pradhanda7c00c2019-08-29 14:12:42 -070062static const char* VIDEO_DEVICE_PATH = "/dev";
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
Michael Wrightd02c5b62014-02-10 15:10:22 -080064static inline const char* toString(bool value) {
65 return value ? "true" : "false";
66}
67
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +010068static std::string sha1(const std::string& in) {
Dan Albert677d87e2014-06-16 17:31:28 -070069 SHA_CTX ctx;
70 SHA1_Init(&ctx);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +010071 SHA1_Update(&ctx, reinterpret_cast<const u_char*>(in.c_str()), in.size());
Dan Albert677d87e2014-06-16 17:31:28 -070072 u_char digest[SHA_DIGEST_LENGTH];
73 SHA1_Final(digest, &ctx);
Michael Wrightd02c5b62014-02-10 15:10:22 -080074
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +010075 std::string out;
Dan Albert677d87e2014-06-16 17:31:28 -070076 for (size_t i = 0; i < SHA_DIGEST_LENGTH; i++) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +010077 out += StringPrintf("%02x", digest[i]);
Michael Wrightd02c5b62014-02-10 15:10:22 -080078 }
79 return out;
80}
81
Siarhei Vishniakou951f3622018-12-12 19:45:42 -080082/**
83 * Return true if name matches "v4l-touch*"
84 */
Chris Ye8594e192020-07-14 10:34:06 -070085static bool isV4lTouchNode(std::string name) {
86 return name.find("v4l-touch") != std::string::npos;
Siarhei Vishniakou951f3622018-12-12 19:45:42 -080087}
88
Philip Quinn39b81682019-01-09 22:20:39 -080089/**
90 * Returns true if V4L devices should be scanned.
91 *
92 * The system property ro.input.video_enabled can be used to control whether
93 * EventHub scans and opens V4L devices. As V4L does not support multiple
94 * clients, EventHub effectively blocks access to these devices when it opens
Siarhei Vishniakou29f88492019-04-05 14:11:43 -070095 * them.
96 *
97 * Setting this to "false" would prevent any video devices from being discovered and
98 * associated with input devices.
99 *
100 * This property can be used as follows:
101 * 1. To turn off features that are dependent on video device presence.
102 * 2. During testing and development, to allow other clients to read video devices
103 * directly from /dev.
Philip Quinn39b81682019-01-09 22:20:39 -0800104 */
105static bool isV4lScanningEnabled() {
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700106 return property_get_bool("ro.input.video_enabled", true /* default_value */);
Philip Quinn39b81682019-01-09 22:20:39 -0800107}
108
Siarhei Vishniakou592bac22018-11-08 19:42:38 -0800109static nsecs_t processEventTimestamp(const struct input_event& event) {
110 // Use the time specified in the event instead of the current time
111 // so that downstream code can get more accurate estimates of
112 // event dispatch latency from the time the event is enqueued onto
113 // the evdev client buffer.
114 //
115 // The event's timestamp fortuitously uses the same monotonic clock
116 // time base as the rest of Android. The kernel event device driver
117 // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts().
118 // The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere
119 // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a
120 // system call that also queries ktime_get_ts().
121
122 const nsecs_t inputEventTime = seconds_to_nanoseconds(event.time.tv_sec) +
123 microseconds_to_nanoseconds(event.time.tv_usec);
124 return inputEventTime;
125}
126
Michael Wrightd02c5b62014-02-10 15:10:22 -0800127// --- Global Functions ---
128
Chris Ye1b0c7342020-07-28 21:57:03 -0700129Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800130 // Touch devices get dibs on touch-related axes.
Chris Ye1b0c7342020-07-28 21:57:03 -0700131 if (deviceClasses.test(InputDeviceClass::TOUCH)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800132 switch (axis) {
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700133 case ABS_X:
134 case ABS_Y:
135 case ABS_PRESSURE:
136 case ABS_TOOL_WIDTH:
137 case ABS_DISTANCE:
138 case ABS_TILT_X:
139 case ABS_TILT_Y:
140 case ABS_MT_SLOT:
141 case ABS_MT_TOUCH_MAJOR:
142 case ABS_MT_TOUCH_MINOR:
143 case ABS_MT_WIDTH_MAJOR:
144 case ABS_MT_WIDTH_MINOR:
145 case ABS_MT_ORIENTATION:
146 case ABS_MT_POSITION_X:
147 case ABS_MT_POSITION_Y:
148 case ABS_MT_TOOL_TYPE:
149 case ABS_MT_BLOB_ID:
150 case ABS_MT_TRACKING_ID:
151 case ABS_MT_PRESSURE:
152 case ABS_MT_DISTANCE:
Chris Ye1b0c7342020-07-28 21:57:03 -0700153 return InputDeviceClass::TOUCH;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154 }
155 }
156
Michael Wright842500e2015-03-13 17:32:02 -0700157 // External stylus gets the pressure axis
Chris Ye1b0c7342020-07-28 21:57:03 -0700158 if (deviceClasses.test(InputDeviceClass::EXTERNAL_STYLUS)) {
Michael Wright842500e2015-03-13 17:32:02 -0700159 if (axis == ABS_PRESSURE) {
Chris Ye1b0c7342020-07-28 21:57:03 -0700160 return InputDeviceClass::EXTERNAL_STYLUS;
Michael Wright842500e2015-03-13 17:32:02 -0700161 }
162 }
163
Michael Wrightd02c5b62014-02-10 15:10:22 -0800164 // Joystick devices get the rest.
Chris Ye1b0c7342020-07-28 21:57:03 -0700165 return deviceClasses & InputDeviceClass::JOYSTICK;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800166}
167
168// --- EventHub::Device ---
169
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100170EventHub::Device::Device(int fd, int32_t id, const std::string& path,
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700171 const InputDeviceIdentifier& identifier)
Chris Ye989bb932020-07-04 16:18:59 -0700172 : fd(fd),
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700173 id(id),
174 path(path),
175 identifier(identifier),
176 classes(0),
177 configuration(nullptr),
178 virtualKeyMap(nullptr),
179 ffEffectPlaying(false),
180 ffEffectId(-1),
181 controllerNumber(0),
182 enabled(true),
Chris Ye66fbac32020-07-06 20:36:43 -0700183 isVirtual(fd < 0) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800184
185EventHub::Device::~Device() {
186 close();
187 delete configuration;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188}
189
190void EventHub::Device::close() {
191 if (fd >= 0) {
192 ::close(fd);
193 fd = -1;
194 }
195}
196
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700197status_t EventHub::Device::enable() {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100198 fd = open(path.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700199 if (fd < 0) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100200 ALOGE("could not open %s, %s\n", path.c_str(), strerror(errno));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700201 return -errno;
202 }
203 enabled = true;
204 return OK;
205}
206
207status_t EventHub::Device::disable() {
208 close();
209 enabled = false;
210 return OK;
211}
212
Chris Ye989bb932020-07-04 16:18:59 -0700213bool EventHub::Device::hasValidFd() const {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700214 return !isVirtual && enabled;
215}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800216
Chris Ye989bb932020-07-04 16:18:59 -0700217const sp<KeyCharacterMap>& EventHub::Device::getKeyCharacterMap() const {
218 if (combinedKeyMap != nullptr) {
219 return combinedKeyMap;
220 }
221 return keyMap.keyCharacterMap;
222}
223
224template <std::size_t N>
225status_t EventHub::Device::readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray) {
226 if (!hasValidFd()) {
227 return BAD_VALUE;
228 }
229 if ((_IOC_SIZE(ioctlCode) == 0)) {
230 ioctlCode |= _IOC(0, 0, 0, bitArray.bytes());
231 }
232
233 typename BitArray<N>::Buffer buffer;
234 status_t ret = ioctl(fd, ioctlCode, buffer.data());
235 bitArray.loadFromBuffer(buffer);
236 return ret;
237}
238
239void EventHub::Device::configureFd() {
240 // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
241 if (classes.test(InputDeviceClass::KEYBOARD)) {
242 // Disable kernel key repeat since we handle it ourselves
243 unsigned int repeatRate[] = {0, 0};
244 if (ioctl(fd, EVIOCSREP, repeatRate)) {
245 ALOGW("Unable to disable kernel key repeat for %s: %s", path.c_str(), strerror(errno));
246 }
247 }
248
249 // Tell the kernel that we want to use the monotonic clock for reporting timestamps
250 // associated with input events. This is important because the input system
251 // uses the timestamps extensively and assumes they were recorded using the monotonic
252 // clock.
253 int clockId = CLOCK_MONOTONIC;
254 bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
255 ALOGI("usingClockIoctl=%s", toString(usingClockIoctl));
256}
257
258bool EventHub::Device::hasKeycodeLocked(int keycode) const {
259 if (!keyMap.haveKeyLayout()) {
260 return false;
261 }
262
263 std::vector<int32_t> scanCodes;
264 keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
265 const size_t N = scanCodes.size();
266 for (size_t i = 0; i < N && i <= KEY_MAX; i++) {
267 int32_t sc = scanCodes[i];
268 if (sc >= 0 && sc <= KEY_MAX && keyBitmask.test(sc)) {
269 return true;
270 }
271 }
272
273 return false;
274}
275
276void EventHub::Device::loadConfigurationLocked() {
277 configurationFile =
278 getInputDeviceConfigurationFilePathByDeviceIdentifier(identifier,
279 InputDeviceConfigurationFileType::
280 CONFIGURATION);
281 if (configurationFile.empty()) {
282 ALOGD("No input device configuration file found for device '%s'.", identifier.name.c_str());
283 } else {
284 status_t status = PropertyMap::load(String8(configurationFile.c_str()), &configuration);
285 if (status) {
286 ALOGE("Error loading input device configuration file for device '%s'. "
287 "Using default configuration.",
288 identifier.name.c_str());
289 }
290 }
291}
292
293bool EventHub::Device::loadVirtualKeyMapLocked() {
294 // The virtual key map is supplied by the kernel as a system board property file.
295 std::string propPath = "/sys/board_properties/virtualkeys.";
296 propPath += identifier.getCanonicalName();
297 if (access(propPath.c_str(), R_OK)) {
298 return false;
299 }
300 virtualKeyMap = VirtualKeyMap::load(propPath);
301 return virtualKeyMap != nullptr;
302}
303
304status_t EventHub::Device::loadKeyMapLocked() {
305 return keyMap.load(identifier, configuration);
306}
307
308bool EventHub::Device::isExternalDeviceLocked() {
309 if (configuration) {
310 bool value;
311 if (configuration->tryGetProperty(String8("device.internal"), value)) {
312 return !value;
313 }
314 }
315 return identifier.bus == BUS_USB || identifier.bus == BUS_BLUETOOTH;
316}
317
318bool EventHub::Device::deviceHasMicLocked() {
319 if (configuration) {
320 bool value;
321 if (configuration->tryGetProperty(String8("audio.mic"), value)) {
322 return value;
323 }
324 }
325 return false;
326}
327
328void EventHub::Device::setLedStateLocked(int32_t led, bool on) {
329 int32_t sc;
330 if (hasValidFd() && mapLed(led, &sc) != NAME_NOT_FOUND) {
331 struct input_event ev;
332 ev.time.tv_sec = 0;
333 ev.time.tv_usec = 0;
334 ev.type = EV_LED;
335 ev.code = sc;
336 ev.value = on ? 1 : 0;
337
338 ssize_t nWrite;
339 do {
340 nWrite = write(fd, &ev, sizeof(struct input_event));
341 } while (nWrite == -1 && errno == EINTR);
342 }
343}
344
345void EventHub::Device::setLedForControllerLocked() {
346 for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
347 setLedStateLocked(ALED_CONTROLLER_1 + i, controllerNumber == i + 1);
348 }
349}
350
351status_t EventHub::Device::mapLed(int32_t led, int32_t* outScanCode) const {
352 if (!keyMap.haveKeyLayout()) {
353 return NAME_NOT_FOUND;
354 }
355
356 int32_t scanCode;
357 if (keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
358 if (scanCode >= 0 && scanCode <= LED_MAX && ledBitmask.test(scanCode)) {
359 *outScanCode = scanCode;
360 return NO_ERROR;
361 }
362 }
363 return NAME_NOT_FOUND;
364}
365
Siarhei Vishniakou7a522bf2019-09-24 12:46:29 +0100366/**
367 * Get the capabilities for the current process.
368 * Crashes the system if unable to create / check / destroy the capabilities object.
369 */
370class Capabilities final {
371public:
372 explicit Capabilities() {
373 mCaps = cap_get_proc();
374 LOG_ALWAYS_FATAL_IF(mCaps == nullptr, "Could not get capabilities of the current process");
375 }
376
377 /**
378 * Check whether the current process has a specific capability
379 * in the set of effective capabilities.
380 * Return CAP_SET if the process has the requested capability
381 * Return CAP_CLEAR otherwise.
382 */
383 cap_flag_value_t checkEffectiveCapability(cap_value_t capability) {
384 cap_flag_value_t value;
385 const int result = cap_get_flag(mCaps, capability, CAP_EFFECTIVE, &value);
386 LOG_ALWAYS_FATAL_IF(result == -1, "Could not obtain the requested capability");
387 return value;
388 }
389
390 ~Capabilities() {
391 const int result = cap_free(mCaps);
392 LOG_ALWAYS_FATAL_IF(result == -1, "Could not release the capabilities structure");
393 }
394
395private:
396 cap_t mCaps;
397};
398
399static void ensureProcessCanBlockSuspend() {
400 Capabilities capabilities;
401 const bool canBlockSuspend =
402 capabilities.checkEffectiveCapability(CAP_BLOCK_SUSPEND) == CAP_SET;
403 LOG_ALWAYS_FATAL_IF(!canBlockSuspend,
404 "Input must be able to block suspend to properly process events");
405}
406
Michael Wrightd02c5b62014-02-10 15:10:22 -0800407// --- EventHub ---
408
Michael Wrightd02c5b62014-02-10 15:10:22 -0800409const int EventHub::EPOLL_MAX_EVENTS;
410
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700411EventHub::EventHub(void)
412 : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
413 mNextDeviceId(1),
414 mControllerNumbers(),
Chris Ye989bb932020-07-04 16:18:59 -0700415 mOpeningDevices(0),
416 mClosingDevices(0),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800417 mNeedToSendFinishedDeviceScan(false),
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700418 mNeedToReopenDevices(false),
419 mNeedToScanDevices(true),
420 mPendingEventCount(0),
421 mPendingEventIndex(0),
422 mPendingINotify(false) {
Siarhei Vishniakou7a522bf2019-09-24 12:46:29 +0100423 ensureProcessCanBlockSuspend();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800424
Nick Kralevichfcf1b2b2018-12-15 11:59:30 -0800425 mEpollFd = epoll_create1(EPOLL_CLOEXEC);
Siarhei Vishniakou951f3622018-12-12 19:45:42 -0800426 LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
Michael Wrightd02c5b62014-02-10 15:10:22 -0800427
428 mINotifyFd = inotify_init();
Siarhei Vishniakou951f3622018-12-12 19:45:42 -0800429 mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700430 LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s", DEVICE_PATH,
431 strerror(errno));
Philip Quinn39b81682019-01-09 22:20:39 -0800432 if (isV4lScanningEnabled()) {
433 mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
434 LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700435 VIDEO_DEVICE_PATH, strerror(errno));
Philip Quinn39b81682019-01-09 22:20:39 -0800436 } else {
437 mVideoWd = -1;
438 ALOGI("Video device scanning disabled");
439 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800440
Siarhei Vishniakou2d0e9482019-09-24 12:52:47 +0100441 struct epoll_event eventItem = {};
442 eventItem.events = EPOLLIN | EPOLLWAKEUP;
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -0700443 eventItem.data.fd = mINotifyFd;
Siarhei Vishniakou951f3622018-12-12 19:45:42 -0800444 int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800445 LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
446
447 int wakeFds[2];
448 result = pipe(wakeFds);
449 LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
450
451 mWakeReadPipeFd = wakeFds[0];
452 mWakeWritePipeFd = wakeFds[1];
453
454 result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
455 LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700456 errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800457
458 result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
459 LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700460 errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800461
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -0700462 eventItem.data.fd = mWakeReadPipeFd;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800463 result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
464 LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700465 errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800466}
467
468EventHub::~EventHub(void) {
469 closeAllDevicesLocked();
470
Chris Ye989bb932020-07-04 16:18:59 -0700471 mClosingDevices.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800472
473 ::close(mEpollFd);
474 ::close(mINotifyFd);
475 ::close(mWakeReadPipeFd);
476 ::close(mWakeWritePipeFd);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800477}
478
479InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
480 AutoMutex _l(mLock);
481 Device* device = getDeviceLocked(deviceId);
Chris Ye989bb932020-07-04 16:18:59 -0700482 return device != nullptr ? device->identifier : InputDeviceIdentifier();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800483}
484
Chris Ye1b0c7342020-07-28 21:57:03 -0700485Flags<InputDeviceClass> EventHub::getDeviceClasses(int32_t deviceId) const {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800486 AutoMutex _l(mLock);
487 Device* device = getDeviceLocked(deviceId);
Chris Ye989bb932020-07-04 16:18:59 -0700488 return device != nullptr ? device->classes : Flags<InputDeviceClass>(0);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800489}
490
491int32_t EventHub::getDeviceControllerNumber(int32_t deviceId) const {
492 AutoMutex _l(mLock);
493 Device* device = getDeviceLocked(deviceId);
Chris Ye989bb932020-07-04 16:18:59 -0700494 return device != nullptr ? device->controllerNumber : 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800495}
496
497void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
498 AutoMutex _l(mLock);
499 Device* device = getDeviceLocked(deviceId);
Chris Ye989bb932020-07-04 16:18:59 -0700500 if (device != nullptr && device->configuration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800501 *outConfiguration = *device->configuration;
502 } else {
503 outConfiguration->clear();
504 }
505}
506
507status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700508 RawAbsoluteAxisInfo* outAxisInfo) const {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800509 outAxisInfo->clear();
510
511 if (axis >= 0 && axis <= ABS_MAX) {
512 AutoMutex _l(mLock);
513
514 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700515 if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800516 struct input_absinfo info;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700517 if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
518 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
519 device->identifier.name.c_str(), device->fd, errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800520 return -errno;
521 }
522
523 if (info.minimum != info.maximum) {
524 outAxisInfo->valid = true;
525 outAxisInfo->minValue = info.minimum;
526 outAxisInfo->maxValue = info.maximum;
527 outAxisInfo->flat = info.flat;
528 outAxisInfo->fuzz = info.fuzz;
529 outAxisInfo->resolution = info.resolution;
530 }
531 return OK;
532 }
533 }
534 return -1;
535}
536
537bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
538 if (axis >= 0 && axis <= REL_MAX) {
539 AutoMutex _l(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800540 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700541 return device != nullptr ? device->relBitmask.test(axis) : false;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 }
543 return false;
544}
545
546bool EventHub::hasInputProperty(int32_t deviceId, int property) const {
Chris Ye989bb932020-07-04 16:18:59 -0700547 AutoMutex _l(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800548
Chris Ye989bb932020-07-04 16:18:59 -0700549 Device* device = getDeviceLocked(deviceId);
550 return property >= 0 && property <= INPUT_PROP_MAX && device != nullptr
551 ? device->propBitmask.test(property)
552 : false;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553}
554
555int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
556 if (scanCode >= 0 && scanCode <= KEY_MAX) {
557 AutoMutex _l(mLock);
558
559 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700560 if (device != nullptr && device->hasValidFd() && device->keyBitmask.test(scanCode)) {
561 if (device->readDeviceBitMask(EVIOCGKEY(0), device->keyState) >= 0) {
562 return device->keyState.test(scanCode) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563 }
564 }
565 }
566 return AKEY_STATE_UNKNOWN;
567}
568
569int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
570 AutoMutex _l(mLock);
571
572 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700573 if (device != nullptr && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800574 std::vector<int32_t> scanCodes;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800575 device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
576 if (scanCodes.size() != 0) {
Chris Ye66fbac32020-07-06 20:36:43 -0700577 if (device->readDeviceBitMask(EVIOCGKEY(0), device->keyState) >= 0) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800578 for (size_t i = 0; i < scanCodes.size(); i++) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800579 int32_t sc = scanCodes[i];
Chris Ye66fbac32020-07-06 20:36:43 -0700580 if (sc >= 0 && sc <= KEY_MAX && device->keyState.test(sc)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800581 return AKEY_STATE_DOWN;
582 }
583 }
584 return AKEY_STATE_UP;
585 }
586 }
587 }
588 return AKEY_STATE_UNKNOWN;
589}
590
591int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
592 if (sw >= 0 && sw <= SW_MAX) {
593 AutoMutex _l(mLock);
594
595 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700596 if (device != nullptr && device->hasValidFd() && device->swBitmask.test(sw)) {
597 if (device->readDeviceBitMask(EVIOCGSW(0), device->swState) >= 0) {
598 return device->swState.test(sw) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 }
600 }
601 }
602 return AKEY_STATE_UNKNOWN;
603}
604
605status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const {
606 *outValue = 0;
607
608 if (axis >= 0 && axis <= ABS_MAX) {
609 AutoMutex _l(mLock);
610
611 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700612 if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800613 struct input_absinfo info;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700614 if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
615 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
616 device->identifier.name.c_str(), device->fd, errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617 return -errno;
618 }
619
620 *outValue = info.value;
621 return OK;
622 }
623 }
624 return -1;
625}
626
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700627bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
628 uint8_t* outFlags) const {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800629 AutoMutex _l(mLock);
630
631 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700632 if (device != nullptr && device->keyMap.haveKeyLayout()) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800633 std::vector<int32_t> scanCodes;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
635 scanCodes.clear();
636
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700637 status_t err = device->keyMap.keyLayoutMap->findScanCodesForKey(keyCodes[codeIndex],
638 &scanCodes);
639 if (!err) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 // check the possible scan codes identified by the layout map against the
641 // map of codes actually emitted by the driver
642 for (size_t sc = 0; sc < scanCodes.size(); sc++) {
Chris Ye66fbac32020-07-06 20:36:43 -0700643 if (device->keyBitmask.test(scanCodes[sc])) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800644 outFlags[codeIndex] = 1;
645 break;
646 }
647 }
648 }
649 }
650 return true;
651 }
652 return false;
653}
654
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700655status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
656 int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800657 AutoMutex _l(mLock);
658 Device* device = getDeviceLocked(deviceId);
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -0700659 status_t status = NAME_NOT_FOUND;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660
Chris Ye66fbac32020-07-06 20:36:43 -0700661 if (device != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800662 // Check the key character map first.
663 sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
Yi Kong9b14ac62018-07-17 13:48:38 -0700664 if (kcm != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665 if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
666 *outFlags = 0;
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -0700667 status = NO_ERROR;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800668 }
669 }
670
671 // Check the key layout next.
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -0700672 if (status != NO_ERROR && device->keyMap.haveKeyLayout()) {
Siarhei Vishniakou592bac22018-11-08 19:42:38 -0800673 if (!device->keyMap.keyLayoutMap->mapKey(scanCode, usageCode, outKeycode, outFlags)) {
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -0700674 status = NO_ERROR;
675 }
676 }
677
678 if (status == NO_ERROR) {
Yi Kong9b14ac62018-07-17 13:48:38 -0700679 if (kcm != nullptr) {
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -0700680 kcm->tryRemapKey(*outKeycode, metaState, outKeycode, outMetaState);
681 } else {
682 *outMetaState = metaState;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800683 }
684 }
685 }
686
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -0700687 if (status != NO_ERROR) {
688 *outKeycode = 0;
689 *outFlags = 0;
690 *outMetaState = metaState;
691 }
692
693 return status;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694}
695
696status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const {
697 AutoMutex _l(mLock);
698 Device* device = getDeviceLocked(deviceId);
699
Chris Ye66fbac32020-07-06 20:36:43 -0700700 if (device != nullptr && device->keyMap.haveKeyLayout()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800701 status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo);
702 if (err == NO_ERROR) {
703 return NO_ERROR;
704 }
705 }
706
707 return NAME_NOT_FOUND;
708}
709
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100710void EventHub::setExcludedDevices(const std::vector<std::string>& devices) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800711 AutoMutex _l(mLock);
712
713 mExcludedDevices = devices;
714}
715
716bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
717 AutoMutex _l(mLock);
718 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700719 if (device != nullptr && scanCode >= 0 && scanCode <= KEY_MAX) {
720 return device->keyBitmask.test(scanCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800721 }
722 return false;
723}
724
725bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
726 AutoMutex _l(mLock);
727 Device* device = getDeviceLocked(deviceId);
728 int32_t sc;
Chris Ye989bb932020-07-04 16:18:59 -0700729 if (device != nullptr && device->mapLed(led, &sc) == NO_ERROR) {
Chris Ye66fbac32020-07-06 20:36:43 -0700730 return device->ledBitmask.test(sc);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800731 }
732 return false;
733}
734
735void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
736 AutoMutex _l(mLock);
737 Device* device = getDeviceLocked(deviceId);
Chris Ye989bb932020-07-04 16:18:59 -0700738 if (device != nullptr && device->hasValidFd()) {
739 device->setLedStateLocked(led, on);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 }
741}
742
743void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700744 std::vector<VirtualKeyDefinition>& outVirtualKeys) const {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800745 outVirtualKeys.clear();
746
747 AutoMutex _l(mLock);
748 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700749 if (device != nullptr && device->virtualKeyMap) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800750 const std::vector<VirtualKeyDefinition> virtualKeys =
751 device->virtualKeyMap->getVirtualKeys();
752 outVirtualKeys.insert(outVirtualKeys.end(), virtualKeys.begin(), virtualKeys.end());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 }
754}
755
756sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
757 AutoMutex _l(mLock);
758 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700759 if (device != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800760 return device->getKeyCharacterMap();
761 }
Yi Kong9b14ac62018-07-17 13:48:38 -0700762 return nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800763}
764
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700765bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800766 AutoMutex _l(mLock);
767 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700768 if (device != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800769 if (map != device->overlayKeyMap) {
770 device->overlayKeyMap = map;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700771 device->combinedKeyMap = KeyCharacterMap::combine(device->keyMap.keyCharacterMap, map);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800772 return true;
773 }
774 }
775 return false;
776}
777
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100778static std::string generateDescriptor(InputDeviceIdentifier& identifier) {
779 std::string rawDescriptor;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700780 rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor, identifier.product);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800781 // TODO add handling for USB devices to not uniqueify kbs that show up twice
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100782 if (!identifier.uniqueId.empty()) {
783 rawDescriptor += "uniqueId:";
784 rawDescriptor += identifier.uniqueId;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800785 } else if (identifier.nonce != 0) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100786 rawDescriptor += StringPrintf("nonce:%04x", identifier.nonce);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787 }
788
789 if (identifier.vendor == 0 && identifier.product == 0) {
790 // If we don't know the vendor and product id, then the device is probably
791 // built-in so we need to rely on other information to uniquely identify
792 // the input device. Usually we try to avoid relying on the device name or
793 // location but for built-in input device, they are unlikely to ever change.
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100794 if (!identifier.name.empty()) {
795 rawDescriptor += "name:";
796 rawDescriptor += identifier.name;
797 } else if (!identifier.location.empty()) {
798 rawDescriptor += "location:";
799 rawDescriptor += identifier.location;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 }
801 }
802 identifier.descriptor = sha1(rawDescriptor);
803 return rawDescriptor;
804}
805
806void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) {
807 // Compute a device descriptor that uniquely identifies the device.
808 // The descriptor is assumed to be a stable identifier. Its value should not
809 // change between reboots, reconnections, firmware updates or new releases
810 // of Android. In practice we sometimes get devices that cannot be uniquely
811 // identified. In this case we enforce uniqueness between connected devices.
812 // Ideally, we also want the descriptor to be short and relatively opaque.
813
814 identifier.nonce = 0;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100815 std::string rawDescriptor = generateDescriptor(identifier);
816 if (identifier.uniqueId.empty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800817 // If it didn't have a unique id check for conflicts and enforce
818 // uniqueness if necessary.
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700819 while (getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800820 identifier.nonce++;
821 rawDescriptor = generateDescriptor(identifier);
822 }
823 }
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100824 ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700825 identifier.descriptor.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826}
827
Nathaniel R. Lewiscacd69a2019-08-12 22:07:00 +0000828void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800829 AutoMutex _l(mLock);
830 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700831 if (device != nullptr && device->hasValidFd()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800832 ff_effect effect;
833 memset(&effect, 0, sizeof(effect));
834 effect.type = FF_RUMBLE;
835 effect.id = device->ffEffectId;
Nathaniel R. Lewiscacd69a2019-08-12 22:07:00 +0000836 // evdev FF_RUMBLE effect only supports two channels of vibration.
837 effect.u.rumble.strong_magnitude = element.getChannel(0);
838 effect.u.rumble.weak_magnitude = element.getChannel(1);
839 effect.replay.length = element.duration.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800840 effect.replay.delay = 0;
841 if (ioctl(device->fd, EVIOCSFF, &effect)) {
842 ALOGW("Could not upload force feedback effect to device %s due to error %d.",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700843 device->identifier.name.c_str(), errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800844 return;
845 }
846 device->ffEffectId = effect.id;
847
848 struct input_event ev;
849 ev.time.tv_sec = 0;
850 ev.time.tv_usec = 0;
851 ev.type = EV_FF;
852 ev.code = device->ffEffectId;
853 ev.value = 1;
854 if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
855 ALOGW("Could not start force feedback effect on device %s due to error %d.",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700856 device->identifier.name.c_str(), errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800857 return;
858 }
859 device->ffEffectPlaying = true;
860 }
861}
862
863void EventHub::cancelVibrate(int32_t deviceId) {
864 AutoMutex _l(mLock);
865 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -0700866 if (device != nullptr && device->hasValidFd()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800867 if (device->ffEffectPlaying) {
868 device->ffEffectPlaying = false;
869
870 struct input_event ev;
871 ev.time.tv_sec = 0;
872 ev.time.tv_usec = 0;
873 ev.type = EV_FF;
874 ev.code = device->ffEffectId;
875 ev.value = 0;
876 if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
877 ALOGW("Could not stop force feedback effect on device %s due to error %d.",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700878 device->identifier.name.c_str(), errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800879 return;
880 }
881 }
882 }
883}
884
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100885EventHub::Device* EventHub::getDeviceByDescriptorLocked(const std::string& descriptor) const {
Chris Ye989bb932020-07-04 16:18:59 -0700886 for (const auto& [id, device] : mDevices) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100887 if (descriptor == device->identifier.descriptor) {
Chris Ye989bb932020-07-04 16:18:59 -0700888 return device.get();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800889 }
890 }
Yi Kong9b14ac62018-07-17 13:48:38 -0700891 return nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800892}
893
894EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
Prabir Pradhancae4b3a2019-02-05 18:51:32 -0800895 if (deviceId == ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800896 deviceId = mBuiltInKeyboardId;
897 }
Chris Ye989bb932020-07-04 16:18:59 -0700898 const auto& it = mDevices.find(deviceId);
899 return it != mDevices.end() ? it->second.get() : nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800900}
901
Chris Ye8594e192020-07-14 10:34:06 -0700902EventHub::Device* EventHub::getDeviceByPathLocked(const std::string& devicePath) const {
Chris Ye989bb932020-07-04 16:18:59 -0700903 for (const auto& [id, device] : mDevices) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800904 if (device->path == devicePath) {
Chris Ye989bb932020-07-04 16:18:59 -0700905 return device.get();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800906 }
907 }
Yi Kong9b14ac62018-07-17 13:48:38 -0700908 return nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800909}
910
Siarhei Vishniakou12598682018-11-02 17:19:19 -0700911/**
912 * The file descriptor could be either input device, or a video device (associated with a
913 * specific input device). Check both cases here, and return the device that this event
914 * belongs to. Caller can compare the fd's once more to determine event type.
915 * Looks through all input devices, and only attached video devices. Unattached video
916 * devices are ignored.
917 */
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -0700918EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const {
Chris Ye989bb932020-07-04 16:18:59 -0700919 for (const auto& [id, device] : mDevices) {
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -0700920 if (device->fd == fd) {
Siarhei Vishniakou12598682018-11-02 17:19:19 -0700921 // This is an input device event
Chris Ye989bb932020-07-04 16:18:59 -0700922 return device.get();
Siarhei Vishniakou12598682018-11-02 17:19:19 -0700923 }
924 if (device->videoDevice && device->videoDevice->getFd() == fd) {
925 // This is a video device event
Chris Ye989bb932020-07-04 16:18:59 -0700926 return device.get();
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -0700927 }
928 }
Siarhei Vishniakou12598682018-11-02 17:19:19 -0700929 // We do not check mUnattachedVideoDevices here because they should not participate in epoll,
930 // and therefore should never be looked up by fd.
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -0700931 return nullptr;
932}
933
Michael Wrightd02c5b62014-02-10 15:10:22 -0800934size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
935 ALOG_ASSERT(bufferSize >= 1);
936
937 AutoMutex _l(mLock);
938
939 struct input_event readBuffer[bufferSize];
940
941 RawEvent* event = buffer;
942 size_t capacity = bufferSize;
943 bool awoken = false;
944 for (;;) {
945 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
946
947 // Reopen input devices if needed.
948 if (mNeedToReopenDevices) {
949 mNeedToReopenDevices = false;
950
951 ALOGI("Reopening all input devices due to a configuration change.");
952
953 closeAllDevicesLocked();
954 mNeedToScanDevices = true;
955 break; // return to the caller before we actually rescan
956 }
957
958 // Report any devices that had last been added/removed.
Chris Ye989bb932020-07-04 16:18:59 -0700959 for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
960 std::unique_ptr<Device> device = std::move(*it);
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700961 ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800962 event->when = now;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700963 event->deviceId = (device->id == mBuiltInKeyboardId)
964 ? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
965 : device->id;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800966 event->type = DEVICE_REMOVED;
967 event += 1;
Chris Ye989bb932020-07-04 16:18:59 -0700968 it = mClosingDevices.erase(it);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800969 mNeedToSendFinishedDeviceScan = true;
970 if (--capacity == 0) {
971 break;
972 }
973 }
974
975 if (mNeedToScanDevices) {
976 mNeedToScanDevices = false;
977 scanDevicesLocked();
978 mNeedToSendFinishedDeviceScan = true;
979 }
980
Chris Ye989bb932020-07-04 16:18:59 -0700981 for (auto it = mOpeningDevices.begin(); it != mOpeningDevices.end();) {
982 std::unique_ptr<Device> device = std::move(*it);
Prabir Pradhanda7c00c2019-08-29 14:12:42 -0700983 ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800984 event->when = now;
985 event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
986 event->type = DEVICE_ADDED;
987 event += 1;
Chris Ye989bb932020-07-04 16:18:59 -0700988 auto [dev_it, insert] = mDevices.insert_or_assign(device->id, std::move(device));
989 if (!insert) {
990 ALOGW("Device id %d exists, replaced.", device->id);
991 }
992 it = mOpeningDevices.erase(it);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800993 mNeedToSendFinishedDeviceScan = true;
994 if (--capacity == 0) {
995 break;
996 }
997 }
998
999 if (mNeedToSendFinishedDeviceScan) {
1000 mNeedToSendFinishedDeviceScan = false;
1001 event->when = now;
1002 event->type = FINISHED_DEVICE_SCAN;
1003 event += 1;
1004 if (--capacity == 0) {
1005 break;
1006 }
1007 }
1008
1009 // Grab the next input event.
1010 bool deviceChanged = false;
1011 while (mPendingEventIndex < mPendingEventCount) {
1012 const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -07001013 if (eventItem.data.fd == mINotifyFd) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001014 if (eventItem.events & EPOLLIN) {
1015 mPendingINotify = true;
1016 } else {
1017 ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
1018 }
1019 continue;
1020 }
1021
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -07001022 if (eventItem.data.fd == mWakeReadPipeFd) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001023 if (eventItem.events & EPOLLIN) {
1024 ALOGV("awoken after wake()");
1025 awoken = true;
Siarhei Vishniakoub4d960d2019-10-03 15:38:44 -05001026 char wakeReadBuffer[16];
Michael Wrightd02c5b62014-02-10 15:10:22 -08001027 ssize_t nRead;
1028 do {
Siarhei Vishniakoub4d960d2019-10-03 15:38:44 -05001029 nRead = read(mWakeReadPipeFd, wakeReadBuffer, sizeof(wakeReadBuffer));
1030 } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(wakeReadBuffer));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001031 } else {
1032 ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001033 eventItem.events);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001034 }
1035 continue;
1036 }
1037
Siarhei Vishniakou4bc561c2018-11-02 17:41:58 -07001038 Device* device = getDeviceByFdLocked(eventItem.data.fd);
Chris Ye989bb932020-07-04 16:18:59 -07001039 if (device == nullptr) {
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001040 ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events,
1041 eventItem.data.fd);
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001042 ALOG_ASSERT(!DEBUG);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001043 continue;
1044 }
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001045 if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) {
1046 if (eventItem.events & EPOLLIN) {
1047 size_t numFrames = device->videoDevice->readAndQueueFrames();
1048 if (numFrames == 0) {
1049 ALOGE("Received epoll event for video device %s, but could not read frame",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001050 device->videoDevice->getName().c_str());
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001051 }
1052 } else if (eventItem.events & EPOLLHUP) {
1053 // TODO(b/121395353) - consider adding EPOLLRDHUP
1054 ALOGI("Removing video device %s due to epoll hang-up event.",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001055 device->videoDevice->getName().c_str());
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001056 unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
1057 device->videoDevice = nullptr;
1058 } else {
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001059 ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
1060 device->videoDevice->getName().c_str());
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001061 ALOG_ASSERT(!DEBUG);
1062 }
1063 continue;
1064 }
1065 // This must be an input event
Michael Wrightd02c5b62014-02-10 15:10:22 -08001066 if (eventItem.events & EPOLLIN) {
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001067 int32_t readSize =
1068 read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001069 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
1070 // Device was removed before INotify noticed.
Mark Salyzyn5aa26b22014-06-10 13:07:44 -07001071 ALOGW("could not get event, removed? (fd: %d size: %" PRId32
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001072 " bufferSize: %zu capacity: %zu errno: %d)\n",
1073 device->fd, readSize, bufferSize, capacity, errno);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001074 deviceChanged = true;
Chris Ye989bb932020-07-04 16:18:59 -07001075 closeDeviceLocked(*device);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001076 } else if (readSize < 0) {
1077 if (errno != EAGAIN && errno != EINTR) {
1078 ALOGW("could not get event (errno=%d)", errno);
1079 }
1080 } else if ((readSize % sizeof(struct input_event)) != 0) {
1081 ALOGE("could not get event (wrong size: %d)", readSize);
1082 } else {
1083 int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
1084
1085 size_t count = size_t(readSize) / sizeof(struct input_event);
1086 for (size_t i = 0; i < count; i++) {
1087 struct input_event& iev = readBuffer[i];
Siarhei Vishniakou592bac22018-11-08 19:42:38 -08001088 event->when = processEventTimestamp(iev);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001089 event->deviceId = deviceId;
1090 event->type = iev.type;
1091 event->code = iev.code;
1092 event->value = iev.value;
1093 event += 1;
1094 capacity -= 1;
1095 }
1096 if (capacity == 0) {
1097 // The result buffer is full. Reset the pending event index
1098 // so we will try to read the device again on the next iteration.
1099 mPendingEventIndex -= 1;
1100 break;
1101 }
1102 }
1103 } else if (eventItem.events & EPOLLHUP) {
1104 ALOGI("Removing device %s due to epoll hang-up event.",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001105 device->identifier.name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001106 deviceChanged = true;
Chris Ye989bb932020-07-04 16:18:59 -07001107 closeDeviceLocked(*device);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001108 } else {
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001109 ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
1110 device->identifier.name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001111 }
1112 }
1113
1114 // readNotify() will modify the list of devices so this must be done after
1115 // processing all other events to ensure that we read all remaining events
1116 // before closing the devices.
1117 if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
1118 mPendingINotify = false;
1119 readNotifyLocked();
1120 deviceChanged = true;
1121 }
1122
1123 // Report added or removed devices immediately.
1124 if (deviceChanged) {
1125 continue;
1126 }
1127
1128 // Return now if we have collected any events or if we were explicitly awoken.
1129 if (event != buffer || awoken) {
1130 break;
1131 }
1132
Siarhei Vishniakou4b5a87f2019-09-24 13:03:58 +01001133 // Poll for events.
1134 // When a device driver has pending (unread) events, it acquires
1135 // a kernel wake lock. Once the last pending event has been read, the device
1136 // driver will release the kernel wake lock, but the epoll will hold the wakelock,
1137 // since we are using EPOLLWAKEUP. The wakelock is released by the epoll when epoll_wait
1138 // is called again for the same fd that produced the event.
1139 // Thus the system can only sleep if there are no events pending or
1140 // currently being processed.
Michael Wrightd02c5b62014-02-10 15:10:22 -08001141 //
1142 // The timeout is advisory only. If the device is asleep, it will not wake just to
1143 // service the timeout.
1144 mPendingEventIndex = 0;
1145
Siarhei Vishniakou4b5a87f2019-09-24 13:03:58 +01001146 mLock.unlock(); // release lock before poll
Michael Wrightd02c5b62014-02-10 15:10:22 -08001147
1148 int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
1149
Siarhei Vishniakou4b5a87f2019-09-24 13:03:58 +01001150 mLock.lock(); // reacquire lock after poll
Michael Wrightd02c5b62014-02-10 15:10:22 -08001151
1152 if (pollResult == 0) {
1153 // Timed out.
1154 mPendingEventCount = 0;
1155 break;
1156 }
1157
1158 if (pollResult < 0) {
1159 // An error occurred.
1160 mPendingEventCount = 0;
1161
1162 // Sleep after errors to avoid locking up the system.
1163 // Hopefully the error is transient.
1164 if (errno != EINTR) {
1165 ALOGW("poll failed (errno=%d)\n", errno);
1166 usleep(100000);
1167 }
1168 } else {
1169 // Some events occurred.
1170 mPendingEventCount = size_t(pollResult);
1171 }
1172 }
1173
1174 // All done, return the number of events we read.
1175 return event - buffer;
1176}
1177
Siarhei Vishniakouadd89292018-12-13 19:23:36 -08001178std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) {
1179 AutoMutex _l(mLock);
1180
1181 Device* device = getDeviceLocked(deviceId);
Chris Ye66fbac32020-07-06 20:36:43 -07001182 if (device == nullptr || !device->videoDevice) {
Siarhei Vishniakouadd89292018-12-13 19:23:36 -08001183 return {};
1184 }
1185 return device->videoDevice->consumeFrames();
1186}
1187
Michael Wrightd02c5b62014-02-10 15:10:22 -08001188void EventHub::wake() {
1189 ALOGV("wake() called");
1190
1191 ssize_t nWrite;
1192 do {
1193 nWrite = write(mWakeWritePipeFd, "W", 1);
1194 } while (nWrite == -1 && errno == EINTR);
1195
1196 if (nWrite != 1 && errno != EAGAIN) {
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001197 ALOGW("Could not write wake signal: %s", strerror(errno));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001198 }
1199}
1200
1201void EventHub::scanDevicesLocked() {
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001202 status_t result = scanDirLocked(DEVICE_PATH);
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001203 if (result < 0) {
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001204 ALOGE("scan dir failed for %s", DEVICE_PATH);
1205 }
Philip Quinn39b81682019-01-09 22:20:39 -08001206 if (isV4lScanningEnabled()) {
1207 result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
1208 if (result != OK) {
1209 ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
1210 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001211 }
Chris Ye989bb932020-07-04 16:18:59 -07001212 if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001213 createVirtualKeyboardLocked();
1214 }
1215}
1216
1217// ----------------------------------------------------------------------------
1218
Michael Wrightd02c5b62014-02-10 15:10:22 -08001219static const int32_t GAMEPAD_KEYCODES[] = {
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001220 AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, //
1221 AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, //
1222 AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1, //
1223 AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2, //
1224 AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR, //
1225 AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE, //
Michael Wrightd02c5b62014-02-10 15:10:22 -08001226};
1227
Siarhei Vishniakou25920312018-12-12 15:24:44 -08001228status_t EventHub::registerFdForEpoll(int fd) {
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001229 // TODO(b/121395353) - consider adding EPOLLRDHUP
Siarhei Vishniakou25920312018-12-12 15:24:44 -08001230 struct epoll_event eventItem = {};
1231 eventItem.events = EPOLLIN | EPOLLWAKEUP;
1232 eventItem.data.fd = fd;
1233 if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
1234 ALOGE("Could not add fd to epoll instance: %s", strerror(errno));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001235 return -errno;
1236 }
1237 return OK;
1238}
1239
Siarhei Vishniakou25920312018-12-12 15:24:44 -08001240status_t EventHub::unregisterFdFromEpoll(int fd) {
1241 if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, nullptr)) {
1242 ALOGW("Could not remove fd from epoll instance: %s", strerror(errno));
1243 return -errno;
1244 }
1245 return OK;
1246}
1247
Chris Ye989bb932020-07-04 16:18:59 -07001248status_t EventHub::registerDeviceForEpollLocked(Device& device) {
1249 status_t result = registerFdForEpoll(device.fd);
Siarhei Vishniakou25920312018-12-12 15:24:44 -08001250 if (result != OK) {
Chris Ye989bb932020-07-04 16:18:59 -07001251 ALOGE("Could not add input device fd to epoll for device %" PRId32, device.id);
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001252 return result;
1253 }
Chris Ye989bb932020-07-04 16:18:59 -07001254 if (device.videoDevice) {
1255 registerVideoDeviceForEpollLocked(*device.videoDevice);
Siarhei Vishniakou25920312018-12-12 15:24:44 -08001256 }
1257 return result;
1258}
1259
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001260void EventHub::registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice) {
1261 status_t result = registerFdForEpoll(videoDevice.getFd());
1262 if (result != OK) {
1263 ALOGE("Could not add video device %s to epoll", videoDevice.getName().c_str());
1264 }
1265}
1266
Chris Ye989bb932020-07-04 16:18:59 -07001267status_t EventHub::unregisterDeviceFromEpollLocked(Device& device) {
1268 if (device.hasValidFd()) {
1269 status_t result = unregisterFdFromEpoll(device.fd);
Siarhei Vishniakou25920312018-12-12 15:24:44 -08001270 if (result != OK) {
Chris Ye989bb932020-07-04 16:18:59 -07001271 ALOGW("Could not remove input device fd from epoll for device %" PRId32, device.id);
Siarhei Vishniakou25920312018-12-12 15:24:44 -08001272 return result;
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001273 }
1274 }
Chris Ye989bb932020-07-04 16:18:59 -07001275 if (device.videoDevice) {
1276 unregisterVideoDeviceFromEpollLocked(*device.videoDevice);
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001277 }
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001278 return OK;
1279}
1280
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001281void EventHub::unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice) {
1282 if (videoDevice.hasValidFd()) {
1283 status_t result = unregisterFdFromEpoll(videoDevice.getFd());
1284 if (result != OK) {
1285 ALOGW("Could not remove video device fd from epoll for device: %s",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001286 videoDevice.getName().c_str());
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001287 }
1288 }
1289}
1290
Chris Ye8594e192020-07-14 10:34:06 -07001291status_t EventHub::openDeviceLocked(const std::string& devicePath) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001292 char buffer[80];
1293
Chris Ye8594e192020-07-14 10:34:06 -07001294 ALOGV("Opening device: %s", devicePath.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001295
Chris Ye8594e192020-07-14 10:34:06 -07001296 int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001297 if (fd < 0) {
Chris Ye8594e192020-07-14 10:34:06 -07001298 ALOGE("could not open %s, %s\n", devicePath.c_str(), strerror(errno));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001299 return -1;
1300 }
1301
1302 InputDeviceIdentifier identifier;
1303
1304 // Get device name.
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001305 if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
Chris Ye8594e192020-07-14 10:34:06 -07001306 ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001307 } else {
1308 buffer[sizeof(buffer) - 1] = '\0';
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001309 identifier.name = buffer;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001310 }
1311
1312 // Check to see if the device is on our excluded list
1313 for (size_t i = 0; i < mExcludedDevices.size(); i++) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001314 const std::string& item = mExcludedDevices[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08001315 if (identifier.name == item) {
Chris Ye8594e192020-07-14 10:34:06 -07001316 ALOGI("ignoring event id %s driver %s\n", devicePath.c_str(), item.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001317 close(fd);
1318 return -1;
1319 }
1320 }
1321
1322 // Get device driver version.
1323 int driverVersion;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001324 if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
Chris Ye8594e192020-07-14 10:34:06 -07001325 ALOGE("could not get driver version for %s, %s\n", devicePath.c_str(), strerror(errno));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001326 close(fd);
1327 return -1;
1328 }
1329
1330 // Get device identifier.
1331 struct input_id inputId;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001332 if (ioctl(fd, EVIOCGID, &inputId)) {
Chris Ye8594e192020-07-14 10:34:06 -07001333 ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001334 close(fd);
1335 return -1;
1336 }
1337 identifier.bus = inputId.bustype;
1338 identifier.product = inputId.product;
1339 identifier.vendor = inputId.vendor;
1340 identifier.version = inputId.version;
1341
1342 // Get device physical location.
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001343 if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
1344 // fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001345 } else {
1346 buffer[sizeof(buffer) - 1] = '\0';
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001347 identifier.location = buffer;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001348 }
1349
1350 // Get device unique id.
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001351 if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
1352 // fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001353 } else {
1354 buffer[sizeof(buffer) - 1] = '\0';
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001355 identifier.uniqueId = buffer;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001356 }
1357
1358 // Fill in the descriptor.
1359 assignDescriptorLocked(identifier);
1360
Michael Wrightd02c5b62014-02-10 15:10:22 -08001361 // Allocate device. (The device object takes ownership of the fd at this point.)
1362 int32_t deviceId = mNextDeviceId++;
Chris Ye989bb932020-07-04 16:18:59 -07001363 std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001364
Chris Ye8594e192020-07-14 10:34:06 -07001365 ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001366 ALOGV(" bus: %04x\n"
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001367 " vendor %04x\n"
1368 " product %04x\n"
1369 " version %04x\n",
1370 identifier.bus, identifier.vendor, identifier.product, identifier.version);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001371 ALOGV(" name: \"%s\"\n", identifier.name.c_str());
1372 ALOGV(" location: \"%s\"\n", identifier.location.c_str());
1373 ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.c_str());
1374 ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.c_str());
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001375 ALOGV(" driver: v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,
1376 driverVersion & 0xff);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001377
1378 // Load the configuration file for the device.
Chris Ye989bb932020-07-04 16:18:59 -07001379 device->loadConfigurationLocked();
Michael Wrightd02c5b62014-02-10 15:10:22 -08001380
1381 // Figure out the kinds of events the device reports.
Chris Ye66fbac32020-07-06 20:36:43 -07001382 device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
1383 device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask);
1384 device->readDeviceBitMask(EVIOCGBIT(EV_REL, 0), device->relBitmask);
1385 device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask);
1386 device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask);
1387 device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask);
1388 device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001389
1390 // See if this is a keyboard. Ignore everything in the button range except for
1391 // joystick and gamepad buttons which are handled like keyboards for the most part.
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001392 bool haveKeyboardKeys =
Chris Ye66fbac32020-07-06 20:36:43 -07001393 device->keyBitmask.any(0, BTN_MISC) || device->keyBitmask.any(BTN_WHEEL, KEY_MAX + 1);
1394 bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) ||
1395 device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001396 if (haveKeyboardKeys || haveGamepadButtons) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001397 device->classes |= InputDeviceClass::KEYBOARD;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001398 }
1399
1400 // See if this is a cursor device such as a trackball or mouse.
Chris Ye66fbac32020-07-06 20:36:43 -07001401 if (device->keyBitmask.test(BTN_MOUSE) && device->relBitmask.test(REL_X) &&
1402 device->relBitmask.test(REL_Y)) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001403 device->classes |= InputDeviceClass::CURSOR;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001404 }
1405
Prashant Malani1941ff52015-08-11 18:29:28 -07001406 // See if this is a rotary encoder type device.
1407 String8 deviceType = String8();
1408 if (device->configuration &&
1409 device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001410 if (!deviceType.compare(String8("rotaryEncoder"))) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001411 device->classes |= InputDeviceClass::ROTARY_ENCODER;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001412 }
Prashant Malani1941ff52015-08-11 18:29:28 -07001413 }
1414
Michael Wrightd02c5b62014-02-10 15:10:22 -08001415 // See if this is a touch pad.
1416 // Is this a new modern multi-touch driver?
Chris Ye66fbac32020-07-06 20:36:43 -07001417 if (device->absBitmask.test(ABS_MT_POSITION_X) && device->absBitmask.test(ABS_MT_POSITION_Y)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001418 // Some joysticks such as the PS3 controller report axes that conflict
1419 // with the ABS_MT range. Try to confirm that the device really is
1420 // a touch screen.
Chris Ye66fbac32020-07-06 20:36:43 -07001421 if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001422 device->classes |= (InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001423 }
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001424 // Is this an old style single-touch driver?
Chris Ye66fbac32020-07-06 20:36:43 -07001425 } else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) &&
1426 device->absBitmask.test(ABS_Y)) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001427 device->classes |= InputDeviceClass::TOUCH;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001428 // Is this a BT stylus?
Chris Ye66fbac32020-07-06 20:36:43 -07001429 } else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) &&
1430 !device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001431 device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
Michael Wright842500e2015-03-13 17:32:02 -07001432 // Keyboard will try to claim some of the buttons but we really want to reserve those so we
1433 // can fuse it with the touch screen data, so just take them back. Note this means an
1434 // external stylus cannot also be a keyboard device.
Chris Ye1b0c7342020-07-28 21:57:03 -07001435 device->classes &= ~InputDeviceClass::KEYBOARD;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001436 }
1437
1438 // See if this device is a joystick.
1439 // Assumes that joysticks always have gamepad buttons in order to distinguish them
1440 // from other devices such as accelerometers that also have absolute axes.
1441 if (haveGamepadButtons) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001442 auto assumedClasses = device->classes | InputDeviceClass::JOYSTICK;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001443 for (int i = 0; i <= ABS_MAX; i++) {
Chris Ye66fbac32020-07-06 20:36:43 -07001444 if (device->absBitmask.test(i) &&
Chris Ye1b0c7342020-07-28 21:57:03 -07001445 (getAbsAxisUsage(i, assumedClasses).test(InputDeviceClass::JOYSTICK))) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001446 device->classes = assumedClasses;
1447 break;
1448 }
1449 }
1450 }
1451
1452 // Check whether this device has switches.
1453 for (int i = 0; i <= SW_MAX; i++) {
Chris Ye66fbac32020-07-06 20:36:43 -07001454 if (device->swBitmask.test(i)) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001455 device->classes |= InputDeviceClass::SWITCH;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001456 break;
1457 }
1458 }
1459
1460 // Check whether this device supports the vibrator.
Chris Ye66fbac32020-07-06 20:36:43 -07001461 if (device->ffBitmask.test(FF_RUMBLE)) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001462 device->classes |= InputDeviceClass::VIBRATOR;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001463 }
1464
1465 // Configure virtual keys.
Chris Ye1b0c7342020-07-28 21:57:03 -07001466 if ((device->classes.test(InputDeviceClass::TOUCH))) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001467 // Load the virtual keys for the touch screen, if any.
1468 // We do this now so that we can make sure to load the keymap if necessary.
Chris Ye989bb932020-07-04 16:18:59 -07001469 bool success = device->loadVirtualKeyMapLocked();
Siarhei Vishniakou3e78dec2019-02-20 16:21:46 -06001470 if (success) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001471 device->classes |= InputDeviceClass::KEYBOARD;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001472 }
1473 }
1474
1475 // Load the key map.
1476 // We need to do this for joysticks too because the key layout may specify axes.
1477 status_t keyMapStatus = NAME_NOT_FOUND;
Chris Ye1b0c7342020-07-28 21:57:03 -07001478 if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001479 // Load the keymap for the device.
Chris Ye989bb932020-07-04 16:18:59 -07001480 keyMapStatus = device->loadKeyMapLocked();
Michael Wrightd02c5b62014-02-10 15:10:22 -08001481 }
1482
1483 // Configure the keyboard, gamepad or virtual keyboard.
Chris Ye1b0c7342020-07-28 21:57:03 -07001484 if (device->classes.test(InputDeviceClass::KEYBOARD)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001485 // Register the keyboard as a built-in keyboard if it is eligible.
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001486 if (!keyMapStatus && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD &&
1487 isEligibleBuiltInKeyboard(device->identifier, device->configuration, &device->keyMap)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001488 mBuiltInKeyboardId = device->id;
1489 }
1490
1491 // 'Q' key support = cheap test of whether this is an alpha-capable kbd
Chris Ye989bb932020-07-04 16:18:59 -07001492 if (device->hasKeycodeLocked(AKEYCODE_Q)) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001493 device->classes |= InputDeviceClass::ALPHAKEY;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001494 }
1495
1496 // See if this device has a DPAD.
Chris Ye989bb932020-07-04 16:18:59 -07001497 if (device->hasKeycodeLocked(AKEYCODE_DPAD_UP) &&
1498 device->hasKeycodeLocked(AKEYCODE_DPAD_DOWN) &&
1499 device->hasKeycodeLocked(AKEYCODE_DPAD_LEFT) &&
1500 device->hasKeycodeLocked(AKEYCODE_DPAD_RIGHT) &&
1501 device->hasKeycodeLocked(AKEYCODE_DPAD_CENTER)) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001502 device->classes |= InputDeviceClass::DPAD;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001503 }
1504
1505 // See if this device has a gamepad.
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001506 for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) {
Chris Ye989bb932020-07-04 16:18:59 -07001507 if (device->hasKeycodeLocked(GAMEPAD_KEYCODES[i])) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001508 device->classes |= InputDeviceClass::GAMEPAD;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001509 break;
1510 }
1511 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001512 }
1513
1514 // If the device isn't recognized as something we handle, don't monitor it.
Chris Ye1b0c7342020-07-28 21:57:03 -07001515 if (device->classes == Flags<InputDeviceClass>(0)) {
Chris Ye8594e192020-07-14 10:34:06 -07001516 ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001517 device->identifier.name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001518 return -1;
1519 }
1520
Tim Kilbourn063ff532015-04-08 10:26:18 -07001521 // Determine whether the device has a mic.
Chris Ye989bb932020-07-04 16:18:59 -07001522 if (device->deviceHasMicLocked()) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001523 device->classes |= InputDeviceClass::MIC;
Tim Kilbourn063ff532015-04-08 10:26:18 -07001524 }
1525
Michael Wrightd02c5b62014-02-10 15:10:22 -08001526 // Determine whether the device is external or internal.
Chris Ye989bb932020-07-04 16:18:59 -07001527 if (device->isExternalDeviceLocked()) {
Chris Ye1b0c7342020-07-28 21:57:03 -07001528 device->classes |= InputDeviceClass::EXTERNAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001529 }
1530
Chris Ye1b0c7342020-07-28 21:57:03 -07001531 if (device->classes.any(InputDeviceClass::JOYSTICK | InputDeviceClass::DPAD) &&
1532 device->classes.test(InputDeviceClass::GAMEPAD)) {
Chris Ye989bb932020-07-04 16:18:59 -07001533 device->controllerNumber = getNextControllerNumberLocked(device->identifier.name);
1534 device->setLedForControllerLocked();
Michael Wrightd02c5b62014-02-10 15:10:22 -08001535 }
1536
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001537 // Find a matching video device by comparing device names
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001538 // This should be done before registerDeviceForEpollLocked, so that both fds are added to epoll
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001539 for (std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) {
1540 if (device->identifier.name == videoDevice->getName()) {
1541 device->videoDevice = std::move(videoDevice);
1542 break;
1543 }
1544 }
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001545 mUnattachedVideoDevices
1546 .erase(std::remove_if(mUnattachedVideoDevices.begin(), mUnattachedVideoDevices.end(),
1547 [](const std::unique_ptr<TouchVideoDevice>& videoDevice) {
1548 return videoDevice == nullptr;
1549 }),
1550 mUnattachedVideoDevices.end());
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001551
Chris Ye989bb932020-07-04 16:18:59 -07001552 if (registerDeviceForEpollLocked(*device) != OK) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001553 return -1;
1554 }
1555
Chris Ye989bb932020-07-04 16:18:59 -07001556 device->configureFd();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001557
Chris Ye1b0c7342020-07-28 21:57:03 -07001558 ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=%s, "
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001559 "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
Chris Ye1b0c7342020-07-28 21:57:03 -07001560 deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(),
1561 device->classes.string().c_str(), device->configurationFile.c_str(),
1562 device->keyMap.keyLayoutFile.c_str(), device->keyMap.keyCharacterMapFile.c_str(),
1563 toString(mBuiltInKeyboardId == deviceId));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001564
Chris Ye989bb932020-07-04 16:18:59 -07001565 addDeviceLocked(std::move(device));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001566 return OK;
1567}
1568
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001569void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
1570 std::unique_ptr<TouchVideoDevice> videoDevice = TouchVideoDevice::create(devicePath);
1571 if (!videoDevice) {
1572 ALOGE("Could not create touch video device for %s. Ignoring", devicePath.c_str());
1573 return;
1574 }
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001575 // Transfer ownership of this video device to a matching input device
Chris Ye989bb932020-07-04 16:18:59 -07001576 for (const auto& [id, device] : mDevices) {
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001577 if (videoDevice->getName() == device->identifier.name) {
1578 device->videoDevice = std::move(videoDevice);
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001579 if (device->enabled) {
1580 registerVideoDeviceForEpollLocked(*device->videoDevice);
1581 }
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001582 return;
1583 }
1584 }
1585
1586 // Couldn't find a matching input device, so just add it to a temporary holding queue.
1587 // A matching input device may appear later.
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001588 ALOGI("Adding video device %s to list of unattached video devices",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001589 videoDevice->getName().c_str());
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001590 mUnattachedVideoDevices.push_back(std::move(videoDevice));
1591}
1592
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001593bool EventHub::isDeviceEnabled(int32_t deviceId) {
1594 AutoMutex _l(mLock);
1595 Device* device = getDeviceLocked(deviceId);
Yi Kong9b14ac62018-07-17 13:48:38 -07001596 if (device == nullptr) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001597 ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
1598 return false;
1599 }
1600 return device->enabled;
1601}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001602
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001603status_t EventHub::enableDevice(int32_t deviceId) {
1604 AutoMutex _l(mLock);
1605 Device* device = getDeviceLocked(deviceId);
Yi Kong9b14ac62018-07-17 13:48:38 -07001606 if (device == nullptr) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001607 ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
1608 return BAD_VALUE;
1609 }
1610 if (device->enabled) {
1611 ALOGW("Duplicate call to %s, input device %" PRId32 " already enabled", __func__, deviceId);
1612 return OK;
1613 }
1614 status_t result = device->enable();
1615 if (result != OK) {
1616 ALOGE("Failed to enable device %" PRId32, deviceId);
1617 return result;
1618 }
1619
Chris Ye989bb932020-07-04 16:18:59 -07001620 device->configureFd();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001621
Chris Ye989bb932020-07-04 16:18:59 -07001622 return registerDeviceForEpollLocked(*device);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001623}
1624
1625status_t EventHub::disableDevice(int32_t deviceId) {
1626 AutoMutex _l(mLock);
1627 Device* device = getDeviceLocked(deviceId);
Yi Kong9b14ac62018-07-17 13:48:38 -07001628 if (device == nullptr) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001629 ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
1630 return BAD_VALUE;
1631 }
1632 if (!device->enabled) {
1633 ALOGW("Duplicate call to %s, input device already disabled", __func__);
1634 return OK;
1635 }
Chris Ye989bb932020-07-04 16:18:59 -07001636 unregisterDeviceFromEpollLocked(*device);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001637 return device->disable();
Michael Wrightd02c5b62014-02-10 15:10:22 -08001638}
1639
1640void EventHub::createVirtualKeyboardLocked() {
1641 InputDeviceIdentifier identifier;
1642 identifier.name = "Virtual";
1643 identifier.uniqueId = "<virtual>";
1644 assignDescriptorLocked(identifier);
1645
Chris Ye989bb932020-07-04 16:18:59 -07001646 std::unique_ptr<Device> device =
1647 std::make_unique<Device>(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>",
1648 identifier);
Chris Ye1b0c7342020-07-28 21:57:03 -07001649 device->classes = InputDeviceClass::KEYBOARD | InputDeviceClass::ALPHAKEY |
1650 InputDeviceClass::DPAD | InputDeviceClass::VIRTUAL;
Chris Ye989bb932020-07-04 16:18:59 -07001651 device->loadKeyMapLocked();
1652 addDeviceLocked(std::move(device));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001653}
1654
Chris Ye989bb932020-07-04 16:18:59 -07001655void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {
1656 mOpeningDevices.push_back(std::move(device));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001657}
1658
Chris Ye989bb932020-07-04 16:18:59 -07001659int32_t EventHub::getNextControllerNumberLocked(const std::string& name) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001660 if (mControllerNumbers.isFull()) {
1661 ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
Chris Ye989bb932020-07-04 16:18:59 -07001662 name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001663 return 0;
1664 }
1665 // Since the controller number 0 is reserved for non-controllers, translate all numbers up by
1666 // one
1667 return static_cast<int32_t>(mControllerNumbers.markFirstUnmarkedBit() + 1);
1668}
1669
Chris Ye989bb932020-07-04 16:18:59 -07001670void EventHub::releaseControllerNumberLocked(int32_t num) {
1671 if (num > 0) {
1672 mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
Michael Wrightd02c5b62014-02-10 15:10:22 -08001673 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001674}
1675
Chris Ye8594e192020-07-14 10:34:06 -07001676void EventHub::closeDeviceByPathLocked(const std::string& devicePath) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001677 Device* device = getDeviceByPathLocked(devicePath);
Chris Ye989bb932020-07-04 16:18:59 -07001678 if (device != nullptr) {
1679 closeDeviceLocked(*device);
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001680 return;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001681 }
Chris Ye8594e192020-07-14 10:34:06 -07001682 ALOGV("Remove device: %s not found, device may already have been removed.", devicePath.c_str());
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001683}
1684
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001685/**
1686 * Find the video device by filename, and close it.
1687 * The video device is closed by path during an inotify event, where we don't have the
1688 * additional context about the video device fd, or the associated input device.
1689 */
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001690void EventHub::closeVideoDeviceByPathLocked(const std::string& devicePath) {
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001691 // A video device may be owned by an existing input device, or it may be stored in
1692 // the mUnattachedVideoDevices queue. Check both locations.
Chris Ye989bb932020-07-04 16:18:59 -07001693 for (const auto& [id, device] : mDevices) {
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001694 if (device->videoDevice && device->videoDevice->getPath() == devicePath) {
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001695 unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001696 device->videoDevice = nullptr;
1697 return;
1698 }
1699 }
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001700 mUnattachedVideoDevices
1701 .erase(std::remove_if(mUnattachedVideoDevices.begin(), mUnattachedVideoDevices.end(),
1702 [&devicePath](
1703 const std::unique_ptr<TouchVideoDevice>& videoDevice) {
1704 return videoDevice->getPath() == devicePath;
1705 }),
1706 mUnattachedVideoDevices.end());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001707}
1708
1709void EventHub::closeAllDevicesLocked() {
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001710 mUnattachedVideoDevices.clear();
Chris Ye989bb932020-07-04 16:18:59 -07001711 for (const auto& [id, device] : mDevices) {
1712 closeDeviceLocked(*device);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001713 }
1714}
1715
Chris Ye989bb932020-07-04 16:18:59 -07001716void EventHub::closeDeviceLocked(Device& device) {
1717 ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=%s", device.path.c_str(),
1718 device.identifier.name.c_str(), device.id, device.fd, device.classes.string().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001719
Chris Ye989bb932020-07-04 16:18:59 -07001720 if (device.id == mBuiltInKeyboardId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001721 ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
Chris Ye989bb932020-07-04 16:18:59 -07001722 device.path.c_str(), mBuiltInKeyboardId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001723 mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
1724 }
1725
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001726 unregisterDeviceFromEpollLocked(device);
Chris Ye989bb932020-07-04 16:18:59 -07001727 if (device.videoDevice) {
Siarhei Vishniakou12598682018-11-02 17:19:19 -07001728 // This must be done after the video device is removed from epoll
Chris Ye989bb932020-07-04 16:18:59 -07001729 mUnattachedVideoDevices.push_back(std::move(device.videoDevice));
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001730 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001731
Chris Ye989bb932020-07-04 16:18:59 -07001732 releaseControllerNumberLocked(device.controllerNumber);
1733 device.close();
Michael Wrightd02c5b62014-02-10 15:10:22 -08001734
Chris Ye989bb932020-07-04 16:18:59 -07001735 // Move device to mClosingDevices
1736 mClosingDevices.push_back(std::move(mDevices[device.id]));
1737 // Erase device from mDevices
1738 mDevices.erase(device.id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001739}
1740
1741status_t EventHub::readNotifyLocked() {
1742 int res;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001743 char event_buf[512];
1744 int event_size;
1745 int event_pos = 0;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001746 struct inotify_event* event;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001747
1748 ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd);
1749 res = read(mINotifyFd, event_buf, sizeof(event_buf));
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001750 if (res < (int)sizeof(*event)) {
1751 if (errno == EINTR) return 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001752 ALOGW("could not get event, %s\n", strerror(errno));
1753 return -1;
1754 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001755
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001756 while (res >= (int)sizeof(*event)) {
1757 event = (struct inotify_event*)(event_buf + event_pos);
1758 if (event->len) {
Siarhei Vishniakou951f3622018-12-12 19:45:42 -08001759 if (event->wd == mInputWd) {
Chris Ye8594e192020-07-14 10:34:06 -07001760 std::string filename = std::string(DEVICE_PATH) + "/" + event->name;
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001761 if (event->mask & IN_CREATE) {
Chris Ye8594e192020-07-14 10:34:06 -07001762 openDeviceLocked(filename);
Siarhei Vishniakou951f3622018-12-12 19:45:42 -08001763 } else {
1764 ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
Chris Ye8594e192020-07-14 10:34:06 -07001765 closeDeviceByPathLocked(filename);
Siarhei Vishniakou951f3622018-12-12 19:45:42 -08001766 }
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001767 } else if (event->wd == mVideoWd) {
Siarhei Vishniakou951f3622018-12-12 19:45:42 -08001768 if (isV4lTouchNode(event->name)) {
Chris Ye8594e192020-07-14 10:34:06 -07001769 std::string filename = std::string(VIDEO_DEVICE_PATH) + "/" + event->name;
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001770 if (event->mask & IN_CREATE) {
1771 openVideoDeviceLocked(filename);
1772 } else {
1773 ALOGI("Removing video device '%s' due to inotify event", filename.c_str());
1774 closeVideoDeviceByPathLocked(filename);
1775 }
Siarhei Vishniakou951f3622018-12-12 19:45:42 -08001776 }
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001777 } else {
Siarhei Vishniakou951f3622018-12-12 19:45:42 -08001778 LOG_ALWAYS_FATAL("Unexpected inotify event, wd = %i", event->wd);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001779 }
1780 }
1781 event_size = sizeof(*event) + event->len;
1782 res -= event_size;
1783 event_pos += event_size;
1784 }
1785 return 0;
1786}
1787
Chris Ye8594e192020-07-14 10:34:06 -07001788status_t EventHub::scanDirLocked(const std::string& dirname) {
1789 for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
1790 openDeviceLocked(entry.path());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001791 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001792 return 0;
1793}
1794
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001795/**
1796 * Look for all dirname/v4l-touch* devices, and open them.
1797 */
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001798status_t EventHub::scanVideoDirLocked(const std::string& dirname) {
Chris Ye8594e192020-07-14 10:34:06 -07001799 for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
1800 if (isV4lTouchNode(entry.path())) {
1801 ALOGI("Found touch video device %s", entry.path().c_str());
1802 openVideoDeviceLocked(entry.path());
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001803 }
1804 }
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001805 return OK;
1806}
1807
Michael Wrightd02c5b62014-02-10 15:10:22 -08001808void EventHub::requestReopenDevices() {
1809 ALOGV("requestReopenDevices() called");
1810
1811 AutoMutex _l(mLock);
1812 mNeedToReopenDevices = true;
1813}
1814
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001815void EventHub::dump(std::string& dump) {
1816 dump += "Event Hub State:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08001817
1818 { // acquire lock
1819 AutoMutex _l(mLock);
1820
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001821 dump += StringPrintf(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001822
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001823 dump += INDENT "Devices:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08001824
Chris Ye989bb932020-07-04 16:18:59 -07001825 for (const auto& [id, device] : mDevices) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001826 if (mBuiltInKeyboardId == device->id) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001827 dump += StringPrintf(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001828 device->id, device->identifier.name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001829 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001830 dump += StringPrintf(INDENT2 "%d: %s\n", device->id,
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001831 device->identifier.name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001832 }
Chris Ye1b0c7342020-07-28 21:57:03 -07001833 dump += StringPrintf(INDENT3 "Classes: %s\n", device->classes.string().c_str());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001834 dump += StringPrintf(INDENT3 "Path: %s\n", device->path.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001835 dump += StringPrintf(INDENT3 "Enabled: %s\n", toString(device->enabled));
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001836 dump += StringPrintf(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.c_str());
1837 dump += StringPrintf(INDENT3 "Location: %s\n", device->identifier.location.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001838 dump += StringPrintf(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001839 dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001840 dump += StringPrintf(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001841 "product=0x%04x, version=0x%04x\n",
1842 device->identifier.bus, device->identifier.vendor,
1843 device->identifier.product, device->identifier.version);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001844 dump += StringPrintf(INDENT3 "KeyLayoutFile: %s\n",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001845 device->keyMap.keyLayoutFile.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001846 dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001847 device->keyMap.keyCharacterMapFile.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001848 dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001849 device->configurationFile.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001850 dump += StringPrintf(INDENT3 "HaveKeyboardLayoutOverlay: %s\n",
Prabir Pradhanda7c00c2019-08-29 14:12:42 -07001851 toString(device->overlayKeyMap != nullptr));
Siarhei Vishniakouec7854a2018-12-14 16:52:34 -08001852 dump += INDENT3 "VideoDevice: ";
1853 if (device->videoDevice) {
1854 dump += device->videoDevice->dump() + "\n";
1855 } else {
1856 dump += "<none>\n";
1857 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001858 }
Siarhei Vishniakou22c88462018-12-13 19:34:53 -08001859
1860 dump += INDENT "Unattached video devices:\n";
1861 for (const std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) {
1862 dump += INDENT2 + videoDevice->dump() + "\n";
1863 }
1864 if (mUnattachedVideoDevices.empty()) {
1865 dump += INDENT2 "<none>\n";
1866 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001867 } // release lock
1868}
1869
1870void EventHub::monitor() {
1871 // Acquire and release the lock to ensure that the event hub has not deadlocked.
1872 mLock.lock();
1873 mLock.unlock();
1874}
1875
Michael Wrightd02c5b62014-02-10 15:10:22 -08001876}; // namespace android