输入系统框架分析

涉及到的关键类

InputEventReceiver.java

从Window addView开始:

WindowManagerGlobal.addView( 先构建 ViewRootImpl的实例 ,root=new ViewRootImpl(view.getContext(),display)

->ViewRootImpl.setView->{

//1、构建双通道,回调中给mInputChannel赋了值(InputChannel[] inputChannels= InputChannel.openInputChannelPair(name))

//将输入对的第二个值赋给了mInputChanne

res=mWindowSession.addToDisplay\(mWindow,mSeq,mWindowAttributes,
getHostVisibility(),mDisplay.getDisplayId(),
mAttachInfo.mContentInsets,mAttachInfo.mStableInsets,
mAttachInfo.mOutsets,mInputChannel);
//2、构建注册监听器

//WindowInputEventReceiver extends InputEventReceiver 是ViewRootImpl的内部类

mInputEventReceiver=new WindowInputEventReceiver(mInputChannel,Looper.myLooper());

}

一、构建双通道的处理流程

从Session.addToDisplay开始

outInputChannel 参数来源于 ViewRootImpl的 mInputChannel = new InputChannel();

WindowManagerService.addWindow(构建新的WindowState)->WindowState.openInputChannel(outInputChannel)

void openInputChannel(InputChannel outInputChannel) {
    if (mInputChannel != null) {
        throw new IllegalStateException("Window already has an input channel.");
    }
    String name = getName();
    InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
    mInputChannel = inputChannels[0];
    mClientChannel = inputChannels[1];
    mInputWindowHandle.inputChannel = inputChannels[0];
    if (outInputChannel != null) {
        mClientChannel.transferTo(outInputChannel);
        mClientChannel.dispose();
        mClientChannel = null;
    } else {
        // If the window died visible, we setup a dummy input channel, so that taps
        // can still detected by input monitor channel, and we can relaunch the app.
        // Create dummy event receiver that simply reports all events as handled.
        mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
    }
    mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}

InputChannel.openInputChannekPair -> InputChannel.nativeOpenInputChannelPair( 进入native层进行构建)

将构建的inputChannels[1] -> mClientChannel.transferTo(outInputChannel);

二、构建注册监听器的流程

对mInputChannel设置监听接收处理

mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,Looper.myLooper());

WindowInputEventReceiver extends InputEventReceiver

InputEventReceiver的构造方法->nativeInit(native层 进行监听的设置)

三、处理、分发事件的流程

事件的接收处理是在native层,在android_view_InputEventReceiver.cpp的NativeInputEventReceiver::consumeEvents方法

中从native层回调java层方法

InputEventReceiver -> dispatchInputEvent

从dispatchInputEvent -> onInputEvent(event, displayId) 跳转到WindowInputEventReceiver 覆写的onInputEvent方法中,

WindowInputEventReceiver.onInputEvent方法主要执行的操作

a)WindowInputEventReceiver.onInputEvent会过滤掉几种特定的touch事件

b) enqueueInputEvent ->1)obtainQueuedInputEvent(构建一个QueuedInputEvent,将InputEvent、InputEventReceiver等封装在里面);2)直接处理->doProcessInputEvents() ; 缓一下再处理->scheduleProcessInputEvents

doProcessInputEvents的作用:

循环处理事件队列的inputEvent->分发QueuedInputEvent-> deliverInputEvent,

在ViewRootImpl.setView中会初始化定义:

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,
        "aq:native-pre-ime:" + counterSuffix);

mSyntheticInputStage = new SyntheticInputStage

mFirstPostImeInputStage = new EarlyPostImeInputStage(nativePostImeStage);

mFirstInputStage = new NativePreImeInputStage(viewPreImeStage, "aq:native-pre-ime:" + counterSuffix);

deliverInputEvent的具体分派逻辑如下:

    InputStage stage;
    // 当 QueuedInputEvent的flag 是FLAG_UNHANDLED 时,返回true
    // 从代码来看,WindowInputEventReceiver.onInputEvent方法传入的flag=0
    // 大部分时候stage= mFirstInputStage,这个变量在最开始的时候赋值 
    //检测ime相关module是否需要处理该输入事件,比如back键,是需要先  
    //让IME处理,这个时候需要先交给mFirstPostImeInputStage处理
    if (q.shouldSendToSynthesizer()) {
        stage = mSyntheticInputStage;
    } else {
        stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
    }

    if (stage != null) {
        stage.deliver(q);// 直接调用到InputStage基类的方法 deliver
    } else {
        finishInputEvent(q);
    }

abstract class InputStage 里面定义了final属性的deliver方法,那么InputStage的子类对该

方法的调用都是会调用这里:

public final void deliver(QueuedInputEvent q) {
    if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
        forward(q);// 转发继续调用到 onDeliverToNext(q)方法 , 不同的InputStage子类对该方法有不同的实现
    } else if (shouldDropInputEvent(q)) {
        finish(q, false);
    } else {
        apply(q, onProcess(q));//不同的InputStage子类,对onProcess方法进行了不同的覆写,具体如下:
    }
}

onProcess方法具体的覆写策略如下:

EarlyPostImeInputStage{

  onProcess(QueuedInputEvent q)
   1)processKeyEvent(q) mFallbackEventHandler.preDispatchKeyEvent(event)
   2)processPointerEvent(q);

}

//将事件发送给view的事件处理器是ViewPostImeInputStage

ViewPostImeInputStage{

   onProcess(QueuedInputEvent q);
   // 向view发送按键事件,或者// 系统默认按键处理,比如CAMERA快捷键处理
   1) processKeyEvent(q); mView.dispatchKeyEventPreIme(event)->

   2)processPointerEvent(q)

   3)processGenericMotionEvent(q)

}

SyntheticInputStage{

   onProcess(QueuedInputEvent q);xx.process(event)(通过各种Handler进行处理)

}

ImeInputStage{

   onProcess(QueuedInputEvent q);InputMethodManager.dispatchInputEvent( event , q)

}

InputEventReceiver.finishInputEvent: client将事件处理完,必须通知server已经完成对该事件的处理,否则server会一直等待事件完成而不能发送后面的事件

public final void finishInputEvent(InputEvent event, boolean handled) {
    if (event == null) {
        throw new IllegalArgumentException("event must not be null");
    }
    if (mReceiverPtr == 0) {
        Log.w(TAG, "Attempted to finish an input event but the input event "
                + "receiver has already been disposed.");
    } else {
        int index = mSeqMap.indexOfKey(event.getSequenceNumber());
        if (index < 0) {
            Log.w(TAG, "Attempted to finish an input event that is not in progress.");
        } else {
            int seq = mSeqMap.valueAt(index);
            mSeqMap.removeAt(index);
            nativeFinishInputEvent(mReceiverPtr, seq, handled);// 回到native层
        }
    }
    event.recycleIfNeededAfterDispatch();
}

从上面的逻辑可以看出处理器的处理有限顺序是:

NativePreImeInputStage;ViewPreImeInputStage; ImeInputStage;

EarlyPostImeInputStage; NativePostImeInputStage;ViewPostImeInputStage;

SyntheticInputStage

重要结论:

view获得输入事件是由ViewPostImeInputStage传递过来的。ViewPostImeInputStage会将事件传递给activity的根View ---DecorView

-> DecorView.dispatchKeyEvent

如果非back按键,则会调用super即View.dispatchKeyEvent的接口,view的事件接收及处理就是从这开始的

results for ""

    No results matching ""