涉及到的关键类
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的事件接收及处理就是从这开始的