您的位置:首页 > 移动开发 > Android开发

InputManagerService分发输入事件给应用程序(下)

2017-09-30 19:43 429 查看

InputManagerService分发输入事件给应用程序(下)

InputManagerService分发输入事件给应用程序下
简介

源码分析

总结

1.简介

在InputManagerService分发输入事件消息给应用程序(上)中介绍了InputReader从EventHub中获取输入事件,并对输入事件进行加工处理,然后将输入事件放入到InputDispatcher的mInboundQueue队列,并通过Looper->wake()方法唤醒InputDispatcherThread线程。本篇文章将从InputDispatcherThread线程开始分析,InputDispatcher如何将输入事件分发到应用程序激活的Activity窗口。

2.源码分析

在InputDispatcherThread线程中,会循环调用其threadLoop()方法。

2.1 InputDispatcherThread.threadLoop()

bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}


当threadLoop()方法返回true时,代表将循环调用loopOnce()方法。当threadLoop()方法返回false时,代表退出循环。

void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();

if (!haveCommandsLocked()) {//当mCommandQueue队列为空时,则说明当前没有等待执行任务,则可以进行分发任务。
dispatchOnceInnerLocked(&nextWakeupTime);//分发输入事件,见2.2
}

if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock

// Wait for callback or timeout or wake.  (make sure we round up, not down)
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);//进入epoll_wait等待状态
}


在调用InputDispatcher的dispatchOnce()方法时,如果没有输入事件需要分发,则会调用Looper的pollOnce()方法,进入epoll_wait等待状态。

当发送以下3种情况时,会退出epoll_wait等待状态:

callback:通过回调方法唤醒;

timeout:超时时间timeoutMillis唤醒;

wake:主动通过Looper->wake()方法唤醒;

当InputDispatcher退出epoll_wait等待状态,会返回到dispatchOnce()方法,再返回到threadLoop()方法,因为返回值为true,所以接着又循环调用threadLoop()方法,重新进入dispatchOnce()方法。因为此时已经有输入事件需要处理了,所以会调用dispatchOnceInnerLocked()方法进行处理。

2.2 InputDispatcher.dispatchOnceInnerLocked()

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();//获取当前时间
//分发禁用了,则重置key重复操作;
if (!mDispatchEnabled) {
resetKeyRepeatLocked();
}
//如果分发冻结了,则不再处理超时和分发事件的工作,直接返回
if (mDispatchFrozen) {
return;
}
// 优化App切换延迟,当切换超时,则抢占分发,丢弃其他所有即将要处理的事件。
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
if (mAppSwitchDueTime < *nextWakeupTime) {
*nextWakeupTime = mAppSwitchDueTime;
}

// 开始准备启动一个新的事件,如果我们还没有准备好待处理的事件,则先获取一个待处理的事件
if (! mPendingEvent) {
if (mInboundQueue.isEmpty()) {//如果mInboundQueue队列为空,则说明没有输入事件需要处理
if (isAppSwitchDue) {
resetPendingAppSwitchLocked(false);// mInboundQueue队列为空,说明我们等待APP切换key不会到来,所以停止等待。
isAppSwitchDue = false;
}

if (mKeyRepeatState.lastKeyEntry) {
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
} else {
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
}
}
}

if (!mPendingEvent) {//没有待处理的事件,直接返回
return;
}
} else {
mPendingEvent = mInboundQueue.dequeueAtHead();//mInboundQueue队列不为空,从mInboundQueue队列中获取输入事件
traceInboundQueueLengthLocked();
}

if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
//开始准备分发事件
resetANRTimeoutsLocked();//重置ANR信息,见2.3
}

ALOG_ASSERT(mPendingEvent != NULL);
bool done = false;
DropReason dropReason = DROP_REASON_NOT_DROPPED;//丢弃的原因
if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
dropReason = DROP_REASON_POLICY;//丢弃原因为策略原因
} else if (!mDispatchEnabled) {
dropReason = DROP_REASON_DISABLED;//丢弃原因为禁用
}

if (mNextUnblockedEvent == mPendingEvent) {
mNextUnblockedEvent = NULL;
}

......
case EventEntry::TYPE_KEY: {//按键输入事件
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEventLocked(typedEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
dropReason = DROP_REASON_APP_SWITCH;//丢弃原因为APP切换
}
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);//分发按键输入事件,见2.4
break;
}

case EventEntry::TYPE_MOTION: {//触摸事件
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
dropReason = DROP_REASON_APP_SWITCH;
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
}

default:
ALOG_ASSERT(false);
break;
}

//分发操作完成,则进入该分支
if (done) {
if (dropReason != DROP_REASON_NOT_DROPPED) {
dropInboundEventLocked(mPendingEvent, dropReason);//丢弃事件,见
}
mLastDropReason = dropReason;

releasePendingEventLocked();//释放待处理的输入事件,见
*nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
}
}


在enqueueInboundEventLocked()的过程中已设置mAppSwitchDueTime等于eventTime加上500ms:

mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;


该方法的主要功能有:

mDispatchFrozen用于决定是否冻结事件分发工作是否继续执行;

当事件分发的时间点距离该事件加入mInboundQueue的时间超过了500ms,则认为APP切换超时,即isAppSwitchDue为true;

当mInboundQueue不为空时,则取出头部的事件,放入mPendingEvent中,并重置ANR时间;

根据输入事件的类型,分别调用不同的处理函数,例如按键事件,则调用dispatchKeyLocked方法进行处理;

当事件处理完成(done)了,根据dropReason(默认NOT_DROPPED)来决定是否丢弃事件dropInboundEventLocked;

释放当前正在处理的事件mPendingEvent,即调用releasePendingEventLocked;

2.3 InputDispatcher.resetANRTimeoutsLocked()

void InputDispatcher::resetANRTimeoutsLocked() {
//清空超时等待cause和handle,将等待原因改为INPUT_TARGET_WAIT_CAUSE_NONE
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
mInputTargetWaitApplicationHandle.clear();
}


2.4 InputDispatcher.dispatchKeyLocked()

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// 预处理
if (! entry->dispatchInProgress) {
if (entry->repeatCount == 0
&& entry->action == AKEY_EVENT_ACTION_DOWN
&& (entry->policyFlags & POLICY_FLAG_TRUSTED)
&& (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
if (mKeyRepeatState.lastKeyEntry
&& mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
// 产生了重复按键,记录下重复按下的次数,并重置重复按键时间为最大
entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; //
} else {
// 不是重复按键,保存下按键状态,以防后面有重复按键
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
}
mKeyRepeatState.lastKeyEntry = entry;//保存最近按键事件为当前处理的按键事件
entry->refCount += 1;//将按键事件的引用次数加1
} else if (! entry->syntheticRepeat) {
resetKeyRepeatLocked();
}

if (entry->repeatCount == 1) {
entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;//长按标志
} else {
entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
}

entry->dispatchInProgress = true;

logOutboundKeyDetailsLocked("dispatchKey - ", entry);
}

// 处理拦截策略请求我们再次尝试处理
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
// 当前时间小于拦截唤醒时间
if (currentTime < entry->interceptKeyWakeupTime) {
if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
*nextWakeupTime = entry->interceptKeyWakeupTime;//更新下一次唤醒时间
}
return false; // wait until next wakeup
}
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
entry->interceptKeyWakeupTime = 0;
}

