自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件
自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件
自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

前言

继续跟MediaSession,按键的分发。续接上文《简单跟一下MediaSession源码3》,对应MediaButton的监听我们已经跟到了PhoneFallbackEventHandler.java的dispatchKeyEvent()中。

今天继续跟,看看哪里调用dispatchKeyEvent()。

我这只关注down事件哈

正文

回到PhoneFallbackEventHandler.dispatchKeyEvent()

PhoneFallbackEventHandler.java

  1. frameworks\base\core\java\com\android\internal\policy\PhoneFallbackEventHandler.java
复制

PhoneFallbackEventHandler实现FallbackEventHandler接口,并重写了。

  1. public void setView(View v);
  2. public void preDispatchKeyEvent(KeyEvent event);
  3. public boolean dispatchKeyEvent(KeyEvent event);
复制
dispatchKeyEvent()
  1. public boolean dispatchKeyEvent(KeyEvent event) {
  2.   final int action = event.getAction();
  3.   final int keyCode = event.getKeyCode();
  4.   if (action == KeyEvent.ACTION_DOWN) {
  5.       return onKeyDown(keyCode, event);
  6.   } else {
  7.       return onKeyUp(keyCode, event);
  8.   }
  9. }
复制

返回true表示被消费了。

查询到调用dispatchKeyEvent()是在ViewRootImpl.java的processKeyEvent()中调用的。

ViewRootImpl.java

ViewRootImpl 是 View 的最高层级,是所有 View 的根。processKeyEvent()是看谁需要消费event事件。

当前我们只关注上一曲事件哈,其他的后续在看。

processKeyEvent()
  1. private int processKeyEvent(QueuedInputEvent q) {
  2. //下面都是看是否需要消费
  3.   final KeyEvent event = (KeyEvent)q.mEvent;
  4.   if (mUnhandledKeyManager.preViewDispatch(event)) {
  5.       return FINISH_HANDLED;
  6.   }
  7.   if (mView.dispatchKeyEvent(event)) {
  8.       return FINISH_HANDLED;
  9.   }
  10.   if (shouldDropInputEvent(q)) {
  11.       return FINISH_NOT_HANDLED;
  12.   }
  13.   if (mUnhandledKeyManager.dispatch(mView, event)) {
  14.       return FINISH_HANDLED;
  15.   }
  16.   //略
  17. //调用mFallbackEventHandler查看是否需要消费
  18. //这里消费了,因为符合条件。
  19.   if (mFallbackEventHandler.dispatchKeyEvent(event)) {
  20.       return FINISH_HANDLED;
  21.   }
  22. //略,后续的后续有机会分析,暂时不走下面
  23.   return FORWARD;
  24. }
复制

processKeyEvent()又在ViewPostImeInputStage.onProcess()中调佣的。

ViewPostImeInputStage.onProcess()

ViewPostImeInputStage是继承InputStage抽象类。

  1. @Override
  2. protected int onProcess(QueuedInputEvent q) {
  3. //当前发送的event是KeyEvent的实例
  4.   if (q.mEvent instanceof KeyEvent) {
  5.   //走这里
  6.       return processKeyEvent(q);
  7.   } else {
  8.       final int source = q.mEvent.getSource();
  9.       if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
  10.           return processPointerEvent(q);
  11.       } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
  12.           return processTrackballEvent(q);
  13.       } else {
  14.           return processGenericMotionEvent(q);
  15.       }
  16.   }
  17. }
复制

onProcess()是在其父类中InputStage.deliver()中调用的,ViewPostImeInputStage没有重写,因此调用时走起父类。

InputStage.deliver()

进入InputStage抽象类

  1. public final void deliver(QueuedInputEvent q) {
  2.   ViewDebugConfig.getInstance().debugInputStageDeliverd(this,
  3.           System.currentTimeMillis());
  4.   //看一下消费
  5.   if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
  6.       forward(q);
  7.   } else if (shouldDropInputEvent(q)) {
  8.       finish(q, false);
  9.   } else {
  10.   //走这里,我们这是88键值且为down事件
  11.       traceEvent(q, Trace.TRACE_TAG_VIEW);
  12.       final int result;
  13.       try {
  14.       //进入onProcess()处理流程,这里result返回值为0
  15.           result = onProcess(q);
  16.       } finally {
  17.           Trace.traceEnd(Trace.TRACE_TAG_VIEW);
  18.       }
  19.       // 接着进入
  20.       apply(q, result);
  21.   }
  22. }
