Android Input -- ViewRootImpl Event Distribution (Activity View Group View)

A Brief Introduction to the Whole Process of Android Event Delivery

 

The source of the Android input event is the device node under / dev/input / and the end point of the input event is a window managed by WMS, which is finally processed by View in the window. The initial input event is the original event generated by the kernel.

The final deliveries to the window are KeyEvent (keyboard) or MotionEvent (mouse and touch screen) objects. The first function that enters the input event from the Native layer into the Java layer is InputEventReceiver.dispatchInputEvent().

In this way, our Motion Event is passed to the Java layer, and the transfer process to the application layer follows the following order: Activity - > Window - > View; that is, View event is first passed to Activity.

Events are then passed from Activity to Window, and finally from Windows to View; when the top-level View (DecorView) receives the event, it distributes the event according to the event distribution mechanism; after the event reaches the Java layer, who passes the event to Activity?

 

// The whole process of event delivery: After the original event is generated by the bottom layer and processed by a series of processes, the event is encapsulated into MotionEvent and keyEvent, and then passed to InputEventReceiver. dispatch TouchEvent of the Java layer.

After the event arrives at the Java layer, how can it be passed to Activity step by step? The following call stack shows how events are passed from Input Event Receive to Activity; after events are passed to Activity, they are passed from Activity to Window s.

Finally, it is transmitted to the top-level View by Window s. When the top-level View (DecorView) receives the event, it distributes the event according to the event distribution mechanism. This paper mainly starts with Activity to analyze the event distribution mechanism.

 

Catalog

Log Pattern1:

Flow chart of Part 3

Logic pattern in Part 3

1. Callback handling of received InputDispatcher events

1.1 handleEvent callback processing

1.2 NativeInputEventReceiver ::consumeEvents

1.3 gInputEventReceiverClassInfo.dispatchInputEvent

2. ViewRootImpl's InputStage

2.1 ViewRootImpl.java dispatchInputEvent/enqueueInputEvent

2.2 InputStage.deliver

2.3 Each InputStage

2.4 InputStage begins distributing event dispatch TouchEvent

3. Event distribution of Activity View Group View dispatch TouchEvent and onTouchEvent

3.1 View ViewGroup DecorView Inheritance

3.2 DecorView dispatchTouchEvent

3.3 Activity dispatchTouchEvent

3.4 ViewGroup dispatchTouchEvent

3.5 View dispatchTouchEvent

 

Log Pattern1:

//Event details, action for event type, x,y for event location, deviceId for hardware device id value
EventTest: MainActivity dispatchTouchEvent: MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=408.94913, y[0]=416.38184, toolType[0]=TOOL_TYPE_MOUSE, buttonState=BUTTON_PRIMARY, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=498914, downTime=498914, deviceId=13, source=0x2002 }
System.err: java.lang.Exception: EventTest2
System.err:     at .*********************.MainActivity.dispatchTouchEvent(MainActivity.java:68)
System.err:     at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71)
System.err:     at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:434)
System.err:     at android.view.View.dispatchPointerEvent(View.java:12029)
System.err:     at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4834)
//In the onProcess method, the event type is judged, and then different processing methods are invoked according to different event types.
System.err:     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4644)
//After event processing is completed in deliver y, finishInputEvent is called to give a feedback to the input system.
System.err:     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)  
System.err:     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4229)
System.err:     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4195)
System.err:     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4322)
System.err:     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4203)
System.err:     at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4379)
System.err:     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)
System.err:     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4229)
System.err:     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4195)
System.err:     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4203)
System.err:     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)   //1.5  InputStage.deliver()
System.err:     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6707)
System.err:     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6681)
System.err:     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6642)    //1.4 
System.err:     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6810)    //Call to Windows InputEventReceiver in the integrated abstract class InputEventReceiver
//Events formally enter the Java layer from the native layer
System.err:     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:187)   //1.3 After InputDiapatcher seedmsg, fd triggers handEvent to call dispatchInputEvent
System.err:     at android.os.MessageQueue.nativePollOnce(Native Method)     //1.1 handleEvent callback processing
System.err:     at android.os.MessageQueue.next(MessageQueue.java:325)
System.err:     at android.os.Looper.loop(Looper.java:142)
System.err:     at android.app.ActivityThread.main(ActivityThread.java:6627)
System.err:     at java.lang.reflect.Method.invoke(Native Method)
System.err:     at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

 

