Android事件分发流程(API-27)(一)

一个点击引起的世界大战

有一个WMS(WindowManagerService)的大管家掌管着Android系统的键盘消息,他有个属性叫mInputManager(IMS,InputManagerService),是Android的输入管理器,属于Java层输入管理器,同时他指向着C++层中的输入管理器InputManager来监控系统的键盘消息(来自《Android系统源代码情景分析 第三版》)

当我们在屏幕上的点击,经过WMS,IMS,到native层,最后会回调到Java层的InputEventReceiver.dispatchInputEvent(int seq, InputEvent event, int displayId),一步步调用到Activity.dispatchTouchEvent()

  • 序列图
  • Android事件分发流程(API-27)(一)_第1张图片
    Android触摸流程.jpg
  • InputEventReceiver.dispatchInputEvent(int seq, InputEvent event, int displayId)

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
        mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event, displayId);
    }
    
  • InputEventReceiverabstract class,在ViewRootImpl中有个内部类叫WindowInputEventReceiver继承InputEventReceiver

    final class WindowInputEventReceiver extends InputEventReceiver {
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }
    
        @Override
        public void onInputEvent(InputEvent event, int displayId) {
            // native 回调在这里
            enqueueInputEvent(event, this, 0, true);
        }
        ...
    }
    
  • onInputEvent()方法中调用enqueueInputEvent()

    void enqueueInputEvent(InputEvent event,
                           InputEventReceiver receiver, int flags, boolean processImmediately) {
        adjustInputEventForCompatibility(event);
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
    
        // Always enqueue the input event in order, regardless of its time stamp.
        // We do this because the application or the IME may inject key events
        // in response to touch events and we want to ensure that the injected keys
        // are processed in the order they were received and we cannot trust that
        // the time stamp of injected events are monotonic.
        QueuedInputEvent last = mPendingInputEventTail;
        if (last == null) {
            mPendingInputEventHead = q;
            mPendingInputEventTail = q;
        } else {
            last.mNext = q;
            mPendingInputEventTail = q;
        }
        mPendingInputEventCount += 1;
        Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                           mPendingInputEventCount);
        // 上面的传参是true,调用doProcessInputEvents()
        if (processImmediately) {
            doProcessInputEvents();
        } else {
            scheduleProcessInputEvents();
        }
    }
    
  • 进入doProcessInputEvents

    void doProcessInputEvents() {
        // Deliver all pending input events in the queue.
        while (mPendingInputEventHead != null) {
            QueuedInputEvent q = mPendingInputEventHead;
            mPendingInputEventHead = q.mNext;
            if (mPendingInputEventHead == null) {
                mPendingInputEventTail = null;
            }
            q.mNext = null;
    
            mPendingInputEventCount -= 1;
            Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                               mPendingInputEventCount);
    
            long eventTime = q.mEvent.getEventTimeNano();
            long oldestEventTime = eventTime;
            if (q.mEvent instanceof MotionEvent) {
                MotionEvent me = (MotionEvent)q.mEvent;
                if (me.getHistorySize() > 0) {
                    oldestEventTime = me.getHistoricalEventTimeNano(0);
                }
            }
            mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
            
            // 到这
            deliverInputEvent(q);
        }
    
        // We are done processing all input events that we can process right now
        // so we can clear the pending flag immediately.
        if (mProcessInputEventsScheduled) {
            mProcessInputEventsScheduled = false;
            mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
        }
    }
    
    
    
  • 进入deliverInputEvent()

    private void deliverInputEvent(QueuedInputEvent q) {
        Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
                              q.mEvent.getSequenceNumber());
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
        }
    
        InputStage stage;
        if (q.shouldSendToSynthesizer()) {
            stage = mSyntheticInputStage;
        } else {
            stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
        }
    
        if (stage != null) {
            // 到这
            stage.deliver(q);
        } else {
            finishInputEvent(q);
        }
    }
    
  • 这里的stageViewPostImeInputStage继承InputStage

    /**
         * Delivers post-ime input events to the view hierarchy.
         */
    final class ViewPostImeInputStage extends InputStage {
        public ViewPostImeInputStage(InputStage next) {
            super(next);
        }
    
        @Override
        protected int onProcess(QueuedInputEvent q) {
            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);
                }
            }
        }
    
        ...
            
        private int processPointerEvent(QueuedInputEvent q) {
            final MotionEvent event = (MotionEvent)q.mEvent;
    
            mAttachInfo.mUnbufferedDispatchRequested = false;
            mAttachInfo.mHandlingPointerEvent = true;
            // 这里的mView是DecorView
            boolean handled = mView.dispatchPointerEvent(event);
            maybeUpdatePointerIcon(event);
            maybeUpdateTooltip(event);
            mAttachInfo.mHandlingPointerEvent = false;
            if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
                mUnbufferedInputDispatch = true;
                if (mConsumeBatchedInputScheduled) {
                    scheduleConsumeBatchedInputImmediately();
                }
            }
            return handled ? FINISH_HANDLED : FORWARD;
        }
    
        ...
    }
    
  • dispatchPointerEvent在view中实现

    /**
     * Dispatch a pointer event.
     * 

    * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches * and should not be expected to handle other pointing device features. *

    * * @param event The motion event to be dispatched. * @return True if the event was handled by the view, false otherwise. * @hide */ public final boolean dispatchPointerEvent(MotionEvent event) { if (event.isTouchEvent()) { // 调用dispatchTouchEvent return dispatchTouchEvent(event); } else { return dispatchGenericMotionEvent(event); } }
  • dispatchTouchEvent,注意这里的Window.Callback就是Activity,

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        final Window.Callback cb = mWindow.getCallback();
        return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
            ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
    }
    
  • Activity.dispatchTouchEvent

Activity.dispatchTouchEvent()之后就是我们熟悉的事件分发了

详情见Android事件分发流程(API-27)(二)

  • 参考资料
    • 《Android系统源代码情景分析 第三版》
    • 从你触摸屏幕开始分析android触摸事件分发

你可能感兴趣的:(Android事件分发流程(API-27)(一))