前言
继续跟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。
参考文章
》
《