Flow chart of Part 3

Logic pattern in Part 3

Write a simple example and verify it. Select a View, rewrite its onTouchEvent method, and print out the call stack information of the current thread through the dumpStack method.

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(TAG, "onTouchEvent, ev=" + event.getAction());
        Thread.dumpStack();
        return true;
    }
06-22 13:25:21.368  7365  7365 D FrameLayoutEx: onTouchEvent, ev=0
06-22 13:25:21.368  7365  7365 W System.err: java.lang.Throwable: stack dump
06-22 13:25:21.368  7365  7365 W System.err:    at java.lang.Thread.dumpStack(Thread.java:490)
06-22 13:25:21.368  7365  7365 W System.err:    at com.ryg.reveallayout.ui.FrameLayoutEx.onTouchEvent(FrameLayoutEx.java:27)
06-22 13:25:21.368  7365  7365 W System.err:    at android.view.View.dispatchTouchEvent(View.java:9294)
06-22 13:25:21.368  7365  7365 W System.err:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2547)
06-22 13:25:21.368  7365  7365 W System.err:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2240)
06-22 13:25:21.368  7365  7365 W System.err:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
06-22 13:25:21.369  7365  7365 W System.err:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
06-22 13:25:21.369  7365  7365 W System.err:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
06-22 13:25:21.369  7365  7365 W System.err:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
06-22 13:25:21.369  7365  7365 W System.err:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
06-22 13:25:21.369  7365  7365 W System.err:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
06-22 13:25:21.369  7365  7365 W System.err:    at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
06-22 13:25:21.369  7365  7365 W System.err:    at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
06-22 13:25:21.369  7365  7365 W System.err:    at android.app.Activity.dispatchTouchEvent(Activity.java:2765)
06-22 13:25:21.369  7365  7365 W System.err:    at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
06-22 13:25:21.369  7365  7365 W System.err:    at android.view.View.dispatchPointerEvent(View.java:9514)
06-22 13:25:21.369  7365  7365 W System.err:    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
06-22 13:25:21.370  7365  7365 W System.err:    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
06-22 13:25:21.371  7365  7365 W System.err:    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922)
06-22 13:25:21.371  7365  7365 W System.err:    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896)
06-22 13:25:21.371  7365  7365 W System.err:    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857)
06-22 13:25:21.371  7365  7365 W System.err:    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025)
06-22 13:25:21.371  7365  7365 W System.err:    at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
06-22 13:25:21.371  7365  7365 W System.err:    at android.os.MessageQueue.nativePollOnce(Native Method)
06-22 13:25:21.371  7365  7365 W System.err:    at android.os.MessageQueue.next(MessageQueue.java:323)
06-22 13:25:21.371  7365  7365 W System.err:    at android.os.Looper.loop(Looper.java:135)
06-22 13:25:21.371  7365  7365 W System.err:    at android.app.ActivityThread.main(ActivityThread.java:5417)
06-22 13:25:21.371  7365  7365 W System.err:    at java.lang.reflect.Method.invoke(Native Method)
06-22 13:25:21.371  7365  7365 W System.err:    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
06-22 13:25:21.371  7365  7365 W System.err:    at com.android.internal.os.ZygoteInit.main(ZygoteInit

onTouchEvent is as follows

09-05 09:28:07.840  7883  7883 W System.err: java.lang.Exception: Stack trace
09-05 09:28:07.840  7883  7883 W System.err: 	at java.lang.Thread.dumpStack(Thread.java:1348)
09-05 09:28:07.840  7883  7883 W System.err: 	at com.tsp.notification.MainActivity.onTouchEvent(MainActivity.java:86)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.app.Activity.dispatchTouchEvent(Activity.java:3404)
09-05 09:28:07.840  7883  7883 W System.err: 	at com.tsp.notification.MainActivity.dispatchTouchEvent(MainActivity.java:81)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
09-05 09:28:07.840  7883  7883 W System.err: 	at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:398)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.view.View.dispatchPointerEvent(View.java:12752)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5113)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4916)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4433)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4486)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4452)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4592)
09-05 09:28:07.840  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4460)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4649)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4433)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4486)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4452)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4460)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4433)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7099)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7068)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7029)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7202)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:186)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.os.MessageQueue.nativePollOnce(Native Method)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.os.MessageQueue.next(MessageQueue.java:326)
09-05 09:28:07.841  7883  7883 W System.err: 	at android.os.Looper.loop(Looper.java:160)

 