// 让policy尝试拦截这个按键事件
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {//传递给用户
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);//将命令放入队列,见2.5
// 如果获取焦点的窗口不为空,则将其作为输入窗口
if (mFocusedWindowHandle != NULL) {
commandEntry->inputWindowHandle = mFocusedWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
return false; //等待命令运行
} else {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
}
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {//跳过
if (*dropReason == DROP_REASON_NOT_DROPPED) {
*dropReason = DROP_REASON_POLICY;//丢弃原因为Policy
}
}

// 如果输入事件丢弃原因不是DROP_REASON_NOT_DROPPED,则清空丢弃的输入事件
if (*dropReason != DROP_REASON_NOT_DROPPED) {
setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
return true;
}

// 验证输入目标
Vector<InputTarget> inputTargets;
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);//找出获取焦点的窗口,见2.6
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}

setInjectionResultLocked(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
return true;
}

addMonitoringTargetsLocked(inputTargets);

dispatchEventLocked(currentTime, entry, inputTargets);//分发输入事件,见2.9
return true;

}


在分发事件前,会做一些预处理工作,如果出现以下情况,则直接返回,跳过事件分发:

当前时间小于拦截唤醒时间的情况,返回false;

输入事件被Policy拦截了,返回false;

输入事件需要被丢弃的情况,返回true;

寻找聚焦窗口,聚焦窗口还未准备好,返回false;

寻找聚焦窗口失败,则返回true;

2.5 InputDispatcher.postCommandLocked()

InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
CommandEntry* commandEntry = new CommandEntry(command);//创建新的CommandEntry
mCommandQueue.enqueueAtTail(commandEntry);//将CommandEntry放入到队列的尾部
return commandEntry;//返回CommandEntry
}

InputDispatcher::CommandEntry::CommandEntry(Command command) :
command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0),
seq(0), handled(false) {
}

// Command类型定义
typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);


postCommandLocked()方法的主要作用是将创建一个CommandEntry,并把CommandEntry放入到命令队列尾部,然后等待执行,最后返回一个CommandEntry。

void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
CommandEntry* commandEntry) {
KeyEntry* entry = commandEntry->keyEntry;

KeyEvent event;
initializeKeyEvent(&event, entry);

mLock.unlock();

nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
&event, entry->policyFlags);//调用到InputManagerService的interceptKeyBeforeDispatching()方法。

mLock.lock();

if (delay < 0) {// delay小于0
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;//跳过拦截
} else if (!delay) {//delay等于0
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;//继续执行
} else {//delay大于0
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;//下次再尝试
entry->interceptKeyWakeupTime = now() + delay;//拦截唤醒事件
}
entry->release();
}


doInterceptKeyBeforeDispatchingLockedInterruptible方法最终会调用到Java层的InputManagerService的interceptKeyBeforeDispatching()方法进行拦截处理,并把拦截结果反馈回来。

2.6 InputDispatcher.findFocusedWindowTargetsLocked()

int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
int32_t injectionResult;
String8 reason;
//如果当前没有聚焦的窗口以及聚焦的应用,则丢弃该输入事件
if (mFocusedWindowHandle == NULL) {
if (mFocusedApplicationHandle != NULL) {
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
mFocusedApplicationHandle, NULL, nextWakeupTime,
"Waiting because no window has focus but there is a "
"focused application that may eventually add a window "
"when it finishes starting up.");//目标窗口还没有准备好,见2.7
goto Unresponsive;
}

ALOGI("Dropping event because there is no focused window or focused application.");
injectionResult = INPUT_EVENT_INJECTION_FAILED;//返回失败
goto Failed;
}

// 权限检查
if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
goto Failed;
}

// 检查窗口是否准备好了接收更多输入
reason = checkWindowReadyForMoreInputLocked(currentTime,
mFocusedWindowHandle, entry, "focused");
if (!reason.isEmpty()) {
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.string());//目标窗口还没有准备好,见2.7
goto Unresponsive;
}

injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;//成功

addWindowTargetLocked(mFocusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
inputTargets);//将聚焦的窗口添加到inputTargets数组中,见2.8

// 处理失败的情况
Failed:
Unresponsive:
nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
updateDispatchStatisticsLocked(currentTime, entry,injectionResult, timeSpentWaitingForApplication);

return injectionResult;//返回处理结果
}


在findFocusedWindowTargetsLocked()方法中,首先查询当前是否有聚焦的窗口,然后再检查权限,检查窗口是否准备好了接收更多输入,并将聚焦的窗口添加到InputTargets数组中等待处理,最后返回处理结果。

此处的mFocusedWindowHandle是在注册输入通道时,在InputDispatcher.setInputWindows()方法中设置的。

2.7 InputDispatcher.handleTargetsNotReadyLocked()

int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
const EventEntry* entry,
const sp<InputApplicationHandle>& applicationHandle,
const sp<InputWindowHandle>& windowHandle,
nsecs_t* nextWakeupTime, const char* reason) {
// 1.如果当前没有聚焦窗口,也没有聚焦的应用
if (applicationHandle == NULL && windowHandle == NULL) {
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {//如果等待的原因不是聚焦窗口还未准备好
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;//更新等待原因为聚焦窗口还未准备好
mInputTargetWaitStartTime = currentTime;//更新等待开始时间为当前时间
mInputTargetWaitTimeoutTime = LONG_LONG_MAX;//更新等待超时时间
mInputTargetWaitTimeoutExpired = false;
mInputTargetWaitApplicationHandle.clear();
}
}else {//2.有聚焦窗口或者有聚焦的应用
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {//等待原因不是应用还未准备就绪
nsecs_t timeout;
if (windowHandle != NULL) {//存在聚焦窗口
timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);//获取聚焦窗口的分发超时时间
} else if (applicationHandle != NULL) {//存在聚焦应用
timeout = applicationHandle->getDispatchingTimeout(
DEFAULT_INPUT_DISPATCHING_TIMEOUT);//获取聚焦应用的分发超时时间
} else {
timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;//默认的分发超时时间为5s
}

mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;//更新等待原因为聚焦应用还未准备好
mInputTargetWaitStartTime = currentTime;//更新等待开始时间为当前时间
mInputTargetWaitTimeoutTime = currentTime + timeout;//更新等待超时时间
mInputTargetWaitTimeoutExpired = false;
mInputTargetWaitApplicationHandle.clear();

// 聚焦窗口不为空
if (windowHandle != NULL) {
mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;//更新聚焦应用为聚焦窗口所属的应用
}

if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
mInputTargetWaitApplicationHandle = applicationHandle;//更新等待处理的应用为聚焦应用
}
}
}