复制

这里有两个重点:

  1. onProcess(),ViewPostImeInputStage重写了,进入ViewPostImeInputStage实现类中,也就是上面我们走的流程。

  2. apply(),ViewPostImeInputStage没有重新,进入InputStage类中。

下面看一下InputStage.apply()。

注意,上面result返回的是0,也就是FORWARD,具体看上面processKeyEvent()返回值。

InputStage.apply()
  1. protected void apply(QueuedInputEvent q, int result) {
  2.   if (result == FORWARD) {
  3.       forward(q);
  4.   } else if (result == FINISH_HANDLED) {
  5.       finish(q, true);
  6.   } else if (result == FINISH_NOT_HANDLED) {
  7.       finish(q, false);
  8.   } else {
  9.       throw new IllegalArgumentException("Invalid result: " + result);
  10.   }
  11. }
复制

InputStage中的forward()方法也没有被ViewPostImeInputStage重写,因此看InputStage。

InputStage.forward()
  1. protected void forward(QueuedInputEvent q) {
  2.   onDeliverToNext(q);
  3. }
复制

这里调用了onDeliverToNext()。

这里要注意,InputStage是抽象类,其子类好几个。这里打断一下,我看看看其子类的初始化哈。

setView()

InputStage子类初始化是在setView()中,

  1. public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
  2.       int userId) {
  3.   synchronized (this) {
  4.       if (mView == null) {
  5.           mView = view;
  6. //略
  7. //初始化InputStage子类
  8.           InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
  9.           InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
  10.                   "aq:native-post-ime:" + counterSuffix);
  11.           InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
  12.           InputStage imeStage = new ImeInputStage(earlyPostImeStage,
  13.                   "aq:ime:" + counterSuffix);
  14.           InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
  15.           InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
  16.                   "aq:native-pre-ime:" + counterSuffix);
  17.           mFirstInputStage = nativePreImeStage;
  18.           mFirstPostImeInputStage = earlyPostImeStage;
  19. //略
  20.       }
  21.   }
  22. }
复制

InputStage子类很多,然后我们会发现ViewPostImeInputStage对象会传入下一个InputStage子类对象中,并赋值给InputStage中定义的变量mNext中。

有点像栈,初始化时先进,退出时最后出。

所以后面onDeliverToNext()中判断mNext是否为null,不为null就事件继续传递。

有点乱,哈哈。

因此,这里要明白如果子类重写了onDeliverToNext(),就走子类,如果没有就走父类。如果mNext最后为null,就走finishInputEvent()。

InputStage.onDeliverToNext()

第一个SyntheticInputStage传入的mNext为null,其他的子类传入mNext不为null。

  1. protected void onDeliverToNext(QueuedInputEvent q) {
  2. //如果mNext不为null,走这里
  3.   if (mNext != null) {
  4.       mNext.deliver(q);
  5.   } else {
  6.       finishInputEvent(q);
  7.   }
  8. }
复制
deliverInputEvent()

回到上面,看一下哪里调用deliver()的,最后发现deliverInputEvent()调用的。

  1. private void deliverInputEvent(QueuedInputEvent q) {
  2. //略
  3.   try {
  4. //略
  5.       InputStage stage;
  6.       if (q.shouldSendToSynthesizer()) {
  7.           stage = mSyntheticInputStage;
  8.       } else {
  9.           stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
  10.       }
  11. //这里的mEvent是KeyEvent对象,我们这里只看发送的上一曲88事件
  12.       if (q.mEvent instanceof KeyEvent) {
  13.           try {
  14.               mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
  15.           } finally {
  16.               Trace.traceEnd(Trace.TRACE_TAG_VIEW);
  17.           }
  18.       }
  19. //不为null
  20.       if (stage != null) {
  21. //处理窗口焦点变化
  22.           handleWindowFocusChanged();
  23. //调用了deliver()
  24.           stage.deliver(q);
  25.       } else {
  26.           finishInputEvent(q);
  27.       }
  28.   } finally {
  29.       Trace.traceEnd(Trace.TRACE_TAG_VIEW);
  30.   }
  31. }
复制

这个方法是在doProcessInputEvents()中调用的。

