概述
上一个章节,我们讲解了App通过注册InputEventReceiver获取从Input服务上报的输入事件的流程,在讲述App处理具体输入事件之前,我们讲述App处理输入事件的模型,也就是本章要讲述的InputState Pipeline。
源码路径
frameworks/base/core/java/android/view/ViewRootImpl.java
Input事件处理模型
View Input事件处理的Pipeline模型建立在InputStage这个抽象接口基础之上,我们这里先讲述InputStage的实现,我们只列出InputStage的核心接口实现,如下所示:
abstract class InputStage {
private final InputStage mNext;
protected static final int FORWARD = 0;
protected static final int FINISH_HANDLED = 1;
protected static final int FINISH_NOT_HANDLED = 2;
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));
}
}
protected void finish(QueuedInputEvent q, boolean handled) {
q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
if (handled) {
q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
}
forward(q);
}
protected void forward(QueuedInputEvent q) {
onDeliverToNext(q);
}
protected void apply(QueuedInputEvent q, int result) {
if (result == FORWARD) {
forward(q);
} else if (result == FINISH_HANDLED) {
finish(q, true);
} else if (result == FINISH_NOT_HANDLED) {
finish(q, false);
} else {
throw new IllegalArgumentException("Invalid result: " + result);
}
}
protected int onProcess(QueuedInputEvent q) {
return FORWARD;
}
protected void onDeliverToNext(QueuedInputEvent q) {
if (DEBUG_INPUT_STAGES) {
Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
}
if (mNext != null) {
mNext.deliver(q);
} else {
finishInputEvent(q);
}
}
}
1、deliver的实现,因为他决定input事件处理方式方法实现如下:
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));
}
}
deliver的核心逻辑,如下所示:
a、当前input事件直接被转发到下一级的InputStage进行处理 forward;
b、如果input事件在当前InputStage中被丢弃了,直接设置input事件被处理完成标记,并转发给下一级的InputStage;
c、当前InputStage进行处理调用process方法,然后根据处理的结果,决定input输入事件,是否向下一级的InputStage进行处理;
2、finish的实现非常简单,将事件打上FINISHED标签,然后转发;
protected void finish(QueuedInputEvent q, boolean handled) {
q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
if (handled) {
q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
}
// 当前InputStage不再处理,直接转发
forward(q);
}
3、forward 转发给下一级的InputStage处理
protected void forward(QueuedInputEvent q) {
onDeliverToNext(q);
}
4、apply 根据result结果,其本质也就是调用onProcess的返回结果,然后决定input事件下一步的处理方式。
protected void apply(QueuedInputEvent q, int result) {
if (result == FORWARD) {
forward(q);
} else if (result == FINISH_HANDLED) {
finish(q, true);
} else if (result == FINISH_NOT_HANDLED) {
finish(q, false);
} else {
throw new IllegalArgumentException("Invalid result: " + result);
}
}
5、onProcess 的默认行为是转发。子类可以覆盖其实现,决定input事件的处理方式;
protected int onProcess(QueuedInputEvent q) {
return FORWARD;
}
6、onDeliverToNext 直接转发给下一级的InputStage进行处理
protected void onDeliverToNext(QueuedInputEvent q) {
if (DEBUG_INPUT_STAGES) {
Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
}
if (mNext != null) {
mNext.deliver(q);
} else {
finishInputEvent(q);
}
}
7、finishInputEvent 结束事件的处理流程。然后直接将处理结果返回给InputEventReceiver处理。
private void finishInputEvent(QueuedInputEvent q) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
q.mEvent.getSequenceNumber());
if (q.mReceiver != null) {
boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
q.mReceiver.finishInputEvent(q.mEvent, handled);
} else {
q.mEvent.recycleIfNeededAfterDispatch();
}
recycleQueuedInputEvent(q);
}
Input Pipeline的建立
Input Pipeline的建立,是在ViewRootImpl中的setView方法中,如下所示:
void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
......
// Set up the input pipeline.
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;
mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
......
}
整个流水线的连接过程我们不再描述,最终建立起来了如下所示的流水线结构,流水从左向右进行执行,流水的起点由mFirstInputStage或者mFirstPostImeInputStage开始。
总结
本文描述了View处理input事件的Pipeline模型的实现,下一个章节讲述App处理input事件的具体过程。