//等待超时了
if (mInputTargetWaitTimeoutExpired) {
return INPUT_EVENT_INJECTION_TIMED_OUT;//返回超时原因
}

//如果当前时间大于输入目标等待超时时间,即当超时5s时进入ANR处理流程
if (currentTime >= mInputTargetWaitTimeoutTime) {
onANRLocked(currentTime, applicationHandle, windowHandle,
entry->eventTime, mInputTargetWaitStartTime, reason);//调用ANR处理流程,见

*nextWakeupTime = LONG_LONG_MIN;//强制立刻执行轮询来执行ANR策略
return INPUT_EVENT_INJECTION_PENDING;//返回需要等待处理
} else {
if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
*nextWakeupTime = mInputTargetWaitTimeoutTime;//更新下次唤醒时间
}
return INPUT_EVENT_INJECTION_PENDING;//返回需要等待处理
}
}


此处的mInputTargetWaitTimeoutTime是当前时间戳加上5s的超时时间,并设置mInputTargetWaitCause为INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY表示等待的原因是由于应用还未准备就绪。当下次调用handleTargetsNotReadyLocked()方法时,如果等待的原因还是INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,并且等待时间超过5s钟,说明发生了ANR,则触发ANR处理流程。在2.3中的resetANRTimeoutsLocked()方法,会将等待原因更新为INPUT_TARGET_WAIT_CAUSE_NONE。

那么ANR的时间区间是指在事件分发过程中执行findFocusedWindowTargetsLocked()开始,到下一次执行resetANRTimeoutsLocked()的时间区间。如果时间区间超过了5s,则会触发ANR执行过程。如果没有发生ANR,则通过addWindowTargetLocked()方法将该事件添加到inputTargets中。

2.8 InputDispatcher.addWindowTargetLocked()

void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
inputTargets.push();

const InputWindowInfo* windowInfo = windowHandle->getInfo();
InputTarget& target = inputTargets.editTop();
target.inputChannel = windowInfo->inputChannel;
target.flags = targetFlags;
target.xOffset = - windowInfo->frameLeft;
target.yOffset = - windowInfo->frameTop;
target.scaleFactor = windowInfo->scaleFactor;
target.pointerIds = pointerIds;
}


该函数的主要作用是将当前聚焦窗口mFocusedWindowHandle的inputChannel传递到inputTarget。

通过findFocusedWindowTargetsLocked()方法找到了聚焦的窗口后,返回到2.4,继续事件的分发过程,调用dispatchEventLocked()方法。

2.9 InputDispatcher.dispatchEventLocked()

void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {

ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
pokeUserActivityLocked(eventEntry);//见2.10

for (size_t i = 0; i < inputTargets.size(); i++) {
const InputTarget& inputTarget = inputTargets.itemAt(i);//获取输入目标

ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);//获取连接索引,见2.11
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);//根据索引找到连接
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);//找到目标连接,见2.12
}
}
}


该方法的主要作用是遍历inputTargets数组,找到能接收eventEntry的inputTargets。

2.10 InputDispatcher.pokeUserActivityLocked()

void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
if (mFocusedWindowHandle != NULL) {
const InputWindowInfo* info = mFocusedWindowHandle->getInfo();//获取聚焦窗口信息
if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
return;
}
}

int32_t eventType = USER_ACTIVITY_EVENT_OTHER;
switch (eventEntry->type) {
case EventEntry::TYPE_MOTION: {//触摸事件
const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
return;
}

if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
eventType = USER_ACTIVITY_EVENT_TOUCH;
}
break;
}
case EventEntry::TYPE_KEY: {//按键事件
const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {//取消了
return;
}
eventType = USER_ACTIVITY_EVENT_BUTTON;
break;
}
}

CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doPokeUserActivityLockedInterruptible);//放入任务队列中,随后执行InputDispatcher的doPokeUserActivityLockedInterruptible方法
commandEntry->eventTime = eventEntry->eventTime;
commandEntry->userActivityEventType = eventType;
}


该方法的主要作用是创建一个doPokeUserActivityLockedInterruptible的任务,并把它放入任务队列中。

void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
mLock.unlock();

mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);//此处的mPolicy是NativeInputManager

mLock.lock();
}


doPokeUserActivityLockedInterruptible()方法会调用NativeInputManager的pokeUserActivity()方法,最终会调用到Java层的PowerManagerService的userActivityFromNative()方法。

2.11 InputDispatcher.getConnectionIndexLocked()

ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());//根据输入通道的文件描述符获取连接索引
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
if (connection->inputChannel.get() == inputChannel.get()) {//如果输入通道相同,则返回索引
return connectionIndex;
}
}

return -1;
}


该方法的主要是根据inputChannel的Fd获取连接索引,然后根据索引获取连接,并返回索引。

2.12 InputDispatcher.prepareDispatchCycleLocked()

void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
// 如果连接状态不正常,则忽略该事件
if (connection->status != Connection::STATUS_NORMAL) {
return;
}
// 将需要分发的eventEntry放入队列中,见2.13
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}


2.13 InputDispatcher.enqueueDispatchEntriesLocked()

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
bool wasEmpty = connection->outboundQueue.isEmpty();//Connection的outboundQueue队列是否为空

//1.根据请求模式,将eventEntry放入队列中
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);//见2.14
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);

// 2.如果outboundQueue队列先前为空,但现在不为空了,则执行该过程,见2.15
if (wasEmpty && !connection->outboundQueue.isEmpty()) {
startDispatchCycleLocked(currentTime, connection);
}
}


该方法的主要功能是根据请求模式,将eventEntry放入队列中。如果outboundQueue队列先前为空,但现在不为空了,则执行startDispatchCycleLocked()方法。

2.14 InputDispatcher.enqueueDispatchEntryLocked()

void InputDispatcher::enqueueDispatchEntryLocked(
const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
int32_t dispatchMode) {
int32_t inputTargetFlags = inputTarget->flags;//获取输入目标的分发模式
if (!(inputTargetFlags & dispatchMode)) {//如果模式不匹配,则直接返回
return;
}

inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;

DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
inputTarget->scaleFactor);//创建一个新的DispatchEntry,将DispatchEntry放入到outboundQueue队列中。

switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {//按键事件
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
dispatchEntry->resolvedAction = keyEntry->action;
dispatchEntry->resolvedFlags = keyEntry->flags;

if (!connection->inputState.trackKey(keyEntry,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
delete dispatchEntry;
return; // skip the inconsistent event
}
break;
}
.......
}
.....
if (dispatchEntry->hasForegroundTarget()) {
incrementPendingForegroundDispatchesLocked(eventEntry);
}

connection->outboundQueue.enqueueAtTail(dispatchEntry);//将DispatchEntry放入到outboundQueue队列
traceOutboundQueueLengthLocked(connection);
}


该方法的主要功能是

根据dispatchMode来决定是否需要添加到outboundQueue队列中;

根据EventEntry,来生成DispatcherEntry事件;

将dispatchEntry加入到connection的outbound队列;

可以看到,从2.2到2.14过程,主要是将InputDispatcher的mInboundQueue中的事件取出来后,然后寻找到目标窗口Window后,将EventEntry封装成DispatcherEntry事件,加入到connection的outbound队列中。

2.15 InputDispatcher.startDispatchCycleLocked()

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
while (connection->status == Connection::STATUS_NORMAL
&& !connection->outboundQueue.isEmpty()) {//如果连接的状态是正常的,并且outboundQueue队列不为空

DispatchEntry* dispatchEntry = connection->outboundQueue.head;//获取outboundQueue队列首部的DispatchEntry
dispatchEntry->deliveryTime = currentTime;

// Publish the event.
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;//获取EventEntry
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);

// Publish the key event.
status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
keyEntry->deviceId, keyEntry->source,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
keyEntry->keyCode, keyEntry->scanCode,
keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
keyEntry->eventTime);//发布按键事件,见2.16
break;
}
......
}

// 检查结果,处理发布失败的情况
if (status) {
if (status == WOULD_BLOCK) {//如果结果是阻塞的
if (connection->waitQueue.isEmpty()) {//等待队列为空
ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
"This is unexpected because the wait queue is empty, so the pipe "
"should be empty and we shouldn't have any problems writing an "
"event to it, status=%d", connection->getInputChannelName(), status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);//停止分发事件
} else {
// 管道已经满了,我们在等待应用结束处理一些输入事件
connection->inputPublisherBlocked = true;
}
} else {
ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
"status=%d", connection->getInputChannelName(), status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);//停止分发事件
}
return;
}

connection->outboundQueue.dequeue(dispatchEntry);//将dispatchEntry出队列
traceOutboundQueueLengthLocked(connection);
connection->waitQueue.enqueueAtTail(dispatchEntry);//将dispatchEntry放入等待队列
traceWaitQueueLengthLocked(connection);
}
}


该方法的主要功能是从outboundQueue队列中取出dispatchEntry事件,然后发布事件,最后将dispatchEntry事件放入到等待队列中。abortBrokenDispatchCycleLocked()方法最终会调用到Java层的InputManagerService的notifyInputChannelBroken()方法。

2.16 InputPublisher.publishKeyEvent()

status_t InputPublisher::publishKeyEvent(
uint32_t seq,
int32_t deviceId,
int32_t source,
int32_t action,
int32_t flags,
int32_t keyCode,
int32_t scanCode,
int32_t metaState,
int32_t repeatCount,
nsecs_t downTime,
nsecs_t eventTime) {
if (!seq) {
ALOGE("Attempted to publish a key event with sequence number 0.");
return BAD_VALUE;
}

//初始化InputMessage对象
InputMessage msg;
msg.header.type = InputMessage::TYPE_KEY;
msg.body.key.seq = seq;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.action = action;
msg.body.key.flags = flags;
msg.body.key.keyCode = keyCode;
msg.body.key.scanCode = scanCode;
msg.body.key.metaState = metaState;
msg.body.key.repeatCount = repeatCount;
msg.body.key.downTime = downTime;
msg.body.key.eventTime = eventTime;
return mChannel->sendMessage(&msg);//调用InputChannel的sendMessage方法,见2.17
}


2.17 InputChannel.sendMessage()

status_t InputChannel::sendMessage(const InputMessage* msg) {
size_t msgLength = msg->size();//获取消息的大小
ssize_t nWrite;
do {
nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);//通过Socket发送消息到InputDispatcher的输入通道
} while (nWrite == -1 && errno == EINTR);

if (nWrite < 0) {//处理失败的情况
int error = errno;
if (error == EAGAIN || error == EWOULDBLOCK) {
return WOULD_BLOCK;
}
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
return DEAD_OBJECT;
}
return -error;
}

if (size_t(nWrite) != msgLength) {
return DEAD_OBJECT;
}

return OK;//返回成功
}


应用程序注册输入消息接收通道的文章中,介绍了输入通道的注册过程中,会创建一个套接字对socketpair,其中一端为server端套接字,保存在system_server中的WindowState的mInputChannel,另外一端为client端套接字,通过Binder机制回传到远程进程的UI主线程ViewRootImpl的mInputChannel。这个socketpair创建了一对匿名的已经连接的套接字,可以实现在同一个文件描述符中进行读写的功能。在Linux中,完全可以把这一对socket当成pipe返回的文件描述符一样使用,唯一的区别就是这一对文件描述符中的任何一个都可读和可写。与一般的管道相区别的是,套接字对建立的通道是双向的,即每一端都可以进行读写。当在socketpair一端写入时,只能在另外一端读出,而在写入端读出时会阻塞。

server端套接字和client端套接字都通过Looper->addFd()方法添加到文件描述符监控范围,分别在InputDispatcher的registerInputChannel()方法和NativeInputEventReceiver的setFdEvents()方法中实现。当套接字对中的套接字有数据可读时,则唤醒epoll_wait等待状态,调用回调函数进行相应的处理。

//server端套接字注册监听
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
......
sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);//创建一个新的连接

int fd = inputChannel->getFd();// 获取输入通道的文件描述符
mConnectionsByFd.add(fd, connection);// 将连接按文件描述符保存

mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);// 通过Looper的addFd方法,将server端套接字文件描述符添加到Looper的监控中,并设置回调处理函数为handleReceiveCallback方法。
mLooper->wake();//唤醒操作
return OK;
}

//client端套接字注册监听
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;//更新文件描述符支持的操作
int fd = mInputConsumer.getChannel()->getFd();//获取输入通道的文件描述符
if (events) {
mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);//将client端套接字文件描述符添加到消息队列关联Looper循环中,监听events事件,并设置事件回调处理对象为NativeInputEventReceiver。
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}


