ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于 Linux 内核官方文档的 Android Input 子系统 Bug 定位指南

基于 Linux 内核官方文档的 Android Input 子系统 Bug 定位指南 基于 Linux 内核官方文档的 Android Input 子系统 Bug 定位指南本文所有协议级结论均来自内核官方文档docs.kernel.org/input/与内核头文件所有工具行为均以 AOSP 源码为准。文末附参考清单。0. 输入事件全链路先想清楚再动手Android 上的一次触摸/按键经过以下层级触摸 IC / 按键硬件 │ ▼ I2C / SPI / USB (HID) / GPIO 设备驱动 (drivers/input/*) │ ▼ input_report_*() / input_sync() input core (drivers/input/input.c) │ ▼ evdev handler /dev/input/eventX ←—— 内核层与用户空间的边界 │ ▼ Android EventHub → InputReader → InputDispatcher │ ▼ App (onTouchEvent / onKeyDown)分层定位的第一原则在内核边界/dev/input/eventX上用工具观测。边界以下getevent 能看到的事件流有问题 → 驱动 / input core / 硬件固件边界以下正常、现象仍异常 → Android Framework / App 层官方文档明确evdev 是通用输入事件接口是用户空间消费输入的首选方式事件码在所有架构上相同且与硬件无关。1. 必备基础知识官方文档校准版1.1 事件结构 input_eventstructinput_event{structtimevaltime;/* 事件时间戳 */unsignedshorttype;/* 事件类型如 EV_KEY / EV_ABS */unsignedshortcode;/* 事件码如 KEY_BACKSPACE / REL_X */intvalue;/* 事件的值 */};value 语义EV_KEY0 释放1 按下2 自动连发内核生成前提是驱动设置了 EV_REP。1.2 常用事件类型与码值源自 include/uapi/linux/input-event-codes.htype (hex)名称说明0x00EV_SYN同步事件codeSYN_REPORT(0) 表示一帧事件结束0x01EV_KEY按键/按钮触摸屏的 BTN_TOUCH(330) 属于此类0x02EV_REL相对坐标鼠标0x03EV_ABS绝对坐标触摸屏、摇杆0x14EV_REP自动连发input core 处理多点触控MT专用码值code (hex)名称十进制说明0x2fABS_MT_SLOT47当前更新的 slotType B 协议0x30ABS_MT_TOUCH_MAJOR48接触面椭圆长轴0x35ABS_MT_POSITION_X53触点中心 X0x36ABS_MT_POSITION_Y54触点中心 Y0x39ABS_MT_TRACKING_ID57触点生命周期唯一 ID-1 slot 释放0x3aABS_MT_PRESSURE58压力resolution0 时为任意单位非 0 时为 units/gram1.3 多点触控 Type B 协议slot 协议要点Android 手机触摸屏全部走 Type B官方明确 Type A 已废弃所有内核驱动已转为 Type B每个触点包以ABS_MT_SLOT n开始帧尾必须SYN_REPORTinput_sync()。ABS_MT_TRACKING_ID非负值 有效触点首次出现视为新建-1 触点销毁释放 slot。触点身份改变时应 invalidate slot改 TRACKING_ID 为 -1slot 不得张冠李戴。驱动只应声明硬件真实可上报的 slot 数硬件跟踪多于可上报触点时用 BTN_TOOL_*TAP 系列事件告知用户空间实际跟踪总数——用户空间可据此检测声明 slot 数 实际跟踪数的不一致。ABS_MT_SLOT 的 min 必须为 0。官方给出的最小合法事件序列两指按下ABS_MT_SLOT 0 ABS_MT_TRACKING_ID 45 ABS_MT_POSITION_X x[0] ABS_MT_POSITION_Y y[0] ABS_MT_SLOT 1 ABS_MT_TRACKING_ID 46 ABS_MT_POSITION_X x[1] ABS_MT_POSITION_Y y[1] SYN_REPORT抬起 slot 0 中的手指ABS_MT_TRACKING_ID -1 /* 当前 slot 未变则省略 ABS_MT_SLOT */ SYN_REPORT1.4 input core 的隐式行为排查时的隐形坑重复值过滤input_report_* 系列函数会自行丢弃与上次相同的值驱动无需也不应自行去重。EV_ABS 噪声过滤absfuzz/absflatinput_set_abs_params(dev, axis, min, max, fuzz, flat)会导致小幅变化被 input core 直接吞掉fuzz 设过大表现为小滑动没反应。坐标范围约束absmin/absmax 应设置正确且设备必须总能达到 min/max 值官方原文要求否则边缘区域报点会被 clamp。按键连发内核 input.c 统一处理驱动设置 EV_REP 即可驱动自己做硬件连发会出现重复事件。EV_KEY 之外EV_LED/EV_SND 等是从系统到设备的输出事件driver-event 回调方向相反。设备开关与省电input core 记录设备用户数open() 仅在第一个 handler 连接时调用、close() 在最后一个断开时调用inhibit抑制状态下任何 handler 都收不到事件与休眠唤醒源正交。轮询设备input_setup_polling()注册的轮询设备用input_set_poll_interval()设置间隔间隔过长会表现为丢帧/延迟。2. 工具箱getevent / sendevent / 系统节点2.1 geteventAndroid 自带位于 /system/bin帮助输出设备上getevent -h可得Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device] -t: show time stamps -p: show possible events (errs, dev, name, pos. events) -i: show all device info and possible events -l: label event types and names in plain text -q: quiet (clear verbosity mask) -c: print given number of events then exit -r: print rate events are received常用组合adb shell getevent-lt# 带时间戳、标签格式监控全部设备adb shell getevent-lt/dev/input/event1# 只监控触摸设备adb shell getevent-p/dev/input/event1# 查看设备能力声明EVIOCGBIT ABS 轴 min/max/fuzz/flat/resolutionadb shell getevent-i/dev/input/event1# -p 基础上加 bus/vendor/product/version/驱动版本adb shell getevent-rlt/dev/input/event1# 加事件上报速率报点率分析2.2 输出格式与进制陷阱极易踩坑裸输出是十六进制无 0x 前缀-l标签模式也一样保留十六进制值/dev/input/event0: 0001 014a 00000001 # typeEV_KEY codeBTN_TOUCH(330) value1 按下 /dev/input/event0: 0003 0035 00000262 # typeEV_ABS codeABS_MT_POSITION_X(53) x610 /dev/input/event0: 0003 0039 ffffffff # ABS_MT_TRACKING_ID -1抬起 /dev/input/event0: 0000 0000 00000000 # EV_SYN/SYN_REPORT 帧结束sendevent 用 atoi() 解析参数只接受十进制AOSP toolbox 与 toybox 两版源码一致sendevent DEVICE TYPE CODE VALUE ev.type atoi(...) ev.code atoi(...) ev.value atoi(...)所以把 getevent 的裸输出直接照抄给 sendevent 是错的0001 014a应写成1 330。2.3 系统节点adb shellcat/proc/bus/input/devices# 设备清单名称/驱动/物理路径/事件节点/handlers/能力位adb shellls-l/dev/input/# eventX 节点major 13adb shellcat/sys/class/input/event1/device/capabilities/{ev,key,abs,sw}# 能力位掩码原始位图adb shellcat/sys/class/input/input1/name# inputN 与 eventN 的对应关系adb shelldmesg|grep-iEinput|touch|i2cadb shellcat/proc/interrupts|grep-iEinput|touch|ts# 中断计数是否增长3. 标准排查流程S1 → S6S1 设备是否注册成功adb shellcat/proc/bus/input/devices adb shell getevent-p# 无输出/设备缺失 → 驱动 probe 失败adb shelldmesg|grep-iinputdevices 列表中找不到设备 → 查驱动 probeI2C 通信ACK 失败、IRQ 申请、regulator/gpio、固件下载firmware失败等按 dmesg 定位。有设备但开不了节点 → 权限/SELinuxadb shell 属 input 组通常可读写。S2 设备是否在产事件adb shell getevent-lt/dev/input/event1完全无事件中断无触发/proc/interrupts 计数不动→ 硬件/中断线中断在但无事件 → 驱动中断处理未调 input_report_*。有事件但与操作不符 → 进入 S3 协议核对。S3 对照官方协议核对事件流用第 1.3 节的官方序列为 checklist逐项检查每帧是否都有 SYN_REPORT按下是否新建 TRACKING_ID抬起是否 -1slot 切换是否成对、有无串 slotX/Y 值域是否在 getevent -p 声明的 min/max 内多指时 BTN_TOOL_*TAP 数量与 slot 数是否自洽S4 注入对照实验二分定位用 sendevent 向内核查入标准事件流观察上层现象# 注入一次触摸按下并抬起假设 event1 为触摸屏X/Y 取值需在设备声明范围内adb shell sendevent /dev/input/event1357100# ABS_MT_TRACKING_ID 100新建触点adb shell sendevent /dev/input/event1353300# ABS_MT_POSITION_X 300adb shell sendevent /dev/input/event1354800# ABS_MT_POSITION_Y 800adb shell sendevent /dev/input/event1000# SYN_REPORTadb shell sendevent /dev/input/event1357-1# TRACKING_ID -1抬起adb shell sendevent /dev/input/event1000# SYN_REPORT# 注入一次按键KEY_VOLUMEDOWN114adb shell sendevent /dev/input/event011141adb shell sendevent /dev/input/event0000adb shell sendevent /dev/input/event011140adb shell sendevent /dev/input/event0000判定注入标准流现象正常真实驱动流异常 → 驱动/固件上报逻辑问题回 S3 找差异。注入标准流现象也不正常 → Framework/App 层问题。S5 Framework 层交叉验证adb shell dumpsys input# EventHub 设备状态、InputReader/InputDispatcher 状态adb shell logcat-bevents|grep-iinput adb shell logcat|grep-iEEventHub|InputReader|InputDispatcherS6 驱动层深挖源码级确认是驱动问题后对照官方 driver 文档检查绝对轴参数input_set_abs_params(dev, ABS_MT_POSITION_X, min, max, fuzz, flat)—— fuzz/flat 过大吞事件、min/max 错误 clamp 坐标。Type B 上报应用input_mt_slot()input_mt_report_slot_state()而非手拼 ABS_MT_SLOT 事件。open()/close() 回调设备用户数语义省电逻辑勿在 close 里做不可逆操作。轮询设备input_setup_polling()input_set_poll_interval()检查间隔。按键映射EVIOCGKEYCODE / EVIOCSKEYCODE 查询与修改 scancode→keycode 映射稀疏键位表需实现 getkeycode/setkeycode。4. 事件流解读实例真实 evtest 输出FT5406 触摸单指按下→移动→抬起双指type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0 type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 162 ← 新触点 type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 191 type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 225 type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1 ← 指针模拟input_mt_report_pointer_emulation type 3 (EV_ABS), code 0 (ABS_X), value 191 ← 同上 type 3 (EV_ABS), code 1 (ABS_Y), value 225 ← 同上 -------------- SYN_REPORT ------------ ... 移动仅更新变化的轴重复帧 ... type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value -1 ← 抬起销毁触点 type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0 -------------- SYN_REPORT ------------注意BTN_TOUCH/ABS_X/ABS_Y 是内核input_mt_report_pointer_emulation()自动生成的单指模拟事件属正常行为不是多余事件。5. 常见 Bug 模式速查表现象getevent 观察官方依据 / 根因方向抬起后图标仍被按住幽灵点抬起帧无 TRACKING_ID-1Type B销毁触点必须置 -1断触、跳点、手指交换TRACKING_ID 频繁重建slot 身份串扰官方要求身份变化时 invalidate slot小滑动无响应微小位移事件缺失absfuzz/absflat 过大被 input core 过滤边缘区域点不准/拉不回边界坐标被 clamp轴 min/max 设置错误官方要求设备必须可达 min/max上报率过低、拖影getevent -r 报点率低轮询设备 interval 过大或固件 report rate 低多点数量不符BTN_TOOL_*TAP slot 数驱动声明 slot 数少于硬件跟踪数官方明确此检测法按键重复/双击同一 code 短时间内多次 value1驱动自行实现连发EV_REP 应交给 input core休眠唤醒后触摸失效resume 后无事件open/close 与 runtime-PM、wakeup source 交互问题inhibit 后仍有事件/无事件—抑制状态下任何 handler 收不到事件与 wakeup source 正交压力值被 Android 误判ABS_MT_PRESSURE 单位不符resolution0 为任意单位非 0 为 units/gram6. 用 uinput 做全虚拟设备对照内核 uinput 模块允许用户空间创建虚拟输入设备并发送事件节点为 /dev/uinput或 /dev/input/uinput。官方建议新代码使用 libevdev 操作 uinput流程open(/dev/uinput, O_WRONLY|O_NONBLOCK) ioctl(UI_SET_EVBIT, EV_ABS) ioctl(UI_SET_ABSBIT, ABS_MT_POSITION_X) ... ioctl(UI_DEV_SETUP, usetup) → ioctl(UI_DEV_CREATE) write(input_event) × N ioctl(UI_DEV_DESTROY)Android 注意uinput 节点受 SELinux 限制user 版本 adb shell 默认无权限写 /dev/uinputsendevent 直接写已有 event 节点shell 属 input 组不受此限日常二分定位优先用 sendevent。7. 参考清单官方文档Input subsystem 简介架构 / evdev / mousedev / joydev / event interfacehttps://docs.kernel.org/input/input.html编写 input 设备驱动input_report_* / abs 参数 / open-close / inhibit / 轮询 / keycodehttps://docs.kernel.org/input/input-programming.htmlMulti-touch (MT) ProtocolType A/B、slot、事件语义、事件计算https://docs.kernel.org/input/multi-touch-protocol.htmluinput module虚拟输入设备https://docs.kernel.org/input/uinput.html事件码定义头文件 include/uapi/linux/input-event-codes.h内核源码树AOSP 工具源码system/core/toolbox/{getevent,sendevent}.c新版在 external/toybox/toys/android/
返回列表