1. Callback handling of received InputDispatcher events

The first part refers to the input content of ViewRootImpl above.

1.1 handleEvent callback processing

int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    if (events & ALOOPER_EVENT_INPUT) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);    //consumeEvents consumption events
        return status == OK || status == NO_MEMORY ? 1 : 0;
    }
    ...
}

1.2 NativeInputEventReceiver ::consumeEvents

status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    bool skipCallbacks = false;
    for (;;) {
        ...
         if (inputEventObj) {
            env->CallVoidMethod(receiverObj.get(),
                    gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj,   //gInputEventReceiverClassInfo.dispatchInputEvent
                    displayId);
         ...
        }
    }
}

1.3 gInputEventReceiverClassInfo.dispatchInputEvent

private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
    mSeqMap.put(event.getSequenceNumber(), seq);
    onInputEvent(event, displayId);
}

2. ViewRootImpl's InputStage

2.1 ViewRootImpl.java dispatchInputEvent/enqueueInputEvent

@frameworks/base/core/java/android/view/ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
    public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
        super(inputChannel, looper);
    }

    @Override
    public void onInputEvent(InputEvent event, int displayId) {
        enqueueInputEvent(event, this, 0, true);
    }
void enqueueInputEvent(InputEvent event,
        InputEventReceiver receiver, int flags, boolean processImmediately) {

    QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);

    QueuedInputEvent last = mPendingInputEventTail;

    if (processImmediately) {
        doProcessInputEvents();
    } else {
        scheduleProcessInputEvents();
    }
}
void doProcessInputEvents() {
    while (mPendingInputEventHead != null) {
        QueuedInputEvent q = mPendingInputEventHead;
        mPendingInputEventHead = q.mNext;
        q.mNext = null;
        deliverInputEvent(q);
    }
}

2.2 InputStage.deliver

// Call each method deliver y of InputStage, and finishInputEvent completes the event distribution operation after the event is processed.

private void deliverInputEvent(QueuedInputEvent q) {
    if (mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
    }
    InputStage stage;
    if (stage != null) {
        stage.deliver(q);
    } else {
        finishInputEvent(q);
    }
}

2.3 Each InputStage

mSyntheticInputStage = new SyntheticInputStage();
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,

Seven implementation classes of InputStage are constructed.

  • native PreImeInputStage: Mainly for putting messages into native Activity to process. native Activity and ordinary Acitivty have little difference in function, but a lot of code is implemented in native layer, which is more efficient, and native Activity is very useful in game development.
  • ViewPreImeInputStage: As you can see from the name, the onkeyPreImage method of all views of Acitivity is finally invoked, which gives View the opportunity to get messages and process them before the input method processes key events.
  • ImeInputStage: The onProcess method of ImeInputStage calls the dispatchInputEvent method of InputMethodManager to process messages.
  • EarlyPostImeInputStage: View s with focus on the screen are highlighted to indicate where the user's focus is.
  • NativePostImeInputStage: To enable the IME to process messages before the normal Activeness.
  • ViewPostImeInputStage: Acitivity and view process various messages.
  • SyntheticInputStage: The last level of the pipeline, filtered through layers, has not many messages arriving here, such as virtual key messages on mobile phones.

Then the main corresponding InputStage for event handling of Activity and View is ViewPostImeInputStage.

// After InputStage. delivery, next is processed to other inputStage, and here to ViewPostImeInputStage of View.

System.err:     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4644)
System.err:     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)  
System.err:     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4229)
System.err:     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4195)
System.err:     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4322)
System.err:     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4203)
System.err:     at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4379)
System.err:     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)
System.err:     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4229)
System.err:     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4195)
System.err:     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4203)
System.err:     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)

2.4 InputStage begins distributing event dispatch TouchEvent

abstract class InputStage {
public final void deliver(QueuedInputEvent q) {
    if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
        forward(q);
    } else if (shouldDropInputEvent(q)) {
        finish(q, false);
    } else {
        apply(q, onProcess(q));
    }
}
protected void onDeliverToNext(QueuedInputEvent q) {
    if (DEBUG_INPUT_STAGES) {
        Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
    }
    if (mNext != null) {
        mNext.deliver(q);   //next deliver()
    } else {
        finishInputEvent(q);
    }
}
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);     //processPointerEvent
              } 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;
    boolean handled = mView.dispatchPointerEvent(event);   //mView Inheritance Relation Call
    int action = event.getActionMasked();
    ...
    return handled ? FINISH_HANDLED : FORWARD;
}

