touch事件处理流程:
touch事件数据获取处理后分发流程:
"InputDispatcher 线程"
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
//创建Looper对象
mLooper = new Looper(false);
bool InputDispatcherThread::threadLoop()
mDispatcher->dispatchOnce() //整个过程不断循环地调用InputDispatcher的dispatchOnce()来分发事件
void InputDispatcher::dispatchOnce() frameworks/native/services/inputflinger/InputDispatcher.cpp
//唤醒等待线程,monitor()用于监控dispatcher是否发生死锁
mDispatcherIsAliveCondition.broadcast();
//当mCommandQueue不为空时处理
>>>>>>>>>>> dispatchOnceInnerLocked(&nextWakeupTime);
nsecs_t currentTime = now(); //当前时间,也是后面ANR计时的起点
if (!mDispatchEnabled) { //默认值为false
resetKeyRepeatLocked(); //重置操作
}
if (mDispatchFrozen) { //默认值为false
return; //当分发被冻结,则不再处理超时和分发事件的工作,直接返回
}
//优化app切换延迟,当切换超时,则抢占分发,丢弃其他所有即将要处理的事件。
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
...
if (!mPendingEvent) {
if (mInboundQueue.isEmpty()) {
if (!mPendingEvent) {
return; //没有事件需要处理,则直接返回
}
} else {
//从mInboundQueue取出头部的事件
mPendingEvent = mInboundQueue.dequeueAtHead();
}
...
resetANRTimeoutsLocked(); //重置ANR信息
void InputDispatcher::resetANRTimeoutsLocked() {
// 重置等待超时cause和handle
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
mInputTargetWaitApplicationHandle.clear();
switch (mPendingEvent->type)
case EventEntry::TYPE_MOTION: //触摸屏
done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime); //开始touch 事件分发
bool InputDispatcher::dispatchMotionLocked
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
if (isPointerEvent) //Pointer event
>>>>>>>>>>>>>>> injectionResult = findTouchedWindowTargetsLocked //判断这个事件是点击事件(isPointEvent)还是其他事件--寻找目标窗口
int32_t InputDispatcher::findTouchedWindowTargetsLocked // Ensure all touched foreground windows are ready确保所有触摸的前台窗口都准备好进行新的
// Check whether the window is ready more input.
String8 reason = checkWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle, entry, "touched");
if (!reason.isEmpty())
injectionResult = handleTargetsNotReadyLocked //如果这个window不能够继续处理事件,就是说这个window的主线程被某些耗时操作占据
int32_t InputDispatcher::handleTargetsNotReadyLocked
mInputTargetWaitStartTime = currentTime; //当前时间
...
timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT; // 5s
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
//这里的currentTime是指执行dispatchOnceInnerLocked方法体的起点
mInputTargetWaitStartTime = currentTime;
mInputTargetWaitTimeoutTime = currentTime + timeout; //ANR 5s时间
if (mInputTargetWaitTimeoutExpired) {
return INPUT_EVENT_INJECTION_TIMED_OUT; //等待超时已过期,则直接返回
}
//当超时5s则进入ANR流程
if (currentTime >= mInputTargetWaitTimeoutTime)
...
*nextWakeupTime = LONG_LONG_MIN; //强制立刻执行轮询来执行ANR策略
// ANR超时时间点为mInputTargetWaitTimeoutTime,该值等于currentTime + 5s,
// 这里的currentTime是指执行dispatchOnceInnerLocked方法体的起点。此处设置mInputTargetWaitCause
// 等于INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY(应用没有准备就绪),
// 而前面resetANRTimeoutsLocked()过程是唯一用于重置等待理由的地方。
// 可见,ANR时间区间是从dispatchOnceInnerLocked方法体的起点,
// 直到下次执行handleTargetsNotReadyLocked()方法的这段应用未准备就绪的时间段,该时间段是否超过5s来决定是否触发ANR。
// 当前这次的事件dispatch过程中执行findFocusedWindowTargetsLocked()方法到下一次执行resetANRTimeoutsLocked()的时间区间。
//handleTargetsNotReadyLocked()的判断过程:
当applicationHandle和windowHandle同时为空, 且system准备就绪的情况下
设置等待理由 INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
设置超时等待时长为无限大;
设置TimeoutExpired= false
清空等待队列;
当applicationHandle和windowHandle至少一个不为空, 且application准备就绪的情况下:
设置等待理由 INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
设置超时等待时长为5s;
设置TimeoutExpired= false
清空等待队列;
//findTouchedWindowTargetsLocked,如果没有发生ANR,则addWindowTargetLocked()将该事件添加到inputTargets
addWindowTargetLocked
void InputDispatcher::addWindowTargetLocked //将当前聚焦窗口mFocusedWindowHandle的inputChannel传递到inputTargets
>>>>>>>>> dispatchEventLocked(currentTime, entry, inputTargets);
void InputDispatcher::dispatchEventLocked
//向mCommandQueue队列添加doPokeUserActivityLockedInterruptible命令
pokeUserActivityLocked(eventEntry);
void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry)
CommandEntry* commandEntry = postCommandLocked
// 将命令加入mCommandQueue队尾
mCommandQueue.enqueueAtTail(commandEntry);
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
ssize_t InputDispatcher::getConnectionIndexLocked //根据inputChannel的fd从mConnectionsByFd队列中查询目标connection
//找到目标连接
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget); //该方法主要功能是将eventEntry发送到目标inputTargets
void InputDispatcher::prepareDispatchCycleLocked
if (connection->status != Connection::STATUS_NORMAL)
return; //当连接已破坏,则直接返回
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
void InputDispatcher::enqueueDispatchEntriesLocked
enqueueDispatchEntryLocked...XXXX
//生成新的事件, 加入connection的outbound队列 //添加到outboundQueue队尾
if (wasEmpty && !connection->outboundQueue.isEmpty()) //当原先的outbound队列为空, 且当前outbound不为空的情况执行
startDispatchCycleLocked(currentTime, connection);
void InputDispatcher::startDispatchCycleLocked
switch (eventEntry->type)
case EventEntry::TYPE_MOTION:
...
status = connection->inputPublisher.publishMotionEvent // Publish the motion event.
//publishKeyEvent失败情况,从outboundQueue中取出事件,重新放入waitQueue队列// connection->outboundQueue.dequeue(dispatchEntry);
// connection->waitQueue.enqueueAtTail(dispatchEntry);
status_t InputPublisher::publishMotionEvent //至此调用了connection的inputPublisher的publishMotionEvent方法将事件分发消耗。
//InputChannel通过socket向远端的socket发送消息
//分发操作完成,则进入该分支
if (done)
if (dropReason != DROP_REASON_NOT_DROPPED)
dropInboundEventLocked(mPendingEvent, dropReason);
switch (dropReason)
DROP_REASON_POLICY,DROP_REASON_DISABLED,DROP_REASON_APP_SWITCH,DROP_REASON_BLOCKED,DROP_REASON_STALE
releasePendingEventLocked(); //释放pending事件
void InputDispatcher::releasePendingEventLocked()
resetANRTimeoutsLocked(); //重置ANR超时时间
releaseInboundEventLocked(mPendingEvent); //释放mPendingEvent对象,并记录到mRecentQueue队列
mPendingEvent = NULL; //置空mPendingEvent变量.
*nextWakeupTime = LONG_LONG_MIN; //强制立刻执行轮询
1.mDispatchFrozen用于决定是否冻结事件分发工作不再往下执行;
2.当事件分发的时间点距离该事件加入mInboundQueue的时间超过500ms,则认为app切换过期,即isAppSwitchDue=true; //在enqueueInboundEventLocked()的过程中已设置mAppSwitchDueTime等于eventTime加上500ms:
3.mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量;并重置ANR时间; //mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
4.根据EventEntry的type类型分别处理,比如按键调用dispatchMotionLocked分发事件;再根据分发结果来决定是否进入done;
5.执行完成(done)的处理:
根据dropReason(默认NOT_DROPPED不处理)来决定是否丢失事件; dropInboundEventLocked
释放当前正在处理的事件(即mPendingEvent); releasePendingEventLocked
关于dispatchMotionLocked分发事件,
1.不会执行done过情况:
当前Event时间小于唤醒时间;
让policy有机会执行拦截操作;
调用findFocusedWindowTargetsLocked方法的返回结果是INPUT_EVENT_INJECTION_PENDING, 即targets没有处于Ready状态;
2.会执行done的情况:
该事件需要丢弃, 即dropReason != DROP_REASON_NOT_DROPPED;
findFocusedWindowTargetsLocked的返回结果不是INPUT_EVENT_INJECTION_PENDING(没有正在处理的事件);
>>>>>>>>>>> if (runCommandsLockedInterruptible())
nextWakeupTime = LONG_LONG_MIN; //通过循环方式处理完mCommandQueue队列的所有命令,处理过程从mCommandQueue中取出CommandEntry.
>>>>>>>>>>> mLooper->pollOnce(timeoutMillis); //进入epoll_wait
//线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:
//callback:通过回调方法来唤醒;
//timeout:到达nextWakeupTime时间,超时唤醒;
//wake: 主动调用Looper的wake()方法;