Input事件流程分析

IMS创建完毕之后,在SystemServer里面会用其来构建WMS。之前已经看到,构造WMS的时候将IMS传了进去

    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
            WindowManagerPolicy policy) {
         mInputManager = inputManager;
        if(mInputManager != null) {
            final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
            mPointerEventDispatcher = inputChannel != null
                    ? new PointerEventDispatcher(inputChannel) : null;
        } else {
            mPointerEventDispatcher = null;
        }
}

IMS-->monitorInput方法

    public InputChannel monitorInput(String inputChannelName) {
        if (inputChannelName == null) {
            throw new IllegalArgumentException("inputChannelName must not be null.");
        }

        InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
        nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
        inputChannels[0].dispose(); // don't need to retain the Java object reference
        return inputChannels[1];
    }

InputChannel用于从InputDispatcher中获取所有的input消息,所以这里构造一对InputChannel,其中index为0的代表server端,index为1的代表client端,一个注册到底层的InputDispatcher中,一个用于PointerEventDispatcher给上层分发消息。

PointerEventDispatcher的构造,它是用来分析点击事件的

public class PointerEventDispatcher extends InputEventReceiver {
    ArrayList<PointerEventListener> mListeners = new ArrayList<PointerEventListener>();
    PointerEventListener[] mListenersArray = new PointerEventListener[0];

    public PointerEventDispatcher(InputChannel inputChannel) {
        super(inputChannel, UiThread.getHandler().getLooper());
    }

PointerEventDispatcher继承InputEventReceiver

    public InputEventReceiver(InputChannel inputChannel, Looper looper) {
        if (inputChannel == null) {
            throw new IllegalArgumentException("inputChannel must not be null");
        }
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

        mInputChannel = inputChannel;
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue);

        mCloseGuard.open("dispose");
    }

nativeInit函数首先获取Java层传入的InputChannel和MessageQueue对象,然后构造NativeInputEventReceiver对象并调用它的initialize方法将InputChannel[1]与UiThread的looper绑定起来。

NativeInputEventReceiver的consumeEvents最终调用InputEventReceiver的dispatchInputEvent方法将此次触摸事件传递给Java层。然后,PointerEventDispatcher的onInputEvent方法将会被调用

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
        mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event, displayId);
    }
    @Override
    public void onInputEvent(InputEvent event, int displayId) {
        try {
            if (event instanceof MotionEvent
                    && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                final MotionEvent motionEvent = (MotionEvent) event;
                PointerEventListener[] listeners;
                synchronized (mListeners) {
                    if (mListenersArray == null) {
                        mListenersArray = new PointerEventListener[mListeners.size()];
                        mListeners.toArray(mListenersArray);
                    }
                    listeners = mListenersArray;
                }
                for (int i = 0; i < listeners.length; ++i) {
                    listeners[i].onPointerEvent(motionEvent, displayId);
                }
            }
        } finally {
            finishInputEvent(event, false);
        }
    

所以接收到底层传上来的Input消息,必须实现InputEventReceiver

View中如何接收到触摸事件

    final class WindowInputEventReceiver extends InputEventReceiver {
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }

        @Override
        public void onInputEvent(InputEvent event, int displayId) {
            /// M: record current key event and motion event to dump input event info for
            /// ANR analysis. {
            ViewDebugManager.getInstance().debugInputEventStart(event);
            /// }
            enqueueInputEvent(event, this, 0, true);
        }

猜你喜欢

转载自blog.csdn.net/liu362732346/article/details/80325765
今日推荐