1.源码解析

  1. /**
  2. * Base class for implementing a stage in the chain of responsibility
  3. * for processing input events.
  4. * <p>
  5. * Events are delivered to the stage by the {@link #deliver} method. The stage
  6. * then has the choice of finishing the event or forwarding it to the next stage.
  7. * </p>
  8. */
  9. abstract class InputStage {
  10. private final InputStage mNext;//下一个节点
  11. protected static final int FORWARD = 0;//onProcess()处理后的结果值之一
  12. protected static final int FINISH_HANDLED = 1;//onProcess()处理后的结果之一
  13. protected static final int FINISH_NOT_HANDLED = 2;//onProcess()处理后的结果之一
  14. private String mTracePrefix;//用于android SystemTrace调试使用的前缀标志字符串
  15. /**
  16. * Creates an input stage.
  17. * @param next The next stage to which events should be forwarded.
  18. */
  19. public InputStage(InputStage next) {
  20. mNext = next;
  21. }
  22. /**
  23. * Delivers an event to be processed.
  24. */
  25. public final void deliver(QueuedInputEvent q) {
  26. if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
  27. forward(q);
  28. } else if (shouldDropInputEvent(q)) {
  29. finish(q, false);
  30. } else {
  31. traceEvent(q, Trace.TRACE_TAG_VIEW);
  32. final int result;
  33. try {
  34. result = onProcess(q);
  35. } finally {
  36. Trace.traceEnd(Trace.TRACE_TAG_VIEW);
  37. }
  38. apply(q, result);
  39. }
  40. }
  41. /**
  42. * Marks the input event as finished then forwards it to the next stage.
  43. */
  44. protected void finish(QueuedInputEvent q, boolean handled) {
  45. q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
  46. if (handled) {
  47. q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
  48. }
  49. forward(q);
  50. }
  51. /**
  52. * Forwards the event to the next stage.
  53. */
  54. protected void forward(QueuedInputEvent q) {
  55. onDeliverToNext(q);
  56. }
  57. /**
  58. * Applies a result code from {@link #onProcess} to the specified event.
  59. */
  60. protected void apply(QueuedInputEvent q, int result) {
  61. if (result == FORWARD) {
  62. forward(q);
  63. } else if (result == FINISH_HANDLED) {
  64. finish(q, true);
  65. } else if (result == FINISH_NOT_HANDLED) {
  66. finish(q, false);
  67. } else {
  68. throw new IllegalArgumentException("Invalid result: " + result);
  69. }
  70. }
  71. /**
  72. * Called when an event is ready to be processed.
  73. * @return A result code indicating how the event was handled.
  74. */
  75. protected int onProcess(QueuedInputEvent q) {
  76. return FORWARD;
  77. }
  78. /**
  79. * Called when an event is being delivered to the next stage.
  80. */
  81. protected void onDeliverToNext(QueuedInputEvent q) {
  82. if (DEBUG_INPUT_STAGES) {
  83. Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
  84. }
  85. if (mNext != null) {
  86. mNext.deliver(q);
  87. } else {
  88. finishInputEvent(q);
  89. }
  90. }
  91. protected void onWindowFocusChanged(boolean hasWindowFocus) {
  92. if (mNext != null) {
  93. mNext.onWindowFocusChanged(hasWindowFocus);
  94. }
  95. }
  96. protected void onDetachedFromWindow() {
  97. if (mNext != null) {
  98. mNext.onDetachedFromWindow();
  99. }
  100. }
  101. protected boolean shouldDropInputEvent(QueuedInputEvent q) {
  102. if (mView == null || !mAdded) {
  103. Slog.w(mTag, "Dropping event due to root view being removed: " + q.mEvent);
  104. return true;
  105. } else if ((!mAttachInfo.mHasWindowFocus
  106. && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
  107. && !isAutofillUiShowing()) || mStopped
  108. || (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON))
  109. || (mPausedForTransition && !isBack(q.mEvent))) {
  110. // This is a focus event and the window doesn't currently have input focus or
  111. // has stopped. This could be an event that came back from the previous stage
  112. // but the window has lost focus or stopped in the meantime.
  113. if (isTerminalInputEvent(q.mEvent)) {
  114. // Don't drop terminal input events, however mark them as canceled.
  115. q.mEvent.cancel();
  116. Slog.w(mTag, "Cancelling event due to no window focus: " + q.mEvent);
  117. return false;
  118. }
  119. // Drop non-terminal input events.
  120. Slog.w(mTag, "Dropping event due to no window focus: " + q.mEvent);
  121. return true;
  122. }
  123. return false;
  124. }
  125. void dump(String prefix, PrintWriter writer) {
  126. if (mNext != null) {
  127. mNext.dump(prefix, writer);
  128. }
  129. }
  130. private boolean isBack(InputEvent event) {
  131. if (event instanceof KeyEvent) {
  132. return ((KeyEvent) event).getKeyCode() == KeyEvent.KEYCODE_BACK;
  133. } else {
  134. return false;
  135. }
  136. }
  137. private void traceEvent(QueuedInputEvent q, long traceTag) {
  138. if (!Trace.isTagEnabled(traceTag)) {
  139. return;
  140. }
  141. if (mTracePrefix == null) {
  142. mTracePrefix = getClass().getSimpleName();
  143. }
  144. Trace.traceBegin(traceTag, mTracePrefix + " id=0x"
  145. + Integer.toHexString(q.mEvent.getId()));
  146. }
  147. }

由上源码可分析得到InputStage调用deliver()方法后,内部方法调用流,如下图所示:
InputStage内部方法调用流程.png
观察该图可知,InputStage调用deliver()方法,最终可能会调用到下个节点的deliver或结束该事件的处理。也就是说具有链式传递调用的特性。
InputStage 设计成一个单向链表的节点,持有下一个节点的引用,其构造方法仅有一个,即下个节点作为参数的构造方法,在ViewRootImpl的setView(View,WindowManager.LayoutParams,View,int)方法中的最后面,创建了一条InputStage处理链,由各个InputStage的子类按顺序初始化,然后作为参数初始化下个节点,代码如下:

  1. // Set up the input pipeline.
  2. CharSequence counterSuffix = attrs.getTitle();
  3. mSyntheticInputStage = new SyntheticInputStage();
  4. InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
  5. InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
  6. "aq:native-post-ime:" + counterSuffix);
  7. InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
  8. InputStage imeStage = new ImeInputStage(earlyPostImeStage,
  9. "aq:ime:" + counterSuffix);
  10. InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
  11. InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
  12. "aq:native-pre-ime:" + counterSuffix);
  13. mFirstInputStage = nativePreImeStage;
  14. mFirstPostImeInputStage = earlyPostImeStage;

由上可知构建的InputStage链结构如下:
NativePreImeInputStage ===> ViewPreImeInputStage ===> ImeInputStage ===> EarlyPostImeInputStage ===> NativePostImeInputStage ===> ViewPostImeInputStage ===> SyetheticInputStage。在创建InputStage链后,将NativePreImeInputStage对象赋值给了 mFirstInputStage,从变量名也可知其指向处理链的头部,所以要追踪哪里开始经过这个处理链,就要追踪mFirstInputStage。