Android Event Delivery Mechanism

Keywords: Windows Android Linux

1. I wanted to start at the bottom and see how Android events came about and how they went from the bottom to Windows, but Summary of a netizen: After Linux Kernel writes rawinputevent to the device node, InputReader reads the original event through EventHub and translates it into an Android input event, which is then handed over to InputDispatcher. Input Dispatcher passes events to the appropriate Window based on the Window information provided by WMS (Windows Manager Service). If the Window is wallpaper/Surface View, it reaches the end point; otherwise, the Windows ViewRoot will continue to distribute events to the appropriate View.

2. Start with Windows. When the original event enters the Input Dispatcher, it has been processed into KeyEvent, MotionEvent (or SwitchEvent). Then Input Dispatcher will distribute the event further.
Put events in the dispatch queue

After adding input events to the dispatch queue, the following steps are performed in turn:

  • The dispatch thread starts dispatching events;
  • Lock the target Window and send events to the target Window.
  • Input Dispatcher sends event to Windows through Input Channel (Input Dispatcher runs in system_server process, Windows runs in application process, and both communicate through Input Channel). ;
  • Looper on the Window s side is woken up, read an InputEvent from the InputChannel, and then call onInputEvent(ev). Specifically, the onInputEvent() method that calls members of the mInputEventReceiver of ViewRootImpl.
  • Call doProcessInputEvents()
  • Call delivery InputEvent ()

In Android system, it is the responsibility of Windows Manager Service to manage all windows in the system.
The presentation of the interface in Android is done by Activity

We know that this DecorView is the display interface we see, so we can understand that the user's touch button message is captured by Windows Manager Service and handed to DecorView in Phone Windows for corresponding processing. The bridge connecting the two is a ViewRoot class, which is created by Windows Manager Service.
This ViewRoot can

  • Distribution to DecorView of received user-initiated event events, such as keystrokes, touch screens, trajectory balls, etc.
  • Interact with Windows Manager Service to complete the drawing of the GUI of the whole Activity.

Let's not talk about how Viewrootimpl and Windows Manager Service complete GUI rendering.
The ViewRootImpl contains a Windows InputEventReceiver object, which we can roughly tell from its name is a class that accepts user events and is an internal class of Viewrootimpl.

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

        @Override
        public void onInputEvent(InputEvent event) {
            enqueueInputEvent(event, this, 0, true);
        }

        @Override
        public void onBatchedInputEventPending() {
            if (mUnbufferedInputDispatch) {
                super.onBatchedInputEventPending();
            } else {
                scheduleConsumeBatchedInput();
            }
        }

        @Override
        public void dispose() {
            unscheduleConsumeBatchedInput();
            super.dispose();
        }
    }

Let's see how he receives events and passes them on to DecorView.
First of all, look at its old man's construction method:

 public InputEventReceiver(InputChannel inputChannel, Looper looper) {
 //... Eliminate judgment as to whether it is null Method
 // Used to deliver messages
        mInputChannel = inputChannel;
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue);
        mCloseGuard.open("dispose");
    }

We can see that acceptance events are definitely related to Input Channel, mMessageQueue (what is the relationship in particular?

2 Look at the methods in Windows Input Event Receiver

onInputEvent(InputEvent event)

Called in this method

void enqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags, boolean processImmediately) {
        adjustInputEventForCompatibility(event);
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
        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);
        if (processImmediately) {
         // Handle events immediately
            doProcessInputEvents();
        } else {
         // Put events at the end of the queue
            scheduleProcessInputEvents();
        }
    }

Both of these methods end up calling the delivery InputEvent (QueuedInputEvent q) method to transmit events.

Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
                q.mEvent.getSequenceNumber());
        if (mInputEventConsistencyVerifier != null) {
        //Verification events validate onKeyEvent (keyEvent, nesting Level) according to different situations;
        // onTouchEvent(motionEvent, nestingLevel); onGenericMotionEvent(motionEvent, //nestingLevel);onTrackballEvent(motionEvent, nestingLevel);
            mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
        }
        InputStage stage;
        if (q.shouldSendToSynthesizer()) {
        //Processing input events from new input events
            stage = mSyntheticInputStage;
        } else {
        //ture?Performs early processing of post-ime input events:Delivers pre-ime //Finput events to a native activity* Does not support pointer events.
            stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
        }

        if (stage != null) {
            stage.deliver(q);
        } else {
            finishInputEvent(q);
        }

Various calls finally call the dispatchInputEvent method or View.dispatchPointerEvent in InputMethodManager
Eventually came up to View!!!

public final boolean dispatchPointerEvent(MotionEvent event) {
        if (event.isTouchEvent()) {
            return dispatchTouchEvent(event);
        } else {
            return dispatchGenericMotionEvent(event);
        }
    }
onBatchedInputEventPending()
dispose()

Events on the View to transmit a little more information on the Internet, here for the time being do not go to analyze it!

Posted by micaudwell on Wed, 03 Apr 2019 15:36:31 -0700