在InputDispatcher的registerInputChannel()和NativeInputEventReceiver的setFdEvents()方法都是监控了套接字的输入事件(ALOOPER_EVENT_INPUT),因此当套接字中有数据到来时,将会唤醒epoll_wait上等待的操作,调用回调方法来处理数据。因为server端套接字和client端套接字是socketpair的两端,只能一端写入,另外一端读出。因此当通过InputDispatcher的mChannel的sendMessage()方法发送消息时,即在server端套接字写入数据,只能在client端套接字读取出来。所以将唤醒在epoll_wait上等待的操作,调用client端回调方法NativeInputEventReceiver.handleEvent()来处理数据。

2.18 NativeInputEventReceiver.handleEvent()

int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
//错误的输出
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred.  "
"events=0x%x", getInputChannelName(), events);
}
return 0;//移除回调
}

if (events & ALOOPER_EVENT_INPUT) {//有数据可读
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);//消费输入事件,见2.19
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");//清除
return status == OK || status == NO_MEMORY ? 1 : 0;
}

if (events & ALOOPER_EVENT_OUTPUT) {//有数据可写
for (size_t i = 0; i < mFinishQueue.size(); i++) {
const Finish& finish = mFinishQueue.itemAt(i);
status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);//发送结束信号,见
if (status) {
mFinishQueue.removeItemsAt(0, i);

if (status == WOULD_BLOCK) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Sent %zu queued finish events; %zu left.",
getInputChannelName(), i, mFinishQueue.size());
}
return 1; // 保留callback,稍后重试
}

ALOGW("Failed to send finished signal on channel '%s'.  status=%d",
getInputChannelName(), status);
if (status != DEAD_OBJECT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
String8 message;
message.appendFormat("Failed to finish input event.  status=%d", status);
jniThrowRuntimeException(env, message.string());
mMessageQueue->raiseAndClearException(env, "finishInputEvent");
}
return 0; // 移除callback
}
}

mFinishQueue.clear();//情况队列
setFdEvents(ALOOPER_EVENT_INPUT);//监控输入
return 1;
}

ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
"events=0x%x", getInputChannelName(), events);
return 1;
}


在NativeInputEventReceiver的会调用函数handleEvent()主要是根据event类型,进行相应的处理。

event是ALOOPER_EVENT_INPUT时,即有数据可读时,调用consumeEvents()方法进行处理;

event是ALOOPER_EVENT_OUTPUT时,即有数据可写时,调用InputConsumer的sendFinishedSignal()方法进行处理;

2.19 NativeInputEventReceiver.consumeEvents()

status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
if (consumeBatches) {
mBatchedInputEventPending = false;
}

if (outConsumedBatch) {
*outConsumedBatch = false;
}

ScopedLocalRef<jobject> receiverObj(env, NULL);
bool skipCallbacks = false;

for (;;) {
uint32_t seq;
InputEvent* inputEvent;
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);// 调用InputConsumer的consume()方法,见2.20
if (status) {
if (status == WOULD_BLOCK) {
......
return OK;//消费完成
}
......
return status;//消费失败
}
assert(inputEvent);

if (!skipCallbacks) {
if (!receiverObj.get()) {
receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
if (!receiverObj.get()) {
ALOGW("channel '%s' ~ Receiver object was finalized "
"without being disposed.", getInputChannelName());
return DEAD_OBJECT;
}
}

jobject inputEventObj;
switch (inputEvent->getType()) {//输入事件的类型
case AINPUT_EVENT_TYPE_KEY://按键事件
inputEventObj = android_view_KeyEvent_fromNative(env,
static_cast<KeyEvent*>(inputEvent));//由Native层的InputEvent来生成Java层的输入事件,见2.22
break;

case AINPUT_EVENT_TYPE_MOTION: {//触摸事件
MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
*outConsumedBatch = true;
}
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);//由Native层的MotionEvent来生成Java层的输入事件
break;
}

default:
assert(false); // InputConsumer should prevent this from ever happening
inputEventObj = NULL;
}

if (inputEventObj) {//输入事件不为空
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);//调用Java层的InputEventReceiver的dispatchInputEvent()方法,见2.23
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching input event.");
skipCallbacks = true;
}
env->DeleteLocalRef(inputEventObj);
} else {
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
skipCallbacks = true;
}
}

if (skipCallbacks) {//跳过执行回调函数
mInputConsumer.sendFinishedSignal(seq, false);
}
}
}


在该方法中,主要完成了以下几件事情:

调用InputConsumer的consume()方法来获取输入事件的序列化seq以及inputEvent实例;

根据输入事件的类型,生成Java层对应的输入事件;

调用Java层的InputEventReceiver的dispatchInputEvent()方法进行分发处理;

根据是否发生了异常,决定是否需要调用sendFinishedSignal()向InputDispatcher发送完成信号。

2.20 InputConsumer.consume()

status_t InputConsumer::consume(InputEventFactoryInterface* factory,
bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
*outSeq = 0;
*outEvent = NULL;
// 获取下一个输入消息,一直循环直至返回一个输入事件,或者没有输入事件可以接收
while (!*outEvent) {
if (mMsgDeferred){
mMsgDeferred = false;
}else {
status_t result = mChannel->receiveMessage(&mMsg);//接收一个新的消息,见2.21
if (result) {
if (consumeBatches || result != WOULD_BLOCK) {
result = consumeBatch(factory, frameTime, outSeq, outEvent);
if (*outEvent) {
break;
}
}
return result;//返回失败
}
}

switch (mMsg.header.type) {
case InputMessage::TYPE_KEY: {//按键事件
KeyEvent* keyEvent = factory->createKeyEvent();//创建一个keyEvent
if (!keyEvent) return NO_MEMORY;

initializeKeyEvent(keyEvent, &mMsg);//初始化KeyEvent
*outSeq = mMsg.body.key.seq;
*outEvent = keyEvent;
break;
}

case AINPUT_EVENT_TYPE_MOTION: {//触摸事件
.....
}

default:
return UNKNOWN_ERROR;
}
}
return OK;
}


在InputConsumer的consume()方法中,首先通过InputChannel的receiveMessage()方法来接收输入信息,然后根据输入信息的类型,创建相应的输入事件。例如按键事件类型,则创建KeyEvent事件。最后将输入事件以及序列号分别赋值给outEvent和outSeq返回。

2.21 InputChannel.receiveMessage()

status_t InputChannel::receiveMessage(InputMessage* msg) {
ssize_t nRead;
do {
nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);//循环从套接字中读取数据,放入到msg中
} while (nRead == -1 && errno == EINTR);

if (nRead < 0) {
....
return -error;
}

if (nRead == 0) {
return DEAD_OBJECT;
}

if (!msg->isValid(nRead)) {
return BAD_VALUE;
}
return OK;
}


该方法的主要作用是从套接字中循环读取数据,并把数据放入到类型为InputMessage的msg中。消息的发送是在2.17中的InputChannel的sendMessage()方法中,发送的数据类型也是InputMessage。