// Called to DecorView dispatchTouchEvent

System.err:     at .*********************.MainActivity.dispatchTouchEvent(MainActivity.java:68)
System.err:     at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71)
System.err:     at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:434)
System.err:     at android.view.View.dispatchPointerEvent(View.java:12029)
System.err:     at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4834)

3. Event distribution of Activity View Group View dispatch TouchEvent and onTouchEvent

InputEvent has two subclasses: KeyEvent and MotionEvent, where KeyEvent represents keyboard events and MotionEvent represents click events.

3.1 View ViewGroup DecorView Inheritance

// View inheritance is as follows

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker{...}
public class FrameLayout extends ViewGroup {...}
public abstract class ViewGroup extends View implements ViewParent, ViewManager{..}

Next, the above mView.dispatchPointerEvent(event) analysis

@frameworks/base/core/java/android/view/View.java
public final boolean dispatchPointerEvent(MotionEvent event) {
    if (event.isTouchEvent()) {
        return dispatchTouchEvent(event);
    } else {
        return dispatchGenericMotionEvent(event);
    }
}

3.2 DecorView dispatchTouchEvent

Inheritance calls based on mView

// First, the subclass DecorView

@frameworks/base/core/java/com/android/internal/policy/DecorView.java
@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);
}

3.3 Activity dispatchTouchEvent

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,   //Inheritance of Window.Callback
 {

// By calling Activity dispatch TouchEvent, you can see that each Dispatch TouchEvent is called first and onTouchEvent is called last. Therefore, the earliest dispatch TouchEvent and the latest onTouchEvent are applied.

@Activity.java
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}

3.4 ViewGroup dispatchTouchEvent

// It will be called to the ____________

@frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
    return mDecor.superDispatchTouchEvent(event);
}

@frameworks/base/core/java/com/android/internal/policy/DecorView.java
public boolean superDispatchTouchEvent(MotionEvent event) {
    return super.dispatchTouchEvent(event);
}
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker{...}
public class FrameLayout extends ViewGroup {...}
public abstract class ViewGroup extends View implements ViewParent, ViewManager{..}

//Enter ViewGroup
@frameworks/base/core/java/android/view/ViewGroup.java
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    ...
    if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {

    }
    ...
    if (mFirstTouchTarget == null) {
        // No touch targets so treat this as an ordinary view.
        handled = dispatchTransformedTouchEvent(ev, canceled, null,
                TouchTarget.ALL_POINTER_IDS);
    } else {
        if (dispatchTransformedTouchEvent(ev, cancelChild,
                target.child, target.pointerIdBits)) {
            handled = true;
        }
    }
    return handled;
}

// Call View dispatch TouchEvent

private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
        View child, int desiredPointerIdBits) {
    final boolean handled;
    ...
    // Perform any necessary transformations and dispatch.
    if (child == null) {
        handled = super.dispatchTouchEvent(transformedEvent);
    } else {
        final float offsetX = mScrollX - child.mLeft;
        final float offsetY = mScrollY - child.mTop;
        transformedEvent.offsetLocation(offsetX, offsetY);
        if (! child.hasIdentityMatrix()) {
            transformedEvent.transform(child.getInverseMatrix());
        }
        handled = child.dispatchTouchEvent(transformedEvent);
    }
}

3.5 View dispatchTouchEvent

@View.java
public boolean dispatchTouchEvent(MotionEvent event) {
    if (onFilterTouchEventForSecurity(event)) {
        if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
            result = true;
        }
        //noinspection SimplifiableIfStatement
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnTouchListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnTouchListener.onTouch(this, event)) {    //If mOnTouchListener exists, it will return and intercept the event, instead of following onTouchEvent, so that the application can handle it.
            result = true;
        }

        if (!result && onTouchEvent(event)) {
            result = true;
        }
    }
    return result;
}

 

Tags: Java Android Windows Mobile

Posted on Wed, 11 Sep 2019 23:15:25 -0700 by feckless