InputReader线程启动后会调用EventHub的getEvents()来获取元事件RawEvent。
arduino
复制代码
// frameworks/native/services/inputflinger/reader/InputReader.cpp
status_t InputReader::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
void InputReader::loopOnce() {
...
std::vector<RawEvent> events = mEventHub->getEvents(timeoutMillis);
...
}
在第一次调用getEvents或者需要重新打开设备的时候,会调用scanDevicesLocked()扫描并添加设备。mNeedToScanDevices的默认设置为true。
ini
复制代码
// frameworks/native/services/inputflinger/reader/EventHub.cpp
std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
...
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// Reopen input devices if needed.
if (mNeedToReopenDevices) {
mNeedToReopenDevices = false;
ALOGI("Reopening all input devices due to a configuration change.");
closeAllDevicesLocked();
mNeedToScanDevices = true;
break; // return to the caller before we actually rescan
}
...
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
}
...
}
这里会扫描/dev/input
目录下所有设备节点。在最后createVirtualKeyboardLocked()
会创建一个deviceId为-1
的虚拟设备,该设备用来标识应用向系统注入的事件。
c
复制代码
static const char* DEVICE_INPUT_PATH = "/dev/input";
...
void EventHub::scanDevicesLocked() {
status_t result;
std::error_code errorCode;
if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
result = scanDirLocked(DEVICE_INPUT_PATH);
if (result < 0) {
ALOGE("scan dir failed for %s", DEVICE_INPUT_PATH);
}
} else {
if (errorCode) {
ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
errorCode.message().c_str());
}
}
if (isV4lScanningEnabled()) {
result = scanVideoDirLocked(DEVICE_PATH);
if (result != OK) {
ALOGE("scan video dir failed for %s", DEVICE_PATH);
}
}
if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
createVirtualKeyboardLocked();
}
}
status_t EventHub::scanDirLocked(const std::string& dirname) {
for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
openDeviceLocked(entry.path());
}
return 0;
}
openDeviceLocked()
负责从设备节点中读取设备的配置信息、确定设备上报事件的类型、加载KEYBOARD和JOYSTICK以及SENSOR类型设备的.kl
按键布局文件和.kcm
按键字符映射文件。
rust
复制代码
void EventHub::openDeviceLocked(const std::string& devicePath) {
// 如果设备已经被注册,直接返回
for (const auto& [deviceId, device] : mDevices) {
if (device->path == devicePath) {
return; // device was already registered
}
}
char buffer[80];
ALOGV("Opening device: %s", devicePath.c_str());
int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
if (fd < 0) {
ALOGE("could not open %s, %s\n", devicePath.c_str(), strerror(errno));
return;
}
InputDeviceIdentifier identifier;
// 获取设备名称
if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name = buffer;
}
// 检查设备是否被添加到排除列表
for (size_t i = 0; i < mExcludedDevices.size(); i++) {
const std::string& item = mExcludedDevices[i];
if (identifier.name == item) {
ALOGI("ignoring event id %s driver %s\n", devicePath.c_str(), item.c_str());
close(fd);
return;
}
}
// 获取设备驱动版本
int driverVersion;
if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
ALOGE("could not get driver version for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return;
}
// 获取设备标识,包括有总线、厂商、产品以及版本。
struct input_id inputId;
if (ioctl(fd, EVIOCGID, &inputId)) {
ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return;
}
identifier.bus = inputId.bustype;
identifier.product = inputId.product;
identifier.vendor = inputId.vendor;
identifier.version = inputId.version;
// 获取设备的物理位置
if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
// fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.location = buffer;
}
// 获取设备的唯一ID
if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
// fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.uniqueId = buffer;
}
// 如果使用的蓝牙总线,获取输入设备的蓝牙地址
if (identifier.bus == BUS_BLUETOOTH &&
std::regex_match(identifier.uniqueId,
std::regex("^[A-Fa-f0-9]{2}(?::[A-Fa-f0-9]{2}){5}$"))) {
identifier.bluetoothAddress = identifier.uniqueId;
// The Bluetooth stack requires alphabetic characters to be uppercase in a valid address.
for (auto& c : *identifier.bluetoothAddress) {
c = ::toupper(c);
}
}
// Fill in the descriptor.
assignDescriptorLocked(identifier);
//创建Device对象
int32_t deviceId = mNextDeviceId++;
std::unique_ptr<Device> device =
std::make_unique<Device>(fd, deviceId, devicePath, identifier,
obtainAssociatedDeviceLocked(devicePath));
ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
ALOGV(" bus: %04x\n"
" vendor %04x\n"
" product %04x\n"
" version %04x\n",
identifier.bus, identifier.vendor, identifier.product, identifier.version);
ALOGV(" name: "%s"\n", identifier.name.c_str());
ALOGV(" location: "%s"\n", identifier.location.c_str());
ALOGV(" unique id: "%s"\n", identifier.uniqueId.c_str());
ALOGV(" descriptor: "%s"\n", identifier.descriptor.c_str());
ALOGV(" driver: v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,
driverVersion & 0xff);
//加载设备的配置文件
device->loadConfigurationLocked();
// 查询一个输入设备(如键盘、鼠标、触摸屏等)支持的事件类型
// 按键事件类型
device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
// 绝对坐标(ABS)事件类型
device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask);
// 相对坐标(REL)事件类型
device->readDeviceBitMask(EVIOCGBIT(EV_REL, 0), device->relBitmask);
// 开关(SW)事件类型
device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask);
// LED状态(LED)事件类型
device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask);
// 力反馈(FF)事件类型, 比如游戏手柄的震动反馈
device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask);
// 其他杂项(MSC)事件类型
device->readDeviceBitMask(EVIOCGBIT(EV_MSC, 0), device->mscBitmask);
device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask);
// 查看这是不是一个带按键的设备,比如键盘、游戏手柄、游戏杆和太有按键的触摸笔
bool haveKeyboardKeys =
device->keyBitmask.any(0, BTN_MISC) || device->keyBitmask.any(BTN_WHEEL, KEY_MAX + 1);
bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) ||
device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI);
bool haveStylusButtons = device->keyBitmask.test(BTN_STYLUS) ||
device->keyBitmask.test(BTN_STYLUS2) || device->keyBitmask.test(BTN_STYLUS3);
if (haveKeyboardKeys || haveGamepadButtons || haveStylusButtons) {
device->classes |= InputDeviceClass::KEYBOARD;
}
// 查看是不是带光标的设备,比如鼠标
if (device->keyBitmask.test(BTN_MOUSE) && device->relBitmask.test(REL_X) &&
device->relBitmask.test(REL_Y)) {
device->classes |= InputDeviceClass::CURSOR;
}
// 查看设备是否专门配置为特定类型。
if (device->configuration) {
std::string deviceType = device->configuration->getString("device.type").value_or("");
if (deviceType == "rotaryEncoder") {
device->classes |= InputDeviceClass::ROTARY_ENCODER;
} else if (deviceType == "externalStylus") {
device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
}
}
// 看看这是不是触摸板。
// Is this a new modern multi-touch driver?
if (device->absBitmask.test(ABS_MT_POSITION_X) && device->absBitmask.test(ABS_MT_POSITION_Y)) {
// Some joysticks such as the PS3 controller report axes that conflict
// with the ABS_MT range. Try to confirm that the device really is
// a touch screen.
if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) {
device->classes |= (InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT);
if (device->propBitmask.test(INPUT_PROP_POINTER) &&
!device->keyBitmask.any(BTN_TOOL_PEN, BTN_TOOL_FINGER) && !haveStylusButtons) {
device->classes |= InputDeviceClass::TOUCHPAD;
}
}
// Is this an old style single-touch driver?
} else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) &&
device->absBitmask.test(ABS_Y)) {
device->classes |= InputDeviceClass::TOUCH;
// Is this a stylus that reports contact/pressure independently of touch coordinates?
} else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) &&
!device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) {
device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
}
// 查看此设备是否为操纵杆。
// Assumes that joysticks always have gamepad buttons in order to distinguish them
// from other devices such as accelerometers that also have absolute axes.
if (haveGamepadButtons) {
auto assumedClasses = device->classes | InputDeviceClass::JOYSTICK;
for (int i = 0; i <= ABS_MAX; i++) {
if (device->absBitmask.test(i) &&
(getAbsAxisUsage(i, assumedClasses).test(InputDeviceClass::JOYSTICK))) {
device->classes = assumedClasses;
break;
}
}
}
// 检查此设备是否为加速度计。
if (device->propBitmask.test(INPUT_PROP_ACCELEROMETER)) {
device->classes |= InputDeviceClass::SENSOR;
}
// 检查此设备是否有开关。
for (int i = 0; i <= SW_MAX; i++) {
if (device->swBitmask.test(i)) {
device->classes |= InputDeviceClass::SWITCH;
break;
}
}
// 检查此设备是否支持振动器。
if (device->ffBitmask.test(FF_RUMBLE)) {
device->classes |= InputDeviceClass::VIBRATOR;
}
// 配置虚拟按键
if ((device->classes.test(InputDeviceClass::TOUCH))) {
// Load the virtual keys for the touch screen, if any.
// We do this now so that we can make sure to load the keymap if necessary.
bool success = device->loadVirtualKeyMapLocked();
if (success) {
device->classes |= InputDeviceClass::KEYBOARD;
}
}
// 加载键映射。我们也需要对操纵杆执行此操作,因为按键布局可以指定轴,而对于传感器也需要这样做,因为按键布局可以指定轴到传感器数据映射。
status_t keyMapStatus = NAME_NOT_FOUND;
if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK |
InputDeviceClass::SENSOR)) {
// Load the keymap for the device.
keyMapStatus = device->loadKeyMapLocked();
}
// Configure the keyboard, gamepad or virtual keyboard.
if (device->classes.test(InputDeviceClass::KEYBOARD)) {
// Register the keyboard as a built-in keyboard if it is eligible.
if (!keyMapStatus && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD &&
isEligibleBuiltInKeyboard(device->identifier, device->configuration.get(),
&device->keyMap)) {
mBuiltInKeyboardId = device->id;
}
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
if (device->hasKeycodeLocked(AKEYCODE_Q)) {
device->classes |= InputDeviceClass::ALPHAKEY;
}
// See if this device has a D-pad.
if (std::all_of(DPAD_REQUIRED_KEYCODES.begin(), DPAD_REQUIRED_KEYCODES.end(),
[&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) {
device->classes |= InputDeviceClass::DPAD;
}
// See if this device has a gamepad.
if (std::any_of(GAMEPAD_KEYCODES.begin(), GAMEPAD_KEYCODES.end(),
[&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) {
device->classes |= InputDeviceClass::GAMEPAD;
}
// See if this device has any stylus buttons that we would want to fuse with touch data.
if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT) &&
!device->classes.any(InputDeviceClass::ALPHAKEY) &&
std::any_of(STYLUS_BUTTON_KEYCODES.begin(), STYLUS_BUTTON_KEYCODES.end(),
[&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) {
device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
}
}
// 如果设备未被识别为我们处理的设备,请不要对其进行监控
if (device->classes == ftl::Flags<InputDeviceClass>(0)) {
ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),
device->identifier.name.c_str());
return;
}
// 查看设备是否带电池
if (device->associatedDevice && !device->associatedDevice->batteryInfos.empty()) {
device->classes |= InputDeviceClass::BATTERY;
}
// 查看设备是否带灯光
if (device->associatedDevice && !device->associatedDevice->lightInfos.empty()) {
device->classes |= InputDeviceClass::LIGHT;
}
// 确定设备是否具有麦克风。
if (device->deviceHasMicLocked()) {
device->classes |= InputDeviceClass::MIC;
}
// 确定设备是外部设备还是内部设备。
if (device->isExternalDeviceLocked()) {
device->classes |= InputDeviceClass::EXTERNAL;
}
if (device->classes.any(InputDeviceClass::JOYSTICK | InputDeviceClass::DPAD) &&
device->classes.test(InputDeviceClass::GAMEPAD)) {
device->controllerNumber = getNextControllerNumberLocked(device->identifier.name);
device->setLedForControllerLocked();
}
// 将设备注册到epoll
if (registerDeviceForEpollLocked(*device) != OK) {
return;
}
device->configureFd();
ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=%s, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(),
device->classes.string().c_str(), device->configurationFile.c_str(),
device->keyMap.keyLayoutFile.c_str(), device->keyMap.keyCharacterMapFile.c_str(),
toString(mBuiltInKeyboardId == deviceId));
addDeviceLocked(std::move(device));
}
void EventHub::Device::loadConfigurationLocked() {
configurationFile =
getInputDeviceConfigurationFilePathByDeviceIdentifier(identifier,
InputDeviceConfigurationFileType::
CONFIGURATION);
if (configurationFile.empty()) {
ALOGD("No input device configuration file found for device '%s'.", identifier.name.c_str());
} else {
android::base::Result<std::unique_ptr<PropertyMap>> propertyMap =
PropertyMap::load(configurationFile.c_str());
if (!propertyMap.ok()) {
ALOGE("Error loading input device configuration file for device '%s'. "
"Using default configuration.",
identifier.name.c_str());
} else {
configuration = std::move(*propertyMap);
}
}
}
加载配置文件的时候,先尝试vendor product version
再尝试vendor product
最后尝试device name
。
c
复制代码
// frameworks/native/libs/input/InputDevice.cpp
std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
const InputDeviceIdentifier& deviceIdentifier, InputDeviceConfigurationFileType type,
const char* suffix) {
if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
if (deviceIdentifier.version != 0) {
// Try vendor product version.
std::string versionPath =
getInputDeviceConfigurationFilePathByName(StringPrintf("Vendor_%04x_Product_%"
"04x_Version_%04x%s",
deviceIdentifier.vendor,
deviceIdentifier.product,
deviceIdentifier.version,
suffix),
type);
if (!versionPath.empty()) {
return versionPath;
}
}
// Try vendor product.
std::string productPath =
getInputDeviceConfigurationFilePathByName(StringPrintf("Vendor_%04x_Product_%04x%s",
deviceIdentifier.vendor,
deviceIdentifier.product,
suffix),
type);
if (!productPath.empty()) {
return productPath;
}
}
// Try device name.
return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName() + suffix,
type);
}
std::string getInputDeviceConfigurationFilePathByName(
const std::string& name, InputDeviceConfigurationFileType type) {
// Search system repository.
std::string path;
// Treblized input device config files will be located /product/usr, /system_ext/usr,
// /odm/usr or /vendor/usr.
std::vector<std::string> pathPrefixes{
"/product/usr/",
"/system_ext/usr/",
"/odm/usr/",
"/vendor/usr/",
};
// These files may also be in the APEX pointed by input_device.config_file.apex sysprop.
if (auto apex = GetProperty("input_device.config_file.apex", ""); !apex.empty()) {
pathPrefixes.push_back("/apex/" + apex + "/etc/usr/");
}
// ANDROID_ROOT may not be set on host
if (auto android_root = getenv("ANDROID_ROOT"); android_root != nullptr) {
pathPrefixes.push_back(std::string(android_root) + "/usr/");
}
for (const auto& prefix : pathPrefixes) {
path = prefix;
appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
ALOGD("Probing for system provided input device configuration file: path='%s'",
path.c_str());
#endif
if (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBE
ALOGD("Found");
#endif
return path;
}
}
// Search user repository.
// TODO Should only look here if not in safe mode.
path = "";
char *androidData = getenv("ANDROID_DATA");
if (androidData != nullptr) {
path += androidData;
}
path += "/system/devices/";
appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
ALOGD("Probing for system user input device configuration file: path='%s'", path.c_str());
#endif
if (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBE
ALOGD("Found");
#endif
return path;
}
// Not found.
#if DEBUG_PROBE
ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
name.c_str(), type);
#endif
return "";
}
ruby
复制代码
// frameworks/native/services/inputflinger/reader/EventHub.cpp
status_t EventHub::Device::loadKeyMapLocked() {
return keyMap.load(identifier, configuration.get());
}
先从设备的配置中映射,没有找到的话再从Generic中映射。
c
复制代码
// frameworks/native/libs/input/Keyboard.cpp
status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier,
const PropertyMap* deviceConfiguration) {
// Use the configured key layout if available.
if (deviceConfiguration) {
std::optional<std::string> keyLayoutName =
deviceConfiguration->getString("keyboard.layout");
if (keyLayoutName.has_value()) {
status_t status = loadKeyLayout(deviceIdentifier, *keyLayoutName);
if (status == NAME_NOT_FOUND) {
ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
"it was not found.",
deviceIdentifier.name.c_str(), keyLayoutName->c_str());
}
}
std::optional<std::string> keyCharacterMapName =
deviceConfiguration->getString("keyboard.characterMap");
if (keyCharacterMapName.has_value()) {
status_t status = loadKeyCharacterMap(deviceIdentifier, *keyCharacterMapName);
if (status == NAME_NOT_FOUND) {
ALOGE("Configuration for keyboard device '%s' requested keyboard character "
"map '%s' but it was not found.",
deviceIdentifier.name.c_str(), keyCharacterMapName->c_str());
}
}
if (isComplete()) {
return OK;
}
}
// Try searching by device identifier.
if (probeKeyMap(deviceIdentifier, "")) {
return OK;
}
// Fall back on the Generic key map.
// TODO Apply some additional heuristics here to figure out what kind of
// generic key map to use (US English, etc.) for typical external keyboards.
if (probeKeyMap(deviceIdentifier, "Generic")) {
return OK;
}
// Try the Virtual key map as a last resort.
if (probeKeyMap(deviceIdentifier, "Virtual")) {
return OK;
}
// Give up!
ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
deviceIdentifier.name.c_str());
return NAME_NOT_FOUND;
}
扫描完设备节点后,会遍历mOpeningDevices,把DEVICE_ADDED
事件添加到evnets,最后返回给InputReader.
c
复制代码
// frameworks/native/services/inputflinger/reader/EventHub.cpp
void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {
reportDeviceAddedForStatisticsLocked(device->identifier, device->classes);
mOpeningDevices.push_back(std::move(device));
}
std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
...
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
...
while (!mOpeningDevices.empty()) {
std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
mOpeningDevices.pop_back();
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
events.push_back({
.when = now,
.deviceId = deviceId,
.type = DEVICE_ADDED,
});
// Try to find a matching video device by comparing device names
for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
it++) {
std::unique_ptr<TouchVideoDevice>& videoDevice = *it;
if (tryAddVideoDeviceLocked(*device, videoDevice)) {
// videoDevice was transferred to 'device'
it = mUnattachedVideoDevices.erase(it);
break;
}
}
auto [dev_it, inserted] = mDevices.insert_or_assign(device->id, std::move(device));
if (!inserted) {
ALOGW("Device id %d exists, replaced.", device->id);
}
mNeedToSendFinishedDeviceScan = true;
if (events.size() == EVENT_BUFFER_SIZE) {
break;
}
}
...
}
...
return events;
}
InputReader获取到事件后,会调用processEventsLocked()对元事件进行处理。processEventsLocked()中判断元事件类型为DEVICE_ADDED
,然后回调用addDeviceLocked()
rust
复制代码
// frameworks/native/services/inputflinger/reader/InputReader.cpp
void InputReader::loopOnce() {
...
std::vector<RawEvent> events = mEventHub->getEvents(timeoutMillis);
{ // acquire lock
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all();
if (!events.empty()) {
mPendingArgs += processEventsLocked(events.data(), events.size());
}
...
}
...
}
std::list<NotifyArgs> InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
std::list<NotifyArgs> out;
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||
rawEvent[batchSize].deviceId != deviceId) {
break;
}
batchSize += 1;
}
if (debugRawEvents()) {
ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
}
out += processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
return out;
}
addDeviceLocked()中创建了InputDevice,并调用device->configure()
进行配置。最后添加到了mDevices。
scss
复制代码
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
if (mDevices.find(eventHubId) != mDevices.end()) {
ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
return;
}
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
std::shared_ptr<InputDevice> device = createDeviceLocked(when, eventHubId, identifier);
mPendingArgs += device->configure(when, mConfig, /*changes=*/{});
mPendingArgs += device->reset(when);
if (device->isIgnored()) {
ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
"(ignored non-input device)",
device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str());
} else {
ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s',sources=%s",
device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str(),
inputEventSourceToString(device->getSources()).c_str());
}
mDevices.emplace(eventHubId, device);
// Add device to device to EventHub ids map.
const auto mapIt = mDeviceToEventHubIdsMap.find(device);
if (mapIt == mDeviceToEventHubIdsMap.end()) {
std::vector<int32_t> ids = {eventHubId};
mDeviceToEventHubIdsMap.emplace(device, ids);
} else {
mapIt->second.push_back(eventHubId);
}
bumpGenerationLocked();
if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) {
notifyExternalStylusPresenceChangedLocked();
}
// Sensor input device is noisy, to save power disable it by default.
// Input device is classified as SENSOR when any sub device is a SENSOR device, check Eventhub
// device class to disable SENSOR sub device only.
if (mEventHub->getDeviceClasses(eventHubId).test(InputDeviceClass::SENSOR)) {
mEventHub->disableDevice(eventHubId);
}
}
std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier) {
auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
const InputDeviceIdentifier identifier2 =
devicePair.second->getDeviceInfo().getIdentifier();
return isSubDevice(identifier, identifier2);
});
std::shared_ptr<InputDevice> device;
if (deviceIt != mDevices.end()) {
device = deviceIt->second;
} else {
int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
identifier);
}
// 将EventHubDevice添加到InputDevice中
mPendingArgs += device->addEventHubDevice(when, eventHubId, mConfig);
return device;
}