当套接字中获取到输入事件数据后,回到2.19中,继续创建Java层的输入事件。

2.22 android_view_KeyEvent_fromNative()

jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz,
gKeyEventClassInfo.obtain,
nanoseconds_to_milliseconds(event->getDownTime()),
nanoseconds_to_milliseconds(event->getEventTime()),
event->getAction(),
event->getKeyCode(),
event->getRepeatCount(),
event->getMetaState(),
event->getDeviceId(),
event->getScanCode(),
event->getFlags(),
event->getSource(),
NULL);
if (env->ExceptionCheck()) {
ALOGE("An exception occurred while obtaining a key event.");
LOGE_EX(env);
env->ExceptionClear();
return NULL;
}
return eventObj;
}


android_view_KeyEvent_fromNative()方法定义在framework/core/jni/android_view_KeyEvent.cpp文件中,其主要作用是调用Java层的KeyEvent的obtain()方法创建一个KeyEvent对象,然后将keyEvent对象返回。

public static KeyEvent obtain(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode, int flags, int source, String characters) {
KeyEvent ev = obtain();
ev.mDownTime = downTime;
ev.mEventTime = eventTime;
ev.mAction = action;
ev.mKeyCode = code;
ev.mRepeatCount = repeat;
ev.mMetaState = metaState;
ev.mDeviceId = deviceId;
ev.mScanCode = scancode;
ev.mFlags = flags;
ev.mSource = source;
ev.mCharacters = characters;
return ev;
}


当返回KeyEvent对象后,回到2.19中,继续通过JNI调用Java层的InputEventReceiver的dispatchInputEvent()方法进行分发处理;

2.23 InputEventReceiver.dispatchInputEvent()

private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);//映射InputEvent的序列号码到分发序列号
onInputEvent(event);//调用ViewRootImpl内部类WindowInputEventReceiver的onInputEvent()方法,见2.24
}


InputEventReceiver是一个抽象类,具体的实现类是ViewRootImpl内部类WindowInputEventReceiver,其在ViewRootImpl调用setView()方法注册输入通道时被初始化的。

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
......
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,Looper.myLooper());
......
}


2.24 WindowInputEventReceiver.onInputEvent()

final class WindowInputEventReceiver extends InputEventReceiver {
......
@Override
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);//见2.25
}
......
}


2.25 ViewRootImpl.enqueueInputEvent()

void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {

adjustInputEventForCompatibility(event);
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);//获取InputEvent事件,见2.26
QueuedInputEvent last = mPendingInputEventTail;//指向待处理事件的尾部
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;//添加到待处理输入事件尾部
mPendingInputEventTail = q;
}

mPendingInputEventCount += 1;//待处理输入事件加1

if (processImmediately) {//立即处理
doProcessInputEvents();//处理输入事件,见2.27
} else {
scheduleProcessInputEvents();
}
}


2.26 ViewRootImpl.obtainQueuedInputEvent()

private QueuedInputEvent obtainQueuedInputEvent(InputEvent event,
InputEventReceiver receiver, int flags) {
QueuedInputEvent q = mQueuedInputEventPool;//对象池
if (q != null) {//如果存在的话,直接从中取一个出来使用
mQueuedInputEventPoolSize -= 1;
mQueuedInputEventPool = q.mNext;
q.mNext = null;
} else {
q = new QueuedInputEvent();
}
//将event和receiver和flags进行赋值
q.mEvent = event;
q.mReceiver = receiver;
q.mFlags = flags;
return q;
}


2.27 ViewRootImpl.doProcessInputEvents()

void doProcessInputEvents() {
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
q.mNext = null;

mPendingInputEventCount -= 1;//待处理事件数量减1
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);

long eventTime = q.mEvent.getEventTimeNano();//记录事件处理时间
long oldestEventTime = eventTime;
if (q.mEvent instanceof MotionEvent) {//触摸事件
MotionEvent me = (MotionEvent)q.mEvent;
if (me.getHistorySize() > 0) {
oldestEventTime = me.getHistoricalEventTimeNano(0);
}
}
mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);//更新输入事件最新和最老的时间

deliverInputEvent(q);//分发事件,见2.28
}

// 已经处理完所有的输入事件,可以清空等待标志
if (mProcessInputEventsScheduled) {
mProcessInputEventsScheduled = false;
mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
}
}


2.28 ViewRootImpl.deliverInputEvent()

private void deliverInputEvent(QueuedInputEvent q) {
if (mInputEventConsistencyVerifier != null) {//调试目的
mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
}

InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}

if (stage != null) {
stage.deliver(q);//分发给最终的处理该事件的窗口
} else {
finishInputEvent(q);//结束输入事件处理,见2.29
}
}


这里的state是mFirstInputStage,mFirstInputStage的初始化在ViewRootImpl的setView()方法中初始化的。

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
.......
//初始化输入管道
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);

mFirstInputStage = nativePreImeStage;
mFirstPostImeInputStage = earlyPostImeStage;
}


可以看到mFirstInputStage指向的是NativePreImeInputStage,而NativePreImeInputStage由持有ViewPreImeInputStage,ViewPreImeInputStage又持有ImeInputStage,这样一层层包装,形成了一个调用链。它们都是InputState的子类,通过next变量连接起来,就像一个单向链表。经过层层的调用,最终会传递给ViewPostImeInputStage处理。

abstract class InputStage {
......
private final InputStage mNext;
public InputStage(InputStage next) {
mNext = next;
}

public final void deliver(QueuedInputEvent q) {
if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
forward(q);
} else if (shouldDropInputEvent(q)) {
finish(q, false);
} else {
apply(q, onProcess(q));
}
}
}


当调用state的deliver方法时,都会调用其父类的deliver方法,根据输入事件的不同状态选择不同的处理方式。

输入事件处理结果了,则调用forward()方法;

输入事件需要被丢弃,则调用finish()方法;

输入事件需要处理,则调用apply()方法,在调用apply()方法之前,首先要调用onProcess()方法进行处理,根据处理结果再决定下一步该如何处理;

在ViewPostImeInputStage类中,实现了onProcess()方法,因此会先调用ViewPostImeInputStage的onProcess()方法进行处理。

ViewPostImeInputStage.onProcess()

final class ViewPostImeInputStage extends InputStage {
public ViewPostImeInputStage(InputStage next) {
super(next);
}

@Override
protected int onProcess(QueuedInputEvent q) {
if (q.mEvent instanceof KeyEvent) {//按键事件
return processKeyEvent(q);//调用
} else {
final int source = q.mEvent.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
return processPointerEvent(q);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
return processTrackballEvent(q);
} else {
return processGenericMotionEvent(q);
}
}
}

