Link:
Android Input (1) -- InputManagerService启动
Android Input (2) -- inputReader
Android Input (3) -- inputDispatcher
Android Input (4) -- inputDispatcher到ViewRootImpl
Android Input (5) -- ViewRootImpl 的事件分发(Activity ViewGroup View )
Android Input (6) -- PhoneWindowManager中Power,BACK等按键处理流程
Android Input (7) -- 模块的锁检测
Android Input (8) -- ANR input event原理
InputDispatcher总结:
目录
1.1 InputDispatcherThread threadLoop()
1.2 dispatchOnceInnerLocked
2.1 InputDispatcher::dispatchMotionLocked
2.2 InputDispatcher::findTouchedWindowTargetsLocked
2.3 handleTargetsNotReadyLocked
2.4 dispatchEventLocked
2.5 prepareDispatchCycleLocked
2.6 enqueueDispatchEntryLocked
2.7 startDispatchCycleLocked
2.8 publishMotionEvent和publishKeyEvent
@frameworks/native/services/inputflinger/InputDispatcher.cpp
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
//唤醒等待线程,monitor()用于监控dispatcher是否发生死锁
mDispatcherIsAliveCondition.broadcast();
if (!haveCommandsLocked()) { 第一次haveCommandsLocked为false,执行dispatchOnceInnerLocked
dispatchOnceInnerLocked(&nextWakeupTime);
}
} // release lock
...
mLooper->pollOnce(timeoutMillis); //inputReader读取事件最后把事件放入minBoundQueue后,调用loop::wake唤醒inputDispatcher
}
bool InputDispatcher::haveCommandsLocked() const {
return !mCommandQueue.isEmpty();
}
线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now(); //当前时间
if (! mPendingEvent) {
if (mInboundQueue.isEmpty()) {
if (isAppSwitchDue) {
} else {
// Inbound queue has at least one entry.
mPendingEvent = mInboundQueue.dequeueAtHead(); //取出mInboundQueue头部事件
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
// Get ready to dispatch the event.
resetANRTimeoutsLocked(); //重置ANR信息
}
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast(mPendingEvent);
if (isAppSwitchDue) { //isAppSwitchDue app切换延迟,当切换超时,则抢占分发,丢弃其他所有即将要处理的事件。
if (isAppSwitchKeyEventLocked(typedEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
dropReason = DROP_REASON_APP_SWITCH; //drop
}
}
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime); //分发key按键事件
break;
}
case EventEntry::TYPE_MOTION: {
done = dispatchMotionLocked(currentTime, typedEntry, //分发motion触摸事件
&dropReason, nextWakeupTime);
break;
}
//分发操作完成,则进入该分支
if (done) {
if (dropReason != DROP_REASON_NOT_DROPPED) {
dropInboundEventLocked(mPendingEvent, dropReason);
}
mLastDropReason = dropReason;
releasePendingEventLocked();//释放pending事件
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
在enqueueInboundEventLocked()的过程中已设置mAppSwitchDueTime等于eventTime加上500ms:
mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
该方法主要功能:
1.mDispatchFrozen用于决定是否冻结事件分发工作不再往下执行;
2.当事件分发的时间点距离该事件加入mInboundQueue的时间超过500ms,则认为app切换过期,即isAppSwitchDue=true;
3.mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量;并重置ANR时间;
4.根据EventEntry的type类型分别处理,比如按键调用dispatchKeyLocked分发事件,触摸事件调用dispatchMotionLocked分发事件;再根据分发结果来决定是否进入done;
执行完成(done)的处理:
5.根据dropReason(默认NOT_DROPPED不处理)来决定是否丢失事件:dropInboundEventLocked
6.释放当前正在处理的事件(即mPendingEvent):releasePendingEventLocked
//dispatchMotionLocked和dispatchKeyLocked最后都会调用dispatchEventLocked来分发事件
bool InputDispatcher::dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
...
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
// Identify targets.
Vector inputTargets;
bool conflictingPointerActions = false;
int32_t injectionResult;
if (isPointerEvent) { //点事件判断 findTouchedWindowTargetsLocked
// Pointer event. (eg. touchscreen)
injectionResult = findTouchedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
} else {
// Non touch event. (eg. trackball)
injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
}
...
addMonitoringTargetsLocked(inputTargets);
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
主要工作
分发事件
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const MotionEntry* entry, Vector& inputTargets, nsecs_t* nextWakeupTime,
bool* outConflictingPointerActions) {
enum InjectionPermission {
INJECTION_PERMISSION_UNKNOWN,
INJECTION_PERMISSION_GRANTED,
INJECTION_PERMISSION_DENIED
};
nsecs_t startTime = now();
......
// Ensure all touched foreground windows are ready for new input.
for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
// Check whether the window is ready for more input.
String8 reason = checkWindowReadyForMoreInputLocked(currentTime,
touchedWindow.windowHandle, entry, "touched");
if (!reason.isEmpty()) {
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
NULL, touchedWindow.windowHandle, nextWakeupTime, reason.string());
goto Unresponsive;
}
}
}
......
for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
touchedWindow.pointerIds, inputTargets);
}
......
return injectionResult;
}
@InputDispatcher.cpp
int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
const EventEntry* entry,
const sp& applicationHandle,
const sp& windowHandle,
nsecs_t* nextWakeupTime, const char* reason) {
if (applicationHandle == NULL && windowHandle == NULL) {
} else {
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
nsecs_t timeout;
if (windowHandle != NULL) {
} else {
timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT; //5s
}
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
mInputTargetWaitStartTime = currentTime;
mInputTargetWaitTimeoutTime = currentTime + timeout; //anr 5s时间
}
}
if (currentTime >= mInputTargetWaitTimeoutTime) {
onANRLocked(currentTime, applicationHandle, windowHandle,
entry->eventTime, mInputTargetWaitStartTime, reason); //onANRLocked
} else {
}
}
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector& inputTargets) {
pokeUserActivityLocked(eventEntry); //向mCommandQueue队列添加doPokeUserActivityLockedInterruptible命令
for (size_t i = 0; i < inputTargets.size(); i++) {
const InputTarget& inputTarget = inputTargets.itemAt(i);
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
if (connectionIndex >= 0) {
sp connection = mConnectionsByFd.valueAt(connectionIndex);
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget); //找到目标连接
} else {
#if DEBUG_FOCUS
ALOGD("Dropping event delivery to target with channel '%s' because it "
"is no longer registered with the input dispatcher.",
inputTarget.inputChannel->getName().string()); //Dropping event log
#endif
}
}
}
该方法主要功能是将eventEntry发送到目标inputTargets.
其中pokeUserActivityLocked(eventEntry)方法最终会调用到Java层的PowerManagerService.java中的userActivityFromNative()方法. 这也是PMS中唯一的native call方法.
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
...
// Not splitting. Enqueue dispatch entries for the event as is.
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
bool wasEmpty = connection->outboundQueue.isEmpty();
//根据dispatchMode来分别执行DispatchEntry事件加入队列的操作
// Enqueue dispatch entries for the requested modes.
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
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);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.isEmpty()) {
startDispatchCycleLocked(currentTime, connection); //当原先的outbound队列为空, 且当前outbound不为空的情况执行.
}
}
该方法主要功能:
void InputDispatcher::enqueueDispatchEntryLocked(
const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
int32_t dispatchMode) {
inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
//构建DispatchEntry
DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
inputTarget->scaleFactor);
// Apply target flags and update the connection's input state.
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
...
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast(eventEntry);
...
break;
}
// Remember that we are waiting for this dispatch to complete.
if (dispatchEntry->hasForegroundTarget()) {
incrementPendingForegroundDispatchesLocked(eventEntry);
}
//添加到outboundQueue队尾
// Enqueue the dispatch entry.
connection->outboundQueue.enqueueAtTail(dispatchEntry);
traceOutboundQueueLengthLocked(connection);
}
根据dispatchMode来决定是否需要加入outboundQueue队列;
根据EventEntry,来生成DispatchEntry事件;
将dispatchEntry加入到connection的outbound队列.
执行到这里,其实等于由做了一次搬运的工作,将InputDispatcher中mInboundQueue中的事件取出后, 找到目标window后,封装dispatchEntry加入到connection的outbound队列.'
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp& connection) {
while (connection->status == Connection::STATUS_NORMAL
&& !connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.head; //get dispatchEntry
dispatchEntry->deliveryTime = currentTime;
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast(eventEntry); //keyEntry
// Publish the key event.
status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq, //publishKeyEvent
keyEntry->deviceId, keyEntry->source,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
keyEntry->keyCode, keyEntry->scanCode,
keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
keyEntry->eventTime);
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast(eventEntry); //motionEntry
// Publish the motion event.
status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq, //publishMotionEvent
motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
dispatchEntry->resolvedAction, motionEntry->actionButton,
dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
motionEntry->metaState, motionEntry->buttonState,
xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, motionEntry->eventTime,
motionEntry->pointerCount, motionEntry->pointerProperties,
usingCoords);
break;
}
...
//从outboundQueue中取出事件,重新放入waitQueue队列
connection->outboundQueue.dequeue(dispatchEntry);
connection->waitQueue.enqueueAtTail(dispatchEntry);
}
}
publishMotionEvent执行结果status不等于OK的情况下:
WOULD_BLOCK,且waitQueue等于空,则调用abortBrokenDispatchCycleLocked(),该方法最终会调用到Java层的IMS.notifyInputChannelBroken().
WOULD_BLOCK,且waitQueue不等于空,则处于阻塞状态,即inputPublisherBlocked=true
其他情况,则调用abortBrokenDispatchCycleLocked
abortBrokenDispatchCycleLocked()方法最终会调用到Java层的IMS.notifyInputChannelBroken().
//publishMotionEvent和publishKeyEvent都是把event封装到msg里面,发送出去
@frameworks/native/libs/input/InputTransport.cpp
status_t InputPublisher::publishMotionEvent(
...
InputMessage msg;
msg.header.type = InputMessage::TYPE_MOTION;
msg.body.motion.seq = seq;
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
msg.body.motion.displayId = displayId;
msg.body.motion.action = action;
msg.body.motion.actionButton = actionButton;
msg.body.motion.flags = flags;
msg.body.motion.edgeFlags = edgeFlags;
msg.body.motion.metaState = metaState;
msg.body.motion.buttonState = buttonState;
msg.body.motion.xOffset = xOffset;
msg.body.motion.yOffset = yOffset;
msg.body.motion.xPrecision = xPrecision;
msg.body.motion.yPrecision = yPrecision;
msg.body.motion.downTime = downTime;
msg.body.motion.eventTime = eventTime;
msg.body.motion.pointerCount = pointerCount;
for (uint32_t i = 0; i < pointerCount; i++) {
msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);
msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
}
return mChannel->sendMessage(&msg); //sendMessage
}
status_t InputPublisher::publishKeyEvent(
...
return mChannel->sendMessage(&msg); //sendMessage
}
InputPublisher::InputPublisher(const sp& channel) :
mChannel(channel) {
}