Android系统MotionEvent处理Receiver端基本原理总结
来源:互联网 发布:anaconda python 安装 编辑:程序博客网 时间:2024/06/03 07:20
Android系统MotionEvent处理Receiver端基本原理总结
InputEventReceiver
Android系统中activity是接收用户触屏事件的基本单位, 一个activity对应一个window, 对应一个view root. activity初始化的时候, 每一个activity实例都会创建一个用于接收事件的socket通讯通道, system server进程通过对windows的管理, 找到当前需要接收事件的activity, 通过socket直接将事件数据发送给 activity, activity内以root view为起点, 对事件进行分发处理.
每一个viewrootimpl都有一个InputEventReceiver对象, WindowInputEventReceiver在viewrootimpl:: setView时, new InputEventReceiver构造时调用nativeInit,创建NativeInputEventReceiver,将自己的指针传给NativeInputEventReceiver,同时保留NativeInputEventReceiver的指针。
所以,每一个ViewRootImpl对应一个NativeInputEventReceiver。NativeInputEventReceiver的handleEvent会调用到相应的ViewRootImpl。
NativeInputEventReceiver是一个LooperCallback
LooperCallback定义在system/core/include/utils/Looper.h中,作为Looper::addFd的回调
NativeInputEventReceiver的构造函数会接收Java层传递的main looper的MessageQueue指针, 初始化过程中, 调用main looper的addFd将改ViewRootImpl的InputChannel的接收端的fd添加到main loope的轮循中,同时将NativeInputEventReceiver注册为回调.
每次receiver端的socket中的事件到达触发NativeInputEventReceiver的函数handleEvent调用.
WindowInputEventReceiver extends InputEventReceiver
WindowInputEventReceiver:: onInputEvent , onBatchedInputEventPending 在NativeInputEventReceiver::handleEvent中被调用
NativeInputEventReceiver
android_view_InputEventReceiver.cpp
handleEvent – > consumeEvents – > InputConsumer::consume
handleEvent调用consumeEvents, consumeEvents调用consumer的consume函数, consumeEvents主要逻辑如图示.
InputConsumer
定义在 InputTransport.cpp
封装receiver 端接收事件的核心逻辑, 从对应的InputChannel的fd中读取事件数据,并转化成App进程端需要的Event数据格式.
事件转化的主要逻辑如图示.
consumeSamples
将一个batch中的sample全部取出, 构造一个MotionEvent, 所有的sample全部添加进该MotionEvent.
consumeBatch
如果frameTime < 0,consume掉当前batch里的所有的samples, return.
sampleTime = frameTime, 如果支持Resample,sampleTime -= RESAMPLE_LATENCY
找到当前batch中,从第一个开始,直到event time < = sampleTime的最后一个event为止。这些sample为当前需要consume的一组sample.
如果支持resample, 对当前的这组sample进行resample, 否则consume掉.
InputChannel
定义在 InputTransport.cpp
call InputChannel :: receiveMessage, after getting the input message, create a event, and assign the event to passed parameter InputEvent** outEvent.
当main looper 轮循到InputChannel的fd有数据到达时, InputConsumer使用InputChannel的receiveMessage来从fd中读取数据.
do { nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);} while (nRead == -1 && errno == EINTR);
如果中断发生,反复进行读取.
if (nRead < 0) { int error = errno;#if DEBUG_CHANNEL_MESSAGES ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.string(), errno);#endif if (error == EAGAIN || error == EWOULDBLOCK) { return WOULD_BLOCK; } if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) { return DEAD_OBJECT; } return -error; }
读取返回错误, 如果是 EAGAIN 或者 EWOULDBLOCK, 返回该错误值, 返回到input receiver后, 需要针对该情况做相应处理.
数据传输连接出现问题, 返回 dead_object, 目前看, input receiver没有对dead_object做针对性处理.
if (nRead == 0) { // check for EOF#if DEBUG_CHANNEL_MESSAGES ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.string());#endif return DEAD_OBJECT; }
读取返回值为0, socket断开.
if (!msg->isValid(nRead)) {#if DEBUG_CHANNEL_MESSAGES ALOGD("channel '%s' ~ received invalid message", mName.string());#endif return BAD_VALUE; }
检查如果没有读取到完整的数据, 返回bad_value
最后, 读取正常, return OK;
错误值 DEAD_OBJECT 等定义在system/core/include/utils/Errors.h
DEAD_OBJECT相当于-EPIPE
InputMessage
System server发送的事件数据的基本数据单元. socket每次读取一个InputMessage.
The body of the InputMessage could be Key or Motion. If it is Motion, there is a pointerCount, and an array of Pointer.
InputMessage定义在 InputTransport.cpp
Sample
一个sample就是一个 InputMessage
receiver通过socket拿到InputMessage后, 先把数据缓存成sample列表, 用一个Vector保存在Batch中.
MotionEvent
一个MotionEvent如果是滑动事件, 包含若干个sample.
Batch
Batch定义在InputConsumer中
struct Batch {
Vector samples;
};
Vector mBatches;
if motion.deviceId and motion.source are both same, it is combined as one batch.
一个设备对应一个Batch
一个Batch是一个InputMessage的数组
Batch在InputConsumer的consume中被创建, 只有当读取到滑动事件的时候才会创建Batch.
所以, down/up事件没有Batch的概念.
- Android系统MotionEvent处理Receiver端基本原理总结
- Android图片处理总结二:(图片手势控制)MotionEvent解析
- Android事件处理之MotionEvent
- android中的MotionEvent 及其它事件处理
- android中的MotionEvent 及其它事件处理
- android中的MotionEvent 及其它事件处理
- android中的MotionEvent 及其它事件处理
- android中的MotionEvent 及其它事件处理
- android view 中 MotionEvent 及其事件处理
- android中的MotionEvent 及其它事件处理
- Android的MotionEvent和事件处理
- Android 笔记 motionEvent 处理触摸事件
- android MotionEvent和TouchSlop触摸处理
- Android 广播事件处理Broadcast Receiver
- Android中Receiver处理机制禁忌小结
- Android的广播事件处理Broadcast Receiver
- android:MotionEvent
- android:MotionEvent
- springboot 普通类获取spring IOC容器中的Bean<七>
- (int&)和(int)的区别
- 常用加密
- 友好城市
- Android Studio修改LogCat的颜色
- Android系统MotionEvent处理Receiver端基本原理总结
- 刷LeetCode(2)——Add Two Numbers
- 贝叶斯推断及其互联网应用
- Lua中调用函数使用点号和冒号的区别
- 让我印象深刻的javascript面试题
- C
- countdownlatch无限等待
- C#中对表进行操作、转换--间断更新
- 开源ETL 工具 Kettle使用