1.源码解析
/*** Base class for implementing a stage in the chain of responsibility* for processing input events.* <p>* Events are delivered to the stage by the {@link #deliver} method. The stage* then has the choice of finishing the event or forwarding it to the next stage.* </p>*/abstract class InputStage {private final InputStage mNext;//下一个节点protected static final int FORWARD = 0;//onProcess()处理后的结果值之一protected static final int FINISH_HANDLED = 1;//onProcess()处理后的结果之一protected static final int FINISH_NOT_HANDLED = 2;//onProcess()处理后的结果之一private String mTracePrefix;//用于android SystemTrace调试使用的前缀标志字符串/*** Creates an input stage.* @param next The next stage to which events should be forwarded.*/public InputStage(InputStage next) {mNext = next;}/*** Delivers an event to be processed.*/public final void deliver(QueuedInputEvent q) {if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {forward(q);} else if (shouldDropInputEvent(q)) {finish(q, false);} else {traceEvent(q, Trace.TRACE_TAG_VIEW);final int result;try {result = onProcess(q);} finally {Trace.traceEnd(Trace.TRACE_TAG_VIEW);}apply(q, result);}}/*** Marks the input event as finished then forwards it to the next stage.*/protected void finish(QueuedInputEvent q, boolean handled) {q.mFlags |= QueuedInputEvent.FLAG_FINISHED;if (handled) {q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;}forward(q);}/*** Forwards the event to the next stage.*/protected void forward(QueuedInputEvent q) {onDeliverToNext(q);}/*** Applies a result code from {@link #onProcess} to the specified event.*/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);}}/*** Called when an event is ready to be processed.* @return A result code indicating how the event was handled.*/protected int onProcess(QueuedInputEvent q) {return FORWARD;}/*** Called when an event is being delivered to the next stage.*/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);}}protected void onWindowFocusChanged(boolean hasWindowFocus) {if (mNext != null) {mNext.onWindowFocusChanged(hasWindowFocus);}}protected void onDetachedFromWindow() {if (mNext != null) {mNext.onDetachedFromWindow();}}protected boolean shouldDropInputEvent(QueuedInputEvent q) {if (mView == null || !mAdded) {Slog.w(mTag, "Dropping event due to root view being removed: " + q.mEvent);return true;} else if ((!mAttachInfo.mHasWindowFocus&& !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)&& !isAutofillUiShowing()) || mStopped|| (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON))|| (mPausedForTransition && !isBack(q.mEvent))) {// This is a focus event and the window doesn't currently have input focus or// has stopped. This could be an event that came back from the previous stage// but the window has lost focus or stopped in the meantime.if (isTerminalInputEvent(q.mEvent)) {// Don't drop terminal input events, however mark them as canceled.q.mEvent.cancel();Slog.w(mTag, "Cancelling event due to no window focus: " + q.mEvent);return false;}// Drop non-terminal input events.Slog.w(mTag, "Dropping event due to no window focus: " + q.mEvent);return true;}return false;}void dump(String prefix, PrintWriter writer) {if (mNext != null) {mNext.dump(prefix, writer);}}private boolean isBack(InputEvent event) {if (event instanceof KeyEvent) {return ((KeyEvent) event).getKeyCode() == KeyEvent.KEYCODE_BACK;} else {return false;}}private void traceEvent(QueuedInputEvent q, long traceTag) {if (!Trace.isTagEnabled(traceTag)) {return;}if (mTracePrefix == null) {mTracePrefix = getClass().getSimpleName();}Trace.traceBegin(traceTag, mTracePrefix + " id=0x"+ Integer.toHexString(q.mEvent.getId()));}}
由上源码可分析得到InputStage调用deliver()方法后,内部方法调用流,如下图所示:
观察该图可知,InputStage调用deliver()方法,最终可能会调用到下个节点的deliver或结束该事件的处理。也就是说具有链式传递调用的特性。
InputStage 设计成一个单向链表的节点,持有下一个节点的引用,其构造方法仅有一个,即下个节点作为参数的构造方法,在ViewRootImpl的setView(View,WindowManager.LayoutParams,View,int)方法中的最后面,创建了一条InputStage处理链,由各个InputStage的子类按顺序初始化,然后作为参数初始化下个节点,代码如下:
// 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;
由上可知构建的InputStage链结构如下:
NativePreImeInputStage ===> ViewPreImeInputStage ===> ImeInputStage ===> EarlyPostImeInputStage ===> NativePostImeInputStage ===> ViewPostImeInputStage ===> SyetheticInputStage。在创建InputStage链后,将NativePreImeInputStage对象赋值给了 mFirstInputStage,从变量名也可知其指向处理链的头部,所以要追踪哪里开始经过这个处理链,就要追踪mFirstInputStage。
