Android系统MotionEvent处理InputReader线程基本原理总结

基本原理

触摸事件数据的传递基本流程大致应该分为如下几个阶段
首先,当然是硬件感应 - - >
固件软件 - - >
Kernel驱动, 驱动将数据写入设备文件 - - >
用户空间进程, android中对应的当然是system进程, 首先input reader线程从设备文件读取数据 - - >
system进程input dispatcher线程拿到input reader线程转化后的数据,准备进行分发 - - >
app进程, native层receiver对象被回调, 接收数据 - - >
app进程, java层ViewRootImpl对象被回调, 接收数据 - - >
最后就是我们熟悉的decorview - > activity - > window - > decorview - > viewgroup

这次先分享一下input reader线程对触摸事件数据处理的大致原理。个人感觉逻辑细节还是相当复杂的,所以,不足之处还请高手们多多指点。

android将从设备文件中读取数据的操作封装在EventHub类, 当有数据到达设备文件后, input reader线程会被唤醒, 调用mEventHub→getEvents获取数据, 数据格式为RawEvent, input reader的主要工作就是将RawEvent转化为Motion Event交给input dispatcher进行分发.

设备文件目录在/dev/input
通过命令 adb shell getevent -p查看哪个设备文件是用于触摸事件的
adb shell getevent /dev/input/设备文件名, 可以打印数据

RawEvent

nsecs_t when;
int32_t deviceId;
int32_t type;
int32_t code;
int32_t value;

type和code用于区分数据类型

根据slot协议, 数据类型应该是分为两种EV_ABS和EV_SYN, 通过type来标识, 每种type对应若干个code, EV_SYN有SYN_REPORT, EV_ABS有

ABS_MT_SLOT
ABS_MT_TRACKING_ID
ABS_MT_POSITION_X
ABS_MT_POSITION_Y
ABS_MT_TOUCH_MAJOR
ABS_MT_TOUCH_MINOR
ABS_MT_WIDTH_MAJOR
ABS_MT_WIDTH_MINOR
ABS_MT_ORIENTATION
ABS_MT_PRESSURE
ABS_MT_DISTANCE
ABS_MT_TOOL_TYPE

Input Reader线程的启动

启动代码入口如下

InputManager::start
InputReaderThread→run
InputReaderThread->threadLoop

主要类结构

Input reader处理数据的主要逻辑封装在类InputMapper中, 主要的类结构如下

Android系统MotionEvent处理InputReader线程基本原理总结_第1张图片

处理数据主要流程

InputReader::loopOnce
EventHub::getEvents
InputReader::processEventsLocked
InputReader::processEventsForDeviceLocked
InputDevice::process
InputMapper:: process
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
TouchInputMapper::process(rawEvent);
mMultiTouchMotionAccumulator.process(rawEvent);
}

Android系统MotionEvent处理InputReader线程基本原理总结_第2张图片

关于 MultiTouchInputMapper::process的处理逻辑如下

Android系统MotionEvent处理InputReader线程基本原理总结_第3张图片

Input Reader依据slot协议转化RawEvent数据

数据处理的主要流程InputReader - > InputDevice - > InputMapper
对于多点触摸,RawEvent数据转化的核心逻辑在 MultiTouchInputMapper
MultiTouchInputMapper对象持有MultiTouchMotionAccumulator, MultiTouchMotionAccumulator对象持有一个Slot对象数组,一个Slot对象对应一个手指的触摸数据.
MultiTouchMotionAccumulator负责将RawEvent数据对slot数组进行赋值,TouchInputMapper::process将slot数组转化成其他数据结构.
数据的转化流程大致如下:
RawEvent - > Slot - > RawPointerData - > CookedPointerData

RawPointerData持有一个Pointer对象数组, 每一个Pointer对应一个Slot
CookedPointerData持有一个PointerCoords数组和一个PointerProperties数组,分别记录不同类别的数据.

数据转为完成后,InputReader线程会将CookedPointerData数据插入到一个数据队列,InputDispatcher线程会从该队列读取数据,进行dispatcher阶段的处理.

一个简单的slot数据示例

EV_ABS ABS_MT_TRACKING_ID 0000000e
EV_ABS ABS_MT_POSITION_X 0000011c
EV_ABS ABS_MT_POSITION_Y 000002b7
EV_ABS ABS_MT_PRESSURE 0000009b
EV_SYN SYN_REPORT 00000000 //一个Slot数据收集完毕,由 ABS_MT_TRACKING_ID的值可以判断出这些数据为down事件数据
EV_ABS ABS_MT_POSITION_X 0000011b
EV_ABS ABS_MT_POSITION_Y 000002b8
EV_ABS ABS_MT_PRESSURE 0000008f
EV_SYN SYN_REPORT 00000000 //一个move事件数据收集完毕
EV_ABS ABS_MT_TRACKING_ID ffffffff
EV_SYN SYN_REPORT 00000000 //up事件完成

前后相邻的两个slot数据不会重复传递, 比如, 最后up事件的各个数据值和move事件是相同的,所以,只有 ABS_MT_TRACKING_ID上报.
这是一个单指滑动的示例,所以没有ABS_MT_SLOT 的数值上报.

你可能感兴趣的:(Android系统MotionEvent处理InputReader线程基本原理总结)