doProcessInputEvents()
  1. void doProcessInputEvents() {
  2.   while (mPendingInputEventHead != null) {
  3. //队列,所有先赋值,然后取下一个
  4.       QueuedInputEvent q = mPendingInputEventHead;
  5. //取下一个
  6.       mPendingInputEventHead = q.mNext;
  7. //如果为null,把尾置为null
  8.       if (mPendingInputEventHead == null) {
  9.           mPendingInputEventTail = null;
  10.       }
  11.       q.mNext = null;
  12. //计数器减去一
  13.       mPendingInputEventCount -= 1;
  14.       mViewFrameInfo.setInputEvent(mInputEventAssigner.processEvent(q.mEvent));
  15. //调用deliverInputEvent处理队列中的QueuedInputEvent
  16.       deliverInputEvent(q);
  17.   }
  18.   if (mProcessInputEventsScheduled) {
  19.       mProcessInputEventsScheduled = false;
  20.       mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
  21.   }
  22. }
复制

这里用了循环处理队列中存在的InputEvent事件。

enqueueInputEvent()

添加事件到队列中,然后判断是否需要立即处理该事件。

  1. @UnsupportedAppUsage
  2. void enqueueInputEvent(InputEvent event,
  3.       InputEventReceiver receiver, int flags, boolean processImmediately) {
  4. //把事件添加到QueuedInputEvent
  5.   QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
  6. //看是否MotionEvent类型事件
  7.   if (event instanceof MotionEvent) {
  8.       MotionEvent me = (MotionEvent) event;
  9.       if (me.getAction() == MotionEvent.ACTION_CANCEL) {
  10.           EventLog.writeEvent(EventLogTags.VIEW_ENQUEUE_INPUT_EVENT, "Motion - Cancel",
  11.                   getTitle().toString());
  12.       }
  13.   } else if (event instanceof KeyEvent) {
  14. //KeyEvent事件
  15.       KeyEvent ke = (KeyEvent) event;
  16.   }
  17.   QueuedInputEvent last = mPendingInputEventTail;
  18. //如果队列尾为null,也就是里面没有数据,赋值
  19.   if (last == null) {
  20. //这里赋值mPendingInputEventHead和mPendingInputEventTail
  21.       mPendingInputEventHead = q;
  22.       mPendingInputEventTail = q;
  23.   } else {
  24.       last.mNext = q;
  25.       mPendingInputEventTail = q;
  26.   }
  27. //事件计数器+1
  28.   mPendingInputEventCount += 1;
  29. //传入的是true,立即处理
  30.   if (processImmediately) {
  31.       doProcessInputEvents();
  32.   } else {
  33.       scheduleProcessInputEvents();
  34.   }
  35. }
复制

上面方便是在onInputEvent()调用的。

WindowInputEventReceiver.onInputEvent()
  1. @Override
  2. public void onInputEvent(InputEvent event) {
  3.   ViewDebugConfig.getInstance().debugInputEventStart(event);
  4.   List<InputEvent> processedEvents;
  5.   try {
  6. //方法中有对事件类型判断,如果不是MotionEvent,一定返回null
  7. //我们这里是Keyevent事件
  8.       processedEvents =
  9.           mInputCompatProcessor.processInputEventForCompatibility(event);
  10.   } finally {
  11.       Trace.traceEnd(Trace.TRACE_TAG_VIEW);
  12.   }
  13. //processedEvents为null
  14.   if (processedEvents != null) {
  15. //略
  16.   } else {
  17. //dropIfNeeded()返回的是false,反一下就为true,调用enqueueInputEvent
  18.       if (!dropIfNeeded(event)) {
  19.           enqueueInputEvent(event, this, 0, true);
  20.       } else {
  21.           finishInputEvent(event, true);
  22.       }
  23.   }
  24. }
复制

这里WindowInputEventReceiver很重要,是ViewRootImpl接受Event事件的分发地方。这里暂时不介绍,有兴趣可以看参考文。

到此,发送的上一曲键值88就从这开始分发的。

后续专门介绍WindowInputEventReceiver。

参考文章

  1. Android InputEventReceiver事件接收流程分析

  2. 当你触摸屏幕时手机都干了什么?你必须知道的Android事件传递

自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

相关文章

自动化零件服务商 - 供应SMC,FESTO,CKD全新正品气动元件

暂无评论

none
暂无评论...