前言
继续跟MediaSession,按键的分发。续接上文《》,对应MediaButton的监听我们已经跟到了PhoneFallbackEventHandler.java的dispatchKeyEvent()中。
今天继续跟,看看哪里调用dispatchKeyEvent()。
我这只关注down事件哈
正文
回到PhoneFallbackEventHandler.dispatchKeyEvent()
PhoneFallbackEventHandler.java
frameworks\base\core\java\com\android\internal\policy\PhoneFallbackEventHandler.java
PhoneFallbackEventHandler实现FallbackEventHandler接口,并重写了。
public void setView(View v); public void preDispatchKeyEvent(KeyEvent event); public boolean dispatchKeyEvent(KeyEvent event);
dispatchKeyEvent()
public boolean dispatchKeyEvent(KeyEvent event) { final int action = event.getAction(); final int keyCode = event.getKeyCode(); if (action == KeyEvent.ACTION_DOWN) { return onKeyDown(keyCode, event); } else { return onKeyUp(keyCode, event); } }
返回true表示被消费了。
查询到调用dispatchKeyEvent()是在ViewRootImpl.java的processKeyEvent()中调用的。
ViewRootImpl.java
ViewRootImpl 是 View 的最高层级,是所有 View 的根。processKeyEvent()是看谁需要消费event事件。
当前我们只关注上一曲事件哈,其他的后续在看。
processKeyEvent()
private int processKeyEvent(QueuedInputEvent q) { //下面都是看是否需要消费 final KeyEvent event = (KeyEvent)q.mEvent; if (mUnhandledKeyManager.preViewDispatch(event)) { return FINISH_HANDLED; } if (mView.dispatchKeyEvent(event)) { return FINISH_HANDLED; } if (shouldDropInputEvent(q)) { return FINISH_NOT_HANDLED; } if (mUnhandledKeyManager.dispatch(mView, event)) { return FINISH_HANDLED; } //略 //调用mFallbackEventHandler查看是否需要消费 //这里消费了,因为符合条件。 if (mFallbackEventHandler.dispatchKeyEvent(event)) { return FINISH_HANDLED; } //略,后续的后续有机会分析,暂时不走下面 return FORWARD; }
processKeyEvent()又在ViewPostImeInputStage.onProcess()中调佣的。
ViewPostImeInputStage.onProcess()
ViewPostImeInputStage是继承InputStage抽象类。
@Override protected int onProcess(QueuedInputEvent q) { //当前发送的event是KeyEvent的实例 if (q.mEvent instanceof KeyEvent) { //走这里 return processKeyEvent(q); } else { final int source = q.mEvent.getSource(); if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { return processPointerEvent(q); } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) { return processTrackballEvent(q); } else { return processGenericMotionEvent(q); } } }
onProcess()是在其父类中InputStage.deliver()中调用的,ViewPostImeInputStage没有重写,因此调用时走起父类。
InputStage.deliver()
进入InputStage抽象类
public final void deliver(QueuedInputEvent q) { ViewDebugConfig.getInstance().debugInputStageDeliverd(this, System.currentTimeMillis()); //看一下消费 if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) { forward(q); } else if (shouldDropInputEvent(q)) { finish(q, false); } else { //走这里,我们这是88键值且为down事件 traceEvent(q, Trace.TRACE_TAG_VIEW); final int result; try { //进入onProcess()处理流程,这里result返回值为0 result = onProcess(q); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } // 接着进入 apply(q, result); } }
这里有两个重点:
onProcess(),ViewPostImeInputStage重写了,进入ViewPostImeInputStage实现类中,也就是上面我们走的流程。
apply(),ViewPostImeInputStage没有重新,进入InputStage类中。
下面看一下InputStage.apply()。
注意,上面result返回的是0,也就是FORWARD,具体看上面processKeyEvent()返回值。
InputStage.apply()
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); } }
InputStage中的forward()方法也没有被ViewPostImeInputStage重写,因此看InputStage。
InputStage.forward()
protected void forward(QueuedInputEvent q) { onDeliverToNext(q); }
这里调用了onDeliverToNext()。
这里要注意,InputStage是抽象类,其子类好几个。这里打断一下,我看看看其子类的初始化哈。
setView()
InputStage子类初始化是在setView()中,
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) { synchronized (this) { if (mView == null) { mView = view; //略 //初始化InputStage子类 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子类很多,然后我们会发现ViewPostImeInputStage对象会传入下一个InputStage子类对象中,并赋值给InputStage中定义的变量mNext中。
有点像栈,初始化时先进,退出时最后出。
所以后面onDeliverToNext()中判断mNext是否为null,不为null就事件继续传递。
有点乱,哈哈。
因此,这里要明白如果子类重写了onDeliverToNext(),就走子类,如果没有就走父类。如果mNext最后为null,就走finishInputEvent()。
InputStage.onDeliverToNext()
第一个SyntheticInputStage传入的mNext为null,其他的子类传入mNext不为null。
protected void onDeliverToNext(QueuedInputEvent q) { //如果mNext不为null,走这里 if (mNext != null) { mNext.deliver(q); } else { finishInputEvent(q); } }
deliverInputEvent()
回到上面,看一下哪里调用deliver()的,最后发现deliverInputEvent()调用的。
private void deliverInputEvent(QueuedInputEvent q) { //略 try { //略 InputStage stage; if (q.shouldSendToSynthesizer()) { stage = mSyntheticInputStage; } else { stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage; } //这里的mEvent是KeyEvent对象,我们这里只看发送的上一曲88事件 if (q.mEvent instanceof KeyEvent) { try { mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } //不为null if (stage != null) { //处理窗口焦点变化 handleWindowFocusChanged(); //调用了deliver() stage.deliver(q); } else { finishInputEvent(q); } } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } }
这个方法是在doProcessInputEvents()中调用的。
doProcessInputEvents()
void doProcessInputEvents() { while (mPendingInputEventHead != null) { //队列,所有先赋值,然后取下一个 QueuedInputEvent q = mPendingInputEventHead; //取下一个 mPendingInputEventHead = q.mNext; //如果为null,把尾置为null if (mPendingInputEventHead == null) { mPendingInputEventTail = null; } q.mNext = null; //计数器减去一 mPendingInputEventCount -= 1; mViewFrameInfo.setInputEvent(mInputEventAssigner.processEvent(q.mEvent)); //调用deliverInputEvent处理队列中的QueuedInputEvent deliverInputEvent(q); } if (mProcessInputEventsScheduled) { mProcessInputEventsScheduled = false; mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS); } }
这里用了循环处理队列中存在的InputEvent事件。
enqueueInputEvent()
添加事件到队列中,然后判断是否需要立即处理该事件。
@UnsupportedAppUsage void enqueueInputEvent(InputEvent event, InputEventReceiver receiver, int flags, boolean processImmediately) { //把事件添加到QueuedInputEvent QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags); //看是否MotionEvent类型事件 if (event instanceof MotionEvent) { MotionEvent me = (MotionEvent) event; if (me.getAction() == MotionEvent.ACTION_CANCEL) { EventLog.writeEvent(EventLogTags.VIEW_ENQUEUE_INPUT_EVENT, "Motion - Cancel", getTitle().toString()); } } else if (event instanceof KeyEvent) { //KeyEvent事件 KeyEvent ke = (KeyEvent) event; } QueuedInputEvent last = mPendingInputEventTail; //如果队列尾为null,也就是里面没有数据,赋值 if (last == null) { //这里赋值mPendingInputEventHead和mPendingInputEventTail mPendingInputEventHead = q; mPendingInputEventTail = q; } else { last.mNext = q; mPendingInputEventTail = q; } //事件计数器+1 mPendingInputEventCount += 1; //传入的是true,立即处理 if (processImmediately) { doProcessInputEvents(); } else { scheduleProcessInputEvents(); } }
上面方便是在onInputEvent()调用的。
WindowInputEventReceiver.onInputEvent()
@Override public void onInputEvent(InputEvent event) { ViewDebugConfig.getInstance().debugInputEventStart(event); List<InputEvent> processedEvents; try { //方法中有对事件类型判断,如果不是MotionEvent,一定返回null //我们这里是Keyevent事件 processedEvents = mInputCompatProcessor.processInputEventForCompatibility(event); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } //processedEvents为null if (processedEvents != null) { //略 } else { //dropIfNeeded()返回的是false,反一下就为true,调用enqueueInputEvent if (!dropIfNeeded(event)) { enqueueInputEvent(event, this, 0, true); } else { finishInputEvent(event, true); } } }
这里WindowInputEventReceiver很重要,是ViewRootImpl接受Event事件的分发地方。这里暂时不介绍,有兴趣可以看参考文。
到此,发送的上一曲键值88就从这开始分发的。
后续专门介绍WindowInputEventReceiver。
参考文章
》
《