private int processKeyEvent(QueuedInputEvent q) {
final KeyEvent event = (KeyEvent)q.mEvent;

// Deliver the key to the view hierarchy.
if (mView.dispatchKeyEvent(event)) {//调用ViewRootImpl中DecorView的dispatchKeyEvent()方法。
return FINISH_HANDLED;
}
......
}

}


可以看到,在ViewPostImeInputStage的onProcess()方法中,会调用到processKeyEvent()方法,在processKeyEvent()方法中,会调用ViewRootImpl中成员变量mView的dispatchKeyEvent()方法。mView是在ViewRootImpl的setView()方法中进行赋值,该View是PhoneWindow的DecorView。DecorView是一个Activity最顶层的View,所有的事件分发都是从这个View开始,逐层的分发到View层级中的各个View。

至此,完成了输入事件从InputDispatcher线程分发到应用程序激活Activity的窗口过程。输入事件处理完成后,还需要通知InputDispatcher,继续处理下一个事件的分发。输入事件处理完成后,会调用ViewRootImpl的finishInputEvent()方法。

2.29 ViewRootImpl.finishInputEvent()

private void finishInputEvent(QueuedInputEvent q) {
if (q.mReceiver != null) {
boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
q.mReceiver.finishInputEvent(q.mEvent, handled);//调用InputEventReceiver的finishInputEvent(),见2.30
} else {
q.mEvent.recycleIfNeededAfterDispatch();
}

recycleQueuedInputEvent(q);
}


当收到输入事件时,需要处理这个输入事件,然后调用finishInputEvent()方法来反馈这个输入事件是否已经被处理了。在调用finishInputEvent()方法之前,不会接收新的输入事件。

2.30 InputEventReceiver.finishInputEvent()

public final void finishInputEvent(InputEvent event, boolean handled) {

if (mReceiverPtr == 0) {
......
} else {
int index = mSeqMap.indexOfKey(event.getSequenceNumber());
if (index < 0) {
.......
} else {
int seq = mSeqMap.valueAt(index);
mSeqMap.removeAt(index);
nativeFinishInputEvent(mReceiverPtr, seq, handled);//调用native方法,见2.31
}
}
event.recycleIfNeededAfterDispatch();
}


nativeFinishInputEvent()方法经过层层调用,会调用android_view_InputEventReceiver类的nativeFinishInputEvent()方法。

2.31 nativeFinishInputEvent()

static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
jint seq, jboolean handled) {
sp<NativeInputEventReceiver> receiver =
reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
status_t status = receiver->finishInputEvent(seq, handled);//调用NativeInputEventReceiver的finishInputEvent()方法,见2.32
if (status && status != DEAD_OBJECT) {
String8 message;
message.appendFormat("Failed to finish input event.  status=%d", status);
jniThrowRuntimeException(env, message.string());
}
}


2.32 NativeInputEventReceiver.finishInputEvent()

status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
.....
status_t status = mInputConsumer.sendFinishedSignal(seq, handled);//调用InputConsumer的sendFinishedSignal()方法,见2.33
if (status) {//异常处理
if (status == WOULD_BLOCK) {
Finish finish;
finish.seq = seq;
finish.handled = handled;
mFinishQueue.add(finish);
if (mFinishQueue.size() == 1) {
setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
}
return OK;
}

}
return status;
}


2.33 InputConsumer.sendFinishedSignal()

status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
if (!seq) {
return BAD_VALUE;
}

size_t seqChainCount = mSeqChains.size();//批量处理
if (seqChainCount) {
uint32_t currentSeq = seq;
uint32_t chainSeqs[seqChainCount];
size_t chainIndex = 0;
//批量处理
for (size_t i = seqChainCount; i-- > 0; ) {
const SeqChain& seqChain = mSeqChains.itemAt(i);
if (seqChain.seq == currentSeq) {
currentSeq = seqChain.chain;
chainSeqs[chainIndex++] = currentSeq;
mSeqChains.removeAt(i);
}
}
status_t status = OK;
while (!status && chainIndex-- > 0) {
status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);//发送结束信号,见2.34
}
if (status) {
// 发生了错误,重新构建这个处理链
do {
SeqChain seqChain;
seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
seqChain.chain = chainSeqs[chainIndex];
mSeqChains.push(seqChain);
} while (chainIndex-- > 0);
return status;
}
}
return sendUnchainedFinishedSignal(seq, handled);
}


2.34 InputConsumer.sendUnchainedFinishedSignal()

status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
InputMessage msg;
msg.header.type = InputMessage::TYPE_FINISHED;
msg.body.finished.seq = seq;
msg.body.finished.handled = handled;
return mChannel->sendMessage(&msg);//通过InputChannel发送Socket消息到InputDispatcher,消息类型为TYPE_FINISHED。
}


通过InputChannel的sendMessage()方法,可以将TYPE_FINISHED类型的输入消息发送到InputDispatcher线程。和之前2.17处理流程一样,只是此处是往client端套接字写入消息。此时在server端epoll_wait上等待输入消息的线程会被唤醒,调用相应的回调方法:InputDispatcher的handleReceiveCallback()方法。

2.35 InputDispatcher.handleReceiveCallback()

int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
InputDispatcher* d = static_cast<InputDispatcher*>(data);//获取传递的数据

{ // acquire lock
AutoMutex _l(d->mLock);
ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
if (connectionIndex < 0) {//没有找到
ALOGE("Received spurious receive callback for unknown input channel.  "
"fd=%d, events=0x%x", fd, events);
return 0; // remove the callback
}

bool notify;

sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);//获得连接
if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {//不是错误或者挂起
if (!(events & ALOOPER_EVENT_INPUT)) {// 不是输入事件
ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
"events=0x%x", connection->getInputChannelName(), events);
return 1;
}

nsecs_t currentTime = now();//当前时间
bool gotOne = false;
status_t status;

for (;;) {
uint32_t seq;
bool handled;
status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);//循环等待接收结束信号,见2.36
if (status) {
break;
}
d->finishDispatchCycleLocked(currentTime, connection, seq, handled);//结束分发操作,见2.37
gotOne = true;
}

if (gotOne) {
d->runCommandsLockedInterruptible();//执行任务,见2.40
if (status == WOULD_BLOCK) {
return 1;
}
}

notify = status != DEAD_OBJECT || !connection->monitor;
}else{
notify = !connection->monitor;
}
d->unregisterInputChannelLocked(connection->inputChannel, notify);//反注册输入通道
return 0;//移除回调
}
}


当client端套接字写入了消息,会唤醒在server端epoll_wait等待的事件,此时会调用回调函数handleReceiveCallback()方法进行处理,在该方法中,首先循环等待接收结束信号,然后结束分发操作;

2.36 InputPublisher.receiveFinishedSignal()

