主要流程涉及以下文件
kernel/msm-4.19/drivers/input/keyboard/gpio_keys.c
kernel/msm-4.19/drivers/input/input.c
kernel/msm-4.19/drivers/input/evdev.c
kernel/msm-4.19/drivers/input/input-compat.c
有按键动作时,根据 dtsi 中配置 code 上报事件。在 gpio_keys.c 中进行处理,最终在 gpio_keys_gpio_report_event 函数中调用 input.c 上报事件。大概流程分为两步。
第一步:获取event事件保存到队列中
input.c:input_event -> input_handle_event -> input_pass_values -> input_to_handler(此函数中调用 handler->events ,handler 定义在 evdev.c 中,events 对应函数 evdev_events)
evdev.c:evdev_events -> evdev_pass_values -> __pass_event (将event事件添加到缓存队列 client->buffer)
第二步:通过循环读取队列中event事件保存到用户内存
evdev.c:evdev_read -> input_event_to_user
input-compat.c:input_event_to_user -> copy_to_user
主要流程涉及以下文件
frameworks/native/services/inputflinger/reader/EventHub.cpp
frameworks/native/services/inputflinger/reader/InputReader.cpp
frameworks/native/services/inputflinger/reader/InputDevice.cpp
frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
frameworks/native/libs/input/KeyLayoutMap.cpp
frameworks/native/libs/input/Keyboard.cpp
上层获取按键事件流程大致如下:
InputReader.cpp:loopOnce -> processEventsLocked -> processEventsForDeviceLocked (调用 device->process)
InputDevice.cpp:process (调用 mapper.process)
KeyboardInputMapper.cpp:process -> processKey(调用 getListener()->notifyKey)
InputDispatcher.cpp:notifyKey(调用 mPolicy->interceptKeyBeforeQueueing 传递到java层)
按键键值有两个,底层驱动键值和上层应用使用键值,这个对应关系定义在 kl 文件中,kl 文件可以有多个,例如 Generic.kl fts_ts.kl 等,默认系统中路径在 /system/usr/keylayout/ 目录下。
#kl 文件内容格式
#key 驱动键值 上层键值
key 113 VOLUME_MUTE
key 114 VOLUME_DOWN
key 115 VOLUME_UP
key 116 POWER
系统开机时,会根据 frameworks/native/libs/input/InputDevice.cpp 规则加载 kl 文件。加载 kl 文件函数在 KeyLayoutMap.cpp 中,将所有文件按照 kl 名称类型加到 KeyedVector
KeyLayoutMap.cpp:load -> parse -> parseKey
//parseKey 代码段
KeyedVector& map = mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
... ...
#if DEBUG_PARSER
ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.",
mapUsage ? "usage" : "scan code", code, keyCode, flags);
#endif
Key key;
key.keyCode = keyCode;
key.flags = flags;
map.add(code, key);
return NO_ERROR;
parseKey 函数 KeyedVector
[KeyboardInputMapper.cpp]processKey(getDeviceContext().mapKey) -> [InputDevice.h]mapKey -> [EventHub.cpp]mapKey -> [KeyLayoutMap.cpp]mapKey -> getKey
const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const {
if (usageCode) {
ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
if (index >= 0) {
return &mKeysByUsageCode.valueAt(index);
}
}
if (scanCode) {
ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
if (index >= 0) {
return &mKeysByScanCode.valueAt(index);
}
}
return nullptr;
}
这里面的 mKeysByScanCode 就是上面解析 kl 保存的键值map,通过 scanCode(驱动键值)获取下标,通过下标获取 Key(上面说过的,保存上层键值的)。最后 KeyboardInputMapper.cpp processKey 后续流程把包含 Key 上报到 java 层使用。