1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2005 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #include <assert.h>
18*38e8c45fSAndroid Build Coastguard Worker #include <dirent.h>
19*38e8c45fSAndroid Build Coastguard Worker #include <errno.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <fcntl.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <linux/ioctl.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <memory.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <stdint.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <stdio.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <stdlib.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <string.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <sys/capability.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <sys/epoll.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <sys/inotify.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <sys/ioctl.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <sys/stat.h>
33*38e8c45fSAndroid Build Coastguard Worker #include <sys/sysmacros.h>
34*38e8c45fSAndroid Build Coastguard Worker #include <unistd.h>
35*38e8c45fSAndroid Build Coastguard Worker
36*38e8c45fSAndroid Build Coastguard Worker #include <android_companion_virtualdevice_flags.h>
37*38e8c45fSAndroid Build Coastguard Worker
38*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "EventHub"
39*38e8c45fSAndroid Build Coastguard Worker
40*38e8c45fSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
41*38e8c45fSAndroid Build Coastguard Worker #include <android-base/file.h>
42*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
43*38e8c45fSAndroid Build Coastguard Worker #include <android-base/strings.h>
44*38e8c45fSAndroid Build Coastguard Worker #include <cutils/properties.h>
45*38e8c45fSAndroid Build Coastguard Worker #include <ftl/enum.h>
46*38e8c45fSAndroid Build Coastguard Worker #include <input/InputEventLabels.h>
47*38e8c45fSAndroid Build Coastguard Worker #include <input/KeyCharacterMap.h>
48*38e8c45fSAndroid Build Coastguard Worker #include <input/KeyLayoutMap.h>
49*38e8c45fSAndroid Build Coastguard Worker #include <input/PrintTools.h>
50*38e8c45fSAndroid Build Coastguard Worker #include <input/VirtualKeyMap.h>
51*38e8c45fSAndroid Build Coastguard Worker #include <openssl/sha.h>
52*38e8c45fSAndroid Build Coastguard Worker #include <statslog.h>
53*38e8c45fSAndroid Build Coastguard Worker #include <utils/Errors.h>
54*38e8c45fSAndroid Build Coastguard Worker #include <utils/Log.h>
55*38e8c45fSAndroid Build Coastguard Worker #include <utils/Timers.h>
56*38e8c45fSAndroid Build Coastguard Worker
57*38e8c45fSAndroid Build Coastguard Worker #include <filesystem>
58*38e8c45fSAndroid Build Coastguard Worker #include <optional>
59*38e8c45fSAndroid Build Coastguard Worker #include <regex>
60*38e8c45fSAndroid Build Coastguard Worker #include <utility>
61*38e8c45fSAndroid Build Coastguard Worker
62*38e8c45fSAndroid Build Coastguard Worker #include "EventHub.h"
63*38e8c45fSAndroid Build Coastguard Worker
64*38e8c45fSAndroid Build Coastguard Worker #include "KeyCodeClassifications.h"
65*38e8c45fSAndroid Build Coastguard Worker
66*38e8c45fSAndroid Build Coastguard Worker #define INDENT " "
67*38e8c45fSAndroid Build Coastguard Worker #define INDENT2 " "
68*38e8c45fSAndroid Build Coastguard Worker #define INDENT3 " "
69*38e8c45fSAndroid Build Coastguard Worker
70*38e8c45fSAndroid Build Coastguard Worker using android::base::StringPrintf;
71*38e8c45fSAndroid Build Coastguard Worker
72*38e8c45fSAndroid Build Coastguard Worker namespace android {
73*38e8c45fSAndroid Build Coastguard Worker
74*38e8c45fSAndroid Build Coastguard Worker namespace vd_flags = android::companion::virtualdevice::flags;
75*38e8c45fSAndroid Build Coastguard Worker
76*38e8c45fSAndroid Build Coastguard Worker using namespace ftl::flag_operators;
77*38e8c45fSAndroid Build Coastguard Worker
78*38e8c45fSAndroid Build Coastguard Worker static const char* DEVICE_INPUT_PATH = "/dev/input";
79*38e8c45fSAndroid Build Coastguard Worker // v4l2 devices go directly into /dev
80*38e8c45fSAndroid Build Coastguard Worker static const char* DEVICE_PATH = "/dev";
81*38e8c45fSAndroid Build Coastguard Worker
82*38e8c45fSAndroid Build Coastguard Worker static constexpr size_t OBFUSCATED_LENGTH = 8;
83*38e8c45fSAndroid Build Coastguard Worker
84*38e8c45fSAndroid Build Coastguard Worker static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
85*38e8c45fSAndroid Build Coastguard Worker static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
86*38e8c45fSAndroid Build Coastguard Worker
87*38e8c45fSAndroid Build Coastguard Worker static constexpr size_t EVENT_BUFFER_SIZE = 256;
88*38e8c45fSAndroid Build Coastguard Worker
89*38e8c45fSAndroid Build Coastguard Worker // Mapping for input battery class node IDs lookup.
90*38e8c45fSAndroid Build Coastguard Worker // https://www.kernel.org/doc/Documentation/power/power_supply_class.txt
91*38e8c45fSAndroid Build Coastguard Worker static const std::unordered_map<std::string, InputBatteryClass> BATTERY_CLASSES =
92*38e8c45fSAndroid Build Coastguard Worker {{"capacity", InputBatteryClass::CAPACITY},
93*38e8c45fSAndroid Build Coastguard Worker {"capacity_level", InputBatteryClass::CAPACITY_LEVEL},
94*38e8c45fSAndroid Build Coastguard Worker {"status", InputBatteryClass::STATUS}};
95*38e8c45fSAndroid Build Coastguard Worker
96*38e8c45fSAndroid Build Coastguard Worker // Mapping for input battery class node names lookup.
97*38e8c45fSAndroid Build Coastguard Worker // https://www.kernel.org/doc/Documentation/power/power_supply_class.txt
98*38e8c45fSAndroid Build Coastguard Worker static const std::unordered_map<InputBatteryClass, std::string> BATTERY_NODES =
99*38e8c45fSAndroid Build Coastguard Worker {{InputBatteryClass::CAPACITY, "capacity"},
100*38e8c45fSAndroid Build Coastguard Worker {InputBatteryClass::CAPACITY_LEVEL, "capacity_level"},
101*38e8c45fSAndroid Build Coastguard Worker {InputBatteryClass::STATUS, "status"}};
102*38e8c45fSAndroid Build Coastguard Worker
103*38e8c45fSAndroid Build Coastguard Worker // must be kept in sync with definitions in kernel /drivers/power/supply/power_supply_sysfs.c
104*38e8c45fSAndroid Build Coastguard Worker static const std::unordered_map<std::string, int32_t> BATTERY_STATUS =
105*38e8c45fSAndroid Build Coastguard Worker {{"Unknown", BATTERY_STATUS_UNKNOWN},
106*38e8c45fSAndroid Build Coastguard Worker {"Charging", BATTERY_STATUS_CHARGING},
107*38e8c45fSAndroid Build Coastguard Worker {"Discharging", BATTERY_STATUS_DISCHARGING},
108*38e8c45fSAndroid Build Coastguard Worker {"Not charging", BATTERY_STATUS_NOT_CHARGING},
109*38e8c45fSAndroid Build Coastguard Worker {"Full", BATTERY_STATUS_FULL}};
110*38e8c45fSAndroid Build Coastguard Worker
111*38e8c45fSAndroid Build Coastguard Worker // Mapping taken from
112*38e8c45fSAndroid Build Coastguard Worker // https://gitlab.freedesktop.org/upower/upower/-/blob/master/src/linux/up-device-supply.c#L484
113*38e8c45fSAndroid Build Coastguard Worker static const std::unordered_map<std::string, int32_t> BATTERY_LEVEL = {{"Critical", 5},
114*38e8c45fSAndroid Build Coastguard Worker {"Low", 10},
115*38e8c45fSAndroid Build Coastguard Worker {"Normal", 55},
116*38e8c45fSAndroid Build Coastguard Worker {"High", 70},
117*38e8c45fSAndroid Build Coastguard Worker {"Full", 100},
118*38e8c45fSAndroid Build Coastguard Worker {"Unknown", 50}};
119*38e8c45fSAndroid Build Coastguard Worker
120*38e8c45fSAndroid Build Coastguard Worker // Mapping for input led class node names lookup.
121*38e8c45fSAndroid Build Coastguard Worker // https://www.kernel.org/doc/html/latest/leds/leds-class.html
122*38e8c45fSAndroid Build Coastguard Worker static const std::unordered_map<std::string, InputLightClass> LIGHT_CLASSES =
123*38e8c45fSAndroid Build Coastguard Worker {{"red", InputLightClass::RED},
124*38e8c45fSAndroid Build Coastguard Worker {"green", InputLightClass::GREEN},
125*38e8c45fSAndroid Build Coastguard Worker {"blue", InputLightClass::BLUE},
126*38e8c45fSAndroid Build Coastguard Worker {"global", InputLightClass::GLOBAL},
127*38e8c45fSAndroid Build Coastguard Worker {"brightness", InputLightClass::BRIGHTNESS},
128*38e8c45fSAndroid Build Coastguard Worker {"multi_index", InputLightClass::MULTI_INDEX},
129*38e8c45fSAndroid Build Coastguard Worker {"multi_intensity", InputLightClass::MULTI_INTENSITY},
130*38e8c45fSAndroid Build Coastguard Worker {"max_brightness", InputLightClass::MAX_BRIGHTNESS},
131*38e8c45fSAndroid Build Coastguard Worker {"kbd_backlight", InputLightClass::KEYBOARD_BACKLIGHT},
132*38e8c45fSAndroid Build Coastguard Worker {"mic_mute", InputLightClass::KEYBOARD_MIC_MUTE},
133*38e8c45fSAndroid Build Coastguard Worker {"mute", InputLightClass::KEYBOARD_VOLUME_MUTE}};
134*38e8c45fSAndroid Build Coastguard Worker
135*38e8c45fSAndroid Build Coastguard Worker // Mapping for input multicolor led class node names.
136*38e8c45fSAndroid Build Coastguard Worker // https://www.kernel.org/doc/html/latest/leds/leds-class-multicolor.html
137*38e8c45fSAndroid Build Coastguard Worker static const std::unordered_map<InputLightClass, std::string> LIGHT_NODES =
138*38e8c45fSAndroid Build Coastguard Worker {{InputLightClass::BRIGHTNESS, "brightness"},
139*38e8c45fSAndroid Build Coastguard Worker {InputLightClass::MULTI_INDEX, "multi_index"},
140*38e8c45fSAndroid Build Coastguard Worker {InputLightClass::MULTI_INTENSITY, "multi_intensity"}};
141*38e8c45fSAndroid Build Coastguard Worker
142*38e8c45fSAndroid Build Coastguard Worker // Mapping for light color name and the light color
143*38e8c45fSAndroid Build Coastguard Worker const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
144*38e8c45fSAndroid Build Coastguard Worker {"green", LightColor::GREEN},
145*38e8c45fSAndroid Build Coastguard Worker {"blue", LightColor::BLUE}};
146*38e8c45fSAndroid Build Coastguard Worker
147*38e8c45fSAndroid Build Coastguard Worker // Mapping for country code to Layout info.
148*38e8c45fSAndroid Build Coastguard Worker // See bCountryCode in 6.2.1 of https://usb.org/sites/default/files/hid1_11.pdf.
149*38e8c45fSAndroid Build Coastguard Worker const std::unordered_map<std::int32_t, RawLayoutInfo> LAYOUT_INFOS =
150*38e8c45fSAndroid Build Coastguard Worker {{0, RawLayoutInfo{.languageTag = "", .layoutType = ""}}, // NOT_SUPPORTED
151*38e8c45fSAndroid Build Coastguard Worker {1, RawLayoutInfo{.languageTag = "ar-Arab", .layoutType = ""}}, // ARABIC
152*38e8c45fSAndroid Build Coastguard Worker {2, RawLayoutInfo{.languageTag = "fr-BE", .layoutType = ""}}, // BELGIAN
153*38e8c45fSAndroid Build Coastguard Worker {3, RawLayoutInfo{.languageTag = "fr-CA", .layoutType = ""}}, // CANADIAN_BILINGUAL
154*38e8c45fSAndroid Build Coastguard Worker {4, RawLayoutInfo{.languageTag = "fr-CA", .layoutType = ""}}, // CANADIAN_FRENCH
155*38e8c45fSAndroid Build Coastguard Worker {5, RawLayoutInfo{.languageTag = "cs", .layoutType = ""}}, // CZECH_REPUBLIC
156*38e8c45fSAndroid Build Coastguard Worker {6, RawLayoutInfo{.languageTag = "da", .layoutType = ""}}, // DANISH
157*38e8c45fSAndroid Build Coastguard Worker {7, RawLayoutInfo{.languageTag = "fi", .layoutType = ""}}, // FINNISH
158*38e8c45fSAndroid Build Coastguard Worker {8, RawLayoutInfo{.languageTag = "fr-FR", .layoutType = ""}}, // FRENCH
159*38e8c45fSAndroid Build Coastguard Worker {9, RawLayoutInfo{.languageTag = "de", .layoutType = ""}}, // GERMAN
160*38e8c45fSAndroid Build Coastguard Worker {10, RawLayoutInfo{.languageTag = "el", .layoutType = ""}}, // GREEK
161*38e8c45fSAndroid Build Coastguard Worker {11, RawLayoutInfo{.languageTag = "iw", .layoutType = ""}}, // HEBREW
162*38e8c45fSAndroid Build Coastguard Worker {12, RawLayoutInfo{.languageTag = "hu", .layoutType = ""}}, // HUNGARY
163*38e8c45fSAndroid Build Coastguard Worker {13, RawLayoutInfo{.languageTag = "en", .layoutType = "extended"}}, // INTERNATIONAL (ISO)
164*38e8c45fSAndroid Build Coastguard Worker {14, RawLayoutInfo{.languageTag = "it", .layoutType = ""}}, // ITALIAN
165*38e8c45fSAndroid Build Coastguard Worker {15, RawLayoutInfo{.languageTag = "ja", .layoutType = ""}}, // JAPAN
166*38e8c45fSAndroid Build Coastguard Worker {16, RawLayoutInfo{.languageTag = "ko", .layoutType = ""}}, // KOREAN
167*38e8c45fSAndroid Build Coastguard Worker {17, RawLayoutInfo{.languageTag = "es-419", .layoutType = ""}}, // LATIN_AMERICA
168*38e8c45fSAndroid Build Coastguard Worker {18, RawLayoutInfo{.languageTag = "nl", .layoutType = ""}}, // DUTCH
169*38e8c45fSAndroid Build Coastguard Worker {19, RawLayoutInfo{.languageTag = "nb", .layoutType = ""}}, // NORWEGIAN
170*38e8c45fSAndroid Build Coastguard Worker {20, RawLayoutInfo{.languageTag = "fa", .layoutType = ""}}, // PERSIAN
171*38e8c45fSAndroid Build Coastguard Worker {21, RawLayoutInfo{.languageTag = "pl", .layoutType = ""}}, // POLAND
172*38e8c45fSAndroid Build Coastguard Worker {22, RawLayoutInfo{.languageTag = "pt", .layoutType = ""}}, // PORTUGUESE
173*38e8c45fSAndroid Build Coastguard Worker {23, RawLayoutInfo{.languageTag = "ru", .layoutType = ""}}, // RUSSIA
174*38e8c45fSAndroid Build Coastguard Worker {24, RawLayoutInfo{.languageTag = "sk", .layoutType = ""}}, // SLOVAKIA
175*38e8c45fSAndroid Build Coastguard Worker {25, RawLayoutInfo{.languageTag = "es-ES", .layoutType = ""}}, // SPANISH
176*38e8c45fSAndroid Build Coastguard Worker {26, RawLayoutInfo{.languageTag = "sv", .layoutType = ""}}, // SWEDISH
177*38e8c45fSAndroid Build Coastguard Worker {27, RawLayoutInfo{.languageTag = "fr-CH", .layoutType = ""}}, // SWISS_FRENCH
178*38e8c45fSAndroid Build Coastguard Worker {28, RawLayoutInfo{.languageTag = "de-CH", .layoutType = ""}}, // SWISS_GERMAN
179*38e8c45fSAndroid Build Coastguard Worker {29, RawLayoutInfo{.languageTag = "de-CH", .layoutType = ""}}, // SWITZERLAND
180*38e8c45fSAndroid Build Coastguard Worker {30, RawLayoutInfo{.languageTag = "zh-TW", .layoutType = ""}}, // TAIWAN
181*38e8c45fSAndroid Build Coastguard Worker {31, RawLayoutInfo{.languageTag = "tr", .layoutType = "turkish_q"}}, // TURKISH_Q
182*38e8c45fSAndroid Build Coastguard Worker {32, RawLayoutInfo{.languageTag = "en-GB", .layoutType = ""}}, // UK
183*38e8c45fSAndroid Build Coastguard Worker {33, RawLayoutInfo{.languageTag = "en-US", .layoutType = ""}}, // US
184*38e8c45fSAndroid Build Coastguard Worker {34, RawLayoutInfo{.languageTag = "", .layoutType = ""}}, // YUGOSLAVIA
185*38e8c45fSAndroid Build Coastguard Worker {35, RawLayoutInfo{.languageTag = "tr", .layoutType = "turkish_f"}}}; // TURKISH_F
186*38e8c45fSAndroid Build Coastguard Worker
sha1(const std::string & in)187*38e8c45fSAndroid Build Coastguard Worker static std::string sha1(const std::string& in) {
188*38e8c45fSAndroid Build Coastguard Worker SHA_CTX ctx;
189*38e8c45fSAndroid Build Coastguard Worker SHA1_Init(&ctx);
190*38e8c45fSAndroid Build Coastguard Worker SHA1_Update(&ctx, reinterpret_cast<const u_char*>(in.c_str()), in.size());
191*38e8c45fSAndroid Build Coastguard Worker u_char digest[SHA_DIGEST_LENGTH];
192*38e8c45fSAndroid Build Coastguard Worker SHA1_Final(digest, &ctx);
193*38e8c45fSAndroid Build Coastguard Worker
194*38e8c45fSAndroid Build Coastguard Worker std::string out;
195*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < SHA_DIGEST_LENGTH; i++) {
196*38e8c45fSAndroid Build Coastguard Worker out += StringPrintf("%02x", digest[i]);
197*38e8c45fSAndroid Build Coastguard Worker }
198*38e8c45fSAndroid Build Coastguard Worker return out;
199*38e8c45fSAndroid Build Coastguard Worker }
200*38e8c45fSAndroid Build Coastguard Worker
201*38e8c45fSAndroid Build Coastguard Worker /**
202*38e8c45fSAndroid Build Coastguard Worker * Return true if name matches "v4l-touch*"
203*38e8c45fSAndroid Build Coastguard Worker */
isV4lTouchNode(std::string name)204*38e8c45fSAndroid Build Coastguard Worker static bool isV4lTouchNode(std::string name) {
205*38e8c45fSAndroid Build Coastguard Worker return name.find("v4l-touch") != std::string::npos;
206*38e8c45fSAndroid Build Coastguard Worker }
207*38e8c45fSAndroid Build Coastguard Worker
208*38e8c45fSAndroid Build Coastguard Worker /**
209*38e8c45fSAndroid Build Coastguard Worker * Returns true if V4L devices should be scanned.
210*38e8c45fSAndroid Build Coastguard Worker *
211*38e8c45fSAndroid Build Coastguard Worker * The system property ro.input.video_enabled can be used to control whether
212*38e8c45fSAndroid Build Coastguard Worker * EventHub scans and opens V4L devices. As V4L does not support multiple
213*38e8c45fSAndroid Build Coastguard Worker * clients, EventHub effectively blocks access to these devices when it opens
214*38e8c45fSAndroid Build Coastguard Worker * them.
215*38e8c45fSAndroid Build Coastguard Worker *
216*38e8c45fSAndroid Build Coastguard Worker * Setting this to "false" would prevent any video devices from being discovered and
217*38e8c45fSAndroid Build Coastguard Worker * associated with input devices.
218*38e8c45fSAndroid Build Coastguard Worker *
219*38e8c45fSAndroid Build Coastguard Worker * This property can be used as follows:
220*38e8c45fSAndroid Build Coastguard Worker * 1. To turn off features that are dependent on video device presence.
221*38e8c45fSAndroid Build Coastguard Worker * 2. During testing and development, to allow other clients to read video devices
222*38e8c45fSAndroid Build Coastguard Worker * directly from /dev.
223*38e8c45fSAndroid Build Coastguard Worker */
isV4lScanningEnabled()224*38e8c45fSAndroid Build Coastguard Worker static bool isV4lScanningEnabled() {
225*38e8c45fSAndroid Build Coastguard Worker return property_get_bool("ro.input.video_enabled", /*default_value=*/true);
226*38e8c45fSAndroid Build Coastguard Worker }
227*38e8c45fSAndroid Build Coastguard Worker
processEventTimestamp(const struct input_event & event)228*38e8c45fSAndroid Build Coastguard Worker static nsecs_t processEventTimestamp(const struct input_event& event) {
229*38e8c45fSAndroid Build Coastguard Worker // Use the time specified in the event instead of the current time
230*38e8c45fSAndroid Build Coastguard Worker // so that downstream code can get more accurate estimates of
231*38e8c45fSAndroid Build Coastguard Worker // event dispatch latency from the time the event is enqueued onto
232*38e8c45fSAndroid Build Coastguard Worker // the evdev client buffer.
233*38e8c45fSAndroid Build Coastguard Worker //
234*38e8c45fSAndroid Build Coastguard Worker // The event's timestamp fortuitously uses the same monotonic clock
235*38e8c45fSAndroid Build Coastguard Worker // time base as the rest of Android. The kernel event device driver
236*38e8c45fSAndroid Build Coastguard Worker // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts().
237*38e8c45fSAndroid Build Coastguard Worker // The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere
238*38e8c45fSAndroid Build Coastguard Worker // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a
239*38e8c45fSAndroid Build Coastguard Worker // system call that also queries ktime_get_ts().
240*38e8c45fSAndroid Build Coastguard Worker
241*38e8c45fSAndroid Build Coastguard Worker const nsecs_t inputEventTime = seconds_to_nanoseconds(event.input_event_sec) +
242*38e8c45fSAndroid Build Coastguard Worker microseconds_to_nanoseconds(event.input_event_usec);
243*38e8c45fSAndroid Build Coastguard Worker return inputEventTime;
244*38e8c45fSAndroid Build Coastguard Worker }
245*38e8c45fSAndroid Build Coastguard Worker
246*38e8c45fSAndroid Build Coastguard Worker /**
247*38e8c45fSAndroid Build Coastguard Worker * Returns the sysfs root path of the input device.
248*38e8c45fSAndroid Build Coastguard Worker */
getSysfsRootPath(const char * devicePath)249*38e8c45fSAndroid Build Coastguard Worker static std::optional<std::filesystem::path> getSysfsRootPath(const char* devicePath) {
250*38e8c45fSAndroid Build Coastguard Worker std::error_code errorCode;
251*38e8c45fSAndroid Build Coastguard Worker
252*38e8c45fSAndroid Build Coastguard Worker // Stat the device path to get the major and minor number of the character file
253*38e8c45fSAndroid Build Coastguard Worker struct stat statbuf;
254*38e8c45fSAndroid Build Coastguard Worker if (stat(devicePath, &statbuf) == -1) {
255*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not stat device %s due to error: %s.", devicePath, std::strerror(errno));
256*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
257*38e8c45fSAndroid Build Coastguard Worker }
258*38e8c45fSAndroid Build Coastguard Worker
259*38e8c45fSAndroid Build Coastguard Worker unsigned int major_num = major(statbuf.st_rdev);
260*38e8c45fSAndroid Build Coastguard Worker unsigned int minor_num = minor(statbuf.st_rdev);
261*38e8c45fSAndroid Build Coastguard Worker
262*38e8c45fSAndroid Build Coastguard Worker // Realpath "/sys/dev/char/{major}:{minor}" to get the sysfs path to the input event
263*38e8c45fSAndroid Build Coastguard Worker auto sysfsPath = std::filesystem::path("/sys/dev/char/");
264*38e8c45fSAndroid Build Coastguard Worker sysfsPath /= std::to_string(major_num) + ":" + std::to_string(minor_num);
265*38e8c45fSAndroid Build Coastguard Worker sysfsPath = std::filesystem::canonical(sysfsPath, errorCode);
266*38e8c45fSAndroid Build Coastguard Worker
267*38e8c45fSAndroid Build Coastguard Worker // Make sure nothing went wrong in call to canonical()
268*38e8c45fSAndroid Build Coastguard Worker if (errorCode) {
269*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not run filesystem::canonical() due to error %d : %s.", errorCode.value(),
270*38e8c45fSAndroid Build Coastguard Worker errorCode.message().c_str());
271*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
272*38e8c45fSAndroid Build Coastguard Worker }
273*38e8c45fSAndroid Build Coastguard Worker
274*38e8c45fSAndroid Build Coastguard Worker // Continue to go up a directory until we reach a directory named "input"
275*38e8c45fSAndroid Build Coastguard Worker while (sysfsPath != "/" && sysfsPath.filename() != "input") {
276*38e8c45fSAndroid Build Coastguard Worker sysfsPath = sysfsPath.parent_path();
277*38e8c45fSAndroid Build Coastguard Worker }
278*38e8c45fSAndroid Build Coastguard Worker
279*38e8c45fSAndroid Build Coastguard Worker // Then go up one more and you will be at the sysfs root of the device
280*38e8c45fSAndroid Build Coastguard Worker sysfsPath = sysfsPath.parent_path();
281*38e8c45fSAndroid Build Coastguard Worker
282*38e8c45fSAndroid Build Coastguard Worker // Make sure we didn't reach root path and that directory actually exists
283*38e8c45fSAndroid Build Coastguard Worker if (sysfsPath == "/" || !std::filesystem::exists(sysfsPath, errorCode)) {
284*38e8c45fSAndroid Build Coastguard Worker if (errorCode) {
285*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
286*38e8c45fSAndroid Build Coastguard Worker errorCode.message().c_str());
287*38e8c45fSAndroid Build Coastguard Worker }
288*38e8c45fSAndroid Build Coastguard Worker
289*38e8c45fSAndroid Build Coastguard Worker // Not found
290*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
291*38e8c45fSAndroid Build Coastguard Worker }
292*38e8c45fSAndroid Build Coastguard Worker
293*38e8c45fSAndroid Build Coastguard Worker return sysfsPath;
294*38e8c45fSAndroid Build Coastguard Worker }
295*38e8c45fSAndroid Build Coastguard Worker
296*38e8c45fSAndroid Build Coastguard Worker /**
297*38e8c45fSAndroid Build Coastguard Worker * Returns the list of files under a specified path.
298*38e8c45fSAndroid Build Coastguard Worker */
allFilesInPath(const std::filesystem::path & path)299*38e8c45fSAndroid Build Coastguard Worker static std::vector<std::filesystem::path> allFilesInPath(const std::filesystem::path& path) {
300*38e8c45fSAndroid Build Coastguard Worker std::vector<std::filesystem::path> nodes;
301*38e8c45fSAndroid Build Coastguard Worker std::error_code errorCode;
302*38e8c45fSAndroid Build Coastguard Worker auto iter = std::filesystem::directory_iterator(path, errorCode);
303*38e8c45fSAndroid Build Coastguard Worker while (!errorCode && iter != std::filesystem::directory_iterator()) {
304*38e8c45fSAndroid Build Coastguard Worker nodes.push_back(iter->path());
305*38e8c45fSAndroid Build Coastguard Worker iter++;
306*38e8c45fSAndroid Build Coastguard Worker }
307*38e8c45fSAndroid Build Coastguard Worker return nodes;
308*38e8c45fSAndroid Build Coastguard Worker }
309*38e8c45fSAndroid Build Coastguard Worker
310*38e8c45fSAndroid Build Coastguard Worker /**
311*38e8c45fSAndroid Build Coastguard Worker * Returns the list of files under a specified directory in a sysfs path.
312*38e8c45fSAndroid Build Coastguard Worker * Example:
313*38e8c45fSAndroid Build Coastguard Worker * findSysfsNodes(sysfsRootPath, SysfsClass::LEDS) will return all led nodes under "leds" directory
314*38e8c45fSAndroid Build Coastguard Worker * in the sysfs path.
315*38e8c45fSAndroid Build Coastguard Worker */
findSysfsNodes(const std::filesystem::path & sysfsRoot,SysfsClass clazz)316*38e8c45fSAndroid Build Coastguard Worker static std::vector<std::filesystem::path> findSysfsNodes(const std::filesystem::path& sysfsRoot,
317*38e8c45fSAndroid Build Coastguard Worker SysfsClass clazz) {
318*38e8c45fSAndroid Build Coastguard Worker std::string nodeStr = ftl::enum_string(clazz);
319*38e8c45fSAndroid Build Coastguard Worker std::for_each(nodeStr.begin(), nodeStr.end(),
320*38e8c45fSAndroid Build Coastguard Worker [](char& c) { c = std::tolower(static_cast<unsigned char>(c)); });
321*38e8c45fSAndroid Build Coastguard Worker std::vector<std::filesystem::path> nodes;
322*38e8c45fSAndroid Build Coastguard Worker for (auto path = sysfsRoot; path != "/" && nodes.empty(); path = path.parent_path()) {
323*38e8c45fSAndroid Build Coastguard Worker nodes = allFilesInPath(path / nodeStr);
324*38e8c45fSAndroid Build Coastguard Worker }
325*38e8c45fSAndroid Build Coastguard Worker return nodes;
326*38e8c45fSAndroid Build Coastguard Worker }
327*38e8c45fSAndroid Build Coastguard Worker
getColorIndexArray(std::filesystem::path path)328*38e8c45fSAndroid Build Coastguard Worker static std::optional<std::array<LightColor, COLOR_NUM>> getColorIndexArray(
329*38e8c45fSAndroid Build Coastguard Worker std::filesystem::path path) {
330*38e8c45fSAndroid Build Coastguard Worker std::string indexStr;
331*38e8c45fSAndroid Build Coastguard Worker if (!base::ReadFileToString(path, &indexStr)) {
332*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
333*38e8c45fSAndroid Build Coastguard Worker }
334*38e8c45fSAndroid Build Coastguard Worker
335*38e8c45fSAndroid Build Coastguard Worker // Parse the multi color LED index file, refer to kernel docs
336*38e8c45fSAndroid Build Coastguard Worker // leds/leds-class-multicolor.html
337*38e8c45fSAndroid Build Coastguard Worker std::regex indexPattern("(red|green|blue)\\s(red|green|blue)\\s(red|green|blue)[\\n]");
338*38e8c45fSAndroid Build Coastguard Worker std::smatch results;
339*38e8c45fSAndroid Build Coastguard Worker std::array<LightColor, COLOR_NUM> colors;
340*38e8c45fSAndroid Build Coastguard Worker if (!std::regex_match(indexStr, results, indexPattern)) {
341*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
342*38e8c45fSAndroid Build Coastguard Worker }
343*38e8c45fSAndroid Build Coastguard Worker
344*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 1; i < results.size(); i++) {
345*38e8c45fSAndroid Build Coastguard Worker const auto it = LIGHT_COLORS.find(results[i].str());
346*38e8c45fSAndroid Build Coastguard Worker if (it != LIGHT_COLORS.end()) {
347*38e8c45fSAndroid Build Coastguard Worker // intensities.emplace(it->second, 0);
348*38e8c45fSAndroid Build Coastguard Worker colors[i - 1] = it->second;
349*38e8c45fSAndroid Build Coastguard Worker }
350*38e8c45fSAndroid Build Coastguard Worker }
351*38e8c45fSAndroid Build Coastguard Worker return colors;
352*38e8c45fSAndroid Build Coastguard Worker }
353*38e8c45fSAndroid Build Coastguard Worker
354*38e8c45fSAndroid Build Coastguard Worker /**
355*38e8c45fSAndroid Build Coastguard Worker * Read country code information exposed through the sysfs path and convert it to Layout info.
356*38e8c45fSAndroid Build Coastguard Worker */
readLayoutConfiguration(const std::filesystem::path & sysfsRootPath)357*38e8c45fSAndroid Build Coastguard Worker static std::optional<RawLayoutInfo> readLayoutConfiguration(
358*38e8c45fSAndroid Build Coastguard Worker const std::filesystem::path& sysfsRootPath) {
359*38e8c45fSAndroid Build Coastguard Worker // Check the sysfs root path
360*38e8c45fSAndroid Build Coastguard Worker int32_t hidCountryCode = -1;
361*38e8c45fSAndroid Build Coastguard Worker std::string str;
362*38e8c45fSAndroid Build Coastguard Worker if (base::ReadFileToString(sysfsRootPath / "country", &str)) {
363*38e8c45fSAndroid Build Coastguard Worker hidCountryCode = std::stoi(str, nullptr, 16);
364*38e8c45fSAndroid Build Coastguard Worker // Update this condition if new supported country codes are added to HID spec.
365*38e8c45fSAndroid Build Coastguard Worker if (hidCountryCode > 35 || hidCountryCode < 0) {
366*38e8c45fSAndroid Build Coastguard Worker ALOGE("HID country code should be in range [0, 35], but for sysfs path %s it was %d",
367*38e8c45fSAndroid Build Coastguard Worker sysfsRootPath.c_str(), hidCountryCode);
368*38e8c45fSAndroid Build Coastguard Worker }
369*38e8c45fSAndroid Build Coastguard Worker }
370*38e8c45fSAndroid Build Coastguard Worker const auto it = LAYOUT_INFOS.find(hidCountryCode);
371*38e8c45fSAndroid Build Coastguard Worker if (it != LAYOUT_INFOS.end()) {
372*38e8c45fSAndroid Build Coastguard Worker return it->second;
373*38e8c45fSAndroid Build Coastguard Worker }
374*38e8c45fSAndroid Build Coastguard Worker
375*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
376*38e8c45fSAndroid Build Coastguard Worker }
377*38e8c45fSAndroid Build Coastguard Worker
378*38e8c45fSAndroid Build Coastguard Worker /**
379*38e8c45fSAndroid Build Coastguard Worker * Read information about batteries exposed through the sysfs path.
380*38e8c45fSAndroid Build Coastguard Worker */
readBatteryConfiguration(const std::filesystem::path & sysfsRootPath)381*38e8c45fSAndroid Build Coastguard Worker static std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> readBatteryConfiguration(
382*38e8c45fSAndroid Build Coastguard Worker const std::filesystem::path& sysfsRootPath) {
383*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<int32_t, RawBatteryInfo> batteryInfos;
384*38e8c45fSAndroid Build Coastguard Worker int32_t nextBatteryId = 0;
385*38e8c45fSAndroid Build Coastguard Worker // Check if device has any battery.
386*38e8c45fSAndroid Build Coastguard Worker const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY);
387*38e8c45fSAndroid Build Coastguard Worker for (const auto& nodePath : paths) {
388*38e8c45fSAndroid Build Coastguard Worker RawBatteryInfo info;
389*38e8c45fSAndroid Build Coastguard Worker info.id = ++nextBatteryId;
390*38e8c45fSAndroid Build Coastguard Worker info.path = nodePath;
391*38e8c45fSAndroid Build Coastguard Worker info.name = nodePath.filename();
392*38e8c45fSAndroid Build Coastguard Worker
393*38e8c45fSAndroid Build Coastguard Worker // Scan the path for all the files
394*38e8c45fSAndroid Build Coastguard Worker // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt
395*38e8c45fSAndroid Build Coastguard Worker const auto& files = allFilesInPath(nodePath);
396*38e8c45fSAndroid Build Coastguard Worker for (const auto& file : files) {
397*38e8c45fSAndroid Build Coastguard Worker const auto it = BATTERY_CLASSES.find(file.filename().string());
398*38e8c45fSAndroid Build Coastguard Worker if (it != BATTERY_CLASSES.end()) {
399*38e8c45fSAndroid Build Coastguard Worker info.flags |= it->second;
400*38e8c45fSAndroid Build Coastguard Worker }
401*38e8c45fSAndroid Build Coastguard Worker }
402*38e8c45fSAndroid Build Coastguard Worker batteryInfos.insert_or_assign(info.id, info);
403*38e8c45fSAndroid Build Coastguard Worker ALOGD("configureBatteryLocked rawBatteryId %d name %s", info.id, info.name.c_str());
404*38e8c45fSAndroid Build Coastguard Worker }
405*38e8c45fSAndroid Build Coastguard Worker return batteryInfos;
406*38e8c45fSAndroid Build Coastguard Worker }
407*38e8c45fSAndroid Build Coastguard Worker
408*38e8c45fSAndroid Build Coastguard Worker /**
409*38e8c45fSAndroid Build Coastguard Worker * Read information about lights exposed through the sysfs path.
410*38e8c45fSAndroid Build Coastguard Worker */
readLightsConfiguration(const std::filesystem::path & sysfsRootPath)411*38e8c45fSAndroid Build Coastguard Worker static std::unordered_map<int32_t /*lightId*/, RawLightInfo> readLightsConfiguration(
412*38e8c45fSAndroid Build Coastguard Worker const std::filesystem::path& sysfsRootPath) {
413*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<int32_t, RawLightInfo> lightInfos;
414*38e8c45fSAndroid Build Coastguard Worker int32_t nextLightId = 0;
415*38e8c45fSAndroid Build Coastguard Worker // Check if device has any lights.
416*38e8c45fSAndroid Build Coastguard Worker const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS);
417*38e8c45fSAndroid Build Coastguard Worker for (const auto& nodePath : paths) {
418*38e8c45fSAndroid Build Coastguard Worker RawLightInfo info;
419*38e8c45fSAndroid Build Coastguard Worker info.id = ++nextLightId;
420*38e8c45fSAndroid Build Coastguard Worker info.path = nodePath;
421*38e8c45fSAndroid Build Coastguard Worker info.name = nodePath.filename();
422*38e8c45fSAndroid Build Coastguard Worker info.maxBrightness = std::nullopt;
423*38e8c45fSAndroid Build Coastguard Worker
424*38e8c45fSAndroid Build Coastguard Worker // Light name should follow the naming pattern <name>:<color>:<function>
425*38e8c45fSAndroid Build Coastguard Worker // Refer kernel docs /leds/leds-class.html for valid supported LED names.
426*38e8c45fSAndroid Build Coastguard Worker std::regex indexPattern("([a-zA-Z0-9_.:]*:)?([a-zA-Z0-9_.]*):([a-zA-Z0-9_.]*)");
427*38e8c45fSAndroid Build Coastguard Worker std::smatch results;
428*38e8c45fSAndroid Build Coastguard Worker
429*38e8c45fSAndroid Build Coastguard Worker if (std::regex_match(info.name, results, indexPattern)) {
430*38e8c45fSAndroid Build Coastguard Worker // regex_match will return full match at index 0 and <name> at index 1. For RawLightInfo
431*38e8c45fSAndroid Build Coastguard Worker // we only care about sections <color> and <function> which will be at index 2 and 3.
432*38e8c45fSAndroid Build Coastguard Worker for (int i = 2; i <= 3; i++) {
433*38e8c45fSAndroid Build Coastguard Worker const auto it = LIGHT_CLASSES.find(results.str(i));
434*38e8c45fSAndroid Build Coastguard Worker if (it != LIGHT_CLASSES.end()) {
435*38e8c45fSAndroid Build Coastguard Worker info.flags |= it->second;
436*38e8c45fSAndroid Build Coastguard Worker }
437*38e8c45fSAndroid Build Coastguard Worker }
438*38e8c45fSAndroid Build Coastguard Worker
439*38e8c45fSAndroid Build Coastguard Worker // Set name of the raw light to <function> which represents playerIDs for LEDs that
440*38e8c45fSAndroid Build Coastguard Worker // turn on/off based on the current player ID (Refer to PeripheralController.cpp for
441*38e8c45fSAndroid Build Coastguard Worker // player ID logic)
442*38e8c45fSAndroid Build Coastguard Worker info.name = results.str(3);
443*38e8c45fSAndroid Build Coastguard Worker }
444*38e8c45fSAndroid Build Coastguard Worker // Scan the path for all the files
445*38e8c45fSAndroid Build Coastguard Worker // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt
446*38e8c45fSAndroid Build Coastguard Worker const auto& files = allFilesInPath(nodePath);
447*38e8c45fSAndroid Build Coastguard Worker for (const auto& file : files) {
448*38e8c45fSAndroid Build Coastguard Worker const auto it = LIGHT_CLASSES.find(file.filename().string());
449*38e8c45fSAndroid Build Coastguard Worker if (it != LIGHT_CLASSES.end()) {
450*38e8c45fSAndroid Build Coastguard Worker info.flags |= it->second;
451*38e8c45fSAndroid Build Coastguard Worker // If the node has maximum brightness, read it
452*38e8c45fSAndroid Build Coastguard Worker if (it->second == InputLightClass::MAX_BRIGHTNESS) {
453*38e8c45fSAndroid Build Coastguard Worker std::string str;
454*38e8c45fSAndroid Build Coastguard Worker if (base::ReadFileToString(file, &str)) {
455*38e8c45fSAndroid Build Coastguard Worker info.maxBrightness = std::stoi(str);
456*38e8c45fSAndroid Build Coastguard Worker }
457*38e8c45fSAndroid Build Coastguard Worker }
458*38e8c45fSAndroid Build Coastguard Worker }
459*38e8c45fSAndroid Build Coastguard Worker }
460*38e8c45fSAndroid Build Coastguard Worker lightInfos.insert_or_assign(info.id, info);
461*38e8c45fSAndroid Build Coastguard Worker ALOGD("configureLightsLocked rawLightId %d name %s", info.id, info.name.c_str());
462*38e8c45fSAndroid Build Coastguard Worker }
463*38e8c45fSAndroid Build Coastguard Worker return lightInfos;
464*38e8c45fSAndroid Build Coastguard Worker }
465*38e8c45fSAndroid Build Coastguard Worker
466*38e8c45fSAndroid Build Coastguard Worker // --- Global Functions ---
467*38e8c45fSAndroid Build Coastguard Worker
getAbsAxisUsage(int32_t axis,ftl::Flags<InputDeviceClass> deviceClasses)468*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis,
469*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputDeviceClass> deviceClasses) {
470*38e8c45fSAndroid Build Coastguard Worker // Touch devices get dibs on touch-related axes.
471*38e8c45fSAndroid Build Coastguard Worker if (deviceClasses.test(InputDeviceClass::TOUCH)) {
472*38e8c45fSAndroid Build Coastguard Worker switch (axis) {
473*38e8c45fSAndroid Build Coastguard Worker case ABS_X:
474*38e8c45fSAndroid Build Coastguard Worker case ABS_Y:
475*38e8c45fSAndroid Build Coastguard Worker case ABS_PRESSURE:
476*38e8c45fSAndroid Build Coastguard Worker case ABS_TOOL_WIDTH:
477*38e8c45fSAndroid Build Coastguard Worker case ABS_DISTANCE:
478*38e8c45fSAndroid Build Coastguard Worker case ABS_TILT_X:
479*38e8c45fSAndroid Build Coastguard Worker case ABS_TILT_Y:
480*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_SLOT:
481*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_TOUCH_MAJOR:
482*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_TOUCH_MINOR:
483*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_WIDTH_MAJOR:
484*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_WIDTH_MINOR:
485*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_ORIENTATION:
486*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_POSITION_X:
487*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_POSITION_Y:
488*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_TOOL_TYPE:
489*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_BLOB_ID:
490*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_TRACKING_ID:
491*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_PRESSURE:
492*38e8c45fSAndroid Build Coastguard Worker case ABS_MT_DISTANCE:
493*38e8c45fSAndroid Build Coastguard Worker return InputDeviceClass::TOUCH;
494*38e8c45fSAndroid Build Coastguard Worker }
495*38e8c45fSAndroid Build Coastguard Worker }
496*38e8c45fSAndroid Build Coastguard Worker
497*38e8c45fSAndroid Build Coastguard Worker if (deviceClasses.test(InputDeviceClass::SENSOR)) {
498*38e8c45fSAndroid Build Coastguard Worker switch (axis) {
499*38e8c45fSAndroid Build Coastguard Worker case ABS_X:
500*38e8c45fSAndroid Build Coastguard Worker case ABS_Y:
501*38e8c45fSAndroid Build Coastguard Worker case ABS_Z:
502*38e8c45fSAndroid Build Coastguard Worker case ABS_RX:
503*38e8c45fSAndroid Build Coastguard Worker case ABS_RY:
504*38e8c45fSAndroid Build Coastguard Worker case ABS_RZ:
505*38e8c45fSAndroid Build Coastguard Worker return InputDeviceClass::SENSOR;
506*38e8c45fSAndroid Build Coastguard Worker }
507*38e8c45fSAndroid Build Coastguard Worker }
508*38e8c45fSAndroid Build Coastguard Worker
509*38e8c45fSAndroid Build Coastguard Worker // External stylus gets the pressure axis
510*38e8c45fSAndroid Build Coastguard Worker if (deviceClasses.test(InputDeviceClass::EXTERNAL_STYLUS)) {
511*38e8c45fSAndroid Build Coastguard Worker if (axis == ABS_PRESSURE) {
512*38e8c45fSAndroid Build Coastguard Worker return InputDeviceClass::EXTERNAL_STYLUS;
513*38e8c45fSAndroid Build Coastguard Worker }
514*38e8c45fSAndroid Build Coastguard Worker }
515*38e8c45fSAndroid Build Coastguard Worker
516*38e8c45fSAndroid Build Coastguard Worker // Joystick devices get the rest.
517*38e8c45fSAndroid Build Coastguard Worker return deviceClasses & InputDeviceClass::JOYSTICK;
518*38e8c45fSAndroid Build Coastguard Worker }
519*38e8c45fSAndroid Build Coastguard Worker
520*38e8c45fSAndroid Build Coastguard Worker // --- RawAbsoluteAxisInfo ---
521*38e8c45fSAndroid Build Coastguard Worker
operator <<(std::ostream & out,const std::optional<RawAbsoluteAxisInfo> & info)522*38e8c45fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, const std::optional<RawAbsoluteAxisInfo>& info) {
523*38e8c45fSAndroid Build Coastguard Worker if (info) {
524*38e8c45fSAndroid Build Coastguard Worker out << "min=" << info->minValue << ", max=" << info->maxValue << ", flat=" << info->flat
525*38e8c45fSAndroid Build Coastguard Worker << ", fuzz=" << info->fuzz << ", resolution=" << info->resolution;
526*38e8c45fSAndroid Build Coastguard Worker } else {
527*38e8c45fSAndroid Build Coastguard Worker out << "unknown range";
528*38e8c45fSAndroid Build Coastguard Worker }
529*38e8c45fSAndroid Build Coastguard Worker return out;
530*38e8c45fSAndroid Build Coastguard Worker }
531*38e8c45fSAndroid Build Coastguard Worker
532*38e8c45fSAndroid Build Coastguard Worker // --- EventHub::Device ---
533*38e8c45fSAndroid Build Coastguard Worker
Device(int fd,int32_t id,std::string path,InputDeviceIdentifier identifier,std::shared_ptr<const AssociatedDevice> assocDev)534*38e8c45fSAndroid Build Coastguard Worker EventHub::Device::Device(int fd, int32_t id, std::string path, InputDeviceIdentifier identifier,
535*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const AssociatedDevice> assocDev)
536*38e8c45fSAndroid Build Coastguard Worker : fd(fd),
537*38e8c45fSAndroid Build Coastguard Worker id(id),
538*38e8c45fSAndroid Build Coastguard Worker path(std::move(path)),
539*38e8c45fSAndroid Build Coastguard Worker identifier(std::move(identifier)),
540*38e8c45fSAndroid Build Coastguard Worker classes(0),
541*38e8c45fSAndroid Build Coastguard Worker configuration(nullptr),
542*38e8c45fSAndroid Build Coastguard Worker virtualKeyMap(nullptr),
543*38e8c45fSAndroid Build Coastguard Worker ffEffectPlaying(false),
544*38e8c45fSAndroid Build Coastguard Worker ffEffectId(-1),
545*38e8c45fSAndroid Build Coastguard Worker associatedDevice(std::move(assocDev)),
546*38e8c45fSAndroid Build Coastguard Worker controllerNumber(0),
547*38e8c45fSAndroid Build Coastguard Worker enabled(true),
548*38e8c45fSAndroid Build Coastguard Worker isVirtual(fd < 0),
549*38e8c45fSAndroid Build Coastguard Worker currentFrameDropped(false) {}
550*38e8c45fSAndroid Build Coastguard Worker
~Device()551*38e8c45fSAndroid Build Coastguard Worker EventHub::Device::~Device() {
552*38e8c45fSAndroid Build Coastguard Worker close();
553*38e8c45fSAndroid Build Coastguard Worker }
554*38e8c45fSAndroid Build Coastguard Worker
close()555*38e8c45fSAndroid Build Coastguard Worker void EventHub::Device::close() {
556*38e8c45fSAndroid Build Coastguard Worker if (fd >= 0) {
557*38e8c45fSAndroid Build Coastguard Worker ::close(fd);
558*38e8c45fSAndroid Build Coastguard Worker fd = -1;
559*38e8c45fSAndroid Build Coastguard Worker }
560*38e8c45fSAndroid Build Coastguard Worker }
561*38e8c45fSAndroid Build Coastguard Worker
enable()562*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::Device::enable() {
563*38e8c45fSAndroid Build Coastguard Worker fd = open(path.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
564*38e8c45fSAndroid Build Coastguard Worker if (fd < 0) {
565*38e8c45fSAndroid Build Coastguard Worker ALOGE("could not open %s, %s\n", path.c_str(), strerror(errno));
566*38e8c45fSAndroid Build Coastguard Worker return -errno;
567*38e8c45fSAndroid Build Coastguard Worker }
568*38e8c45fSAndroid Build Coastguard Worker enabled = true;
569*38e8c45fSAndroid Build Coastguard Worker return OK;
570*38e8c45fSAndroid Build Coastguard Worker }
571*38e8c45fSAndroid Build Coastguard Worker
disable()572*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::Device::disable() {
573*38e8c45fSAndroid Build Coastguard Worker close();
574*38e8c45fSAndroid Build Coastguard Worker enabled = false;
575*38e8c45fSAndroid Build Coastguard Worker return OK;
576*38e8c45fSAndroid Build Coastguard Worker }
577*38e8c45fSAndroid Build Coastguard Worker
hasValidFd() const578*38e8c45fSAndroid Build Coastguard Worker bool EventHub::Device::hasValidFd() const {
579*38e8c45fSAndroid Build Coastguard Worker return !isVirtual && enabled;
580*38e8c45fSAndroid Build Coastguard Worker }
581*38e8c45fSAndroid Build Coastguard Worker
getKeyCharacterMap() const582*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<KeyCharacterMap> EventHub::Device::getKeyCharacterMap() const {
583*38e8c45fSAndroid Build Coastguard Worker return keyMap.keyCharacterMap;
584*38e8c45fSAndroid Build Coastguard Worker }
585*38e8c45fSAndroid Build Coastguard Worker
586*38e8c45fSAndroid Build Coastguard Worker template <std::size_t N>
readDeviceBitMask(unsigned long ioctlCode,BitArray<N> & bitArray)587*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::Device::readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray) {
588*38e8c45fSAndroid Build Coastguard Worker if (!hasValidFd()) {
589*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
590*38e8c45fSAndroid Build Coastguard Worker }
591*38e8c45fSAndroid Build Coastguard Worker if ((_IOC_SIZE(ioctlCode) == 0)) {
592*38e8c45fSAndroid Build Coastguard Worker ioctlCode |= _IOC(0, 0, 0, bitArray.bytes());
593*38e8c45fSAndroid Build Coastguard Worker }
594*38e8c45fSAndroid Build Coastguard Worker
595*38e8c45fSAndroid Build Coastguard Worker typename BitArray<N>::Buffer buffer;
596*38e8c45fSAndroid Build Coastguard Worker status_t ret = ioctl(fd, ioctlCode, buffer.data());
597*38e8c45fSAndroid Build Coastguard Worker bitArray.loadFromBuffer(buffer);
598*38e8c45fSAndroid Build Coastguard Worker return ret;
599*38e8c45fSAndroid Build Coastguard Worker }
600*38e8c45fSAndroid Build Coastguard Worker
configureFd()601*38e8c45fSAndroid Build Coastguard Worker void EventHub::Device::configureFd() {
602*38e8c45fSAndroid Build Coastguard Worker // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
603*38e8c45fSAndroid Build Coastguard Worker if (classes.test(InputDeviceClass::KEYBOARD)) {
604*38e8c45fSAndroid Build Coastguard Worker // Disable kernel key repeat since we handle it ourselves
605*38e8c45fSAndroid Build Coastguard Worker unsigned int repeatRate[] = {0, 0};
606*38e8c45fSAndroid Build Coastguard Worker if (ioctl(fd, EVIOCSREP, repeatRate)) {
607*38e8c45fSAndroid Build Coastguard Worker ALOGW("Unable to disable kernel key repeat for %s: %s", path.c_str(), strerror(errno));
608*38e8c45fSAndroid Build Coastguard Worker }
609*38e8c45fSAndroid Build Coastguard Worker }
610*38e8c45fSAndroid Build Coastguard Worker
611*38e8c45fSAndroid Build Coastguard Worker // Tell the kernel that we want to use the monotonic clock for reporting timestamps
612*38e8c45fSAndroid Build Coastguard Worker // associated with input events. This is important because the input system
613*38e8c45fSAndroid Build Coastguard Worker // uses the timestamps extensively and assumes they were recorded using the monotonic
614*38e8c45fSAndroid Build Coastguard Worker // clock.
615*38e8c45fSAndroid Build Coastguard Worker int clockId = CLOCK_MONOTONIC;
616*38e8c45fSAndroid Build Coastguard Worker if (classes.test(InputDeviceClass::SENSOR)) {
617*38e8c45fSAndroid Build Coastguard Worker // Each new sensor event should use the same time base as
618*38e8c45fSAndroid Build Coastguard Worker // SystemClock.elapsedRealtimeNanos().
619*38e8c45fSAndroid Build Coastguard Worker clockId = CLOCK_BOOTTIME;
620*38e8c45fSAndroid Build Coastguard Worker }
621*38e8c45fSAndroid Build Coastguard Worker bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
622*38e8c45fSAndroid Build Coastguard Worker ALOGI("usingClockIoctl=%s", toString(usingClockIoctl));
623*38e8c45fSAndroid Build Coastguard Worker
624*38e8c45fSAndroid Build Coastguard Worker // Query the initial state of keys and switches, which is tracked by EventHub.
625*38e8c45fSAndroid Build Coastguard Worker readDeviceState();
626*38e8c45fSAndroid Build Coastguard Worker }
627*38e8c45fSAndroid Build Coastguard Worker
readDeviceState()628*38e8c45fSAndroid Build Coastguard Worker void EventHub::Device::readDeviceState() {
629*38e8c45fSAndroid Build Coastguard Worker if (readDeviceBitMask(EVIOCGKEY(0), keyState) < 0) {
630*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unable to query the global key state for %s: %s", path.c_str(), strerror(errno));
631*38e8c45fSAndroid Build Coastguard Worker }
632*38e8c45fSAndroid Build Coastguard Worker if (readDeviceBitMask(EVIOCGSW(0), swState) < 0) {
633*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unable to query the global switch state for %s: %s", path.c_str(), strerror(errno));
634*38e8c45fSAndroid Build Coastguard Worker }
635*38e8c45fSAndroid Build Coastguard Worker
636*38e8c45fSAndroid Build Coastguard Worker // Read absolute axis info and values for all available axes for the device.
637*38e8c45fSAndroid Build Coastguard Worker populateAbsoluteAxisStates();
638*38e8c45fSAndroid Build Coastguard Worker }
639*38e8c45fSAndroid Build Coastguard Worker
populateAbsoluteAxisStates()640*38e8c45fSAndroid Build Coastguard Worker void EventHub::Device::populateAbsoluteAxisStates() {
641*38e8c45fSAndroid Build Coastguard Worker absState.clear();
642*38e8c45fSAndroid Build Coastguard Worker
643*38e8c45fSAndroid Build Coastguard Worker for (int axis = 0; axis <= ABS_MAX; axis++) {
644*38e8c45fSAndroid Build Coastguard Worker if (!absBitmask.test(axis)) {
645*38e8c45fSAndroid Build Coastguard Worker continue;
646*38e8c45fSAndroid Build Coastguard Worker }
647*38e8c45fSAndroid Build Coastguard Worker struct input_absinfo info {};
648*38e8c45fSAndroid Build Coastguard Worker if (ioctl(fd, EVIOCGABS(axis), &info)) {
649*38e8c45fSAndroid Build Coastguard Worker ALOGE("Error reading absolute controller %d for device %s fd %d: %s", axis,
650*38e8c45fSAndroid Build Coastguard Worker identifier.name.c_str(), fd, strerror(errno));
651*38e8c45fSAndroid Build Coastguard Worker continue;
652*38e8c45fSAndroid Build Coastguard Worker }
653*38e8c45fSAndroid Build Coastguard Worker auto& [axisInfo, value] = absState[axis];
654*38e8c45fSAndroid Build Coastguard Worker axisInfo.minValue = info.minimum;
655*38e8c45fSAndroid Build Coastguard Worker axisInfo.maxValue = info.maximum;
656*38e8c45fSAndroid Build Coastguard Worker axisInfo.flat = info.flat;
657*38e8c45fSAndroid Build Coastguard Worker axisInfo.fuzz = info.fuzz;
658*38e8c45fSAndroid Build Coastguard Worker axisInfo.resolution = info.resolution;
659*38e8c45fSAndroid Build Coastguard Worker value = info.value;
660*38e8c45fSAndroid Build Coastguard Worker }
661*38e8c45fSAndroid Build Coastguard Worker }
662*38e8c45fSAndroid Build Coastguard Worker
hasKeycodeLocked(int keycode) const663*38e8c45fSAndroid Build Coastguard Worker bool EventHub::Device::hasKeycodeLocked(int keycode) const {
664*38e8c45fSAndroid Build Coastguard Worker if (hasKeycodeInternalLocked(keycode)) {
665*38e8c45fSAndroid Build Coastguard Worker return true;
666*38e8c45fSAndroid Build Coastguard Worker }
667*38e8c45fSAndroid Build Coastguard Worker if (!keyMap.haveKeyCharacterMap()) {
668*38e8c45fSAndroid Build Coastguard Worker return false;
669*38e8c45fSAndroid Build Coastguard Worker }
670*38e8c45fSAndroid Build Coastguard Worker for (auto& fromKey : getKeyCharacterMap()->findKeyCodesMappedToKeyCode(keycode)) {
671*38e8c45fSAndroid Build Coastguard Worker if (hasKeycodeInternalLocked(fromKey)) {
672*38e8c45fSAndroid Build Coastguard Worker return true;
673*38e8c45fSAndroid Build Coastguard Worker }
674*38e8c45fSAndroid Build Coastguard Worker }
675*38e8c45fSAndroid Build Coastguard Worker return false;
676*38e8c45fSAndroid Build Coastguard Worker }
677*38e8c45fSAndroid Build Coastguard Worker
hasKeycodeInternalLocked(int keycode) const678*38e8c45fSAndroid Build Coastguard Worker bool EventHub::Device::hasKeycodeInternalLocked(int keycode) const {
679*38e8c45fSAndroid Build Coastguard Worker if (!keyMap.haveKeyLayout()) {
680*38e8c45fSAndroid Build Coastguard Worker return false;
681*38e8c45fSAndroid Build Coastguard Worker }
682*38e8c45fSAndroid Build Coastguard Worker
683*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> scanCodes = keyMap.keyLayoutMap->findScanCodesForKey(keycode);
684*38e8c45fSAndroid Build Coastguard Worker const size_t N = scanCodes.size();
685*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < N && i <= KEY_MAX; i++) {
686*38e8c45fSAndroid Build Coastguard Worker int32_t sc = scanCodes[i];
687*38e8c45fSAndroid Build Coastguard Worker if (sc >= 0 && sc <= KEY_MAX && keyBitmask.test(sc)) {
688*38e8c45fSAndroid Build Coastguard Worker return true;
689*38e8c45fSAndroid Build Coastguard Worker }
690*38e8c45fSAndroid Build Coastguard Worker }
691*38e8c45fSAndroid Build Coastguard Worker
692*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> usageCodes = keyMap.keyLayoutMap->findUsageCodesForKey(keycode);
693*38e8c45fSAndroid Build Coastguard Worker if (usageCodes.size() > 0 && mscBitmask.test(MSC_SCAN)) {
694*38e8c45fSAndroid Build Coastguard Worker return true;
695*38e8c45fSAndroid Build Coastguard Worker }
696*38e8c45fSAndroid Build Coastguard Worker return false;
697*38e8c45fSAndroid Build Coastguard Worker }
698*38e8c45fSAndroid Build Coastguard Worker
loadConfigurationLocked()699*38e8c45fSAndroid Build Coastguard Worker void EventHub::Device::loadConfigurationLocked() {
700*38e8c45fSAndroid Build Coastguard Worker configurationFile =
701*38e8c45fSAndroid Build Coastguard Worker getInputDeviceConfigurationFilePathByDeviceIdentifier(identifier,
702*38e8c45fSAndroid Build Coastguard Worker InputDeviceConfigurationFileType::
703*38e8c45fSAndroid Build Coastguard Worker CONFIGURATION);
704*38e8c45fSAndroid Build Coastguard Worker if (configurationFile.empty()) {
705*38e8c45fSAndroid Build Coastguard Worker ALOGD("No input device configuration file found for device '%s'.", identifier.name.c_str());
706*38e8c45fSAndroid Build Coastguard Worker } else {
707*38e8c45fSAndroid Build Coastguard Worker android::base::Result<std::unique_ptr<PropertyMap>> propertyMap =
708*38e8c45fSAndroid Build Coastguard Worker PropertyMap::load(configurationFile.c_str());
709*38e8c45fSAndroid Build Coastguard Worker if (!propertyMap.ok()) {
710*38e8c45fSAndroid Build Coastguard Worker ALOGE("Error loading input device configuration file for device '%s'. "
711*38e8c45fSAndroid Build Coastguard Worker "Using default configuration.",
712*38e8c45fSAndroid Build Coastguard Worker identifier.name.c_str());
713*38e8c45fSAndroid Build Coastguard Worker } else {
714*38e8c45fSAndroid Build Coastguard Worker configuration = std::move(*propertyMap);
715*38e8c45fSAndroid Build Coastguard Worker }
716*38e8c45fSAndroid Build Coastguard Worker }
717*38e8c45fSAndroid Build Coastguard Worker }
718*38e8c45fSAndroid Build Coastguard Worker
loadVirtualKeyMapLocked()719*38e8c45fSAndroid Build Coastguard Worker bool EventHub::Device::loadVirtualKeyMapLocked() {
720*38e8c45fSAndroid Build Coastguard Worker // The virtual key map is supplied by the kernel as a system board property file.
721*38e8c45fSAndroid Build Coastguard Worker std::string propPath = "/sys/board_properties/virtualkeys.";
722*38e8c45fSAndroid Build Coastguard Worker propPath += identifier.getCanonicalName();
723*38e8c45fSAndroid Build Coastguard Worker if (access(propPath.c_str(), R_OK)) {
724*38e8c45fSAndroid Build Coastguard Worker return false;
725*38e8c45fSAndroid Build Coastguard Worker }
726*38e8c45fSAndroid Build Coastguard Worker virtualKeyMap = VirtualKeyMap::load(propPath);
727*38e8c45fSAndroid Build Coastguard Worker return virtualKeyMap != nullptr;
728*38e8c45fSAndroid Build Coastguard Worker }
729*38e8c45fSAndroid Build Coastguard Worker
loadKeyMapLocked()730*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::Device::loadKeyMapLocked() {
731*38e8c45fSAndroid Build Coastguard Worker return keyMap.load(identifier, configuration.get());
732*38e8c45fSAndroid Build Coastguard Worker }
733*38e8c45fSAndroid Build Coastguard Worker
isExternalDeviceLocked()734*38e8c45fSAndroid Build Coastguard Worker bool EventHub::Device::isExternalDeviceLocked() {
735*38e8c45fSAndroid Build Coastguard Worker if (configuration) {
736*38e8c45fSAndroid Build Coastguard Worker std::optional<bool> isInternal = configuration->getBool("device.internal");
737*38e8c45fSAndroid Build Coastguard Worker if (isInternal.has_value()) {
738*38e8c45fSAndroid Build Coastguard Worker return !isInternal.value();
739*38e8c45fSAndroid Build Coastguard Worker }
740*38e8c45fSAndroid Build Coastguard Worker }
741*38e8c45fSAndroid Build Coastguard Worker return identifier.bus == BUS_USB || identifier.bus == BUS_BLUETOOTH;
742*38e8c45fSAndroid Build Coastguard Worker }
743*38e8c45fSAndroid Build Coastguard Worker
deviceHasMicLocked()744*38e8c45fSAndroid Build Coastguard Worker bool EventHub::Device::deviceHasMicLocked() {
745*38e8c45fSAndroid Build Coastguard Worker if (configuration) {
746*38e8c45fSAndroid Build Coastguard Worker std::optional<bool> hasMic = configuration->getBool("audio.mic");
747*38e8c45fSAndroid Build Coastguard Worker if (hasMic.has_value()) {
748*38e8c45fSAndroid Build Coastguard Worker return hasMic.value();
749*38e8c45fSAndroid Build Coastguard Worker }
750*38e8c45fSAndroid Build Coastguard Worker }
751*38e8c45fSAndroid Build Coastguard Worker return false;
752*38e8c45fSAndroid Build Coastguard Worker }
753*38e8c45fSAndroid Build Coastguard Worker
setLedStateLocked(int32_t led,bool on)754*38e8c45fSAndroid Build Coastguard Worker void EventHub::Device::setLedStateLocked(int32_t led, bool on) {
755*38e8c45fSAndroid Build Coastguard Worker int32_t sc;
756*38e8c45fSAndroid Build Coastguard Worker if (hasValidFd() && mapLed(led, &sc) != NAME_NOT_FOUND) {
757*38e8c45fSAndroid Build Coastguard Worker struct input_event ev;
758*38e8c45fSAndroid Build Coastguard Worker ev.input_event_sec = 0;
759*38e8c45fSAndroid Build Coastguard Worker ev.input_event_usec = 0;
760*38e8c45fSAndroid Build Coastguard Worker ev.type = EV_LED;
761*38e8c45fSAndroid Build Coastguard Worker ev.code = sc;
762*38e8c45fSAndroid Build Coastguard Worker ev.value = on ? 1 : 0;
763*38e8c45fSAndroid Build Coastguard Worker
764*38e8c45fSAndroid Build Coastguard Worker ssize_t nWrite;
765*38e8c45fSAndroid Build Coastguard Worker do {
766*38e8c45fSAndroid Build Coastguard Worker nWrite = write(fd, &ev, sizeof(struct input_event));
767*38e8c45fSAndroid Build Coastguard Worker } while (nWrite == -1 && errno == EINTR);
768*38e8c45fSAndroid Build Coastguard Worker }
769*38e8c45fSAndroid Build Coastguard Worker }
770*38e8c45fSAndroid Build Coastguard Worker
setLedForControllerLocked()771*38e8c45fSAndroid Build Coastguard Worker void EventHub::Device::setLedForControllerLocked() {
772*38e8c45fSAndroid Build Coastguard Worker for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
773*38e8c45fSAndroid Build Coastguard Worker setLedStateLocked(ALED_CONTROLLER_1 + i, controllerNumber == i + 1);
774*38e8c45fSAndroid Build Coastguard Worker }
775*38e8c45fSAndroid Build Coastguard Worker }
776*38e8c45fSAndroid Build Coastguard Worker
mapLed(int32_t led,int32_t * outScanCode) const777*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::Device::mapLed(int32_t led, int32_t* outScanCode) const {
778*38e8c45fSAndroid Build Coastguard Worker if (!keyMap.haveKeyLayout()) {
779*38e8c45fSAndroid Build Coastguard Worker return NAME_NOT_FOUND;
780*38e8c45fSAndroid Build Coastguard Worker }
781*38e8c45fSAndroid Build Coastguard Worker
782*38e8c45fSAndroid Build Coastguard Worker std::optional<int32_t> scanCode = keyMap.keyLayoutMap->findScanCodeForLed(led);
783*38e8c45fSAndroid Build Coastguard Worker if (scanCode.has_value()) {
784*38e8c45fSAndroid Build Coastguard Worker if (*scanCode >= 0 && *scanCode <= LED_MAX && ledBitmask.test(*scanCode)) {
785*38e8c45fSAndroid Build Coastguard Worker *outScanCode = *scanCode;
786*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
787*38e8c45fSAndroid Build Coastguard Worker }
788*38e8c45fSAndroid Build Coastguard Worker }
789*38e8c45fSAndroid Build Coastguard Worker return NAME_NOT_FOUND;
790*38e8c45fSAndroid Build Coastguard Worker }
791*38e8c45fSAndroid Build Coastguard Worker
trackInputEvent(const struct input_event & event)792*38e8c45fSAndroid Build Coastguard Worker void EventHub::Device::trackInputEvent(const struct input_event& event) {
793*38e8c45fSAndroid Build Coastguard Worker switch (event.type) {
794*38e8c45fSAndroid Build Coastguard Worker case EV_KEY: {
795*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!currentFrameDropped &&
796*38e8c45fSAndroid Build Coastguard Worker !keyState.set(static_cast<size_t>(event.code),
797*38e8c45fSAndroid Build Coastguard Worker event.value != 0),
798*38e8c45fSAndroid Build Coastguard Worker "%s: device '%s' received invalid EV_KEY event code: %s value: %d",
799*38e8c45fSAndroid Build Coastguard Worker __func__, identifier.name.c_str(),
800*38e8c45fSAndroid Build Coastguard Worker InputEventLookup::getLinuxEvdevLabel(EV_KEY, event.code, 1)
801*38e8c45fSAndroid Build Coastguard Worker .code.c_str(),
802*38e8c45fSAndroid Build Coastguard Worker event.value);
803*38e8c45fSAndroid Build Coastguard Worker break;
804*38e8c45fSAndroid Build Coastguard Worker }
805*38e8c45fSAndroid Build Coastguard Worker case EV_SW: {
806*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!currentFrameDropped &&
807*38e8c45fSAndroid Build Coastguard Worker !swState.set(static_cast<size_t>(event.code),
808*38e8c45fSAndroid Build Coastguard Worker event.value != 0),
809*38e8c45fSAndroid Build Coastguard Worker "%s: device '%s' received invalid EV_SW event code: %s value: %d",
810*38e8c45fSAndroid Build Coastguard Worker __func__, identifier.name.c_str(),
811*38e8c45fSAndroid Build Coastguard Worker InputEventLookup::getLinuxEvdevLabel(EV_SW, event.code, 1)
812*38e8c45fSAndroid Build Coastguard Worker .code.c_str(),
813*38e8c45fSAndroid Build Coastguard Worker event.value);
814*38e8c45fSAndroid Build Coastguard Worker break;
815*38e8c45fSAndroid Build Coastguard Worker }
816*38e8c45fSAndroid Build Coastguard Worker case EV_ABS: {
817*38e8c45fSAndroid Build Coastguard Worker if (currentFrameDropped) {
818*38e8c45fSAndroid Build Coastguard Worker break;
819*38e8c45fSAndroid Build Coastguard Worker }
820*38e8c45fSAndroid Build Coastguard Worker auto it = absState.find(event.code);
821*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(it == absState.end(),
822*38e8c45fSAndroid Build Coastguard Worker "%s: device '%s' received invalid EV_ABS event code: %s value: %d",
823*38e8c45fSAndroid Build Coastguard Worker __func__, identifier.name.c_str(),
824*38e8c45fSAndroid Build Coastguard Worker InputEventLookup::getLinuxEvdevLabel(EV_ABS, event.code, 0)
825*38e8c45fSAndroid Build Coastguard Worker .code.c_str(),
826*38e8c45fSAndroid Build Coastguard Worker event.value);
827*38e8c45fSAndroid Build Coastguard Worker it->second.value = event.value;
828*38e8c45fSAndroid Build Coastguard Worker break;
829*38e8c45fSAndroid Build Coastguard Worker }
830*38e8c45fSAndroid Build Coastguard Worker case EV_SYN: {
831*38e8c45fSAndroid Build Coastguard Worker switch (event.code) {
832*38e8c45fSAndroid Build Coastguard Worker case SYN_REPORT:
833*38e8c45fSAndroid Build Coastguard Worker if (currentFrameDropped) {
834*38e8c45fSAndroid Build Coastguard Worker // To recover after a SYN_DROPPED, we need to query the state of the device
835*38e8c45fSAndroid Build Coastguard Worker // to synchronize our device state with the kernel's to account for the
836*38e8c45fSAndroid Build Coastguard Worker // dropped events on receiving the next SYN_REPORT.
837*38e8c45fSAndroid Build Coastguard Worker // Note we don't drop the SYN_REPORT at this point but it is used by the
838*38e8c45fSAndroid Build Coastguard Worker // InputDevice to reset and repopulate mapper state
839*38e8c45fSAndroid Build Coastguard Worker readDeviceState();
840*38e8c45fSAndroid Build Coastguard Worker currentFrameDropped = false;
841*38e8c45fSAndroid Build Coastguard Worker }
842*38e8c45fSAndroid Build Coastguard Worker break;
843*38e8c45fSAndroid Build Coastguard Worker case SYN_DROPPED:
844*38e8c45fSAndroid Build Coastguard Worker // When we receive SYN_DROPPED, all events in the current frame should be
845*38e8c45fSAndroid Build Coastguard Worker // dropped up to and including next SYN_REPORT
846*38e8c45fSAndroid Build Coastguard Worker currentFrameDropped = true;
847*38e8c45fSAndroid Build Coastguard Worker break;
848*38e8c45fSAndroid Build Coastguard Worker default:
849*38e8c45fSAndroid Build Coastguard Worker break;
850*38e8c45fSAndroid Build Coastguard Worker }
851*38e8c45fSAndroid Build Coastguard Worker break;
852*38e8c45fSAndroid Build Coastguard Worker }
853*38e8c45fSAndroid Build Coastguard Worker default:
854*38e8c45fSAndroid Build Coastguard Worker break;
855*38e8c45fSAndroid Build Coastguard Worker }
856*38e8c45fSAndroid Build Coastguard Worker }
857*38e8c45fSAndroid Build Coastguard Worker
858*38e8c45fSAndroid Build Coastguard Worker /**
859*38e8c45fSAndroid Build Coastguard Worker * Get the capabilities for the current process.
860*38e8c45fSAndroid Build Coastguard Worker * Crashes the system if unable to create / check / destroy the capabilities object.
861*38e8c45fSAndroid Build Coastguard Worker */
862*38e8c45fSAndroid Build Coastguard Worker class Capabilities final {
863*38e8c45fSAndroid Build Coastguard Worker public:
Capabilities()864*38e8c45fSAndroid Build Coastguard Worker explicit Capabilities() {
865*38e8c45fSAndroid Build Coastguard Worker mCaps = cap_get_proc();
866*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mCaps == nullptr, "Could not get capabilities of the current process");
867*38e8c45fSAndroid Build Coastguard Worker }
868*38e8c45fSAndroid Build Coastguard Worker
869*38e8c45fSAndroid Build Coastguard Worker /**
870*38e8c45fSAndroid Build Coastguard Worker * Check whether the current process has a specific capability
871*38e8c45fSAndroid Build Coastguard Worker * in the set of effective capabilities.
872*38e8c45fSAndroid Build Coastguard Worker * Return CAP_SET if the process has the requested capability
873*38e8c45fSAndroid Build Coastguard Worker * Return CAP_CLEAR otherwise.
874*38e8c45fSAndroid Build Coastguard Worker */
checkEffectiveCapability(cap_value_t capability)875*38e8c45fSAndroid Build Coastguard Worker cap_flag_value_t checkEffectiveCapability(cap_value_t capability) {
876*38e8c45fSAndroid Build Coastguard Worker cap_flag_value_t value;
877*38e8c45fSAndroid Build Coastguard Worker const int result = cap_get_flag(mCaps, capability, CAP_EFFECTIVE, &value);
878*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(result == -1, "Could not obtain the requested capability");
879*38e8c45fSAndroid Build Coastguard Worker return value;
880*38e8c45fSAndroid Build Coastguard Worker }
881*38e8c45fSAndroid Build Coastguard Worker
~Capabilities()882*38e8c45fSAndroid Build Coastguard Worker ~Capabilities() {
883*38e8c45fSAndroid Build Coastguard Worker const int result = cap_free(mCaps);
884*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(result == -1, "Could not release the capabilities structure");
885*38e8c45fSAndroid Build Coastguard Worker }
886*38e8c45fSAndroid Build Coastguard Worker
887*38e8c45fSAndroid Build Coastguard Worker private:
888*38e8c45fSAndroid Build Coastguard Worker cap_t mCaps;
889*38e8c45fSAndroid Build Coastguard Worker };
890*38e8c45fSAndroid Build Coastguard Worker
ensureProcessCanBlockSuspend()891*38e8c45fSAndroid Build Coastguard Worker static void ensureProcessCanBlockSuspend() {
892*38e8c45fSAndroid Build Coastguard Worker Capabilities capabilities;
893*38e8c45fSAndroid Build Coastguard Worker const bool canBlockSuspend =
894*38e8c45fSAndroid Build Coastguard Worker capabilities.checkEffectiveCapability(CAP_BLOCK_SUSPEND) == CAP_SET;
895*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!canBlockSuspend,
896*38e8c45fSAndroid Build Coastguard Worker "Input must be able to block suspend to properly process events");
897*38e8c45fSAndroid Build Coastguard Worker }
898*38e8c45fSAndroid Build Coastguard Worker
899*38e8c45fSAndroid Build Coastguard Worker // --- EventHub ---
900*38e8c45fSAndroid Build Coastguard Worker
901*38e8c45fSAndroid Build Coastguard Worker const int EventHub::EPOLL_MAX_EVENTS;
902*38e8c45fSAndroid Build Coastguard Worker
EventHub(void)903*38e8c45fSAndroid Build Coastguard Worker EventHub::EventHub(void)
904*38e8c45fSAndroid Build Coastguard Worker : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
905*38e8c45fSAndroid Build Coastguard Worker mNextDeviceId(1),
906*38e8c45fSAndroid Build Coastguard Worker mControllerNumbers(),
907*38e8c45fSAndroid Build Coastguard Worker mNeedToReopenDevices(false),
908*38e8c45fSAndroid Build Coastguard Worker mNeedToScanDevices(true),
909*38e8c45fSAndroid Build Coastguard Worker mPendingEventCount(0),
910*38e8c45fSAndroid Build Coastguard Worker mPendingEventIndex(0),
911*38e8c45fSAndroid Build Coastguard Worker mPendingINotify(false) {
912*38e8c45fSAndroid Build Coastguard Worker ensureProcessCanBlockSuspend();
913*38e8c45fSAndroid Build Coastguard Worker
914*38e8c45fSAndroid Build Coastguard Worker mEpollFd = epoll_create1(EPOLL_CLOEXEC);
915*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
916*38e8c45fSAndroid Build Coastguard Worker
917*38e8c45fSAndroid Build Coastguard Worker mINotifyFd = inotify_init1(IN_CLOEXEC);
918*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mINotifyFd < 0, "Could not create inotify instance: %s", strerror(errno));
919*38e8c45fSAndroid Build Coastguard Worker
920*38e8c45fSAndroid Build Coastguard Worker std::error_code errorCode;
921*38e8c45fSAndroid Build Coastguard Worker bool isDeviceInotifyAdded = false;
922*38e8c45fSAndroid Build Coastguard Worker if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
923*38e8c45fSAndroid Build Coastguard Worker addDeviceInputInotify();
924*38e8c45fSAndroid Build Coastguard Worker } else {
925*38e8c45fSAndroid Build Coastguard Worker addDeviceInotify();
926*38e8c45fSAndroid Build Coastguard Worker isDeviceInotifyAdded = true;
927*38e8c45fSAndroid Build Coastguard Worker if (errorCode) {
928*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
929*38e8c45fSAndroid Build Coastguard Worker errorCode.message().c_str());
930*38e8c45fSAndroid Build Coastguard Worker }
931*38e8c45fSAndroid Build Coastguard Worker }
932*38e8c45fSAndroid Build Coastguard Worker
933*38e8c45fSAndroid Build Coastguard Worker if (isV4lScanningEnabled() && !isDeviceInotifyAdded) {
934*38e8c45fSAndroid Build Coastguard Worker addDeviceInotify();
935*38e8c45fSAndroid Build Coastguard Worker } else {
936*38e8c45fSAndroid Build Coastguard Worker ALOGI("Video device scanning disabled");
937*38e8c45fSAndroid Build Coastguard Worker }
938*38e8c45fSAndroid Build Coastguard Worker
939*38e8c45fSAndroid Build Coastguard Worker struct epoll_event eventItem = {};
940*38e8c45fSAndroid Build Coastguard Worker eventItem.events = EPOLLIN | EPOLLWAKEUP;
941*38e8c45fSAndroid Build Coastguard Worker eventItem.data.fd = mINotifyFd;
942*38e8c45fSAndroid Build Coastguard Worker int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
943*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
944*38e8c45fSAndroid Build Coastguard Worker
945*38e8c45fSAndroid Build Coastguard Worker int wakeFds[2];
946*38e8c45fSAndroid Build Coastguard Worker result = pipe2(wakeFds, O_CLOEXEC);
947*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
948*38e8c45fSAndroid Build Coastguard Worker
949*38e8c45fSAndroid Build Coastguard Worker mWakeReadPipeFd = wakeFds[0];
950*38e8c45fSAndroid Build Coastguard Worker mWakeWritePipeFd = wakeFds[1];
951*38e8c45fSAndroid Build Coastguard Worker
952*38e8c45fSAndroid Build Coastguard Worker result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
953*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
954*38e8c45fSAndroid Build Coastguard Worker errno);
955*38e8c45fSAndroid Build Coastguard Worker
956*38e8c45fSAndroid Build Coastguard Worker result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
957*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
958*38e8c45fSAndroid Build Coastguard Worker errno);
959*38e8c45fSAndroid Build Coastguard Worker
960*38e8c45fSAndroid Build Coastguard Worker eventItem.data.fd = mWakeReadPipeFd;
961*38e8c45fSAndroid Build Coastguard Worker result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
962*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
963*38e8c45fSAndroid Build Coastguard Worker errno);
964*38e8c45fSAndroid Build Coastguard Worker }
965*38e8c45fSAndroid Build Coastguard Worker
~EventHub(void)966*38e8c45fSAndroid Build Coastguard Worker EventHub::~EventHub(void) {
967*38e8c45fSAndroid Build Coastguard Worker closeAllDevicesLocked();
968*38e8c45fSAndroid Build Coastguard Worker
969*38e8c45fSAndroid Build Coastguard Worker ::close(mEpollFd);
970*38e8c45fSAndroid Build Coastguard Worker ::close(mINotifyFd);
971*38e8c45fSAndroid Build Coastguard Worker ::close(mWakeReadPipeFd);
972*38e8c45fSAndroid Build Coastguard Worker ::close(mWakeWritePipeFd);
973*38e8c45fSAndroid Build Coastguard Worker }
974*38e8c45fSAndroid Build Coastguard Worker
975*38e8c45fSAndroid Build Coastguard Worker /**
976*38e8c45fSAndroid Build Coastguard Worker * On devices that don't have any input devices (like some development boards), the /dev/input
977*38e8c45fSAndroid Build Coastguard Worker * directory will be absent. However, the user may still plug in an input device at a later time.
978*38e8c45fSAndroid Build Coastguard Worker * Add watch for contents of /dev/input only when /dev/input appears.
979*38e8c45fSAndroid Build Coastguard Worker */
addDeviceInputInotify()980*38e8c45fSAndroid Build Coastguard Worker void EventHub::addDeviceInputInotify() {
981*38e8c45fSAndroid Build Coastguard Worker mDeviceInputWd = inotify_add_watch(mINotifyFd, DEVICE_INPUT_PATH, IN_DELETE | IN_CREATE);
982*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mDeviceInputWd < 0, "Could not register INotify for %s: %s",
983*38e8c45fSAndroid Build Coastguard Worker DEVICE_INPUT_PATH, strerror(errno));
984*38e8c45fSAndroid Build Coastguard Worker }
985*38e8c45fSAndroid Build Coastguard Worker
addDeviceInotify()986*38e8c45fSAndroid Build Coastguard Worker void EventHub::addDeviceInotify() {
987*38e8c45fSAndroid Build Coastguard Worker mDeviceWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
988*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mDeviceWd < 0, "Could not register INotify for %s: %s", DEVICE_PATH,
989*38e8c45fSAndroid Build Coastguard Worker strerror(errno));
990*38e8c45fSAndroid Build Coastguard Worker }
991*38e8c45fSAndroid Build Coastguard Worker
getDeviceIdentifier(int32_t deviceId) const992*38e8c45fSAndroid Build Coastguard Worker InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
993*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
994*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
995*38e8c45fSAndroid Build Coastguard Worker return device != nullptr ? device->identifier : InputDeviceIdentifier();
996*38e8c45fSAndroid Build Coastguard Worker }
997*38e8c45fSAndroid Build Coastguard Worker
getDeviceClasses(int32_t deviceId) const998*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputDeviceClass> EventHub::getDeviceClasses(int32_t deviceId) const {
999*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1000*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1001*38e8c45fSAndroid Build Coastguard Worker return device != nullptr ? device->classes : ftl::Flags<InputDeviceClass>(0);
1002*38e8c45fSAndroid Build Coastguard Worker }
1003*38e8c45fSAndroid Build Coastguard Worker
getDeviceControllerNumber(int32_t deviceId) const1004*38e8c45fSAndroid Build Coastguard Worker int32_t EventHub::getDeviceControllerNumber(int32_t deviceId) const {
1005*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1006*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1007*38e8c45fSAndroid Build Coastguard Worker return device != nullptr ? device->controllerNumber : 0;
1008*38e8c45fSAndroid Build Coastguard Worker }
1009*38e8c45fSAndroid Build Coastguard Worker
getConfiguration(int32_t deviceId) const1010*38e8c45fSAndroid Build Coastguard Worker std::optional<PropertyMap> EventHub::getConfiguration(int32_t deviceId) const {
1011*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1012*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1013*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || device->configuration == nullptr) {
1014*38e8c45fSAndroid Build Coastguard Worker return {};
1015*38e8c45fSAndroid Build Coastguard Worker }
1016*38e8c45fSAndroid Build Coastguard Worker return *device->configuration;
1017*38e8c45fSAndroid Build Coastguard Worker }
1018*38e8c45fSAndroid Build Coastguard Worker
getAbsoluteAxisInfo(int32_t deviceId,int axis) const1019*38e8c45fSAndroid Build Coastguard Worker std::optional<RawAbsoluteAxisInfo> EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis) const {
1020*38e8c45fSAndroid Build Coastguard Worker if (axis < 0 || axis > ABS_MAX) {
1021*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1022*38e8c45fSAndroid Build Coastguard Worker }
1023*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1024*38e8c45fSAndroid Build Coastguard Worker const Device* device = getDeviceLocked(deviceId);
1025*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr) {
1026*38e8c45fSAndroid Build Coastguard Worker ALOGE("Couldn't find device with ID %d, so returning null axis info for axis %s", deviceId,
1027*38e8c45fSAndroid Build Coastguard Worker InputEventLookup::getLinuxEvdevLabel(EV_ABS, axis, 0).code.c_str());
1028*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1029*38e8c45fSAndroid Build Coastguard Worker }
1030*38e8c45fSAndroid Build Coastguard Worker // We can read the RawAbsoluteAxisInfo even if the device is disabled and doesn't have a valid
1031*38e8c45fSAndroid Build Coastguard Worker // fd, because the info is populated once when the device is first opened, and it doesn't change
1032*38e8c45fSAndroid Build Coastguard Worker // throughout the device lifecycle.
1033*38e8c45fSAndroid Build Coastguard Worker auto it = device->absState.find(axis);
1034*38e8c45fSAndroid Build Coastguard Worker if (it == device->absState.end()) {
1035*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1036*38e8c45fSAndroid Build Coastguard Worker }
1037*38e8c45fSAndroid Build Coastguard Worker return it->second.info;
1038*38e8c45fSAndroid Build Coastguard Worker }
1039*38e8c45fSAndroid Build Coastguard Worker
hasRelativeAxis(int32_t deviceId,int axis) const1040*38e8c45fSAndroid Build Coastguard Worker bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
1041*38e8c45fSAndroid Build Coastguard Worker if (axis >= 0 && axis <= REL_MAX) {
1042*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1043*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1044*38e8c45fSAndroid Build Coastguard Worker return device != nullptr ? device->relBitmask.test(axis) : false;
1045*38e8c45fSAndroid Build Coastguard Worker }
1046*38e8c45fSAndroid Build Coastguard Worker return false;
1047*38e8c45fSAndroid Build Coastguard Worker }
1048*38e8c45fSAndroid Build Coastguard Worker
hasInputProperty(int32_t deviceId,int property) const1049*38e8c45fSAndroid Build Coastguard Worker bool EventHub::hasInputProperty(int32_t deviceId, int property) const {
1050*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1051*38e8c45fSAndroid Build Coastguard Worker
1052*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1053*38e8c45fSAndroid Build Coastguard Worker return property >= 0 && property <= INPUT_PROP_MAX && device != nullptr
1054*38e8c45fSAndroid Build Coastguard Worker ? device->propBitmask.test(property)
1055*38e8c45fSAndroid Build Coastguard Worker : false;
1056*38e8c45fSAndroid Build Coastguard Worker }
1057*38e8c45fSAndroid Build Coastguard Worker
hasMscEvent(int32_t deviceId,int mscEvent) const1058*38e8c45fSAndroid Build Coastguard Worker bool EventHub::hasMscEvent(int32_t deviceId, int mscEvent) const {
1059*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1060*38e8c45fSAndroid Build Coastguard Worker
1061*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1062*38e8c45fSAndroid Build Coastguard Worker return mscEvent >= 0 && mscEvent <= MSC_MAX && device != nullptr
1063*38e8c45fSAndroid Build Coastguard Worker ? device->mscBitmask.test(mscEvent)
1064*38e8c45fSAndroid Build Coastguard Worker : false;
1065*38e8c45fSAndroid Build Coastguard Worker }
1066*38e8c45fSAndroid Build Coastguard Worker
getScanCodeState(int32_t deviceId,int32_t scanCode) const1067*38e8c45fSAndroid Build Coastguard Worker int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
1068*38e8c45fSAndroid Build Coastguard Worker if (scanCode < 0 || scanCode > KEY_MAX) {
1069*38e8c45fSAndroid Build Coastguard Worker return AKEY_STATE_UNKNOWN;
1070*38e8c45fSAndroid Build Coastguard Worker }
1071*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1072*38e8c45fSAndroid Build Coastguard Worker const Device* device = getDeviceLocked(deviceId);
1073*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->hasValidFd() || !device->keyBitmask.test(scanCode)) {
1074*38e8c45fSAndroid Build Coastguard Worker return AKEY_STATE_UNKNOWN;
1075*38e8c45fSAndroid Build Coastguard Worker }
1076*38e8c45fSAndroid Build Coastguard Worker return device->keyState.test(scanCode) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
1077*38e8c45fSAndroid Build Coastguard Worker }
1078*38e8c45fSAndroid Build Coastguard Worker
getKeyCodeState(int32_t deviceId,int32_t keyCode) const1079*38e8c45fSAndroid Build Coastguard Worker int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
1080*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1081*38e8c45fSAndroid Build Coastguard Worker const Device* device = getDeviceLocked(deviceId);
1082*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->hasValidFd() || !device->keyMap.haveKeyLayout()) {
1083*38e8c45fSAndroid Build Coastguard Worker return AKEY_STATE_UNKNOWN;
1084*38e8c45fSAndroid Build Coastguard Worker }
1085*38e8c45fSAndroid Build Coastguard Worker const std::vector<int32_t> scanCodes =
1086*38e8c45fSAndroid Build Coastguard Worker device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode);
1087*38e8c45fSAndroid Build Coastguard Worker if (scanCodes.empty()) {
1088*38e8c45fSAndroid Build Coastguard Worker return AKEY_STATE_UNKNOWN;
1089*38e8c45fSAndroid Build Coastguard Worker }
1090*38e8c45fSAndroid Build Coastguard Worker return std::any_of(scanCodes.begin(), scanCodes.end(),
1091*38e8c45fSAndroid Build Coastguard Worker [&device](const int32_t sc) {
1092*38e8c45fSAndroid Build Coastguard Worker return sc >= 0 && sc <= KEY_MAX && device->keyState.test(sc);
1093*38e8c45fSAndroid Build Coastguard Worker })
1094*38e8c45fSAndroid Build Coastguard Worker ? AKEY_STATE_DOWN
1095*38e8c45fSAndroid Build Coastguard Worker : AKEY_STATE_UP;
1096*38e8c45fSAndroid Build Coastguard Worker }
1097*38e8c45fSAndroid Build Coastguard Worker
getKeyCodeForKeyLocation(int32_t deviceId,int32_t locationKeyCode) const1098*38e8c45fSAndroid Build Coastguard Worker int32_t EventHub::getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const {
1099*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1100*38e8c45fSAndroid Build Coastguard Worker
1101*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1102*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->hasValidFd() || device->keyMap.keyCharacterMap == nullptr ||
1103*38e8c45fSAndroid Build Coastguard Worker device->keyMap.keyLayoutMap == nullptr) {
1104*38e8c45fSAndroid Build Coastguard Worker return AKEYCODE_UNKNOWN;
1105*38e8c45fSAndroid Build Coastguard Worker }
1106*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> scanCodes =
1107*38e8c45fSAndroid Build Coastguard Worker device->keyMap.keyLayoutMap->findScanCodesForKey(locationKeyCode);
1108*38e8c45fSAndroid Build Coastguard Worker if (scanCodes.empty()) {
1109*38e8c45fSAndroid Build Coastguard Worker ALOGW("Failed to get key code for key location: no scan code maps to key code %d for input"
1110*38e8c45fSAndroid Build Coastguard Worker "device %d",
1111*38e8c45fSAndroid Build Coastguard Worker locationKeyCode, deviceId);
1112*38e8c45fSAndroid Build Coastguard Worker return AKEYCODE_UNKNOWN;
1113*38e8c45fSAndroid Build Coastguard Worker }
1114*38e8c45fSAndroid Build Coastguard Worker if (scanCodes.size() > 1) {
1115*38e8c45fSAndroid Build Coastguard Worker ALOGW("Multiple scan codes map to the same key code %d, returning only the first match",
1116*38e8c45fSAndroid Build Coastguard Worker locationKeyCode);
1117*38e8c45fSAndroid Build Coastguard Worker }
1118*38e8c45fSAndroid Build Coastguard Worker int32_t outKeyCode;
1119*38e8c45fSAndroid Build Coastguard Worker status_t mapKeyRes =
1120*38e8c45fSAndroid Build Coastguard Worker device->getKeyCharacterMap()->mapKey(scanCodes[0], /*usageCode=*/0, &outKeyCode);
1121*38e8c45fSAndroid Build Coastguard Worker switch (mapKeyRes) {
1122*38e8c45fSAndroid Build Coastguard Worker case OK:
1123*38e8c45fSAndroid Build Coastguard Worker break;
1124*38e8c45fSAndroid Build Coastguard Worker case NAME_NOT_FOUND:
1125*38e8c45fSAndroid Build Coastguard Worker // key character map doesn't re-map this scanCode, hence the keyCode remains the same
1126*38e8c45fSAndroid Build Coastguard Worker outKeyCode = locationKeyCode;
1127*38e8c45fSAndroid Build Coastguard Worker break;
1128*38e8c45fSAndroid Build Coastguard Worker default:
1129*38e8c45fSAndroid Build Coastguard Worker ALOGW("Failed to get key code for key location: Key character map returned error %s",
1130*38e8c45fSAndroid Build Coastguard Worker statusToString(mapKeyRes).c_str());
1131*38e8c45fSAndroid Build Coastguard Worker outKeyCode = AKEYCODE_UNKNOWN;
1132*38e8c45fSAndroid Build Coastguard Worker break;
1133*38e8c45fSAndroid Build Coastguard Worker }
1134*38e8c45fSAndroid Build Coastguard Worker // Remap if there is a Key remapping added to the KCM and return the remapped key
1135*38e8c45fSAndroid Build Coastguard Worker return device->getKeyCharacterMap()->applyKeyRemapping(outKeyCode);
1136*38e8c45fSAndroid Build Coastguard Worker }
1137*38e8c45fSAndroid Build Coastguard Worker
getSwitchState(int32_t deviceId,int32_t sw) const1138*38e8c45fSAndroid Build Coastguard Worker int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
1139*38e8c45fSAndroid Build Coastguard Worker if (sw < 0 || sw > SW_MAX) {
1140*38e8c45fSAndroid Build Coastguard Worker return AKEY_STATE_UNKNOWN;
1141*38e8c45fSAndroid Build Coastguard Worker }
1142*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1143*38e8c45fSAndroid Build Coastguard Worker const Device* device = getDeviceLocked(deviceId);
1144*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->hasValidFd() || !device->swBitmask.test(sw)) {
1145*38e8c45fSAndroid Build Coastguard Worker return AKEY_STATE_UNKNOWN;
1146*38e8c45fSAndroid Build Coastguard Worker }
1147*38e8c45fSAndroid Build Coastguard Worker return device->swState.test(sw) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
1148*38e8c45fSAndroid Build Coastguard Worker }
1149*38e8c45fSAndroid Build Coastguard Worker
getAbsoluteAxisValue(int32_t deviceId,int32_t axis) const1150*38e8c45fSAndroid Build Coastguard Worker std::optional<int32_t> EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const {
1151*38e8c45fSAndroid Build Coastguard Worker if (axis < 0 || axis > ABS_MAX) {
1152*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1153*38e8c45fSAndroid Build Coastguard Worker }
1154*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1155*38e8c45fSAndroid Build Coastguard Worker const Device* device = getDeviceLocked(deviceId);
1156*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->hasValidFd()) {
1157*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1158*38e8c45fSAndroid Build Coastguard Worker }
1159*38e8c45fSAndroid Build Coastguard Worker const auto it = device->absState.find(axis);
1160*38e8c45fSAndroid Build Coastguard Worker if (it == device->absState.end()) {
1161*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1162*38e8c45fSAndroid Build Coastguard Worker }
1163*38e8c45fSAndroid Build Coastguard Worker return it->second.value;
1164*38e8c45fSAndroid Build Coastguard Worker }
1165*38e8c45fSAndroid Build Coastguard Worker
getMtSlotValues(int32_t deviceId,int32_t axis,size_t slotCount) const1166*38e8c45fSAndroid Build Coastguard Worker base::Result<std::vector<int32_t>> EventHub::getMtSlotValues(int32_t deviceId, int32_t axis,
1167*38e8c45fSAndroid Build Coastguard Worker size_t slotCount) const {
1168*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1169*38e8c45fSAndroid Build Coastguard Worker const Device* device = getDeviceLocked(deviceId);
1170*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->hasValidFd() || !device->absBitmask.test(axis)) {
1171*38e8c45fSAndroid Build Coastguard Worker return base::ResultError("device problem or axis not supported", NAME_NOT_FOUND);
1172*38e8c45fSAndroid Build Coastguard Worker }
1173*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> outValues(slotCount + 1);
1174*38e8c45fSAndroid Build Coastguard Worker outValues[0] = axis;
1175*38e8c45fSAndroid Build Coastguard Worker const size_t bufferSize = outValues.size() * sizeof(int32_t);
1176*38e8c45fSAndroid Build Coastguard Worker if (ioctl(device->fd, EVIOCGMTSLOTS(bufferSize), outValues.data()) != OK) {
1177*38e8c45fSAndroid Build Coastguard Worker return base::ErrnoError();
1178*38e8c45fSAndroid Build Coastguard Worker }
1179*38e8c45fSAndroid Build Coastguard Worker return std::move(outValues);
1180*38e8c45fSAndroid Build Coastguard Worker }
1181*38e8c45fSAndroid Build Coastguard Worker
markSupportedKeyCodes(int32_t deviceId,const std::vector<int32_t> & keyCodes,uint8_t * outFlags) const1182*38e8c45fSAndroid Build Coastguard Worker bool EventHub::markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
1183*38e8c45fSAndroid Build Coastguard Worker uint8_t* outFlags) const {
1184*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1185*38e8c45fSAndroid Build Coastguard Worker
1186*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1187*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && device->keyMap.haveKeyLayout()) {
1188*38e8c45fSAndroid Build Coastguard Worker for (size_t codeIndex = 0; codeIndex < keyCodes.size(); codeIndex++) {
1189*38e8c45fSAndroid Build Coastguard Worker if (device->hasKeycodeLocked(keyCodes[codeIndex])) {
1190*38e8c45fSAndroid Build Coastguard Worker outFlags[codeIndex] = 1;
1191*38e8c45fSAndroid Build Coastguard Worker }
1192*38e8c45fSAndroid Build Coastguard Worker }
1193*38e8c45fSAndroid Build Coastguard Worker return true;
1194*38e8c45fSAndroid Build Coastguard Worker }
1195*38e8c45fSAndroid Build Coastguard Worker return false;
1196*38e8c45fSAndroid Build Coastguard Worker }
1197*38e8c45fSAndroid Build Coastguard Worker
setKeyRemapping(int32_t deviceId,const std::map<int32_t,int32_t> & keyRemapping) const1198*38e8c45fSAndroid Build Coastguard Worker void EventHub::setKeyRemapping(int32_t deviceId,
1199*38e8c45fSAndroid Build Coastguard Worker const std::map<int32_t, int32_t>& keyRemapping) const {
1200*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1201*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1202*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr) {
1203*38e8c45fSAndroid Build Coastguard Worker return;
1204*38e8c45fSAndroid Build Coastguard Worker }
1205*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<KeyCharacterMap> kcm = device->getKeyCharacterMap();
1206*38e8c45fSAndroid Build Coastguard Worker if (kcm) {
1207*38e8c45fSAndroid Build Coastguard Worker kcm->setKeyRemapping(keyRemapping);
1208*38e8c45fSAndroid Build Coastguard Worker }
1209*38e8c45fSAndroid Build Coastguard Worker }
1210*38e8c45fSAndroid Build Coastguard Worker
mapKey(int32_t deviceId,int32_t scanCode,int32_t usageCode,int32_t metaState,int32_t * outKeycode,int32_t * outMetaState,uint32_t * outFlags) const1211*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
1212*38e8c45fSAndroid Build Coastguard Worker int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
1213*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1214*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1215*38e8c45fSAndroid Build Coastguard Worker status_t status = NAME_NOT_FOUND;
1216*38e8c45fSAndroid Build Coastguard Worker
1217*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr) {
1218*38e8c45fSAndroid Build Coastguard Worker // Check the key character map first.
1219*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<KeyCharacterMap> kcm = device->getKeyCharacterMap();
1220*38e8c45fSAndroid Build Coastguard Worker if (kcm) {
1221*38e8c45fSAndroid Build Coastguard Worker if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
1222*38e8c45fSAndroid Build Coastguard Worker *outFlags = 0;
1223*38e8c45fSAndroid Build Coastguard Worker status = NO_ERROR;
1224*38e8c45fSAndroid Build Coastguard Worker }
1225*38e8c45fSAndroid Build Coastguard Worker }
1226*38e8c45fSAndroid Build Coastguard Worker
1227*38e8c45fSAndroid Build Coastguard Worker // Check the key layout next.
1228*38e8c45fSAndroid Build Coastguard Worker if (status != NO_ERROR && device->keyMap.haveKeyLayout()) {
1229*38e8c45fSAndroid Build Coastguard Worker if (!device->keyMap.keyLayoutMap->mapKey(scanCode, usageCode, outKeycode, outFlags)) {
1230*38e8c45fSAndroid Build Coastguard Worker status = NO_ERROR;
1231*38e8c45fSAndroid Build Coastguard Worker }
1232*38e8c45fSAndroid Build Coastguard Worker }
1233*38e8c45fSAndroid Build Coastguard Worker
1234*38e8c45fSAndroid Build Coastguard Worker if (status == NO_ERROR) {
1235*38e8c45fSAndroid Build Coastguard Worker if (kcm) {
1236*38e8c45fSAndroid Build Coastguard Worker // Remap keys based on user-defined key remappings and key behavior defined in the
1237*38e8c45fSAndroid Build Coastguard Worker // corresponding kcm file
1238*38e8c45fSAndroid Build Coastguard Worker *outKeycode = kcm->applyKeyRemapping(*outKeycode);
1239*38e8c45fSAndroid Build Coastguard Worker
1240*38e8c45fSAndroid Build Coastguard Worker // Remap keys based on Key behavior defined in KCM file
1241*38e8c45fSAndroid Build Coastguard Worker std::tie(*outKeycode, *outMetaState) =
1242*38e8c45fSAndroid Build Coastguard Worker kcm->applyKeyBehavior(*outKeycode, metaState);
1243*38e8c45fSAndroid Build Coastguard Worker } else {
1244*38e8c45fSAndroid Build Coastguard Worker *outMetaState = metaState;
1245*38e8c45fSAndroid Build Coastguard Worker }
1246*38e8c45fSAndroid Build Coastguard Worker }
1247*38e8c45fSAndroid Build Coastguard Worker }
1248*38e8c45fSAndroid Build Coastguard Worker
1249*38e8c45fSAndroid Build Coastguard Worker if (status != NO_ERROR) {
1250*38e8c45fSAndroid Build Coastguard Worker *outKeycode = 0;
1251*38e8c45fSAndroid Build Coastguard Worker *outFlags = 0;
1252*38e8c45fSAndroid Build Coastguard Worker *outMetaState = metaState;
1253*38e8c45fSAndroid Build Coastguard Worker }
1254*38e8c45fSAndroid Build Coastguard Worker
1255*38e8c45fSAndroid Build Coastguard Worker return status;
1256*38e8c45fSAndroid Build Coastguard Worker }
1257*38e8c45fSAndroid Build Coastguard Worker
mapAxis(int32_t deviceId,int32_t scanCode,AxisInfo * outAxisInfo) const1258*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const {
1259*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1260*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1261*38e8c45fSAndroid Build Coastguard Worker
1262*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->keyMap.haveKeyLayout()) {
1263*38e8c45fSAndroid Build Coastguard Worker return NAME_NOT_FOUND;
1264*38e8c45fSAndroid Build Coastguard Worker }
1265*38e8c45fSAndroid Build Coastguard Worker std::optional<AxisInfo> info = device->keyMap.keyLayoutMap->mapAxis(scanCode);
1266*38e8c45fSAndroid Build Coastguard Worker if (!info.has_value()) {
1267*38e8c45fSAndroid Build Coastguard Worker return NAME_NOT_FOUND;
1268*38e8c45fSAndroid Build Coastguard Worker }
1269*38e8c45fSAndroid Build Coastguard Worker *outAxisInfo = *info;
1270*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
1271*38e8c45fSAndroid Build Coastguard Worker }
1272*38e8c45fSAndroid Build Coastguard Worker
mapSensor(int32_t deviceId,int32_t absCode) const1273*38e8c45fSAndroid Build Coastguard Worker base::Result<std::pair<InputDeviceSensorType, int32_t>> EventHub::mapSensor(int32_t deviceId,
1274*38e8c45fSAndroid Build Coastguard Worker int32_t absCode) const {
1275*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1276*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1277*38e8c45fSAndroid Build Coastguard Worker
1278*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && device->keyMap.haveKeyLayout()) {
1279*38e8c45fSAndroid Build Coastguard Worker return device->keyMap.keyLayoutMap->mapSensor(absCode);
1280*38e8c45fSAndroid Build Coastguard Worker }
1281*38e8c45fSAndroid Build Coastguard Worker return Errorf("Device not found or device has no key layout.");
1282*38e8c45fSAndroid Build Coastguard Worker }
1283*38e8c45fSAndroid Build Coastguard Worker
1284*38e8c45fSAndroid Build Coastguard Worker // Gets the battery info map from battery ID to RawBatteryInfo of the miscellaneous device
1285*38e8c45fSAndroid Build Coastguard Worker // associated with the device ID. Returns an empty map if no miscellaneous device found.
getBatteryInfoLocked(int32_t deviceId) const1286*38e8c45fSAndroid Build Coastguard Worker const std::unordered_map<int32_t, RawBatteryInfo>& EventHub::getBatteryInfoLocked(
1287*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId) const {
1288*38e8c45fSAndroid Build Coastguard Worker static const std::unordered_map<int32_t, RawBatteryInfo> EMPTY_BATTERY_INFO = {};
1289*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1290*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->associatedDevice) {
1291*38e8c45fSAndroid Build Coastguard Worker return EMPTY_BATTERY_INFO;
1292*38e8c45fSAndroid Build Coastguard Worker }
1293*38e8c45fSAndroid Build Coastguard Worker return device->associatedDevice->batteryInfos;
1294*38e8c45fSAndroid Build Coastguard Worker }
1295*38e8c45fSAndroid Build Coastguard Worker
getRawBatteryIds(int32_t deviceId) const1296*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) const {
1297*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1298*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> batteryIds;
1299*38e8c45fSAndroid Build Coastguard Worker
1300*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, info] : getBatteryInfoLocked(deviceId)) {
1301*38e8c45fSAndroid Build Coastguard Worker batteryIds.push_back(id);
1302*38e8c45fSAndroid Build Coastguard Worker }
1303*38e8c45fSAndroid Build Coastguard Worker
1304*38e8c45fSAndroid Build Coastguard Worker return batteryIds;
1305*38e8c45fSAndroid Build Coastguard Worker }
1306*38e8c45fSAndroid Build Coastguard Worker
getRawBatteryInfo(int32_t deviceId,int32_t batteryId) const1307*38e8c45fSAndroid Build Coastguard Worker std::optional<RawBatteryInfo> EventHub::getRawBatteryInfo(int32_t deviceId,
1308*38e8c45fSAndroid Build Coastguard Worker int32_t batteryId) const {
1309*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1310*38e8c45fSAndroid Build Coastguard Worker
1311*38e8c45fSAndroid Build Coastguard Worker const auto infos = getBatteryInfoLocked(deviceId);
1312*38e8c45fSAndroid Build Coastguard Worker
1313*38e8c45fSAndroid Build Coastguard Worker auto it = infos.find(batteryId);
1314*38e8c45fSAndroid Build Coastguard Worker if (it != infos.end()) {
1315*38e8c45fSAndroid Build Coastguard Worker return it->second;
1316*38e8c45fSAndroid Build Coastguard Worker }
1317*38e8c45fSAndroid Build Coastguard Worker
1318*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1319*38e8c45fSAndroid Build Coastguard Worker }
1320*38e8c45fSAndroid Build Coastguard Worker
1321*38e8c45fSAndroid Build Coastguard Worker // Gets the light info map from light ID to RawLightInfo of the miscellaneous device associated
1322*38e8c45fSAndroid Build Coastguard Worker // with the device ID. Returns an empty map if no miscellaneous device found.
getLightInfoLocked(int32_t deviceId) const1323*38e8c45fSAndroid Build Coastguard Worker const std::unordered_map<int32_t, RawLightInfo>& EventHub::getLightInfoLocked(
1324*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId) const {
1325*38e8c45fSAndroid Build Coastguard Worker static const std::unordered_map<int32_t, RawLightInfo> EMPTY_LIGHT_INFO = {};
1326*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1327*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->associatedDevice) {
1328*38e8c45fSAndroid Build Coastguard Worker return EMPTY_LIGHT_INFO;
1329*38e8c45fSAndroid Build Coastguard Worker }
1330*38e8c45fSAndroid Build Coastguard Worker return device->associatedDevice->lightInfos;
1331*38e8c45fSAndroid Build Coastguard Worker }
1332*38e8c45fSAndroid Build Coastguard Worker
getRawLightIds(int32_t deviceId) const1333*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) const {
1334*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1335*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> lightIds;
1336*38e8c45fSAndroid Build Coastguard Worker
1337*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, info] : getLightInfoLocked(deviceId)) {
1338*38e8c45fSAndroid Build Coastguard Worker lightIds.push_back(id);
1339*38e8c45fSAndroid Build Coastguard Worker }
1340*38e8c45fSAndroid Build Coastguard Worker
1341*38e8c45fSAndroid Build Coastguard Worker return lightIds;
1342*38e8c45fSAndroid Build Coastguard Worker }
1343*38e8c45fSAndroid Build Coastguard Worker
getRawLightInfo(int32_t deviceId,int32_t lightId) const1344*38e8c45fSAndroid Build Coastguard Worker std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t lightId) const {
1345*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1346*38e8c45fSAndroid Build Coastguard Worker
1347*38e8c45fSAndroid Build Coastguard Worker const auto infos = getLightInfoLocked(deviceId);
1348*38e8c45fSAndroid Build Coastguard Worker
1349*38e8c45fSAndroid Build Coastguard Worker auto it = infos.find(lightId);
1350*38e8c45fSAndroid Build Coastguard Worker if (it != infos.end()) {
1351*38e8c45fSAndroid Build Coastguard Worker return it->second;
1352*38e8c45fSAndroid Build Coastguard Worker }
1353*38e8c45fSAndroid Build Coastguard Worker
1354*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1355*38e8c45fSAndroid Build Coastguard Worker }
1356*38e8c45fSAndroid Build Coastguard Worker
getLightBrightness(int32_t deviceId,int32_t lightId) const1357*38e8c45fSAndroid Build Coastguard Worker std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t lightId) const {
1358*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1359*38e8c45fSAndroid Build Coastguard Worker
1360*38e8c45fSAndroid Build Coastguard Worker const auto infos = getLightInfoLocked(deviceId);
1361*38e8c45fSAndroid Build Coastguard Worker auto it = infos.find(lightId);
1362*38e8c45fSAndroid Build Coastguard Worker if (it == infos.end()) {
1363*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1364*38e8c45fSAndroid Build Coastguard Worker }
1365*38e8c45fSAndroid Build Coastguard Worker std::string buffer;
1366*38e8c45fSAndroid Build Coastguard Worker if (!base::ReadFileToString(it->second.path / LIGHT_NODES.at(InputLightClass::BRIGHTNESS),
1367*38e8c45fSAndroid Build Coastguard Worker &buffer)) {
1368*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1369*38e8c45fSAndroid Build Coastguard Worker }
1370*38e8c45fSAndroid Build Coastguard Worker return std::stoi(buffer);
1371*38e8c45fSAndroid Build Coastguard Worker }
1372*38e8c45fSAndroid Build Coastguard Worker
getLightIntensities(int32_t deviceId,int32_t lightId) const1373*38e8c45fSAndroid Build Coastguard Worker std::optional<std::unordered_map<LightColor, int32_t>> EventHub::getLightIntensities(
1374*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId, int32_t lightId) const {
1375*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1376*38e8c45fSAndroid Build Coastguard Worker
1377*38e8c45fSAndroid Build Coastguard Worker const auto infos = getLightInfoLocked(deviceId);
1378*38e8c45fSAndroid Build Coastguard Worker auto lightIt = infos.find(lightId);
1379*38e8c45fSAndroid Build Coastguard Worker if (lightIt == infos.end()) {
1380*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1381*38e8c45fSAndroid Build Coastguard Worker }
1382*38e8c45fSAndroid Build Coastguard Worker
1383*38e8c45fSAndroid Build Coastguard Worker auto ret =
1384*38e8c45fSAndroid Build Coastguard Worker getColorIndexArray(lightIt->second.path / LIGHT_NODES.at(InputLightClass::MULTI_INDEX));
1385*38e8c45fSAndroid Build Coastguard Worker
1386*38e8c45fSAndroid Build Coastguard Worker if (!ret.has_value()) {
1387*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1388*38e8c45fSAndroid Build Coastguard Worker }
1389*38e8c45fSAndroid Build Coastguard Worker std::array<LightColor, COLOR_NUM> colors = ret.value();
1390*38e8c45fSAndroid Build Coastguard Worker
1391*38e8c45fSAndroid Build Coastguard Worker std::string intensityStr;
1392*38e8c45fSAndroid Build Coastguard Worker if (!base::ReadFileToString(lightIt->second.path /
1393*38e8c45fSAndroid Build Coastguard Worker LIGHT_NODES.at(InputLightClass::MULTI_INTENSITY),
1394*38e8c45fSAndroid Build Coastguard Worker &intensityStr)) {
1395*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1396*38e8c45fSAndroid Build Coastguard Worker }
1397*38e8c45fSAndroid Build Coastguard Worker
1398*38e8c45fSAndroid Build Coastguard Worker // Intensity node outputs 3 color values
1399*38e8c45fSAndroid Build Coastguard Worker std::regex intensityPattern("([0-9]+)\\s([0-9]+)\\s([0-9]+)[\\n]");
1400*38e8c45fSAndroid Build Coastguard Worker std::smatch results;
1401*38e8c45fSAndroid Build Coastguard Worker
1402*38e8c45fSAndroid Build Coastguard Worker if (!std::regex_match(intensityStr, results, intensityPattern)) {
1403*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1404*38e8c45fSAndroid Build Coastguard Worker }
1405*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<LightColor, int32_t> intensities;
1406*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 1; i < results.size(); i++) {
1407*38e8c45fSAndroid Build Coastguard Worker int value = std::stoi(results[i].str());
1408*38e8c45fSAndroid Build Coastguard Worker intensities.emplace(colors[i - 1], value);
1409*38e8c45fSAndroid Build Coastguard Worker }
1410*38e8c45fSAndroid Build Coastguard Worker return intensities;
1411*38e8c45fSAndroid Build Coastguard Worker }
1412*38e8c45fSAndroid Build Coastguard Worker
setLightBrightness(int32_t deviceId,int32_t lightId,int32_t brightness)1413*38e8c45fSAndroid Build Coastguard Worker void EventHub::setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) {
1414*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1415*38e8c45fSAndroid Build Coastguard Worker
1416*38e8c45fSAndroid Build Coastguard Worker const auto infos = getLightInfoLocked(deviceId);
1417*38e8c45fSAndroid Build Coastguard Worker auto lightIt = infos.find(lightId);
1418*38e8c45fSAndroid Build Coastguard Worker if (lightIt == infos.end()) {
1419*38e8c45fSAndroid Build Coastguard Worker ALOGE("%s lightId %d not found ", __func__, lightId);
1420*38e8c45fSAndroid Build Coastguard Worker return;
1421*38e8c45fSAndroid Build Coastguard Worker }
1422*38e8c45fSAndroid Build Coastguard Worker
1423*38e8c45fSAndroid Build Coastguard Worker if (!base::WriteStringToFile(std::to_string(brightness),
1424*38e8c45fSAndroid Build Coastguard Worker lightIt->second.path /
1425*38e8c45fSAndroid Build Coastguard Worker LIGHT_NODES.at(InputLightClass::BRIGHTNESS))) {
1426*38e8c45fSAndroid Build Coastguard Worker ALOGE("Can not write to file, error: %s", strerror(errno));
1427*38e8c45fSAndroid Build Coastguard Worker }
1428*38e8c45fSAndroid Build Coastguard Worker }
1429*38e8c45fSAndroid Build Coastguard Worker
setLightIntensities(int32_t deviceId,int32_t lightId,std::unordered_map<LightColor,int32_t> intensities)1430*38e8c45fSAndroid Build Coastguard Worker void EventHub::setLightIntensities(int32_t deviceId, int32_t lightId,
1431*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<LightColor, int32_t> intensities) {
1432*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1433*38e8c45fSAndroid Build Coastguard Worker
1434*38e8c45fSAndroid Build Coastguard Worker const auto infos = getLightInfoLocked(deviceId);
1435*38e8c45fSAndroid Build Coastguard Worker auto lightIt = infos.find(lightId);
1436*38e8c45fSAndroid Build Coastguard Worker if (lightIt == infos.end()) {
1437*38e8c45fSAndroid Build Coastguard Worker ALOGE("Light Id %d does not exist.", lightId);
1438*38e8c45fSAndroid Build Coastguard Worker return;
1439*38e8c45fSAndroid Build Coastguard Worker }
1440*38e8c45fSAndroid Build Coastguard Worker
1441*38e8c45fSAndroid Build Coastguard Worker auto ret =
1442*38e8c45fSAndroid Build Coastguard Worker getColorIndexArray(lightIt->second.path / LIGHT_NODES.at(InputLightClass::MULTI_INDEX));
1443*38e8c45fSAndroid Build Coastguard Worker
1444*38e8c45fSAndroid Build Coastguard Worker if (!ret.has_value()) {
1445*38e8c45fSAndroid Build Coastguard Worker return;
1446*38e8c45fSAndroid Build Coastguard Worker }
1447*38e8c45fSAndroid Build Coastguard Worker std::array<LightColor, COLOR_NUM> colors = ret.value();
1448*38e8c45fSAndroid Build Coastguard Worker
1449*38e8c45fSAndroid Build Coastguard Worker std::string rgbStr;
1450*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < COLOR_NUM; i++) {
1451*38e8c45fSAndroid Build Coastguard Worker auto it = intensities.find(colors[i]);
1452*38e8c45fSAndroid Build Coastguard Worker if (it != intensities.end()) {
1453*38e8c45fSAndroid Build Coastguard Worker rgbStr += std::to_string(it->second);
1454*38e8c45fSAndroid Build Coastguard Worker // Insert space between colors
1455*38e8c45fSAndroid Build Coastguard Worker if (i < COLOR_NUM - 1) {
1456*38e8c45fSAndroid Build Coastguard Worker rgbStr += " ";
1457*38e8c45fSAndroid Build Coastguard Worker }
1458*38e8c45fSAndroid Build Coastguard Worker }
1459*38e8c45fSAndroid Build Coastguard Worker }
1460*38e8c45fSAndroid Build Coastguard Worker // Append new line
1461*38e8c45fSAndroid Build Coastguard Worker rgbStr += "\n";
1462*38e8c45fSAndroid Build Coastguard Worker
1463*38e8c45fSAndroid Build Coastguard Worker if (!base::WriteStringToFile(rgbStr,
1464*38e8c45fSAndroid Build Coastguard Worker lightIt->second.path /
1465*38e8c45fSAndroid Build Coastguard Worker LIGHT_NODES.at(InputLightClass::MULTI_INTENSITY))) {
1466*38e8c45fSAndroid Build Coastguard Worker ALOGE("Can not write to file, error: %s", strerror(errno));
1467*38e8c45fSAndroid Build Coastguard Worker }
1468*38e8c45fSAndroid Build Coastguard Worker }
1469*38e8c45fSAndroid Build Coastguard Worker
getRawLayoutInfo(int32_t deviceId) const1470*38e8c45fSAndroid Build Coastguard Worker std::optional<RawLayoutInfo> EventHub::getRawLayoutInfo(int32_t deviceId) const {
1471*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1472*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1473*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->associatedDevice) {
1474*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1475*38e8c45fSAndroid Build Coastguard Worker }
1476*38e8c45fSAndroid Build Coastguard Worker return device->associatedDevice->layoutInfo;
1477*38e8c45fSAndroid Build Coastguard Worker }
1478*38e8c45fSAndroid Build Coastguard Worker
setExcludedDevices(const std::vector<std::string> & devices)1479*38e8c45fSAndroid Build Coastguard Worker void EventHub::setExcludedDevices(const std::vector<std::string>& devices) {
1480*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1481*38e8c45fSAndroid Build Coastguard Worker
1482*38e8c45fSAndroid Build Coastguard Worker mExcludedDevices = devices;
1483*38e8c45fSAndroid Build Coastguard Worker }
1484*38e8c45fSAndroid Build Coastguard Worker
hasScanCode(int32_t deviceId,int32_t scanCode) const1485*38e8c45fSAndroid Build Coastguard Worker bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
1486*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1487*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1488*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && scanCode >= 0 && scanCode <= KEY_MAX) {
1489*38e8c45fSAndroid Build Coastguard Worker return device->keyBitmask.test(scanCode);
1490*38e8c45fSAndroid Build Coastguard Worker }
1491*38e8c45fSAndroid Build Coastguard Worker return false;
1492*38e8c45fSAndroid Build Coastguard Worker }
1493*38e8c45fSAndroid Build Coastguard Worker
hasKeyCode(int32_t deviceId,int32_t keyCode) const1494*38e8c45fSAndroid Build Coastguard Worker bool EventHub::hasKeyCode(int32_t deviceId, int32_t keyCode) const {
1495*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1496*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1497*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr) {
1498*38e8c45fSAndroid Build Coastguard Worker return device->hasKeycodeLocked(keyCode);
1499*38e8c45fSAndroid Build Coastguard Worker }
1500*38e8c45fSAndroid Build Coastguard Worker return false;
1501*38e8c45fSAndroid Build Coastguard Worker }
1502*38e8c45fSAndroid Build Coastguard Worker
hasLed(int32_t deviceId,int32_t led) const1503*38e8c45fSAndroid Build Coastguard Worker bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
1504*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1505*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1506*38e8c45fSAndroid Build Coastguard Worker int32_t sc;
1507*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && device->mapLed(led, &sc) == NO_ERROR) {
1508*38e8c45fSAndroid Build Coastguard Worker return device->ledBitmask.test(sc);
1509*38e8c45fSAndroid Build Coastguard Worker }
1510*38e8c45fSAndroid Build Coastguard Worker return false;
1511*38e8c45fSAndroid Build Coastguard Worker }
1512*38e8c45fSAndroid Build Coastguard Worker
setLedState(int32_t deviceId,int32_t led,bool on)1513*38e8c45fSAndroid Build Coastguard Worker void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
1514*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1515*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1516*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && device->hasValidFd()) {
1517*38e8c45fSAndroid Build Coastguard Worker device->setLedStateLocked(led, on);
1518*38e8c45fSAndroid Build Coastguard Worker }
1519*38e8c45fSAndroid Build Coastguard Worker }
1520*38e8c45fSAndroid Build Coastguard Worker
getVirtualKeyDefinitions(int32_t deviceId,std::vector<VirtualKeyDefinition> & outVirtualKeys) const1521*38e8c45fSAndroid Build Coastguard Worker void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
1522*38e8c45fSAndroid Build Coastguard Worker std::vector<VirtualKeyDefinition>& outVirtualKeys) const {
1523*38e8c45fSAndroid Build Coastguard Worker outVirtualKeys.clear();
1524*38e8c45fSAndroid Build Coastguard Worker
1525*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1526*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1527*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && device->virtualKeyMap) {
1528*38e8c45fSAndroid Build Coastguard Worker const std::vector<VirtualKeyDefinition> virtualKeys =
1529*38e8c45fSAndroid Build Coastguard Worker device->virtualKeyMap->getVirtualKeys();
1530*38e8c45fSAndroid Build Coastguard Worker outVirtualKeys.insert(outVirtualKeys.end(), virtualKeys.begin(), virtualKeys.end());
1531*38e8c45fSAndroid Build Coastguard Worker }
1532*38e8c45fSAndroid Build Coastguard Worker }
1533*38e8c45fSAndroid Build Coastguard Worker
getKeyCharacterMap(int32_t deviceId) const1534*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
1535*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1536*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1537*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr) {
1538*38e8c45fSAndroid Build Coastguard Worker return device->getKeyCharacterMap();
1539*38e8c45fSAndroid Build Coastguard Worker }
1540*38e8c45fSAndroid Build Coastguard Worker return nullptr;
1541*38e8c45fSAndroid Build Coastguard Worker }
1542*38e8c45fSAndroid Build Coastguard Worker
1543*38e8c45fSAndroid Build Coastguard Worker // If provided map is null, it will reset key character map to default KCM.
setKeyboardLayoutOverlay(int32_t deviceId,std::shared_ptr<KeyCharacterMap> map)1544*38e8c45fSAndroid Build Coastguard Worker bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, std::shared_ptr<KeyCharacterMap> map) {
1545*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1546*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1547*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || device->keyMap.keyCharacterMap == nullptr) {
1548*38e8c45fSAndroid Build Coastguard Worker return false;
1549*38e8c45fSAndroid Build Coastguard Worker }
1550*38e8c45fSAndroid Build Coastguard Worker if (map == nullptr) {
1551*38e8c45fSAndroid Build Coastguard Worker device->keyMap.keyCharacterMap->clearLayoutOverlay();
1552*38e8c45fSAndroid Build Coastguard Worker return true;
1553*38e8c45fSAndroid Build Coastguard Worker }
1554*38e8c45fSAndroid Build Coastguard Worker device->keyMap.keyCharacterMap->combine(*map);
1555*38e8c45fSAndroid Build Coastguard Worker return true;
1556*38e8c45fSAndroid Build Coastguard Worker }
1557*38e8c45fSAndroid Build Coastguard Worker
generateDescriptor(InputDeviceIdentifier & identifier)1558*38e8c45fSAndroid Build Coastguard Worker static std::string generateDescriptor(InputDeviceIdentifier& identifier) {
1559*38e8c45fSAndroid Build Coastguard Worker std::string rawDescriptor;
1560*38e8c45fSAndroid Build Coastguard Worker rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor, identifier.product);
1561*38e8c45fSAndroid Build Coastguard Worker // TODO add handling for USB devices to not uniqueify kbs that show up twice
1562*38e8c45fSAndroid Build Coastguard Worker if (!identifier.uniqueId.empty()) {
1563*38e8c45fSAndroid Build Coastguard Worker rawDescriptor += "uniqueId:";
1564*38e8c45fSAndroid Build Coastguard Worker rawDescriptor += identifier.uniqueId;
1565*38e8c45fSAndroid Build Coastguard Worker }
1566*38e8c45fSAndroid Build Coastguard Worker if (identifier.nonce != 0) {
1567*38e8c45fSAndroid Build Coastguard Worker rawDescriptor += StringPrintf("nonce:%04x", identifier.nonce);
1568*38e8c45fSAndroid Build Coastguard Worker }
1569*38e8c45fSAndroid Build Coastguard Worker
1570*38e8c45fSAndroid Build Coastguard Worker if (identifier.vendor == 0 && identifier.product == 0) {
1571*38e8c45fSAndroid Build Coastguard Worker // If we don't know the vendor and product id, then the device is probably
1572*38e8c45fSAndroid Build Coastguard Worker // built-in so we need to rely on other information to uniquely identify
1573*38e8c45fSAndroid Build Coastguard Worker // the input device. Usually we try to avoid relying on the device name or
1574*38e8c45fSAndroid Build Coastguard Worker // location but for built-in input device, they are unlikely to ever change.
1575*38e8c45fSAndroid Build Coastguard Worker if (!identifier.name.empty()) {
1576*38e8c45fSAndroid Build Coastguard Worker rawDescriptor += "name:";
1577*38e8c45fSAndroid Build Coastguard Worker rawDescriptor += identifier.name;
1578*38e8c45fSAndroid Build Coastguard Worker } else if (!identifier.location.empty()) {
1579*38e8c45fSAndroid Build Coastguard Worker rawDescriptor += "location:";
1580*38e8c45fSAndroid Build Coastguard Worker rawDescriptor += identifier.location;
1581*38e8c45fSAndroid Build Coastguard Worker }
1582*38e8c45fSAndroid Build Coastguard Worker }
1583*38e8c45fSAndroid Build Coastguard Worker identifier.descriptor = sha1(rawDescriptor);
1584*38e8c45fSAndroid Build Coastguard Worker return rawDescriptor;
1585*38e8c45fSAndroid Build Coastguard Worker }
1586*38e8c45fSAndroid Build Coastguard Worker
assignDescriptorLocked(InputDeviceIdentifier & identifier)1587*38e8c45fSAndroid Build Coastguard Worker void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) {
1588*38e8c45fSAndroid Build Coastguard Worker // Compute a device descriptor that uniquely identifies the device.
1589*38e8c45fSAndroid Build Coastguard Worker // The descriptor is assumed to be a stable identifier. Its value should not
1590*38e8c45fSAndroid Build Coastguard Worker // change between reboots, reconnections, firmware updates or new releases
1591*38e8c45fSAndroid Build Coastguard Worker // of Android. In practice we sometimes get devices that cannot be uniquely
1592*38e8c45fSAndroid Build Coastguard Worker // identified. In this case we enforce uniqueness between connected devices.
1593*38e8c45fSAndroid Build Coastguard Worker // Ideally, we also want the descriptor to be short and relatively opaque.
1594*38e8c45fSAndroid Build Coastguard Worker // Note that we explicitly do not use the path or location for external devices
1595*38e8c45fSAndroid Build Coastguard Worker // as their path or location will change as they are plugged/unplugged or moved
1596*38e8c45fSAndroid Build Coastguard Worker // to different ports. We do fallback to using name and location in the case of
1597*38e8c45fSAndroid Build Coastguard Worker // internal devices which are detected by the vendor and product being 0 in
1598*38e8c45fSAndroid Build Coastguard Worker // generateDescriptor. If two identical descriptors are detected we will fallback
1599*38e8c45fSAndroid Build Coastguard Worker // to using a 'nonce' and incrementing it until the new descriptor no longer has
1600*38e8c45fSAndroid Build Coastguard Worker // a match with any existing descriptors.
1601*38e8c45fSAndroid Build Coastguard Worker
1602*38e8c45fSAndroid Build Coastguard Worker identifier.nonce = 0;
1603*38e8c45fSAndroid Build Coastguard Worker std::string rawDescriptor = generateDescriptor(identifier);
1604*38e8c45fSAndroid Build Coastguard Worker // Enforce that the generated descriptor is unique.
1605*38e8c45fSAndroid Build Coastguard Worker while (hasDeviceWithDescriptorLocked(identifier.descriptor)) {
1606*38e8c45fSAndroid Build Coastguard Worker identifier.nonce++;
1607*38e8c45fSAndroid Build Coastguard Worker rawDescriptor = generateDescriptor(identifier);
1608*38e8c45fSAndroid Build Coastguard Worker }
1609*38e8c45fSAndroid Build Coastguard Worker ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
1610*38e8c45fSAndroid Build Coastguard Worker identifier.descriptor.c_str());
1611*38e8c45fSAndroid Build Coastguard Worker }
1612*38e8c45fSAndroid Build Coastguard Worker
obtainAssociatedDeviceLocked(const std::filesystem::path & devicePath) const1613*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDeviceLocked(
1614*38e8c45fSAndroid Build Coastguard Worker const std::filesystem::path& devicePath) const {
1615*38e8c45fSAndroid Build Coastguard Worker const std::optional<std::filesystem::path> sysfsRootPathOpt =
1616*38e8c45fSAndroid Build Coastguard Worker getSysfsRootPath(devicePath.c_str());
1617*38e8c45fSAndroid Build Coastguard Worker if (!sysfsRootPathOpt) {
1618*38e8c45fSAndroid Build Coastguard Worker return nullptr;
1619*38e8c45fSAndroid Build Coastguard Worker }
1620*38e8c45fSAndroid Build Coastguard Worker
1621*38e8c45fSAndroid Build Coastguard Worker const auto& path = *sysfsRootPathOpt;
1622*38e8c45fSAndroid Build Coastguard Worker
1623*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const AssociatedDevice> associatedDevice = std::make_shared<AssociatedDevice>(
1624*38e8c45fSAndroid Build Coastguard Worker AssociatedDevice{.sysfsRootPath = path,
1625*38e8c45fSAndroid Build Coastguard Worker .batteryInfos = readBatteryConfiguration(path),
1626*38e8c45fSAndroid Build Coastguard Worker .lightInfos = readLightsConfiguration(path),
1627*38e8c45fSAndroid Build Coastguard Worker .layoutInfo = readLayoutConfiguration(path)});
1628*38e8c45fSAndroid Build Coastguard Worker
1629*38e8c45fSAndroid Build Coastguard Worker bool associatedDeviceChanged = false;
1630*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, dev] : mDevices) {
1631*38e8c45fSAndroid Build Coastguard Worker if (dev->associatedDevice && dev->associatedDevice->sysfsRootPath == path) {
1632*38e8c45fSAndroid Build Coastguard Worker if (*associatedDevice != *dev->associatedDevice) {
1633*38e8c45fSAndroid Build Coastguard Worker associatedDeviceChanged = true;
1634*38e8c45fSAndroid Build Coastguard Worker dev->associatedDevice = associatedDevice;
1635*38e8c45fSAndroid Build Coastguard Worker }
1636*38e8c45fSAndroid Build Coastguard Worker associatedDevice = dev->associatedDevice;
1637*38e8c45fSAndroid Build Coastguard Worker }
1638*38e8c45fSAndroid Build Coastguard Worker }
1639*38e8c45fSAndroid Build Coastguard Worker ALOGI_IF(associatedDeviceChanged,
1640*38e8c45fSAndroid Build Coastguard Worker "The AssociatedDevice changed for path '%s'. Using new AssociatedDevice: %s",
1641*38e8c45fSAndroid Build Coastguard Worker path.c_str(), associatedDevice->dump().c_str());
1642*38e8c45fSAndroid Build Coastguard Worker
1643*38e8c45fSAndroid Build Coastguard Worker return associatedDevice;
1644*38e8c45fSAndroid Build Coastguard Worker }
1645*38e8c45fSAndroid Build Coastguard Worker
isChanged() const1646*38e8c45fSAndroid Build Coastguard Worker bool EventHub::AssociatedDevice::isChanged() const {
1647*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<int32_t, RawBatteryInfo> newBatteryInfos =
1648*38e8c45fSAndroid Build Coastguard Worker readBatteryConfiguration(sysfsRootPath);
1649*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<int32_t, RawLightInfo> newLightInfos =
1650*38e8c45fSAndroid Build Coastguard Worker readLightsConfiguration(sysfsRootPath);
1651*38e8c45fSAndroid Build Coastguard Worker std::optional<RawLayoutInfo> newLayoutInfo = readLayoutConfiguration(sysfsRootPath);
1652*38e8c45fSAndroid Build Coastguard Worker
1653*38e8c45fSAndroid Build Coastguard Worker if (newBatteryInfos == batteryInfos && newLightInfos == lightInfos &&
1654*38e8c45fSAndroid Build Coastguard Worker newLayoutInfo == layoutInfo) {
1655*38e8c45fSAndroid Build Coastguard Worker return false;
1656*38e8c45fSAndroid Build Coastguard Worker }
1657*38e8c45fSAndroid Build Coastguard Worker return true;
1658*38e8c45fSAndroid Build Coastguard Worker }
1659*38e8c45fSAndroid Build Coastguard Worker
vibrate(int32_t deviceId,const VibrationElement & element)1660*38e8c45fSAndroid Build Coastguard Worker void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
1661*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1662*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1663*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && device->hasValidFd()) {
1664*38e8c45fSAndroid Build Coastguard Worker ff_effect effect;
1665*38e8c45fSAndroid Build Coastguard Worker memset(&effect, 0, sizeof(effect));
1666*38e8c45fSAndroid Build Coastguard Worker effect.type = FF_RUMBLE;
1667*38e8c45fSAndroid Build Coastguard Worker effect.id = device->ffEffectId;
1668*38e8c45fSAndroid Build Coastguard Worker // evdev FF_RUMBLE effect only supports two channels of vibration.
1669*38e8c45fSAndroid Build Coastguard Worker effect.u.rumble.strong_magnitude = element.getMagnitude(FF_STRONG_MAGNITUDE_CHANNEL_IDX);
1670*38e8c45fSAndroid Build Coastguard Worker effect.u.rumble.weak_magnitude = element.getMagnitude(FF_WEAK_MAGNITUDE_CHANNEL_IDX);
1671*38e8c45fSAndroid Build Coastguard Worker effect.replay.length = element.duration.count();
1672*38e8c45fSAndroid Build Coastguard Worker effect.replay.delay = 0;
1673*38e8c45fSAndroid Build Coastguard Worker if (ioctl(device->fd, EVIOCSFF, &effect)) {
1674*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not upload force feedback effect to device %s due to error %d.",
1675*38e8c45fSAndroid Build Coastguard Worker device->identifier.name.c_str(), errno);
1676*38e8c45fSAndroid Build Coastguard Worker return;
1677*38e8c45fSAndroid Build Coastguard Worker }
1678*38e8c45fSAndroid Build Coastguard Worker device->ffEffectId = effect.id;
1679*38e8c45fSAndroid Build Coastguard Worker
1680*38e8c45fSAndroid Build Coastguard Worker struct input_event ev;
1681*38e8c45fSAndroid Build Coastguard Worker ev.input_event_sec = 0;
1682*38e8c45fSAndroid Build Coastguard Worker ev.input_event_usec = 0;
1683*38e8c45fSAndroid Build Coastguard Worker ev.type = EV_FF;
1684*38e8c45fSAndroid Build Coastguard Worker ev.code = device->ffEffectId;
1685*38e8c45fSAndroid Build Coastguard Worker ev.value = 1;
1686*38e8c45fSAndroid Build Coastguard Worker if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
1687*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not start force feedback effect on device %s due to error %d.",
1688*38e8c45fSAndroid Build Coastguard Worker device->identifier.name.c_str(), errno);
1689*38e8c45fSAndroid Build Coastguard Worker return;
1690*38e8c45fSAndroid Build Coastguard Worker }
1691*38e8c45fSAndroid Build Coastguard Worker device->ffEffectPlaying = true;
1692*38e8c45fSAndroid Build Coastguard Worker }
1693*38e8c45fSAndroid Build Coastguard Worker }
1694*38e8c45fSAndroid Build Coastguard Worker
cancelVibrate(int32_t deviceId)1695*38e8c45fSAndroid Build Coastguard Worker void EventHub::cancelVibrate(int32_t deviceId) {
1696*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1697*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1698*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && device->hasValidFd()) {
1699*38e8c45fSAndroid Build Coastguard Worker if (device->ffEffectPlaying) {
1700*38e8c45fSAndroid Build Coastguard Worker device->ffEffectPlaying = false;
1701*38e8c45fSAndroid Build Coastguard Worker
1702*38e8c45fSAndroid Build Coastguard Worker struct input_event ev;
1703*38e8c45fSAndroid Build Coastguard Worker ev.input_event_sec = 0;
1704*38e8c45fSAndroid Build Coastguard Worker ev.input_event_usec = 0;
1705*38e8c45fSAndroid Build Coastguard Worker ev.type = EV_FF;
1706*38e8c45fSAndroid Build Coastguard Worker ev.code = device->ffEffectId;
1707*38e8c45fSAndroid Build Coastguard Worker ev.value = 0;
1708*38e8c45fSAndroid Build Coastguard Worker if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
1709*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not stop force feedback effect on device %s due to error %d.",
1710*38e8c45fSAndroid Build Coastguard Worker device->identifier.name.c_str(), errno);
1711*38e8c45fSAndroid Build Coastguard Worker return;
1712*38e8c45fSAndroid Build Coastguard Worker }
1713*38e8c45fSAndroid Build Coastguard Worker }
1714*38e8c45fSAndroid Build Coastguard Worker }
1715*38e8c45fSAndroid Build Coastguard Worker }
1716*38e8c45fSAndroid Build Coastguard Worker
getVibratorIds(int32_t deviceId) const1717*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> EventHub::getVibratorIds(int32_t deviceId) const {
1718*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1719*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> vibrators;
1720*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
1721*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr && device->hasValidFd() &&
1722*38e8c45fSAndroid Build Coastguard Worker device->classes.test(InputDeviceClass::VIBRATOR)) {
1723*38e8c45fSAndroid Build Coastguard Worker vibrators.push_back(FF_STRONG_MAGNITUDE_CHANNEL_IDX);
1724*38e8c45fSAndroid Build Coastguard Worker vibrators.push_back(FF_WEAK_MAGNITUDE_CHANNEL_IDX);
1725*38e8c45fSAndroid Build Coastguard Worker }
1726*38e8c45fSAndroid Build Coastguard Worker return vibrators;
1727*38e8c45fSAndroid Build Coastguard Worker }
1728*38e8c45fSAndroid Build Coastguard Worker
1729*38e8c45fSAndroid Build Coastguard Worker /**
1730*38e8c45fSAndroid Build Coastguard Worker * Checks both mDevices and mOpeningDevices for a device with the descriptor passed.
1731*38e8c45fSAndroid Build Coastguard Worker */
hasDeviceWithDescriptorLocked(const std::string & descriptor) const1732*38e8c45fSAndroid Build Coastguard Worker bool EventHub::hasDeviceWithDescriptorLocked(const std::string& descriptor) const {
1733*38e8c45fSAndroid Build Coastguard Worker for (const auto& device : mOpeningDevices) {
1734*38e8c45fSAndroid Build Coastguard Worker if (descriptor == device->identifier.descriptor) {
1735*38e8c45fSAndroid Build Coastguard Worker return true;
1736*38e8c45fSAndroid Build Coastguard Worker }
1737*38e8c45fSAndroid Build Coastguard Worker }
1738*38e8c45fSAndroid Build Coastguard Worker
1739*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, device] : mDevices) {
1740*38e8c45fSAndroid Build Coastguard Worker if (descriptor == device->identifier.descriptor) {
1741*38e8c45fSAndroid Build Coastguard Worker return true;
1742*38e8c45fSAndroid Build Coastguard Worker }
1743*38e8c45fSAndroid Build Coastguard Worker }
1744*38e8c45fSAndroid Build Coastguard Worker return false;
1745*38e8c45fSAndroid Build Coastguard Worker }
1746*38e8c45fSAndroid Build Coastguard Worker
getDeviceLocked(int32_t deviceId) const1747*38e8c45fSAndroid Build Coastguard Worker EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
1748*38e8c45fSAndroid Build Coastguard Worker if (deviceId == ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID) {
1749*38e8c45fSAndroid Build Coastguard Worker deviceId = mBuiltInKeyboardId;
1750*38e8c45fSAndroid Build Coastguard Worker }
1751*38e8c45fSAndroid Build Coastguard Worker const auto& it = mDevices.find(deviceId);
1752*38e8c45fSAndroid Build Coastguard Worker return it != mDevices.end() ? it->second.get() : nullptr;
1753*38e8c45fSAndroid Build Coastguard Worker }
1754*38e8c45fSAndroid Build Coastguard Worker
getDeviceByPathLocked(const std::string & devicePath) const1755*38e8c45fSAndroid Build Coastguard Worker EventHub::Device* EventHub::getDeviceByPathLocked(const std::string& devicePath) const {
1756*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, device] : mDevices) {
1757*38e8c45fSAndroid Build Coastguard Worker if (device->path == devicePath) {
1758*38e8c45fSAndroid Build Coastguard Worker return device.get();
1759*38e8c45fSAndroid Build Coastguard Worker }
1760*38e8c45fSAndroid Build Coastguard Worker }
1761*38e8c45fSAndroid Build Coastguard Worker return nullptr;
1762*38e8c45fSAndroid Build Coastguard Worker }
1763*38e8c45fSAndroid Build Coastguard Worker
1764*38e8c45fSAndroid Build Coastguard Worker /**
1765*38e8c45fSAndroid Build Coastguard Worker * The file descriptor could be either input device, or a video device (associated with a
1766*38e8c45fSAndroid Build Coastguard Worker * specific input device). Check both cases here, and return the device that this event
1767*38e8c45fSAndroid Build Coastguard Worker * belongs to. Caller can compare the fd's once more to determine event type.
1768*38e8c45fSAndroid Build Coastguard Worker * Looks through all input devices, and only attached video devices. Unattached video
1769*38e8c45fSAndroid Build Coastguard Worker * devices are ignored.
1770*38e8c45fSAndroid Build Coastguard Worker */
getDeviceByFdLocked(int fd) const1771*38e8c45fSAndroid Build Coastguard Worker EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const {
1772*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, device] : mDevices) {
1773*38e8c45fSAndroid Build Coastguard Worker if (device->fd == fd) {
1774*38e8c45fSAndroid Build Coastguard Worker // This is an input device event
1775*38e8c45fSAndroid Build Coastguard Worker return device.get();
1776*38e8c45fSAndroid Build Coastguard Worker }
1777*38e8c45fSAndroid Build Coastguard Worker if (device->videoDevice && device->videoDevice->getFd() == fd) {
1778*38e8c45fSAndroid Build Coastguard Worker // This is a video device event
1779*38e8c45fSAndroid Build Coastguard Worker return device.get();
1780*38e8c45fSAndroid Build Coastguard Worker }
1781*38e8c45fSAndroid Build Coastguard Worker }
1782*38e8c45fSAndroid Build Coastguard Worker // We do not check mUnattachedVideoDevices here because they should not participate in epoll,
1783*38e8c45fSAndroid Build Coastguard Worker // and therefore should never be looked up by fd.
1784*38e8c45fSAndroid Build Coastguard Worker return nullptr;
1785*38e8c45fSAndroid Build Coastguard Worker }
1786*38e8c45fSAndroid Build Coastguard Worker
getBatteryCapacity(int32_t deviceId,int32_t batteryId) const1787*38e8c45fSAndroid Build Coastguard Worker std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId, int32_t batteryId) const {
1788*38e8c45fSAndroid Build Coastguard Worker std::filesystem::path batteryPath;
1789*38e8c45fSAndroid Build Coastguard Worker {
1790*38e8c45fSAndroid Build Coastguard Worker // Do not read the sysfs node to get the battery state while holding
1791*38e8c45fSAndroid Build Coastguard Worker // the EventHub lock. For some peripheral devices, reading battery state
1792*38e8c45fSAndroid Build Coastguard Worker // can be broken and take 5+ seconds. Holding the lock in this case would
1793*38e8c45fSAndroid Build Coastguard Worker // block all other event processing during this time. For now, we assume this
1794*38e8c45fSAndroid Build Coastguard Worker // call never happens on the InputReader thread and read the sysfs node outside
1795*38e8c45fSAndroid Build Coastguard Worker // the lock to prevent event processing from being blocked by this call.
1796*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1797*38e8c45fSAndroid Build Coastguard Worker
1798*38e8c45fSAndroid Build Coastguard Worker const auto& infos = getBatteryInfoLocked(deviceId);
1799*38e8c45fSAndroid Build Coastguard Worker auto it = infos.find(batteryId);
1800*38e8c45fSAndroid Build Coastguard Worker if (it == infos.end()) {
1801*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1802*38e8c45fSAndroid Build Coastguard Worker }
1803*38e8c45fSAndroid Build Coastguard Worker batteryPath = it->second.path;
1804*38e8c45fSAndroid Build Coastguard Worker } // release lock
1805*38e8c45fSAndroid Build Coastguard Worker
1806*38e8c45fSAndroid Build Coastguard Worker std::string buffer;
1807*38e8c45fSAndroid Build Coastguard Worker
1808*38e8c45fSAndroid Build Coastguard Worker // Some devices report battery capacity as an integer through the "capacity" file
1809*38e8c45fSAndroid Build Coastguard Worker if (base::ReadFileToString(batteryPath / BATTERY_NODES.at(InputBatteryClass::CAPACITY),
1810*38e8c45fSAndroid Build Coastguard Worker &buffer)) {
1811*38e8c45fSAndroid Build Coastguard Worker return std::stoi(base::Trim(buffer));
1812*38e8c45fSAndroid Build Coastguard Worker }
1813*38e8c45fSAndroid Build Coastguard Worker
1814*38e8c45fSAndroid Build Coastguard Worker // Other devices report capacity as an enum value POWER_SUPPLY_CAPACITY_LEVEL_XXX
1815*38e8c45fSAndroid Build Coastguard Worker // These values are taken from kernel source code include/linux/power_supply.h
1816*38e8c45fSAndroid Build Coastguard Worker if (base::ReadFileToString(batteryPath / BATTERY_NODES.at(InputBatteryClass::CAPACITY_LEVEL),
1817*38e8c45fSAndroid Build Coastguard Worker &buffer)) {
1818*38e8c45fSAndroid Build Coastguard Worker // Remove any white space such as trailing new line
1819*38e8c45fSAndroid Build Coastguard Worker const auto levelIt = BATTERY_LEVEL.find(base::Trim(buffer));
1820*38e8c45fSAndroid Build Coastguard Worker if (levelIt != BATTERY_LEVEL.end()) {
1821*38e8c45fSAndroid Build Coastguard Worker return levelIt->second;
1822*38e8c45fSAndroid Build Coastguard Worker }
1823*38e8c45fSAndroid Build Coastguard Worker }
1824*38e8c45fSAndroid Build Coastguard Worker
1825*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1826*38e8c45fSAndroid Build Coastguard Worker }
1827*38e8c45fSAndroid Build Coastguard Worker
getBatteryStatus(int32_t deviceId,int32_t batteryId) const1828*38e8c45fSAndroid Build Coastguard Worker std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId, int32_t batteryId) const {
1829*38e8c45fSAndroid Build Coastguard Worker std::filesystem::path batteryPath;
1830*38e8c45fSAndroid Build Coastguard Worker {
1831*38e8c45fSAndroid Build Coastguard Worker // Do not read the sysfs node to get the battery state while holding
1832*38e8c45fSAndroid Build Coastguard Worker // the EventHub lock. For some peripheral devices, reading battery state
1833*38e8c45fSAndroid Build Coastguard Worker // can be broken and take 5+ seconds. Holding the lock in this case would
1834*38e8c45fSAndroid Build Coastguard Worker // block all other event processing during this time. For now, we assume this
1835*38e8c45fSAndroid Build Coastguard Worker // call never happens on the InputReader thread and read the sysfs node outside
1836*38e8c45fSAndroid Build Coastguard Worker // the lock to prevent event processing from being blocked by this call.
1837*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1838*38e8c45fSAndroid Build Coastguard Worker
1839*38e8c45fSAndroid Build Coastguard Worker const auto& infos = getBatteryInfoLocked(deviceId);
1840*38e8c45fSAndroid Build Coastguard Worker auto it = infos.find(batteryId);
1841*38e8c45fSAndroid Build Coastguard Worker if (it == infos.end()) {
1842*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1843*38e8c45fSAndroid Build Coastguard Worker }
1844*38e8c45fSAndroid Build Coastguard Worker batteryPath = it->second.path;
1845*38e8c45fSAndroid Build Coastguard Worker } // release lock
1846*38e8c45fSAndroid Build Coastguard Worker
1847*38e8c45fSAndroid Build Coastguard Worker std::string buffer;
1848*38e8c45fSAndroid Build Coastguard Worker
1849*38e8c45fSAndroid Build Coastguard Worker if (!base::ReadFileToString(batteryPath / BATTERY_NODES.at(InputBatteryClass::STATUS),
1850*38e8c45fSAndroid Build Coastguard Worker &buffer)) {
1851*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to read sysfs battery info: %s", strerror(errno));
1852*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1853*38e8c45fSAndroid Build Coastguard Worker }
1854*38e8c45fSAndroid Build Coastguard Worker
1855*38e8c45fSAndroid Build Coastguard Worker // Remove white space like trailing new line
1856*38e8c45fSAndroid Build Coastguard Worker const auto statusIt = BATTERY_STATUS.find(base::Trim(buffer));
1857*38e8c45fSAndroid Build Coastguard Worker if (statusIt != BATTERY_STATUS.end()) {
1858*38e8c45fSAndroid Build Coastguard Worker return statusIt->second;
1859*38e8c45fSAndroid Build Coastguard Worker }
1860*38e8c45fSAndroid Build Coastguard Worker
1861*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
1862*38e8c45fSAndroid Build Coastguard Worker }
1863*38e8c45fSAndroid Build Coastguard Worker
getEvents(int timeoutMillis)1864*38e8c45fSAndroid Build Coastguard Worker std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
1865*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1866*38e8c45fSAndroid Build Coastguard Worker
1867*38e8c45fSAndroid Build Coastguard Worker std::array<input_event, EVENT_BUFFER_SIZE> readBuffer;
1868*38e8c45fSAndroid Build Coastguard Worker
1869*38e8c45fSAndroid Build Coastguard Worker std::vector<RawEvent> events;
1870*38e8c45fSAndroid Build Coastguard Worker bool awoken = false;
1871*38e8c45fSAndroid Build Coastguard Worker for (;;) {
1872*38e8c45fSAndroid Build Coastguard Worker nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
1873*38e8c45fSAndroid Build Coastguard Worker
1874*38e8c45fSAndroid Build Coastguard Worker // Reopen input devices if needed.
1875*38e8c45fSAndroid Build Coastguard Worker if (mNeedToReopenDevices) {
1876*38e8c45fSAndroid Build Coastguard Worker mNeedToReopenDevices = false;
1877*38e8c45fSAndroid Build Coastguard Worker
1878*38e8c45fSAndroid Build Coastguard Worker ALOGI("Reopening all input devices due to a configuration change.");
1879*38e8c45fSAndroid Build Coastguard Worker
1880*38e8c45fSAndroid Build Coastguard Worker closeAllDevicesLocked();
1881*38e8c45fSAndroid Build Coastguard Worker mNeedToScanDevices = true;
1882*38e8c45fSAndroid Build Coastguard Worker break; // return to the caller before we actually rescan
1883*38e8c45fSAndroid Build Coastguard Worker }
1884*38e8c45fSAndroid Build Coastguard Worker
1885*38e8c45fSAndroid Build Coastguard Worker // Report any devices that had last been added/removed.
1886*38e8c45fSAndroid Build Coastguard Worker for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
1887*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<Device> device = std::move(*it);
1888*38e8c45fSAndroid Build Coastguard Worker ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
1889*38e8c45fSAndroid Build Coastguard Worker const int32_t deviceId = (device->id == mBuiltInKeyboardId)
1890*38e8c45fSAndroid Build Coastguard Worker ? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
1891*38e8c45fSAndroid Build Coastguard Worker : device->id;
1892*38e8c45fSAndroid Build Coastguard Worker events.push_back({
1893*38e8c45fSAndroid Build Coastguard Worker .when = now,
1894*38e8c45fSAndroid Build Coastguard Worker .deviceId = deviceId,
1895*38e8c45fSAndroid Build Coastguard Worker .type = DEVICE_REMOVED,
1896*38e8c45fSAndroid Build Coastguard Worker });
1897*38e8c45fSAndroid Build Coastguard Worker it = mClosingDevices.erase(it);
1898*38e8c45fSAndroid Build Coastguard Worker if (events.size() == EVENT_BUFFER_SIZE) {
1899*38e8c45fSAndroid Build Coastguard Worker break;
1900*38e8c45fSAndroid Build Coastguard Worker }
1901*38e8c45fSAndroid Build Coastguard Worker }
1902*38e8c45fSAndroid Build Coastguard Worker
1903*38e8c45fSAndroid Build Coastguard Worker if (mNeedToScanDevices) {
1904*38e8c45fSAndroid Build Coastguard Worker mNeedToScanDevices = false;
1905*38e8c45fSAndroid Build Coastguard Worker scanDevicesLocked();
1906*38e8c45fSAndroid Build Coastguard Worker }
1907*38e8c45fSAndroid Build Coastguard Worker
1908*38e8c45fSAndroid Build Coastguard Worker while (!mOpeningDevices.empty()) {
1909*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
1910*38e8c45fSAndroid Build Coastguard Worker mOpeningDevices.pop_back();
1911*38e8c45fSAndroid Build Coastguard Worker ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
1912*38e8c45fSAndroid Build Coastguard Worker const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
1913*38e8c45fSAndroid Build Coastguard Worker events.push_back({
1914*38e8c45fSAndroid Build Coastguard Worker .when = now,
1915*38e8c45fSAndroid Build Coastguard Worker .deviceId = deviceId,
1916*38e8c45fSAndroid Build Coastguard Worker .type = DEVICE_ADDED,
1917*38e8c45fSAndroid Build Coastguard Worker });
1918*38e8c45fSAndroid Build Coastguard Worker
1919*38e8c45fSAndroid Build Coastguard Worker // Try to find a matching video device by comparing device names
1920*38e8c45fSAndroid Build Coastguard Worker for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
1921*38e8c45fSAndroid Build Coastguard Worker it++) {
1922*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<TouchVideoDevice>& videoDevice = *it;
1923*38e8c45fSAndroid Build Coastguard Worker if (tryAddVideoDeviceLocked(*device, videoDevice)) {
1924*38e8c45fSAndroid Build Coastguard Worker // videoDevice was transferred to 'device'
1925*38e8c45fSAndroid Build Coastguard Worker it = mUnattachedVideoDevices.erase(it);
1926*38e8c45fSAndroid Build Coastguard Worker break;
1927*38e8c45fSAndroid Build Coastguard Worker }
1928*38e8c45fSAndroid Build Coastguard Worker }
1929*38e8c45fSAndroid Build Coastguard Worker
1930*38e8c45fSAndroid Build Coastguard Worker auto [dev_it, inserted] = mDevices.insert_or_assign(device->id, std::move(device));
1931*38e8c45fSAndroid Build Coastguard Worker if (!inserted) {
1932*38e8c45fSAndroid Build Coastguard Worker ALOGW("Device id %d exists, replaced.", device->id);
1933*38e8c45fSAndroid Build Coastguard Worker }
1934*38e8c45fSAndroid Build Coastguard Worker if (events.size() == EVENT_BUFFER_SIZE) {
1935*38e8c45fSAndroid Build Coastguard Worker break;
1936*38e8c45fSAndroid Build Coastguard Worker }
1937*38e8c45fSAndroid Build Coastguard Worker }
1938*38e8c45fSAndroid Build Coastguard Worker
1939*38e8c45fSAndroid Build Coastguard Worker // Grab the next input event.
1940*38e8c45fSAndroid Build Coastguard Worker bool deviceChanged = false;
1941*38e8c45fSAndroid Build Coastguard Worker while (mPendingEventIndex < mPendingEventCount) {
1942*38e8c45fSAndroid Build Coastguard Worker const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
1943*38e8c45fSAndroid Build Coastguard Worker if (eventItem.data.fd == mINotifyFd) {
1944*38e8c45fSAndroid Build Coastguard Worker if (eventItem.events & EPOLLIN) {
1945*38e8c45fSAndroid Build Coastguard Worker mPendingINotify = true;
1946*38e8c45fSAndroid Build Coastguard Worker } else {
1947*38e8c45fSAndroid Build Coastguard Worker ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
1948*38e8c45fSAndroid Build Coastguard Worker }
1949*38e8c45fSAndroid Build Coastguard Worker continue;
1950*38e8c45fSAndroid Build Coastguard Worker }
1951*38e8c45fSAndroid Build Coastguard Worker
1952*38e8c45fSAndroid Build Coastguard Worker if (eventItem.data.fd == mWakeReadPipeFd) {
1953*38e8c45fSAndroid Build Coastguard Worker if (eventItem.events & EPOLLIN) {
1954*38e8c45fSAndroid Build Coastguard Worker ALOGV("awoken after wake()");
1955*38e8c45fSAndroid Build Coastguard Worker awoken = true;
1956*38e8c45fSAndroid Build Coastguard Worker char wakeReadBuffer[16];
1957*38e8c45fSAndroid Build Coastguard Worker ssize_t nRead;
1958*38e8c45fSAndroid Build Coastguard Worker do {
1959*38e8c45fSAndroid Build Coastguard Worker nRead = read(mWakeReadPipeFd, wakeReadBuffer, sizeof(wakeReadBuffer));
1960*38e8c45fSAndroid Build Coastguard Worker } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(wakeReadBuffer));
1961*38e8c45fSAndroid Build Coastguard Worker } else {
1962*38e8c45fSAndroid Build Coastguard Worker ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
1963*38e8c45fSAndroid Build Coastguard Worker eventItem.events);
1964*38e8c45fSAndroid Build Coastguard Worker }
1965*38e8c45fSAndroid Build Coastguard Worker continue;
1966*38e8c45fSAndroid Build Coastguard Worker }
1967*38e8c45fSAndroid Build Coastguard Worker
1968*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceByFdLocked(eventItem.data.fd);
1969*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr) {
1970*38e8c45fSAndroid Build Coastguard Worker ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events,
1971*38e8c45fSAndroid Build Coastguard Worker eventItem.data.fd);
1972*38e8c45fSAndroid Build Coastguard Worker ALOG_ASSERT(!DEBUG);
1973*38e8c45fSAndroid Build Coastguard Worker continue;
1974*38e8c45fSAndroid Build Coastguard Worker }
1975*38e8c45fSAndroid Build Coastguard Worker if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) {
1976*38e8c45fSAndroid Build Coastguard Worker if (eventItem.events & EPOLLIN) {
1977*38e8c45fSAndroid Build Coastguard Worker size_t numFrames = device->videoDevice->readAndQueueFrames();
1978*38e8c45fSAndroid Build Coastguard Worker if (numFrames == 0) {
1979*38e8c45fSAndroid Build Coastguard Worker ALOGE("Received epoll event for video device %s, but could not read frame",
1980*38e8c45fSAndroid Build Coastguard Worker device->videoDevice->getName().c_str());
1981*38e8c45fSAndroid Build Coastguard Worker }
1982*38e8c45fSAndroid Build Coastguard Worker } else if (eventItem.events & EPOLLHUP) {
1983*38e8c45fSAndroid Build Coastguard Worker // TODO(b/121395353) - consider adding EPOLLRDHUP
1984*38e8c45fSAndroid Build Coastguard Worker ALOGI("Removing video device %s due to epoll hang-up event.",
1985*38e8c45fSAndroid Build Coastguard Worker device->videoDevice->getName().c_str());
1986*38e8c45fSAndroid Build Coastguard Worker unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
1987*38e8c45fSAndroid Build Coastguard Worker device->videoDevice = nullptr;
1988*38e8c45fSAndroid Build Coastguard Worker } else {
1989*38e8c45fSAndroid Build Coastguard Worker ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
1990*38e8c45fSAndroid Build Coastguard Worker device->videoDevice->getName().c_str());
1991*38e8c45fSAndroid Build Coastguard Worker ALOG_ASSERT(!DEBUG);
1992*38e8c45fSAndroid Build Coastguard Worker }
1993*38e8c45fSAndroid Build Coastguard Worker continue;
1994*38e8c45fSAndroid Build Coastguard Worker }
1995*38e8c45fSAndroid Build Coastguard Worker // This must be an input event
1996*38e8c45fSAndroid Build Coastguard Worker if (eventItem.events & EPOLLIN) {
1997*38e8c45fSAndroid Build Coastguard Worker int32_t readSize =
1998*38e8c45fSAndroid Build Coastguard Worker read(device->fd, readBuffer.data(),
1999*38e8c45fSAndroid Build Coastguard Worker sizeof(decltype(readBuffer)::value_type) * readBuffer.size());
2000*38e8c45fSAndroid Build Coastguard Worker if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
2001*38e8c45fSAndroid Build Coastguard Worker // Device was removed before INotify noticed.
2002*38e8c45fSAndroid Build Coastguard Worker ALOGW("could not get event, removed? (fd: %d size: %" PRId32
2003*38e8c45fSAndroid Build Coastguard Worker " capacity: %zu errno: %d)\n",
2004*38e8c45fSAndroid Build Coastguard Worker device->fd, readSize, readBuffer.size(), errno);
2005*38e8c45fSAndroid Build Coastguard Worker deviceChanged = true;
2006*38e8c45fSAndroid Build Coastguard Worker closeDeviceLocked(*device);
2007*38e8c45fSAndroid Build Coastguard Worker } else if (readSize < 0) {
2008*38e8c45fSAndroid Build Coastguard Worker if (errno != EAGAIN && errno != EINTR) {
2009*38e8c45fSAndroid Build Coastguard Worker ALOGW("could not get event (errno=%d)", errno);
2010*38e8c45fSAndroid Build Coastguard Worker }
2011*38e8c45fSAndroid Build Coastguard Worker } else if ((readSize % sizeof(struct input_event)) != 0) {
2012*38e8c45fSAndroid Build Coastguard Worker ALOGE("could not get event (wrong size: %d)", readSize);
2013*38e8c45fSAndroid Build Coastguard Worker } else {
2014*38e8c45fSAndroid Build Coastguard Worker const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
2015*38e8c45fSAndroid Build Coastguard Worker
2016*38e8c45fSAndroid Build Coastguard Worker const size_t count = size_t(readSize) / sizeof(struct input_event);
2017*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++) {
2018*38e8c45fSAndroid Build Coastguard Worker struct input_event& iev = readBuffer[i];
2019*38e8c45fSAndroid Build Coastguard Worker device->trackInputEvent(iev);
2020*38e8c45fSAndroid Build Coastguard Worker events.push_back({
2021*38e8c45fSAndroid Build Coastguard Worker .when = processEventTimestamp(iev),
2022*38e8c45fSAndroid Build Coastguard Worker .readTime = systemTime(SYSTEM_TIME_MONOTONIC),
2023*38e8c45fSAndroid Build Coastguard Worker .deviceId = deviceId,
2024*38e8c45fSAndroid Build Coastguard Worker .type = iev.type,
2025*38e8c45fSAndroid Build Coastguard Worker .code = iev.code,
2026*38e8c45fSAndroid Build Coastguard Worker .value = iev.value,
2027*38e8c45fSAndroid Build Coastguard Worker });
2028*38e8c45fSAndroid Build Coastguard Worker }
2029*38e8c45fSAndroid Build Coastguard Worker if (events.size() >= EVENT_BUFFER_SIZE) {
2030*38e8c45fSAndroid Build Coastguard Worker // The result buffer is full. Reset the pending event index
2031*38e8c45fSAndroid Build Coastguard Worker // so we will try to read the device again on the next iteration.
2032*38e8c45fSAndroid Build Coastguard Worker mPendingEventIndex -= 1;
2033*38e8c45fSAndroid Build Coastguard Worker break;
2034*38e8c45fSAndroid Build Coastguard Worker }
2035*38e8c45fSAndroid Build Coastguard Worker }
2036*38e8c45fSAndroid Build Coastguard Worker } else if (eventItem.events & EPOLLHUP) {
2037*38e8c45fSAndroid Build Coastguard Worker ALOGI("Removing device %s due to epoll hang-up event.",
2038*38e8c45fSAndroid Build Coastguard Worker device->identifier.name.c_str());
2039*38e8c45fSAndroid Build Coastguard Worker deviceChanged = true;
2040*38e8c45fSAndroid Build Coastguard Worker closeDeviceLocked(*device);
2041*38e8c45fSAndroid Build Coastguard Worker } else {
2042*38e8c45fSAndroid Build Coastguard Worker ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
2043*38e8c45fSAndroid Build Coastguard Worker device->identifier.name.c_str());
2044*38e8c45fSAndroid Build Coastguard Worker }
2045*38e8c45fSAndroid Build Coastguard Worker }
2046*38e8c45fSAndroid Build Coastguard Worker
2047*38e8c45fSAndroid Build Coastguard Worker // readNotify() will modify the list of devices so this must be done after
2048*38e8c45fSAndroid Build Coastguard Worker // processing all other events to ensure that we read all remaining events
2049*38e8c45fSAndroid Build Coastguard Worker // before closing the devices.
2050*38e8c45fSAndroid Build Coastguard Worker if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
2051*38e8c45fSAndroid Build Coastguard Worker mPendingINotify = false;
2052*38e8c45fSAndroid Build Coastguard Worker const auto res = readNotifyLocked();
2053*38e8c45fSAndroid Build Coastguard Worker if (!res.ok()) {
2054*38e8c45fSAndroid Build Coastguard Worker ALOGW("Failed to read from inotify: %s", res.error().message().c_str());
2055*38e8c45fSAndroid Build Coastguard Worker }
2056*38e8c45fSAndroid Build Coastguard Worker deviceChanged = true;
2057*38e8c45fSAndroid Build Coastguard Worker }
2058*38e8c45fSAndroid Build Coastguard Worker
2059*38e8c45fSAndroid Build Coastguard Worker // Report added or removed devices immediately.
2060*38e8c45fSAndroid Build Coastguard Worker if (deviceChanged) {
2061*38e8c45fSAndroid Build Coastguard Worker continue;
2062*38e8c45fSAndroid Build Coastguard Worker }
2063*38e8c45fSAndroid Build Coastguard Worker
2064*38e8c45fSAndroid Build Coastguard Worker // Return now if we have collected any events or if we were explicitly awoken.
2065*38e8c45fSAndroid Build Coastguard Worker if (!events.empty() || awoken) {
2066*38e8c45fSAndroid Build Coastguard Worker break;
2067*38e8c45fSAndroid Build Coastguard Worker }
2068*38e8c45fSAndroid Build Coastguard Worker
2069*38e8c45fSAndroid Build Coastguard Worker // Poll for events.
2070*38e8c45fSAndroid Build Coastguard Worker // When a device driver has pending (unread) events, it acquires
2071*38e8c45fSAndroid Build Coastguard Worker // a kernel wake lock. Once the last pending event has been read, the device
2072*38e8c45fSAndroid Build Coastguard Worker // driver will release the kernel wake lock, but the epoll will hold the wakelock,
2073*38e8c45fSAndroid Build Coastguard Worker // since we are using EPOLLWAKEUP. The wakelock is released by the epoll when epoll_wait
2074*38e8c45fSAndroid Build Coastguard Worker // is called again for the same fd that produced the event.
2075*38e8c45fSAndroid Build Coastguard Worker // Thus the system can only sleep if there are no events pending or
2076*38e8c45fSAndroid Build Coastguard Worker // currently being processed.
2077*38e8c45fSAndroid Build Coastguard Worker //
2078*38e8c45fSAndroid Build Coastguard Worker // The timeout is advisory only. If the device is asleep, it will not wake just to
2079*38e8c45fSAndroid Build Coastguard Worker // service the timeout.
2080*38e8c45fSAndroid Build Coastguard Worker mPendingEventIndex = 0;
2081*38e8c45fSAndroid Build Coastguard Worker
2082*38e8c45fSAndroid Build Coastguard Worker mLock.unlock(); // release lock before poll
2083*38e8c45fSAndroid Build Coastguard Worker
2084*38e8c45fSAndroid Build Coastguard Worker int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
2085*38e8c45fSAndroid Build Coastguard Worker
2086*38e8c45fSAndroid Build Coastguard Worker mLock.lock(); // reacquire lock after poll
2087*38e8c45fSAndroid Build Coastguard Worker
2088*38e8c45fSAndroid Build Coastguard Worker if (pollResult == 0) {
2089*38e8c45fSAndroid Build Coastguard Worker // Timed out.
2090*38e8c45fSAndroid Build Coastguard Worker mPendingEventCount = 0;
2091*38e8c45fSAndroid Build Coastguard Worker break;
2092*38e8c45fSAndroid Build Coastguard Worker }
2093*38e8c45fSAndroid Build Coastguard Worker
2094*38e8c45fSAndroid Build Coastguard Worker if (pollResult < 0) {
2095*38e8c45fSAndroid Build Coastguard Worker // An error occurred.
2096*38e8c45fSAndroid Build Coastguard Worker mPendingEventCount = 0;
2097*38e8c45fSAndroid Build Coastguard Worker
2098*38e8c45fSAndroid Build Coastguard Worker // Sleep after errors to avoid locking up the system.
2099*38e8c45fSAndroid Build Coastguard Worker // Hopefully the error is transient.
2100*38e8c45fSAndroid Build Coastguard Worker if (errno != EINTR) {
2101*38e8c45fSAndroid Build Coastguard Worker ALOGW("poll failed (errno=%d)\n", errno);
2102*38e8c45fSAndroid Build Coastguard Worker usleep(100000);
2103*38e8c45fSAndroid Build Coastguard Worker }
2104*38e8c45fSAndroid Build Coastguard Worker } else {
2105*38e8c45fSAndroid Build Coastguard Worker // Some events occurred.
2106*38e8c45fSAndroid Build Coastguard Worker mPendingEventCount = size_t(pollResult);
2107*38e8c45fSAndroid Build Coastguard Worker }
2108*38e8c45fSAndroid Build Coastguard Worker }
2109*38e8c45fSAndroid Build Coastguard Worker
2110*38e8c45fSAndroid Build Coastguard Worker // All done, return the number of events we read.
2111*38e8c45fSAndroid Build Coastguard Worker return events;
2112*38e8c45fSAndroid Build Coastguard Worker }
2113*38e8c45fSAndroid Build Coastguard Worker
getVideoFrames(int32_t deviceId)2114*38e8c45fSAndroid Build Coastguard Worker std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) {
2115*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2116*38e8c45fSAndroid Build Coastguard Worker
2117*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
2118*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr || !device->videoDevice) {
2119*38e8c45fSAndroid Build Coastguard Worker return {};
2120*38e8c45fSAndroid Build Coastguard Worker }
2121*38e8c45fSAndroid Build Coastguard Worker return device->videoDevice->consumeFrames();
2122*38e8c45fSAndroid Build Coastguard Worker }
2123*38e8c45fSAndroid Build Coastguard Worker
wake()2124*38e8c45fSAndroid Build Coastguard Worker void EventHub::wake() {
2125*38e8c45fSAndroid Build Coastguard Worker ALOGV("wake() called");
2126*38e8c45fSAndroid Build Coastguard Worker
2127*38e8c45fSAndroid Build Coastguard Worker ssize_t nWrite;
2128*38e8c45fSAndroid Build Coastguard Worker do {
2129*38e8c45fSAndroid Build Coastguard Worker nWrite = write(mWakeWritePipeFd, "W", 1);
2130*38e8c45fSAndroid Build Coastguard Worker } while (nWrite == -1 && errno == EINTR);
2131*38e8c45fSAndroid Build Coastguard Worker
2132*38e8c45fSAndroid Build Coastguard Worker if (nWrite != 1 && errno != EAGAIN) {
2133*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not write wake signal: %s", strerror(errno));
2134*38e8c45fSAndroid Build Coastguard Worker }
2135*38e8c45fSAndroid Build Coastguard Worker }
2136*38e8c45fSAndroid Build Coastguard Worker
scanDevicesLocked()2137*38e8c45fSAndroid Build Coastguard Worker void EventHub::scanDevicesLocked() {
2138*38e8c45fSAndroid Build Coastguard Worker status_t result;
2139*38e8c45fSAndroid Build Coastguard Worker std::error_code errorCode;
2140*38e8c45fSAndroid Build Coastguard Worker
2141*38e8c45fSAndroid Build Coastguard Worker if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
2142*38e8c45fSAndroid Build Coastguard Worker result = scanDirLocked(DEVICE_INPUT_PATH);
2143*38e8c45fSAndroid Build Coastguard Worker if (result < 0) {
2144*38e8c45fSAndroid Build Coastguard Worker ALOGE("scan dir failed for %s", DEVICE_INPUT_PATH);
2145*38e8c45fSAndroid Build Coastguard Worker }
2146*38e8c45fSAndroid Build Coastguard Worker } else {
2147*38e8c45fSAndroid Build Coastguard Worker if (errorCode) {
2148*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
2149*38e8c45fSAndroid Build Coastguard Worker errorCode.message().c_str());
2150*38e8c45fSAndroid Build Coastguard Worker }
2151*38e8c45fSAndroid Build Coastguard Worker }
2152*38e8c45fSAndroid Build Coastguard Worker if (isV4lScanningEnabled()) {
2153*38e8c45fSAndroid Build Coastguard Worker result = scanVideoDirLocked(DEVICE_PATH);
2154*38e8c45fSAndroid Build Coastguard Worker if (result != OK) {
2155*38e8c45fSAndroid Build Coastguard Worker ALOGE("scan video dir failed for %s", DEVICE_PATH);
2156*38e8c45fSAndroid Build Coastguard Worker }
2157*38e8c45fSAndroid Build Coastguard Worker }
2158*38e8c45fSAndroid Build Coastguard Worker if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
2159*38e8c45fSAndroid Build Coastguard Worker createVirtualKeyboardLocked();
2160*38e8c45fSAndroid Build Coastguard Worker }
2161*38e8c45fSAndroid Build Coastguard Worker }
2162*38e8c45fSAndroid Build Coastguard Worker
2163*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
2164*38e8c45fSAndroid Build Coastguard Worker
registerFdForEpoll(int fd)2165*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::registerFdForEpoll(int fd) {
2166*38e8c45fSAndroid Build Coastguard Worker // TODO(b/121395353) - consider adding EPOLLRDHUP
2167*38e8c45fSAndroid Build Coastguard Worker struct epoll_event eventItem = {};
2168*38e8c45fSAndroid Build Coastguard Worker eventItem.events = EPOLLIN | EPOLLWAKEUP;
2169*38e8c45fSAndroid Build Coastguard Worker eventItem.data.fd = fd;
2170*38e8c45fSAndroid Build Coastguard Worker if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
2171*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not add fd to epoll instance: %s", strerror(errno));
2172*38e8c45fSAndroid Build Coastguard Worker return -errno;
2173*38e8c45fSAndroid Build Coastguard Worker }
2174*38e8c45fSAndroid Build Coastguard Worker return OK;
2175*38e8c45fSAndroid Build Coastguard Worker }
2176*38e8c45fSAndroid Build Coastguard Worker
unregisterFdFromEpoll(int fd)2177*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::unregisterFdFromEpoll(int fd) {
2178*38e8c45fSAndroid Build Coastguard Worker if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, nullptr)) {
2179*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not remove fd from epoll instance: %s", strerror(errno));
2180*38e8c45fSAndroid Build Coastguard Worker return -errno;
2181*38e8c45fSAndroid Build Coastguard Worker }
2182*38e8c45fSAndroid Build Coastguard Worker return OK;
2183*38e8c45fSAndroid Build Coastguard Worker }
2184*38e8c45fSAndroid Build Coastguard Worker
registerDeviceForEpollLocked(Device & device)2185*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::registerDeviceForEpollLocked(Device& device) {
2186*38e8c45fSAndroid Build Coastguard Worker status_t result = registerFdForEpoll(device.fd);
2187*38e8c45fSAndroid Build Coastguard Worker if (result != OK) {
2188*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not add input device fd to epoll for device %" PRId32, device.id);
2189*38e8c45fSAndroid Build Coastguard Worker return result;
2190*38e8c45fSAndroid Build Coastguard Worker }
2191*38e8c45fSAndroid Build Coastguard Worker if (device.videoDevice) {
2192*38e8c45fSAndroid Build Coastguard Worker registerVideoDeviceForEpollLocked(*device.videoDevice);
2193*38e8c45fSAndroid Build Coastguard Worker }
2194*38e8c45fSAndroid Build Coastguard Worker return result;
2195*38e8c45fSAndroid Build Coastguard Worker }
2196*38e8c45fSAndroid Build Coastguard Worker
registerVideoDeviceForEpollLocked(const TouchVideoDevice & videoDevice)2197*38e8c45fSAndroid Build Coastguard Worker void EventHub::registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice) {
2198*38e8c45fSAndroid Build Coastguard Worker status_t result = registerFdForEpoll(videoDevice.getFd());
2199*38e8c45fSAndroid Build Coastguard Worker if (result != OK) {
2200*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not add video device %s to epoll", videoDevice.getName().c_str());
2201*38e8c45fSAndroid Build Coastguard Worker }
2202*38e8c45fSAndroid Build Coastguard Worker }
2203*38e8c45fSAndroid Build Coastguard Worker
unregisterDeviceFromEpollLocked(Device & device)2204*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::unregisterDeviceFromEpollLocked(Device& device) {
2205*38e8c45fSAndroid Build Coastguard Worker if (device.hasValidFd()) {
2206*38e8c45fSAndroid Build Coastguard Worker status_t result = unregisterFdFromEpoll(device.fd);
2207*38e8c45fSAndroid Build Coastguard Worker if (result != OK) {
2208*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not remove input device fd from epoll for device %" PRId32, device.id);
2209*38e8c45fSAndroid Build Coastguard Worker return result;
2210*38e8c45fSAndroid Build Coastguard Worker }
2211*38e8c45fSAndroid Build Coastguard Worker }
2212*38e8c45fSAndroid Build Coastguard Worker if (device.videoDevice) {
2213*38e8c45fSAndroid Build Coastguard Worker unregisterVideoDeviceFromEpollLocked(*device.videoDevice);
2214*38e8c45fSAndroid Build Coastguard Worker }
2215*38e8c45fSAndroid Build Coastguard Worker return OK;
2216*38e8c45fSAndroid Build Coastguard Worker }
2217*38e8c45fSAndroid Build Coastguard Worker
unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice & videoDevice)2218*38e8c45fSAndroid Build Coastguard Worker void EventHub::unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice) {
2219*38e8c45fSAndroid Build Coastguard Worker if (videoDevice.hasValidFd()) {
2220*38e8c45fSAndroid Build Coastguard Worker status_t result = unregisterFdFromEpoll(videoDevice.getFd());
2221*38e8c45fSAndroid Build Coastguard Worker if (result != OK) {
2222*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not remove video device fd from epoll for device: %s",
2223*38e8c45fSAndroid Build Coastguard Worker videoDevice.getName().c_str());
2224*38e8c45fSAndroid Build Coastguard Worker }
2225*38e8c45fSAndroid Build Coastguard Worker }
2226*38e8c45fSAndroid Build Coastguard Worker }
2227*38e8c45fSAndroid Build Coastguard Worker
reportDeviceAddedForStatisticsLocked(const InputDeviceIdentifier & identifier,ftl::Flags<InputDeviceClass> classes)2228*38e8c45fSAndroid Build Coastguard Worker void EventHub::reportDeviceAddedForStatisticsLocked(const InputDeviceIdentifier& identifier,
2229*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputDeviceClass> classes) {
2230*38e8c45fSAndroid Build Coastguard Worker SHA256_CTX ctx;
2231*38e8c45fSAndroid Build Coastguard Worker SHA256_Init(&ctx);
2232*38e8c45fSAndroid Build Coastguard Worker SHA256_Update(&ctx, reinterpret_cast<const uint8_t*>(identifier.uniqueId.c_str()),
2233*38e8c45fSAndroid Build Coastguard Worker identifier.uniqueId.size());
2234*38e8c45fSAndroid Build Coastguard Worker std::array<uint8_t, SHA256_DIGEST_LENGTH> digest;
2235*38e8c45fSAndroid Build Coastguard Worker SHA256_Final(digest.data(), &ctx);
2236*38e8c45fSAndroid Build Coastguard Worker
2237*38e8c45fSAndroid Build Coastguard Worker std::string obfuscatedId;
2238*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < OBFUSCATED_LENGTH; i++) {
2239*38e8c45fSAndroid Build Coastguard Worker obfuscatedId += StringPrintf("%02x", digest[i]);
2240*38e8c45fSAndroid Build Coastguard Worker }
2241*38e8c45fSAndroid Build Coastguard Worker
2242*38e8c45fSAndroid Build Coastguard Worker android::util::stats_write(android::util::INPUTDEVICE_REGISTERED, identifier.name.c_str(),
2243*38e8c45fSAndroid Build Coastguard Worker identifier.vendor, identifier.product, identifier.version,
2244*38e8c45fSAndroid Build Coastguard Worker identifier.bus, obfuscatedId.c_str(), classes.get());
2245*38e8c45fSAndroid Build Coastguard Worker }
2246*38e8c45fSAndroid Build Coastguard Worker
openDeviceLocked(const std::string & devicePath)2247*38e8c45fSAndroid Build Coastguard Worker void EventHub::openDeviceLocked(const std::string& devicePath) {
2248*38e8c45fSAndroid Build Coastguard Worker // If an input device happens to register around the time when EventHub's constructor runs, it
2249*38e8c45fSAndroid Build Coastguard Worker // is possible that the same input event node (for example, /dev/input/event3) will be noticed
2250*38e8c45fSAndroid Build Coastguard Worker // in both 'inotify' callback and also in the 'scanDirLocked' pass. To prevent duplicate devices
2251*38e8c45fSAndroid Build Coastguard Worker // from getting registered, ensure that this path is not already covered by an existing device.
2252*38e8c45fSAndroid Build Coastguard Worker for (const auto& [deviceId, device] : mDevices) {
2253*38e8c45fSAndroid Build Coastguard Worker if (device->path == devicePath) {
2254*38e8c45fSAndroid Build Coastguard Worker return; // device was already registered
2255*38e8c45fSAndroid Build Coastguard Worker }
2256*38e8c45fSAndroid Build Coastguard Worker }
2257*38e8c45fSAndroid Build Coastguard Worker
2258*38e8c45fSAndroid Build Coastguard Worker char buffer[80];
2259*38e8c45fSAndroid Build Coastguard Worker
2260*38e8c45fSAndroid Build Coastguard Worker ALOGV("Opening device: %s", devicePath.c_str());
2261*38e8c45fSAndroid Build Coastguard Worker
2262*38e8c45fSAndroid Build Coastguard Worker int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
2263*38e8c45fSAndroid Build Coastguard Worker if (fd < 0) {
2264*38e8c45fSAndroid Build Coastguard Worker ALOGE("could not open %s, %s\n", devicePath.c_str(), strerror(errno));
2265*38e8c45fSAndroid Build Coastguard Worker return;
2266*38e8c45fSAndroid Build Coastguard Worker }
2267*38e8c45fSAndroid Build Coastguard Worker
2268*38e8c45fSAndroid Build Coastguard Worker InputDeviceIdentifier identifier;
2269*38e8c45fSAndroid Build Coastguard Worker
2270*38e8c45fSAndroid Build Coastguard Worker // Get device name.
2271*38e8c45fSAndroid Build Coastguard Worker if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
2272*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
2273*38e8c45fSAndroid Build Coastguard Worker } else {
2274*38e8c45fSAndroid Build Coastguard Worker buffer[sizeof(buffer) - 1] = '\0';
2275*38e8c45fSAndroid Build Coastguard Worker identifier.name = buffer;
2276*38e8c45fSAndroid Build Coastguard Worker }
2277*38e8c45fSAndroid Build Coastguard Worker
2278*38e8c45fSAndroid Build Coastguard Worker // Check to see if the device is on our excluded list
2279*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mExcludedDevices.size(); i++) {
2280*38e8c45fSAndroid Build Coastguard Worker const std::string& item = mExcludedDevices[i];
2281*38e8c45fSAndroid Build Coastguard Worker if (identifier.name == item) {
2282*38e8c45fSAndroid Build Coastguard Worker ALOGI("ignoring event id %s driver %s\n", devicePath.c_str(), item.c_str());
2283*38e8c45fSAndroid Build Coastguard Worker close(fd);
2284*38e8c45fSAndroid Build Coastguard Worker return;
2285*38e8c45fSAndroid Build Coastguard Worker }
2286*38e8c45fSAndroid Build Coastguard Worker }
2287*38e8c45fSAndroid Build Coastguard Worker
2288*38e8c45fSAndroid Build Coastguard Worker // Get device driver version.
2289*38e8c45fSAndroid Build Coastguard Worker int driverVersion;
2290*38e8c45fSAndroid Build Coastguard Worker if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
2291*38e8c45fSAndroid Build Coastguard Worker ALOGE("could not get driver version for %s, %s\n", devicePath.c_str(), strerror(errno));
2292*38e8c45fSAndroid Build Coastguard Worker close(fd);
2293*38e8c45fSAndroid Build Coastguard Worker return;
2294*38e8c45fSAndroid Build Coastguard Worker }
2295*38e8c45fSAndroid Build Coastguard Worker
2296*38e8c45fSAndroid Build Coastguard Worker // Get device identifier.
2297*38e8c45fSAndroid Build Coastguard Worker struct input_id inputId;
2298*38e8c45fSAndroid Build Coastguard Worker if (ioctl(fd, EVIOCGID, &inputId)) {
2299*38e8c45fSAndroid Build Coastguard Worker ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
2300*38e8c45fSAndroid Build Coastguard Worker close(fd);
2301*38e8c45fSAndroid Build Coastguard Worker return;
2302*38e8c45fSAndroid Build Coastguard Worker }
2303*38e8c45fSAndroid Build Coastguard Worker identifier.bus = inputId.bustype;
2304*38e8c45fSAndroid Build Coastguard Worker identifier.product = inputId.product;
2305*38e8c45fSAndroid Build Coastguard Worker identifier.vendor = inputId.vendor;
2306*38e8c45fSAndroid Build Coastguard Worker identifier.version = inputId.version;
2307*38e8c45fSAndroid Build Coastguard Worker
2308*38e8c45fSAndroid Build Coastguard Worker // Get device physical location.
2309*38e8c45fSAndroid Build Coastguard Worker if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
2310*38e8c45fSAndroid Build Coastguard Worker // fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
2311*38e8c45fSAndroid Build Coastguard Worker } else {
2312*38e8c45fSAndroid Build Coastguard Worker buffer[sizeof(buffer) - 1] = '\0';
2313*38e8c45fSAndroid Build Coastguard Worker identifier.location = buffer;
2314*38e8c45fSAndroid Build Coastguard Worker }
2315*38e8c45fSAndroid Build Coastguard Worker
2316*38e8c45fSAndroid Build Coastguard Worker // Get device unique id.
2317*38e8c45fSAndroid Build Coastguard Worker if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
2318*38e8c45fSAndroid Build Coastguard Worker // fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
2319*38e8c45fSAndroid Build Coastguard Worker } else {
2320*38e8c45fSAndroid Build Coastguard Worker buffer[sizeof(buffer) - 1] = '\0';
2321*38e8c45fSAndroid Build Coastguard Worker identifier.uniqueId = buffer;
2322*38e8c45fSAndroid Build Coastguard Worker }
2323*38e8c45fSAndroid Build Coastguard Worker
2324*38e8c45fSAndroid Build Coastguard Worker // Attempt to get the bluetooth address of an input device from the uniqueId.
2325*38e8c45fSAndroid Build Coastguard Worker if (identifier.bus == BUS_BLUETOOTH &&
2326*38e8c45fSAndroid Build Coastguard Worker std::regex_match(identifier.uniqueId,
2327*38e8c45fSAndroid Build Coastguard Worker std::regex("^[A-Fa-f0-9]{2}(?::[A-Fa-f0-9]{2}){5}$"))) {
2328*38e8c45fSAndroid Build Coastguard Worker identifier.bluetoothAddress = identifier.uniqueId;
2329*38e8c45fSAndroid Build Coastguard Worker // The Bluetooth stack requires alphabetic characters to be uppercase in a valid address.
2330*38e8c45fSAndroid Build Coastguard Worker for (auto& c : *identifier.bluetoothAddress) {
2331*38e8c45fSAndroid Build Coastguard Worker c = ::toupper(c);
2332*38e8c45fSAndroid Build Coastguard Worker }
2333*38e8c45fSAndroid Build Coastguard Worker }
2334*38e8c45fSAndroid Build Coastguard Worker
2335*38e8c45fSAndroid Build Coastguard Worker // Fill in the descriptor.
2336*38e8c45fSAndroid Build Coastguard Worker assignDescriptorLocked(identifier);
2337*38e8c45fSAndroid Build Coastguard Worker
2338*38e8c45fSAndroid Build Coastguard Worker // Allocate device. (The device object takes ownership of the fd at this point.)
2339*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId = mNextDeviceId++;
2340*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<Device> device =
2341*38e8c45fSAndroid Build Coastguard Worker std::make_unique<Device>(fd, deviceId, devicePath, identifier,
2342*38e8c45fSAndroid Build Coastguard Worker obtainAssociatedDeviceLocked(devicePath));
2343*38e8c45fSAndroid Build Coastguard Worker
2344*38e8c45fSAndroid Build Coastguard Worker ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
2345*38e8c45fSAndroid Build Coastguard Worker ALOGV(" bus: %04x\n"
2346*38e8c45fSAndroid Build Coastguard Worker " vendor %04x\n"
2347*38e8c45fSAndroid Build Coastguard Worker " product %04x\n"
2348*38e8c45fSAndroid Build Coastguard Worker " version %04x\n",
2349*38e8c45fSAndroid Build Coastguard Worker identifier.bus, identifier.vendor, identifier.product, identifier.version);
2350*38e8c45fSAndroid Build Coastguard Worker ALOGV(" name: \"%s\"\n", identifier.name.c_str());
2351*38e8c45fSAndroid Build Coastguard Worker ALOGV(" location: \"%s\"\n", identifier.location.c_str());
2352*38e8c45fSAndroid Build Coastguard Worker ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.c_str());
2353*38e8c45fSAndroid Build Coastguard Worker ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.c_str());
2354*38e8c45fSAndroid Build Coastguard Worker ALOGV(" driver: v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,
2355*38e8c45fSAndroid Build Coastguard Worker driverVersion & 0xff);
2356*38e8c45fSAndroid Build Coastguard Worker
2357*38e8c45fSAndroid Build Coastguard Worker // Load the configuration file for the device.
2358*38e8c45fSAndroid Build Coastguard Worker device->loadConfigurationLocked();
2359*38e8c45fSAndroid Build Coastguard Worker
2360*38e8c45fSAndroid Build Coastguard Worker // Figure out the kinds of events the device reports.
2361*38e8c45fSAndroid Build Coastguard Worker device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
2362*38e8c45fSAndroid Build Coastguard Worker device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask);
2363*38e8c45fSAndroid Build Coastguard Worker device->readDeviceBitMask(EVIOCGBIT(EV_REL, 0), device->relBitmask);
2364*38e8c45fSAndroid Build Coastguard Worker device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask);
2365*38e8c45fSAndroid Build Coastguard Worker device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask);
2366*38e8c45fSAndroid Build Coastguard Worker device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask);
2367*38e8c45fSAndroid Build Coastguard Worker device->readDeviceBitMask(EVIOCGBIT(EV_MSC, 0), device->mscBitmask);
2368*38e8c45fSAndroid Build Coastguard Worker device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask);
2369*38e8c45fSAndroid Build Coastguard Worker
2370*38e8c45fSAndroid Build Coastguard Worker // See if this is a device with keys. This could be full keyboard, or other devices like
2371*38e8c45fSAndroid Build Coastguard Worker // gamepads, joysticks, and styluses with buttons that should generate key presses.
2372*38e8c45fSAndroid Build Coastguard Worker bool haveKeyboardKeys =
2373*38e8c45fSAndroid Build Coastguard Worker device->keyBitmask.any(0, BTN_MISC) || device->keyBitmask.any(BTN_WHEEL, KEY_MAX + 1);
2374*38e8c45fSAndroid Build Coastguard Worker bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) ||
2375*38e8c45fSAndroid Build Coastguard Worker device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI);
2376*38e8c45fSAndroid Build Coastguard Worker bool haveStylusButtons = device->keyBitmask.test(BTN_STYLUS) ||
2377*38e8c45fSAndroid Build Coastguard Worker device->keyBitmask.test(BTN_STYLUS2) || device->keyBitmask.test(BTN_STYLUS3);
2378*38e8c45fSAndroid Build Coastguard Worker if (haveKeyboardKeys || haveGamepadButtons || haveStylusButtons) {
2379*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::KEYBOARD;
2380*38e8c45fSAndroid Build Coastguard Worker }
2381*38e8c45fSAndroid Build Coastguard Worker
2382*38e8c45fSAndroid Build Coastguard Worker // See if this is a cursor device such as a trackball or mouse.
2383*38e8c45fSAndroid Build Coastguard Worker if (device->keyBitmask.test(BTN_MOUSE) && device->relBitmask.test(REL_X) &&
2384*38e8c45fSAndroid Build Coastguard Worker device->relBitmask.test(REL_Y)) {
2385*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::CURSOR;
2386*38e8c45fSAndroid Build Coastguard Worker }
2387*38e8c45fSAndroid Build Coastguard Worker
2388*38e8c45fSAndroid Build Coastguard Worker // See if the device is specially configured to be of a certain type.
2389*38e8c45fSAndroid Build Coastguard Worker if (device->configuration) {
2390*38e8c45fSAndroid Build Coastguard Worker std::string deviceType = device->configuration->getString("device.type").value_or("");
2391*38e8c45fSAndroid Build Coastguard Worker if (deviceType == "rotaryEncoder") {
2392*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::ROTARY_ENCODER;
2393*38e8c45fSAndroid Build Coastguard Worker } else if (deviceType == "externalStylus") {
2394*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
2395*38e8c45fSAndroid Build Coastguard Worker }
2396*38e8c45fSAndroid Build Coastguard Worker }
2397*38e8c45fSAndroid Build Coastguard Worker
2398*38e8c45fSAndroid Build Coastguard Worker // See if this is a touch pad.
2399*38e8c45fSAndroid Build Coastguard Worker // Is this a new modern multi-touch driver?
2400*38e8c45fSAndroid Build Coastguard Worker if (device->absBitmask.test(ABS_MT_POSITION_X) && device->absBitmask.test(ABS_MT_POSITION_Y)) {
2401*38e8c45fSAndroid Build Coastguard Worker // Some joysticks such as the PS3 controller report axes that conflict
2402*38e8c45fSAndroid Build Coastguard Worker // with the ABS_MT range. Try to confirm that the device really is
2403*38e8c45fSAndroid Build Coastguard Worker // a touch screen.
2404*38e8c45fSAndroid Build Coastguard Worker if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) {
2405*38e8c45fSAndroid Build Coastguard Worker device->classes |= (InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT);
2406*38e8c45fSAndroid Build Coastguard Worker if (device->propBitmask.test(INPUT_PROP_POINTER) &&
2407*38e8c45fSAndroid Build Coastguard Worker !device->keyBitmask.any(BTN_TOOL_PEN, BTN_TOOL_FINGER) && !haveStylusButtons) {
2408*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::TOUCHPAD;
2409*38e8c45fSAndroid Build Coastguard Worker }
2410*38e8c45fSAndroid Build Coastguard Worker }
2411*38e8c45fSAndroid Build Coastguard Worker // Is this an old style single-touch driver?
2412*38e8c45fSAndroid Build Coastguard Worker } else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) &&
2413*38e8c45fSAndroid Build Coastguard Worker device->absBitmask.test(ABS_Y)) {
2414*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::TOUCH;
2415*38e8c45fSAndroid Build Coastguard Worker // Is this a stylus that reports contact/pressure independently of touch coordinates?
2416*38e8c45fSAndroid Build Coastguard Worker } else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) &&
2417*38e8c45fSAndroid Build Coastguard Worker !device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) {
2418*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
2419*38e8c45fSAndroid Build Coastguard Worker }
2420*38e8c45fSAndroid Build Coastguard Worker
2421*38e8c45fSAndroid Build Coastguard Worker // See if this device is a joystick.
2422*38e8c45fSAndroid Build Coastguard Worker // Assumes that joysticks always have gamepad buttons in order to distinguish them
2423*38e8c45fSAndroid Build Coastguard Worker // from other devices such as accelerometers that also have absolute axes.
2424*38e8c45fSAndroid Build Coastguard Worker if (haveGamepadButtons) {
2425*38e8c45fSAndroid Build Coastguard Worker auto assumedClasses = device->classes | InputDeviceClass::JOYSTICK;
2426*38e8c45fSAndroid Build Coastguard Worker for (int i = 0; i <= ABS_MAX; i++) {
2427*38e8c45fSAndroid Build Coastguard Worker if (device->absBitmask.test(i) &&
2428*38e8c45fSAndroid Build Coastguard Worker (getAbsAxisUsage(i, assumedClasses).test(InputDeviceClass::JOYSTICK))) {
2429*38e8c45fSAndroid Build Coastguard Worker device->classes = assumedClasses;
2430*38e8c45fSAndroid Build Coastguard Worker break;
2431*38e8c45fSAndroid Build Coastguard Worker }
2432*38e8c45fSAndroid Build Coastguard Worker }
2433*38e8c45fSAndroid Build Coastguard Worker }
2434*38e8c45fSAndroid Build Coastguard Worker
2435*38e8c45fSAndroid Build Coastguard Worker // Check whether this device is an accelerometer.
2436*38e8c45fSAndroid Build Coastguard Worker if (device->propBitmask.test(INPUT_PROP_ACCELEROMETER)) {
2437*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::SENSOR;
2438*38e8c45fSAndroid Build Coastguard Worker }
2439*38e8c45fSAndroid Build Coastguard Worker
2440*38e8c45fSAndroid Build Coastguard Worker // Check whether this device has switches.
2441*38e8c45fSAndroid Build Coastguard Worker for (int i = 0; i <= SW_MAX; i++) {
2442*38e8c45fSAndroid Build Coastguard Worker if (device->swBitmask.test(i)) {
2443*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::SWITCH;
2444*38e8c45fSAndroid Build Coastguard Worker break;
2445*38e8c45fSAndroid Build Coastguard Worker }
2446*38e8c45fSAndroid Build Coastguard Worker }
2447*38e8c45fSAndroid Build Coastguard Worker
2448*38e8c45fSAndroid Build Coastguard Worker // Check whether this device supports the vibrator.
2449*38e8c45fSAndroid Build Coastguard Worker if (device->ffBitmask.test(FF_RUMBLE)) {
2450*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::VIBRATOR;
2451*38e8c45fSAndroid Build Coastguard Worker }
2452*38e8c45fSAndroid Build Coastguard Worker
2453*38e8c45fSAndroid Build Coastguard Worker // Configure virtual keys.
2454*38e8c45fSAndroid Build Coastguard Worker if ((device->classes.test(InputDeviceClass::TOUCH))) {
2455*38e8c45fSAndroid Build Coastguard Worker // Load the virtual keys for the touch screen, if any.
2456*38e8c45fSAndroid Build Coastguard Worker // We do this now so that we can make sure to load the keymap if necessary.
2457*38e8c45fSAndroid Build Coastguard Worker bool success = device->loadVirtualKeyMapLocked();
2458*38e8c45fSAndroid Build Coastguard Worker if (success) {
2459*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::KEYBOARD;
2460*38e8c45fSAndroid Build Coastguard Worker }
2461*38e8c45fSAndroid Build Coastguard Worker }
2462*38e8c45fSAndroid Build Coastguard Worker
2463*38e8c45fSAndroid Build Coastguard Worker // Load the key map.
2464*38e8c45fSAndroid Build Coastguard Worker // We need to do this for joysticks too because the key layout may specify axes, and for
2465*38e8c45fSAndroid Build Coastguard Worker // sensor as well because the key layout may specify the axes to sensor data mapping.
2466*38e8c45fSAndroid Build Coastguard Worker status_t keyMapStatus = NAME_NOT_FOUND;
2467*38e8c45fSAndroid Build Coastguard Worker if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK |
2468*38e8c45fSAndroid Build Coastguard Worker InputDeviceClass::SENSOR)) {
2469*38e8c45fSAndroid Build Coastguard Worker // Load the keymap for the device.
2470*38e8c45fSAndroid Build Coastguard Worker keyMapStatus = device->loadKeyMapLocked();
2471*38e8c45fSAndroid Build Coastguard Worker }
2472*38e8c45fSAndroid Build Coastguard Worker
2473*38e8c45fSAndroid Build Coastguard Worker // Configure the keyboard, gamepad or virtual keyboard.
2474*38e8c45fSAndroid Build Coastguard Worker if (device->classes.test(InputDeviceClass::KEYBOARD)) {
2475*38e8c45fSAndroid Build Coastguard Worker // Register the keyboard as a built-in keyboard if it is eligible.
2476*38e8c45fSAndroid Build Coastguard Worker if (!keyMapStatus && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD &&
2477*38e8c45fSAndroid Build Coastguard Worker isEligibleBuiltInKeyboard(device->identifier, device->configuration.get(),
2478*38e8c45fSAndroid Build Coastguard Worker &device->keyMap)) {
2479*38e8c45fSAndroid Build Coastguard Worker mBuiltInKeyboardId = device->id;
2480*38e8c45fSAndroid Build Coastguard Worker }
2481*38e8c45fSAndroid Build Coastguard Worker
2482*38e8c45fSAndroid Build Coastguard Worker // 'Q' key support = cheap test of whether this is an alpha-capable kbd
2483*38e8c45fSAndroid Build Coastguard Worker if (device->hasKeycodeLocked(AKEYCODE_Q)) {
2484*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::ALPHAKEY;
2485*38e8c45fSAndroid Build Coastguard Worker }
2486*38e8c45fSAndroid Build Coastguard Worker
2487*38e8c45fSAndroid Build Coastguard Worker // See if this device has a D-pad.
2488*38e8c45fSAndroid Build Coastguard Worker if (std::all_of(DPAD_REQUIRED_KEYCODES.begin(), DPAD_REQUIRED_KEYCODES.end(),
2489*38e8c45fSAndroid Build Coastguard Worker [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) {
2490*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::DPAD;
2491*38e8c45fSAndroid Build Coastguard Worker }
2492*38e8c45fSAndroid Build Coastguard Worker
2493*38e8c45fSAndroid Build Coastguard Worker // See if this device has a gamepad.
2494*38e8c45fSAndroid Build Coastguard Worker if (std::any_of(GAMEPAD_KEYCODES.begin(), GAMEPAD_KEYCODES.end(),
2495*38e8c45fSAndroid Build Coastguard Worker [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) {
2496*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::GAMEPAD;
2497*38e8c45fSAndroid Build Coastguard Worker }
2498*38e8c45fSAndroid Build Coastguard Worker
2499*38e8c45fSAndroid Build Coastguard Worker // See if this device has any stylus buttons that we would want to fuse with touch data.
2500*38e8c45fSAndroid Build Coastguard Worker if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT) &&
2501*38e8c45fSAndroid Build Coastguard Worker !device->classes.any(InputDeviceClass::ALPHAKEY) &&
2502*38e8c45fSAndroid Build Coastguard Worker std::any_of(STYLUS_BUTTON_KEYCODES.begin(), STYLUS_BUTTON_KEYCODES.end(),
2503*38e8c45fSAndroid Build Coastguard Worker [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) {
2504*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
2505*38e8c45fSAndroid Build Coastguard Worker }
2506*38e8c45fSAndroid Build Coastguard Worker }
2507*38e8c45fSAndroid Build Coastguard Worker
2508*38e8c45fSAndroid Build Coastguard Worker // See if the device is a rotary encoder with a single scroll axis and nothing else.
2509*38e8c45fSAndroid Build Coastguard Worker if (vd_flags::virtual_rotary() && device->classes == ftl::Flags<InputDeviceClass>(0) &&
2510*38e8c45fSAndroid Build Coastguard Worker device->relBitmask.test(REL_WHEEL) && !device->relBitmask.test(REL_HWHEEL)) {
2511*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::ROTARY_ENCODER;
2512*38e8c45fSAndroid Build Coastguard Worker }
2513*38e8c45fSAndroid Build Coastguard Worker
2514*38e8c45fSAndroid Build Coastguard Worker // If the device isn't recognized as something we handle, don't monitor it.
2515*38e8c45fSAndroid Build Coastguard Worker if (device->classes == ftl::Flags<InputDeviceClass>(0)) {
2516*38e8c45fSAndroid Build Coastguard Worker ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),
2517*38e8c45fSAndroid Build Coastguard Worker device->identifier.name.c_str());
2518*38e8c45fSAndroid Build Coastguard Worker return;
2519*38e8c45fSAndroid Build Coastguard Worker }
2520*38e8c45fSAndroid Build Coastguard Worker
2521*38e8c45fSAndroid Build Coastguard Worker // Classify InputDeviceClass::BATTERY.
2522*38e8c45fSAndroid Build Coastguard Worker if (device->associatedDevice && !device->associatedDevice->batteryInfos.empty()) {
2523*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::BATTERY;
2524*38e8c45fSAndroid Build Coastguard Worker }
2525*38e8c45fSAndroid Build Coastguard Worker
2526*38e8c45fSAndroid Build Coastguard Worker // Classify InputDeviceClass::LIGHT.
2527*38e8c45fSAndroid Build Coastguard Worker if (device->associatedDevice && !device->associatedDevice->lightInfos.empty()) {
2528*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::LIGHT;
2529*38e8c45fSAndroid Build Coastguard Worker }
2530*38e8c45fSAndroid Build Coastguard Worker
2531*38e8c45fSAndroid Build Coastguard Worker // Determine whether the device has a mic.
2532*38e8c45fSAndroid Build Coastguard Worker if (device->deviceHasMicLocked()) {
2533*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::MIC;
2534*38e8c45fSAndroid Build Coastguard Worker }
2535*38e8c45fSAndroid Build Coastguard Worker
2536*38e8c45fSAndroid Build Coastguard Worker // Determine whether the device is external or internal.
2537*38e8c45fSAndroid Build Coastguard Worker if (device->isExternalDeviceLocked()) {
2538*38e8c45fSAndroid Build Coastguard Worker device->classes |= InputDeviceClass::EXTERNAL;
2539*38e8c45fSAndroid Build Coastguard Worker }
2540*38e8c45fSAndroid Build Coastguard Worker
2541*38e8c45fSAndroid Build Coastguard Worker if (device->classes.any(InputDeviceClass::JOYSTICK | InputDeviceClass::DPAD) &&
2542*38e8c45fSAndroid Build Coastguard Worker device->classes.test(InputDeviceClass::GAMEPAD)) {
2543*38e8c45fSAndroid Build Coastguard Worker device->controllerNumber = getNextControllerNumberLocked(device->identifier.name);
2544*38e8c45fSAndroid Build Coastguard Worker device->setLedForControllerLocked();
2545*38e8c45fSAndroid Build Coastguard Worker }
2546*38e8c45fSAndroid Build Coastguard Worker
2547*38e8c45fSAndroid Build Coastguard Worker if (registerDeviceForEpollLocked(*device) != OK) {
2548*38e8c45fSAndroid Build Coastguard Worker return;
2549*38e8c45fSAndroid Build Coastguard Worker }
2550*38e8c45fSAndroid Build Coastguard Worker
2551*38e8c45fSAndroid Build Coastguard Worker device->configureFd();
2552*38e8c45fSAndroid Build Coastguard Worker
2553*38e8c45fSAndroid Build Coastguard Worker ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=%s, "
2554*38e8c45fSAndroid Build Coastguard Worker "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
2555*38e8c45fSAndroid Build Coastguard Worker deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(),
2556*38e8c45fSAndroid Build Coastguard Worker device->classes.string().c_str(), device->configurationFile.c_str(),
2557*38e8c45fSAndroid Build Coastguard Worker device->keyMap.keyLayoutFile.c_str(), device->keyMap.keyCharacterMapFile.c_str(),
2558*38e8c45fSAndroid Build Coastguard Worker toString(mBuiltInKeyboardId == deviceId));
2559*38e8c45fSAndroid Build Coastguard Worker
2560*38e8c45fSAndroid Build Coastguard Worker addDeviceLocked(std::move(device));
2561*38e8c45fSAndroid Build Coastguard Worker }
2562*38e8c45fSAndroid Build Coastguard Worker
openVideoDeviceLocked(const std::string & devicePath)2563*38e8c45fSAndroid Build Coastguard Worker void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
2564*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<TouchVideoDevice> videoDevice = TouchVideoDevice::create(devicePath);
2565*38e8c45fSAndroid Build Coastguard Worker if (!videoDevice) {
2566*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not create touch video device for %s. Ignoring", devicePath.c_str());
2567*38e8c45fSAndroid Build Coastguard Worker return;
2568*38e8c45fSAndroid Build Coastguard Worker }
2569*38e8c45fSAndroid Build Coastguard Worker // Transfer ownership of this video device to a matching input device
2570*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, device] : mDevices) {
2571*38e8c45fSAndroid Build Coastguard Worker if (tryAddVideoDeviceLocked(*device, videoDevice)) {
2572*38e8c45fSAndroid Build Coastguard Worker return; // 'device' now owns 'videoDevice'
2573*38e8c45fSAndroid Build Coastguard Worker }
2574*38e8c45fSAndroid Build Coastguard Worker }
2575*38e8c45fSAndroid Build Coastguard Worker
2576*38e8c45fSAndroid Build Coastguard Worker // Couldn't find a matching input device, so just add it to a temporary holding queue.
2577*38e8c45fSAndroid Build Coastguard Worker // A matching input device may appear later.
2578*38e8c45fSAndroid Build Coastguard Worker ALOGI("Adding video device %s to list of unattached video devices",
2579*38e8c45fSAndroid Build Coastguard Worker videoDevice->getName().c_str());
2580*38e8c45fSAndroid Build Coastguard Worker mUnattachedVideoDevices.push_back(std::move(videoDevice));
2581*38e8c45fSAndroid Build Coastguard Worker }
2582*38e8c45fSAndroid Build Coastguard Worker
tryAddVideoDeviceLocked(EventHub::Device & device,std::unique_ptr<TouchVideoDevice> & videoDevice)2583*38e8c45fSAndroid Build Coastguard Worker bool EventHub::tryAddVideoDeviceLocked(EventHub::Device& device,
2584*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<TouchVideoDevice>& videoDevice) {
2585*38e8c45fSAndroid Build Coastguard Worker if (videoDevice->getName() != device.identifier.name) {
2586*38e8c45fSAndroid Build Coastguard Worker return false;
2587*38e8c45fSAndroid Build Coastguard Worker }
2588*38e8c45fSAndroid Build Coastguard Worker device.videoDevice = std::move(videoDevice);
2589*38e8c45fSAndroid Build Coastguard Worker if (device.enabled) {
2590*38e8c45fSAndroid Build Coastguard Worker registerVideoDeviceForEpollLocked(*device.videoDevice);
2591*38e8c45fSAndroid Build Coastguard Worker }
2592*38e8c45fSAndroid Build Coastguard Worker return true;
2593*38e8c45fSAndroid Build Coastguard Worker }
2594*38e8c45fSAndroid Build Coastguard Worker
isDeviceEnabled(int32_t deviceId) const2595*38e8c45fSAndroid Build Coastguard Worker bool EventHub::isDeviceEnabled(int32_t deviceId) const {
2596*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2597*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
2598*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr) {
2599*38e8c45fSAndroid Build Coastguard Worker ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
2600*38e8c45fSAndroid Build Coastguard Worker return false;
2601*38e8c45fSAndroid Build Coastguard Worker }
2602*38e8c45fSAndroid Build Coastguard Worker return device->enabled;
2603*38e8c45fSAndroid Build Coastguard Worker }
2604*38e8c45fSAndroid Build Coastguard Worker
enableDevice(int32_t deviceId)2605*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::enableDevice(int32_t deviceId) {
2606*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2607*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
2608*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr) {
2609*38e8c45fSAndroid Build Coastguard Worker ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
2610*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
2611*38e8c45fSAndroid Build Coastguard Worker }
2612*38e8c45fSAndroid Build Coastguard Worker if (device->enabled) {
2613*38e8c45fSAndroid Build Coastguard Worker ALOGW("Duplicate call to %s, input device %" PRId32 " already enabled", __func__, deviceId);
2614*38e8c45fSAndroid Build Coastguard Worker return OK;
2615*38e8c45fSAndroid Build Coastguard Worker }
2616*38e8c45fSAndroid Build Coastguard Worker status_t result = device->enable();
2617*38e8c45fSAndroid Build Coastguard Worker if (result != OK) {
2618*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to enable device %" PRId32, deviceId);
2619*38e8c45fSAndroid Build Coastguard Worker return result;
2620*38e8c45fSAndroid Build Coastguard Worker }
2621*38e8c45fSAndroid Build Coastguard Worker
2622*38e8c45fSAndroid Build Coastguard Worker device->configureFd();
2623*38e8c45fSAndroid Build Coastguard Worker
2624*38e8c45fSAndroid Build Coastguard Worker return registerDeviceForEpollLocked(*device);
2625*38e8c45fSAndroid Build Coastguard Worker }
2626*38e8c45fSAndroid Build Coastguard Worker
disableDevice(int32_t deviceId)2627*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::disableDevice(int32_t deviceId) {
2628*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2629*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
2630*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr) {
2631*38e8c45fSAndroid Build Coastguard Worker ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
2632*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
2633*38e8c45fSAndroid Build Coastguard Worker }
2634*38e8c45fSAndroid Build Coastguard Worker if (!device->enabled) {
2635*38e8c45fSAndroid Build Coastguard Worker ALOGW("Duplicate call to %s, input device already disabled", __func__);
2636*38e8c45fSAndroid Build Coastguard Worker return OK;
2637*38e8c45fSAndroid Build Coastguard Worker }
2638*38e8c45fSAndroid Build Coastguard Worker unregisterDeviceFromEpollLocked(*device);
2639*38e8c45fSAndroid Build Coastguard Worker return device->disable();
2640*38e8c45fSAndroid Build Coastguard Worker }
2641*38e8c45fSAndroid Build Coastguard Worker
2642*38e8c45fSAndroid Build Coastguard Worker // TODO(b/274755573): Shift to uevent handling on native side and remove this method
2643*38e8c45fSAndroid Build Coastguard Worker // Currently using Java UEventObserver to trigger this which uses UEvent infrastructure that uses a
2644*38e8c45fSAndroid Build Coastguard Worker // NETLINK socket to observe UEvents. We can create similar infrastructure on Eventhub side to
2645*38e8c45fSAndroid Build Coastguard Worker // directly observe UEvents instead of triggering from Java side.
sysfsNodeChanged(const std::string & sysfsNodePath)2646*38e8c45fSAndroid Build Coastguard Worker void EventHub::sysfsNodeChanged(const std::string& sysfsNodePath) {
2647*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2648*38e8c45fSAndroid Build Coastguard Worker
2649*38e8c45fSAndroid Build Coastguard Worker // Check in opening devices
2650*38e8c45fSAndroid Build Coastguard Worker for (auto it = mOpeningDevices.begin(); it != mOpeningDevices.end(); it++) {
2651*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<Device>& device = *it;
2652*38e8c45fSAndroid Build Coastguard Worker if (device->associatedDevice &&
2653*38e8c45fSAndroid Build Coastguard Worker sysfsNodePath.find(device->associatedDevice->sysfsRootPath.string()) !=
2654*38e8c45fSAndroid Build Coastguard Worker std::string::npos &&
2655*38e8c45fSAndroid Build Coastguard Worker device->associatedDevice->isChanged()) {
2656*38e8c45fSAndroid Build Coastguard Worker it = mOpeningDevices.erase(it);
2657*38e8c45fSAndroid Build Coastguard Worker openDeviceLocked(device->path);
2658*38e8c45fSAndroid Build Coastguard Worker }
2659*38e8c45fSAndroid Build Coastguard Worker }
2660*38e8c45fSAndroid Build Coastguard Worker
2661*38e8c45fSAndroid Build Coastguard Worker // Check in already added device
2662*38e8c45fSAndroid Build Coastguard Worker std::vector<Device*> devicesToReopen;
2663*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, device] : mDevices) {
2664*38e8c45fSAndroid Build Coastguard Worker if (device->associatedDevice &&
2665*38e8c45fSAndroid Build Coastguard Worker sysfsNodePath.find(device->associatedDevice->sysfsRootPath.string()) !=
2666*38e8c45fSAndroid Build Coastguard Worker std::string::npos &&
2667*38e8c45fSAndroid Build Coastguard Worker device->associatedDevice->isChanged()) {
2668*38e8c45fSAndroid Build Coastguard Worker devicesToReopen.push_back(device.get());
2669*38e8c45fSAndroid Build Coastguard Worker }
2670*38e8c45fSAndroid Build Coastguard Worker }
2671*38e8c45fSAndroid Build Coastguard Worker for (const auto& device : devicesToReopen) {
2672*38e8c45fSAndroid Build Coastguard Worker closeDeviceLocked(*device);
2673*38e8c45fSAndroid Build Coastguard Worker openDeviceLocked(device->path);
2674*38e8c45fSAndroid Build Coastguard Worker }
2675*38e8c45fSAndroid Build Coastguard Worker devicesToReopen.clear();
2676*38e8c45fSAndroid Build Coastguard Worker }
2677*38e8c45fSAndroid Build Coastguard Worker
createVirtualKeyboardLocked()2678*38e8c45fSAndroid Build Coastguard Worker void EventHub::createVirtualKeyboardLocked() {
2679*38e8c45fSAndroid Build Coastguard Worker InputDeviceIdentifier identifier;
2680*38e8c45fSAndroid Build Coastguard Worker identifier.name = "Virtual";
2681*38e8c45fSAndroid Build Coastguard Worker identifier.uniqueId = "<virtual>";
2682*38e8c45fSAndroid Build Coastguard Worker assignDescriptorLocked(identifier);
2683*38e8c45fSAndroid Build Coastguard Worker
2684*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<Device> device =
2685*38e8c45fSAndroid Build Coastguard Worker std::make_unique<Device>(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>",
2686*38e8c45fSAndroid Build Coastguard Worker identifier, /*associatedDevice=*/nullptr);
2687*38e8c45fSAndroid Build Coastguard Worker device->classes = InputDeviceClass::KEYBOARD | InputDeviceClass::ALPHAKEY |
2688*38e8c45fSAndroid Build Coastguard Worker InputDeviceClass::DPAD | InputDeviceClass::VIRTUAL;
2689*38e8c45fSAndroid Build Coastguard Worker device->loadKeyMapLocked();
2690*38e8c45fSAndroid Build Coastguard Worker addDeviceLocked(std::move(device));
2691*38e8c45fSAndroid Build Coastguard Worker }
2692*38e8c45fSAndroid Build Coastguard Worker
addDeviceLocked(std::unique_ptr<Device> device)2693*38e8c45fSAndroid Build Coastguard Worker void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {
2694*38e8c45fSAndroid Build Coastguard Worker reportDeviceAddedForStatisticsLocked(device->identifier, device->classes);
2695*38e8c45fSAndroid Build Coastguard Worker mOpeningDevices.push_back(std::move(device));
2696*38e8c45fSAndroid Build Coastguard Worker }
2697*38e8c45fSAndroid Build Coastguard Worker
getNextControllerNumberLocked(const std::string & name)2698*38e8c45fSAndroid Build Coastguard Worker int32_t EventHub::getNextControllerNumberLocked(const std::string& name) {
2699*38e8c45fSAndroid Build Coastguard Worker if (mControllerNumbers.isFull()) {
2700*38e8c45fSAndroid Build Coastguard Worker ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
2701*38e8c45fSAndroid Build Coastguard Worker name.c_str());
2702*38e8c45fSAndroid Build Coastguard Worker return 0;
2703*38e8c45fSAndroid Build Coastguard Worker }
2704*38e8c45fSAndroid Build Coastguard Worker // Since the controller number 0 is reserved for non-controllers, translate all numbers up by
2705*38e8c45fSAndroid Build Coastguard Worker // one
2706*38e8c45fSAndroid Build Coastguard Worker return static_cast<int32_t>(mControllerNumbers.markFirstUnmarkedBit() + 1);
2707*38e8c45fSAndroid Build Coastguard Worker }
2708*38e8c45fSAndroid Build Coastguard Worker
releaseControllerNumberLocked(int32_t num)2709*38e8c45fSAndroid Build Coastguard Worker void EventHub::releaseControllerNumberLocked(int32_t num) {
2710*38e8c45fSAndroid Build Coastguard Worker if (num > 0) {
2711*38e8c45fSAndroid Build Coastguard Worker mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
2712*38e8c45fSAndroid Build Coastguard Worker }
2713*38e8c45fSAndroid Build Coastguard Worker }
2714*38e8c45fSAndroid Build Coastguard Worker
closeDeviceByPathLocked(const std::string & devicePath)2715*38e8c45fSAndroid Build Coastguard Worker void EventHub::closeDeviceByPathLocked(const std::string& devicePath) {
2716*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceByPathLocked(devicePath);
2717*38e8c45fSAndroid Build Coastguard Worker if (device != nullptr) {
2718*38e8c45fSAndroid Build Coastguard Worker closeDeviceLocked(*device);
2719*38e8c45fSAndroid Build Coastguard Worker return;
2720*38e8c45fSAndroid Build Coastguard Worker }
2721*38e8c45fSAndroid Build Coastguard Worker ALOGV("Remove device: %s not found, device may already have been removed.", devicePath.c_str());
2722*38e8c45fSAndroid Build Coastguard Worker }
2723*38e8c45fSAndroid Build Coastguard Worker
2724*38e8c45fSAndroid Build Coastguard Worker /**
2725*38e8c45fSAndroid Build Coastguard Worker * Find the video device by filename, and close it.
2726*38e8c45fSAndroid Build Coastguard Worker * The video device is closed by path during an inotify event, where we don't have the
2727*38e8c45fSAndroid Build Coastguard Worker * additional context about the video device fd, or the associated input device.
2728*38e8c45fSAndroid Build Coastguard Worker */
closeVideoDeviceByPathLocked(const std::string & devicePath)2729*38e8c45fSAndroid Build Coastguard Worker void EventHub::closeVideoDeviceByPathLocked(const std::string& devicePath) {
2730*38e8c45fSAndroid Build Coastguard Worker // A video device may be owned by an existing input device, or it may be stored in
2731*38e8c45fSAndroid Build Coastguard Worker // the mUnattachedVideoDevices queue. Check both locations.
2732*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, device] : mDevices) {
2733*38e8c45fSAndroid Build Coastguard Worker if (device->videoDevice && device->videoDevice->getPath() == devicePath) {
2734*38e8c45fSAndroid Build Coastguard Worker unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
2735*38e8c45fSAndroid Build Coastguard Worker device->videoDevice = nullptr;
2736*38e8c45fSAndroid Build Coastguard Worker return;
2737*38e8c45fSAndroid Build Coastguard Worker }
2738*38e8c45fSAndroid Build Coastguard Worker }
2739*38e8c45fSAndroid Build Coastguard Worker std::erase_if(mUnattachedVideoDevices,
2740*38e8c45fSAndroid Build Coastguard Worker [&devicePath](const std::unique_ptr<TouchVideoDevice>& videoDevice) {
2741*38e8c45fSAndroid Build Coastguard Worker return videoDevice->getPath() == devicePath;
2742*38e8c45fSAndroid Build Coastguard Worker });
2743*38e8c45fSAndroid Build Coastguard Worker }
2744*38e8c45fSAndroid Build Coastguard Worker
closeAllDevicesLocked()2745*38e8c45fSAndroid Build Coastguard Worker void EventHub::closeAllDevicesLocked() {
2746*38e8c45fSAndroid Build Coastguard Worker mUnattachedVideoDevices.clear();
2747*38e8c45fSAndroid Build Coastguard Worker while (!mDevices.empty()) {
2748*38e8c45fSAndroid Build Coastguard Worker closeDeviceLocked(*(mDevices.begin()->second));
2749*38e8c45fSAndroid Build Coastguard Worker }
2750*38e8c45fSAndroid Build Coastguard Worker }
2751*38e8c45fSAndroid Build Coastguard Worker
closeDeviceLocked(Device & device)2752*38e8c45fSAndroid Build Coastguard Worker void EventHub::closeDeviceLocked(Device& device) {
2753*38e8c45fSAndroid Build Coastguard Worker ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=%s", device.path.c_str(),
2754*38e8c45fSAndroid Build Coastguard Worker device.identifier.name.c_str(), device.id, device.fd, device.classes.string().c_str());
2755*38e8c45fSAndroid Build Coastguard Worker
2756*38e8c45fSAndroid Build Coastguard Worker if (device.id == mBuiltInKeyboardId) {
2757*38e8c45fSAndroid Build Coastguard Worker ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
2758*38e8c45fSAndroid Build Coastguard Worker device.path.c_str(), mBuiltInKeyboardId);
2759*38e8c45fSAndroid Build Coastguard Worker mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
2760*38e8c45fSAndroid Build Coastguard Worker }
2761*38e8c45fSAndroid Build Coastguard Worker
2762*38e8c45fSAndroid Build Coastguard Worker unregisterDeviceFromEpollLocked(device);
2763*38e8c45fSAndroid Build Coastguard Worker if (device.videoDevice) {
2764*38e8c45fSAndroid Build Coastguard Worker // This must be done after the video device is removed from epoll
2765*38e8c45fSAndroid Build Coastguard Worker mUnattachedVideoDevices.push_back(std::move(device.videoDevice));
2766*38e8c45fSAndroid Build Coastguard Worker }
2767*38e8c45fSAndroid Build Coastguard Worker
2768*38e8c45fSAndroid Build Coastguard Worker releaseControllerNumberLocked(device.controllerNumber);
2769*38e8c45fSAndroid Build Coastguard Worker device.controllerNumber = 0;
2770*38e8c45fSAndroid Build Coastguard Worker device.close();
2771*38e8c45fSAndroid Build Coastguard Worker mClosingDevices.push_back(std::move(mDevices[device.id]));
2772*38e8c45fSAndroid Build Coastguard Worker
2773*38e8c45fSAndroid Build Coastguard Worker mDevices.erase(device.id);
2774*38e8c45fSAndroid Build Coastguard Worker }
2775*38e8c45fSAndroid Build Coastguard Worker
readNotifyLocked()2776*38e8c45fSAndroid Build Coastguard Worker base::Result<void> EventHub::readNotifyLocked() {
2777*38e8c45fSAndroid Build Coastguard Worker static constexpr auto EVENT_SIZE = static_cast<ssize_t>(sizeof(inotify_event));
2778*38e8c45fSAndroid Build Coastguard Worker uint8_t eventBuffer[512];
2779*38e8c45fSAndroid Build Coastguard Worker ssize_t sizeRead;
2780*38e8c45fSAndroid Build Coastguard Worker
2781*38e8c45fSAndroid Build Coastguard Worker ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd);
2782*38e8c45fSAndroid Build Coastguard Worker do {
2783*38e8c45fSAndroid Build Coastguard Worker sizeRead = read(mINotifyFd, eventBuffer, sizeof(eventBuffer));
2784*38e8c45fSAndroid Build Coastguard Worker } while (sizeRead < 0 && errno == EINTR);
2785*38e8c45fSAndroid Build Coastguard Worker
2786*38e8c45fSAndroid Build Coastguard Worker if (sizeRead < EVENT_SIZE) return Errorf("could not get event, %s", strerror(errno));
2787*38e8c45fSAndroid Build Coastguard Worker
2788*38e8c45fSAndroid Build Coastguard Worker for (ssize_t eventPos = 0; sizeRead >= EVENT_SIZE;) {
2789*38e8c45fSAndroid Build Coastguard Worker const inotify_event* event;
2790*38e8c45fSAndroid Build Coastguard Worker event = (const inotify_event*)(eventBuffer + eventPos);
2791*38e8c45fSAndroid Build Coastguard Worker if (event->len == 0) continue;
2792*38e8c45fSAndroid Build Coastguard Worker
2793*38e8c45fSAndroid Build Coastguard Worker handleNotifyEventLocked(*event);
2794*38e8c45fSAndroid Build Coastguard Worker
2795*38e8c45fSAndroid Build Coastguard Worker const ssize_t eventSize = EVENT_SIZE + event->len;
2796*38e8c45fSAndroid Build Coastguard Worker sizeRead -= eventSize;
2797*38e8c45fSAndroid Build Coastguard Worker eventPos += eventSize;
2798*38e8c45fSAndroid Build Coastguard Worker }
2799*38e8c45fSAndroid Build Coastguard Worker return {};
2800*38e8c45fSAndroid Build Coastguard Worker }
2801*38e8c45fSAndroid Build Coastguard Worker
handleNotifyEventLocked(const inotify_event & event)2802*38e8c45fSAndroid Build Coastguard Worker void EventHub::handleNotifyEventLocked(const inotify_event& event) {
2803*38e8c45fSAndroid Build Coastguard Worker if (event.wd == mDeviceInputWd) {
2804*38e8c45fSAndroid Build Coastguard Worker std::string filename = std::string(DEVICE_INPUT_PATH) + "/" + event.name;
2805*38e8c45fSAndroid Build Coastguard Worker if (event.mask & IN_CREATE) {
2806*38e8c45fSAndroid Build Coastguard Worker openDeviceLocked(filename);
2807*38e8c45fSAndroid Build Coastguard Worker } else {
2808*38e8c45fSAndroid Build Coastguard Worker ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
2809*38e8c45fSAndroid Build Coastguard Worker closeDeviceByPathLocked(filename);
2810*38e8c45fSAndroid Build Coastguard Worker }
2811*38e8c45fSAndroid Build Coastguard Worker } else if (event.wd == mDeviceWd) {
2812*38e8c45fSAndroid Build Coastguard Worker if (isV4lTouchNode(event.name)) {
2813*38e8c45fSAndroid Build Coastguard Worker std::string filename = std::string(DEVICE_PATH) + "/" + event.name;
2814*38e8c45fSAndroid Build Coastguard Worker if (event.mask & IN_CREATE) {
2815*38e8c45fSAndroid Build Coastguard Worker openVideoDeviceLocked(filename);
2816*38e8c45fSAndroid Build Coastguard Worker } else {
2817*38e8c45fSAndroid Build Coastguard Worker ALOGI("Removing video device '%s' due to inotify event", filename.c_str());
2818*38e8c45fSAndroid Build Coastguard Worker closeVideoDeviceByPathLocked(filename);
2819*38e8c45fSAndroid Build Coastguard Worker }
2820*38e8c45fSAndroid Build Coastguard Worker } else if (strcmp(event.name, "input") == 0 && event.mask & IN_CREATE) {
2821*38e8c45fSAndroid Build Coastguard Worker addDeviceInputInotify();
2822*38e8c45fSAndroid Build Coastguard Worker }
2823*38e8c45fSAndroid Build Coastguard Worker } else {
2824*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Unexpected inotify event, wd = %i", event.wd);
2825*38e8c45fSAndroid Build Coastguard Worker }
2826*38e8c45fSAndroid Build Coastguard Worker }
2827*38e8c45fSAndroid Build Coastguard Worker
scanDirLocked(const std::string & dirname)2828*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::scanDirLocked(const std::string& dirname) {
2829*38e8c45fSAndroid Build Coastguard Worker for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
2830*38e8c45fSAndroid Build Coastguard Worker openDeviceLocked(entry.path());
2831*38e8c45fSAndroid Build Coastguard Worker }
2832*38e8c45fSAndroid Build Coastguard Worker return 0;
2833*38e8c45fSAndroid Build Coastguard Worker }
2834*38e8c45fSAndroid Build Coastguard Worker
2835*38e8c45fSAndroid Build Coastguard Worker /**
2836*38e8c45fSAndroid Build Coastguard Worker * Look for all dirname/v4l-touch* devices, and open them.
2837*38e8c45fSAndroid Build Coastguard Worker */
scanVideoDirLocked(const std::string & dirname)2838*38e8c45fSAndroid Build Coastguard Worker status_t EventHub::scanVideoDirLocked(const std::string& dirname) {
2839*38e8c45fSAndroid Build Coastguard Worker for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
2840*38e8c45fSAndroid Build Coastguard Worker if (isV4lTouchNode(entry.path())) {
2841*38e8c45fSAndroid Build Coastguard Worker ALOGI("Found touch video device %s", entry.path().c_str());
2842*38e8c45fSAndroid Build Coastguard Worker openVideoDeviceLocked(entry.path());
2843*38e8c45fSAndroid Build Coastguard Worker }
2844*38e8c45fSAndroid Build Coastguard Worker }
2845*38e8c45fSAndroid Build Coastguard Worker return OK;
2846*38e8c45fSAndroid Build Coastguard Worker }
2847*38e8c45fSAndroid Build Coastguard Worker
requestReopenDevices()2848*38e8c45fSAndroid Build Coastguard Worker void EventHub::requestReopenDevices() {
2849*38e8c45fSAndroid Build Coastguard Worker ALOGV("requestReopenDevices() called");
2850*38e8c45fSAndroid Build Coastguard Worker
2851*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2852*38e8c45fSAndroid Build Coastguard Worker mNeedToReopenDevices = true;
2853*38e8c45fSAndroid Build Coastguard Worker }
2854*38e8c45fSAndroid Build Coastguard Worker
setKernelWakeEnabled(int32_t deviceId,bool enabled)2855*38e8c45fSAndroid Build Coastguard Worker bool EventHub::setKernelWakeEnabled(int32_t deviceId, bool enabled) {
2856*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2857*38e8c45fSAndroid Build Coastguard Worker std::string enabledStr = enabled ? "enabled" : "disabled";
2858*38e8c45fSAndroid Build Coastguard Worker Device* device = getDeviceLocked(deviceId);
2859*38e8c45fSAndroid Build Coastguard Worker if (device == nullptr) {
2860*38e8c45fSAndroid Build Coastguard Worker ALOGE("Device Id %d does not exist for setting power wakeup", deviceId);
2861*38e8c45fSAndroid Build Coastguard Worker return false;
2862*38e8c45fSAndroid Build Coastguard Worker }
2863*38e8c45fSAndroid Build Coastguard Worker if (device->associatedDevice == nullptr) {
2864*38e8c45fSAndroid Build Coastguard Worker return false;
2865*38e8c45fSAndroid Build Coastguard Worker }
2866*38e8c45fSAndroid Build Coastguard Worker std::filesystem::path currentPath = device->associatedDevice->sysfsRootPath;
2867*38e8c45fSAndroid Build Coastguard Worker while (!currentPath.empty() && currentPath != "/") {
2868*38e8c45fSAndroid Build Coastguard Worker std::string nodePath = currentPath / "power/wakeup";
2869*38e8c45fSAndroid Build Coastguard Worker if (std::filesystem::exists(nodePath)) {
2870*38e8c45fSAndroid Build Coastguard Worker if (base::WriteStringToFile(enabledStr, nodePath)) {
2871*38e8c45fSAndroid Build Coastguard Worker return true;
2872*38e8c45fSAndroid Build Coastguard Worker
2873*38e8c45fSAndroid Build Coastguard Worker }
2874*38e8c45fSAndroid Build Coastguard Worker // No need to continue searching in parent directories as power/wakeup nodes
2875*38e8c45fSAndroid Build Coastguard Worker // higher up may control other subdevices.
2876*38e8c45fSAndroid Build Coastguard Worker ALOGW("Failed to set power/wakeup node at %s", nodePath.c_str());
2877*38e8c45fSAndroid Build Coastguard Worker return false;
2878*38e8c45fSAndroid Build Coastguard Worker }
2879*38e8c45fSAndroid Build Coastguard Worker currentPath = currentPath.parent_path();
2880*38e8c45fSAndroid Build Coastguard Worker }
2881*38e8c45fSAndroid Build Coastguard Worker return false;
2882*38e8c45fSAndroid Build Coastguard Worker }
2883*38e8c45fSAndroid Build Coastguard Worker
dump(std::string & dump) const2884*38e8c45fSAndroid Build Coastguard Worker void EventHub::dump(std::string& dump) const {
2885*38e8c45fSAndroid Build Coastguard Worker dump += "Event Hub State:\n";
2886*38e8c45fSAndroid Build Coastguard Worker
2887*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
2888*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2889*38e8c45fSAndroid Build Coastguard Worker
2890*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
2891*38e8c45fSAndroid Build Coastguard Worker
2892*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "Devices:\n";
2893*38e8c45fSAndroid Build Coastguard Worker
2894*38e8c45fSAndroid Build Coastguard Worker for (const auto& [id, device] : mDevices) {
2895*38e8c45fSAndroid Build Coastguard Worker if (mBuiltInKeyboardId == device->id) {
2896*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
2897*38e8c45fSAndroid Build Coastguard Worker device->id, device->identifier.name.c_str());
2898*38e8c45fSAndroid Build Coastguard Worker } else {
2899*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "%d: %s\n", device->id,
2900*38e8c45fSAndroid Build Coastguard Worker device->identifier.name.c_str());
2901*38e8c45fSAndroid Build Coastguard Worker }
2902*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "Classes: %s\n", device->classes.string().c_str());
2903*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "Path: %s\n", device->path.c_str());
2904*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "Enabled: %s\n", toString(device->enabled));
2905*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.c_str());
2906*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "Location: %s\n", device->identifier.location.c_str());
2907*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
2908*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.c_str());
2909*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
2910*38e8c45fSAndroid Build Coastguard Worker "product=0x%04x, version=0x%04x, bluetoothAddress=%s\n",
2911*38e8c45fSAndroid Build Coastguard Worker device->identifier.bus, device->identifier.vendor,
2912*38e8c45fSAndroid Build Coastguard Worker device->identifier.product, device->identifier.version,
2913*38e8c45fSAndroid Build Coastguard Worker toString(device->identifier.bluetoothAddress).c_str());
2914*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "KeyLayoutFile: %s\n",
2915*38e8c45fSAndroid Build Coastguard Worker device->keyMap.keyLayoutFile.c_str());
2916*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n",
2917*38e8c45fSAndroid Build Coastguard Worker device->keyMap.keyCharacterMapFile.c_str());
2918*38e8c45fSAndroid Build Coastguard Worker if (device->associatedDevice && device->associatedDevice->layoutInfo) {
2919*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "LanguageTag: %s\n",
2920*38e8c45fSAndroid Build Coastguard Worker device->associatedDevice->layoutInfo->languageTag.c_str());
2921*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "LayoutType: %s\n",
2922*38e8c45fSAndroid Build Coastguard Worker device->associatedDevice->layoutInfo->layoutType.c_str());
2923*38e8c45fSAndroid Build Coastguard Worker }
2924*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n",
2925*38e8c45fSAndroid Build Coastguard Worker device->configurationFile.c_str());
2926*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "VideoDevice: %s\n",
2927*38e8c45fSAndroid Build Coastguard Worker device->videoDevice ? device->videoDevice->dump().c_str()
2928*38e8c45fSAndroid Build Coastguard Worker : "<none>");
2929*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "SysfsDevicePath: %s\n",
2930*38e8c45fSAndroid Build Coastguard Worker device->associatedDevice
2931*38e8c45fSAndroid Build Coastguard Worker ? device->associatedDevice->sysfsRootPath.c_str()
2932*38e8c45fSAndroid Build Coastguard Worker : "<none>");
2933*38e8c45fSAndroid Build Coastguard Worker if (device->keyBitmask.any(0, KEY_MAX + 1)) {
2934*38e8c45fSAndroid Build Coastguard Worker const auto pressedKeys = device->keyState.dumpSetIndices(", ", [](int i) {
2935*38e8c45fSAndroid Build Coastguard Worker return InputEventLookup::getLinuxEvdevLabel(EV_KEY, i, 1).code;
2936*38e8c45fSAndroid Build Coastguard Worker });
2937*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "KeyState (pressed): %s\n", pressedKeys.c_str());
2938*38e8c45fSAndroid Build Coastguard Worker }
2939*38e8c45fSAndroid Build Coastguard Worker if (device->swBitmask.any(0, SW_MAX + 1)) {
2940*38e8c45fSAndroid Build Coastguard Worker const auto pressedSwitches = device->swState.dumpSetIndices(", ", [](int i) {
2941*38e8c45fSAndroid Build Coastguard Worker return InputEventLookup::getLinuxEvdevLabel(EV_SW, i, 1).code;
2942*38e8c45fSAndroid Build Coastguard Worker });
2943*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "SwState (pressed): %s\n", pressedSwitches.c_str());
2944*38e8c45fSAndroid Build Coastguard Worker }
2945*38e8c45fSAndroid Build Coastguard Worker if (!device->absState.empty()) {
2946*38e8c45fSAndroid Build Coastguard Worker std::string axisValues;
2947*38e8c45fSAndroid Build Coastguard Worker for (const auto& [axis, state] : device->absState) {
2948*38e8c45fSAndroid Build Coastguard Worker if (!axisValues.empty()) {
2949*38e8c45fSAndroid Build Coastguard Worker axisValues += ", ";
2950*38e8c45fSAndroid Build Coastguard Worker }
2951*38e8c45fSAndroid Build Coastguard Worker axisValues += StringPrintf("%s=%d",
2952*38e8c45fSAndroid Build Coastguard Worker InputEventLookup::getLinuxEvdevLabel(EV_ABS, axis, 0)
2953*38e8c45fSAndroid Build Coastguard Worker .code.c_str(),
2954*38e8c45fSAndroid Build Coastguard Worker state.value);
2955*38e8c45fSAndroid Build Coastguard Worker }
2956*38e8c45fSAndroid Build Coastguard Worker dump += INDENT3 "AbsState: " + axisValues + "\n";
2957*38e8c45fSAndroid Build Coastguard Worker }
2958*38e8c45fSAndroid Build Coastguard Worker }
2959*38e8c45fSAndroid Build Coastguard Worker
2960*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "Unattached video devices:\n";
2961*38e8c45fSAndroid Build Coastguard Worker for (const std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) {
2962*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2 + videoDevice->dump() + "\n";
2963*38e8c45fSAndroid Build Coastguard Worker }
2964*38e8c45fSAndroid Build Coastguard Worker if (mUnattachedVideoDevices.empty()) {
2965*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2 "<none>\n";
2966*38e8c45fSAndroid Build Coastguard Worker }
2967*38e8c45fSAndroid Build Coastguard Worker } // release lock
2968*38e8c45fSAndroid Build Coastguard Worker }
2969*38e8c45fSAndroid Build Coastguard Worker
monitor() const2970*38e8c45fSAndroid Build Coastguard Worker void EventHub::monitor() const {
2971*38e8c45fSAndroid Build Coastguard Worker // Acquire and release the lock to ensure that the event hub has not deadlocked.
2972*38e8c45fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mLock);
2973*38e8c45fSAndroid Build Coastguard Worker }
2974*38e8c45fSAndroid Build Coastguard Worker
dump() const2975*38e8c45fSAndroid Build Coastguard Worker std::string EventHub::AssociatedDevice::dump() const {
2976*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("path=%s, numBatteries=%zu, numLight=%zu", sysfsRootPath.c_str(),
2977*38e8c45fSAndroid Build Coastguard Worker batteryInfos.size(), lightInfos.size());
2978*38e8c45fSAndroid Build Coastguard Worker }
2979*38e8c45fSAndroid Build Coastguard Worker
2980*38e8c45fSAndroid Build Coastguard Worker } // namespace android
2981