status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {
InputMessage msg;
status_t result = mChannel->receiveMessage(&msg);//调用InputChannel的receiveMessage()方法,接收消息,过程见2.21
if (result) {//结果为空
*outSeq = 0;
*outHandled = false;
return result;
}
if (msg.header.type != InputMessage::TYPE_FINISHED) {//消息类型不是结束类型
ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",
mChannel->getName().string(), msg.header.type);
return UNKNOWN_ERROR;
}
*outSeq = msg.body.finished.seq;
*outHandled = msg.body.finished.handled;
return OK;
}


2.37 InputDispatcher.finishDispatchCycleLocked()

void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, uint32_t seq, bool handled) {
connection->inputPublisherBlocked = false;

if (connection->status == Connection::STATUS_BROKEN
|| connection->status == Connection::STATUS_ZOMBIE) {
return;
}

// Notify other system components and prepare to start the next dispatch cycle.
//通知其他系统组件并且准备开始下一个分发周期,见2.38
onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
}


2.38 InputDispatcher.onDispatchCycleFinishedLocked()

void InputDispatcher::onDispatchCycleFinishedLocked(
nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doDispatchCycleFinishedLockedInterruptible);//将任务放入任务队列,随后执行doDispatchCycleFinishedLockedInterruptible,见2.39
commandEntry->connection = connection;
commandEntry->eventTime = currentTime;
commandEntry->seq = seq;
commandEntry->handled = handled;
}


2.39 InputDispatcher.doDispatchCycleFinishedLockedInterruptible()

void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
CommandEntry* commandEntry) {

sp<Connection> connection = commandEntry->connection;
nsecs_t finishTime = commandEntry->eventTime;
uint32_t seq = commandEntry->seq;
bool handled = commandEntry->handled;

DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);//寻找等待的DispatchEntry

if (dispatchEntry) {
nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;//计算事件分发所花费的时间
if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {//1.事件分发时间超过2s
String8 msg;
msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ",
connection->getWindowName(), eventDuration * 0.000001f);
dispatchEntry->eventEntry->appendDescription(msg);//打印出所有事件分发时间超过2s中的事件
ALOGI("%s", msg.string());
}

bool restartEvent;//是否需要重新处理
if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {//处理按键事件
KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
restartEvent = afterKeyEventLockedInterruptible(connection,
dispatchEntry, keyEntry, handled);
} else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {//处理触摸事件
MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
restartEvent = afterMotionEventLockedInterruptible(connection,
dispatchEntry, motionEntry, handled);
} else {
restartEvent = false;
}

// 将事件出队列,并开始处理下一个事件
if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
connection->waitQueue.dequeue(dispatchEntry);//2.事件出队列
traceWaitQueueLengthLocked(connection);
if (restartEvent && connection->status == Connection::STATUS_NORMAL) {//需要重新处理该事件
connection->outboundQueue.enqueueAtHead(dispatchEntry);//放入输入队列的首部
traceOutboundQueueLengthLocked(connection);
} else {
releaseDispatchEntryLocked(dispatchEntry);//释放dispatchEntry
}
}

//3.启动下一个循环,见2.15
startDispatchCycleLocked(now(), connection);
}
}


在该方法中,首先计算事件分发所花费的时间,如果大于2s的话,则打印出该事件;接着将DispatcherEntry事件从等待队列中移除;最后通过startDispatchCycleLocked()方法启动下一个循环。

在2.38中,通过postCommandLocked()方法加入的任务不会理解执行,而是需要通过runCommandsLockedInterruptible()方法来执行任务队列中任务。返回到2.35中,执行完finishDispatchCycleLocked()方法之后,会马上执行runCommandsLockedInterruptible()方法。

2.40 InputDispatcher.runCommandsLockedInterruptible()

bool InputDispatcher::runCommandsLockedInterruptible() {
if (mCommandQueue.isEmpty()) {//队列为空,则直接返回
return false;
}

do {
CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();//会去任务队列头部的任务

Command command = commandEntry->command;
(this->*command)(commandEntry); //执行任务,此处调用的命令隐式地包含'LockedInterruptible'

commandEntry->connection.clear();
delete commandEntry;//删除任务
} while (! mCommandQueue.isEmpty());
return true;
}


该方法的逻辑比较简单,只是不断地从mCommandQueue队列取出命令,然后执行直到全部执行完成。 除了doPokeUserActivityLockedInterruptible,还有其他如下命令:

doNotifyANRLockedInterruptible

doInterceptKeyBeforeDispatchingLockedInterruptible

doDispatchCycleFinishedLockedInterruptible

doNotifyInputChannelBrokenLockedInterruptible

doNotifyConfigurationChangedInterruptible

至此,完成了从应用程序通知InputDispatcher,输入事件处理完成了,并启动下一个输入事件处理流程的过程。

3.总结

当InputDispatcher线程从InputReader线程中获取到输入事件后,需要将输入事件分发给应用程序激活的Activity窗口。其中包含了两个过程:

从InputDispatcher线程将输入事件分发给应用程序窗口处理,其处理流程见2.1~2.28过程。通过InputChannel的sendMessage()方法往server端套接字写入输入事件消息,唤醒在client端套接字上epoll_wait等待的事件,调用回调方法NativeInputEventReceiver.handleEvent()处理输入事件。通过调用InputChannel的receiveMessage()方法读取InputDispatcher发送的输入事件,最终交给应用程序的窗口处理。

从应用程序处理完输入事件到InputDispatcher线程开启下一个输入事件处理,其处理流程见2.29~2.40过程。通过InputChannel的sendMessage()方法往client端套接字写入输入事件处理完成消息,唤醒在server端套接字上epoll_wait等待的事件,调用回调方法InputDispatcher.handleReceiveCallback()处理输入结束事件。通过startDispatchCycleLocked()方法开始下一个输入事件处理流程;

在server端和client端分别创建了输入通道InputChannel,它们之间是通过一个socketpair连接起来的,socketpair()函数建立的是一对匿名的套接字,可以实现在同一个文件描述符中实现读写功能。socketpair与管道pipe的区别是,socketpair建立的通道是双向的,即每一端都可以进行读写,只是有一点需要注意,在一端写入,只能在另外一端读出,在写入一端读出时,会阻塞。因此我们可以看到,在InputDispatcher线程将输入事件分发给应用程序处理的过程,是在server端套接字写入,只能在client端套接字读出,唤醒的是NativeInputEventReceiver.handleEvent()回调方法。虽然在server端和client端都通过Looper->addFd()方法,监听了套接字描述符中有数据可读的场景,但只有一端套接字描述符会响应,因为socketpair同时只有一端可以读,另外一端只能写。同样的,从应用程序处理完输入事件到InputDispatcher线程开启下一个输入事件的过程,是在client端套接字写入,只能在server端套接字读出,唤醒的是InputDispatcher.handleReceiveCallback()回调方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息