InputDispatch中的发送部分(待补充)
继续接着上篇文章分析NativeInputEventReceiver中的
NativeInputEventReceiver中的handleEvent()
建立好channel之后,就是通信了。从InputDispatcher从InBoundQueue队列头中取出事件,然后通过将中将消息发出来了,ViewRootImpl通过就是NativeInputEventReceiver中的handleEvent()方法。
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);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
.................
return 1;
}
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
ScopedLocalRef<jobject> receiverObj(env, NULL);
bool skipCallbacks = false;
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
1、这里通过inputConsumer的counsume方法将输入invent事件转为native的inputEvent;
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);
....................
if (!skipCallbacks) {
....................
jobject inputEventObj;
switch (inputEvent->getType()) {
2、根据native层的inputEvent中的type类型,区分是keyEvent还是motionEvent,然后分别转为不同java对象inputEventObj 。
case AINPUT_EVENT_TYPE_KEY:
inputEventObj = android_view_KeyEvent_fromNative(env,
static_cast<KeyEvent*>(inputEvent));
break;
case AINPUT_EVENT_TYPE_MOTION: {
MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch){
*outConsumedBatch = true;
}
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
break;
}
3、最后,如果java层的inputEvent对象创建成功,就把该对象通过InputEventReceiver中dispatchInputEvent方法分发到java层去。
if (inputEventObj) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
}
env->CallVoidMethod(receiverObj.get(),
//这个gInputEventReceiverClassInfo其实就是WindowInputEventReceiver的父类InputEventReceiver
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching input event.");
skipCallbacks = true;
}
env->DeleteLocalRef(inputEventObj);
} else {
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
skipCallbacks = true;
}
}
}
}
WindowInputEventReceiver的onInputEvent()
WindowInputEventReceiver的作用:
1、通过父类InputEventReceiver的dispatchInputEvent()方法接受InputEvent事件;
2、通过onInputEvent()方法启动InputStage责任链并传递InputEvent事件。
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
adjustInputEventForCompatibility(event);
1、首先创建一个QueueInputEvent,然后将它添加到队尾
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);
2、添加结束就立即执行,这里传入的是true
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
3、doProcessInputEvents的作用就是while循环分发所有的InputEvent事件。分发过程是调用7个InputStage实现类,通过责任链的方式一次传递的。
void doProcessInputEvents() {
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
.......................
deliverInputEvent(q);
}
}
4、其中ViewPostImeInputStage是Activity和View的的事件处理InputStage对象的实现类。执行方法是onProcess()。
ViewPostImeInputStage的onProcess()
protected int onProcess(QueuedInputEvent q) {
1、首先区分是KeyEvent还是TouchEvent。
if (q.mEvent instanceof KeyEvent) {
return processKeyEvent(q);
} else {
2、然后区分是是触摸还是轨迹球还是生成器
final int source = q.mEvent.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
return processPointerEvent(q);
} 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;
3、这个因为不是鼠标输入,因此View就是setView方法中传入的mView,也就是DecorView
final View eventTarget =
(event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?
mCapturingView : mView;
mAttachInfo.mHandlingPointerEvent = true;
4、这句话就很眼熟了,执行eventTarget的dispatchPointerEvent;返回分发结果:handled。这里eventTargt就是这里子类对应的是viewtree的根视图:DecorView,dispatchPointEvent方法在View中,dispatchPointEvent方法又调用了DecorView的dispatchTouchEvent();
boolean handled = eventTarget.dispatchPointerEvent(event);
.................
return handled ? FINISH_HANDLED : FORWARD;
}
5、Activity和Dialog都有mWindow.getCallBack回调,这里调用的是Activity的dispatchTouchEvent方法。之后,就是就开始了触摸事件分发。
public boolean dispatchTouchEvent(MotionEvent ev) {
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}
总结:
在建立完InputChannel后,接受信息并传递到开始事件分发主要经过4个步骤:
- NativeInputEventReceiver中的handleEvent()收到事件,将事件最后转为java层的InputEvent,然后抛出。
- Java层通过WindowInputEventReceiver接受事件,然后将事件添加到事件队列队尾,开启责任链调用模式
- Java层的inputEvent事件在责任链的ViewPostImeInputStage对象中处理,根据事件的类型,分发事件。
- 将MotionEvent事件通过发到View的根节点DecorView中,在根据Window回调,将事件发到Activity的dipatchTouchEvent()中,从此开始了touch事件的分发机制。