Android 知识笔记:记录 2 个 “容易误解 (1),【干货】
2、Input 系统—InputReader 线程:loop 起来让 EventHub 调用 getEvent()不断的从/dev/input/文件夹下读取输入事件。然后转换成 EventEntry 事件加入到 InputDispatcher 的 mInboundQueue。
3、Input 系统—InputDispatcher 线程:从 mInboundQueue 队列取出事件,转换成 DispatchEntry 事件加入到 connection 的 outboundQueue 队列。再然后开始处理分发事件 (比如分发到 ViewRootImpl 的 WindowInputEventReceiver 中),取出 outbound 队列,放入 waitQueue.
4、Input 系统—UI 线程:创建 socket pair,分别位于”InputDispatcher”线程和 focused 窗口所在进程的 UI 主线程,可相互通信。
这里只说大概,详情请看 gityuan 的这篇文章 Input 系统—事件处理全过程,文章 3.3.3 小节讲的是 input 系统事件从 Native 层分发 Framework 层的 InputEventReceiver.dispachInputEvent()。
http://gityuan.com/2016/12/31/input-ipc/
Framework 层
//InputEventReceiver.dispachInputEvent()
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
ViewRootImpl.WindowInputEventReceiver
Native 层通过 JNI 执行 Framework 层的 InputEventReceiver.dispachInputEvent(),而真正调用的是继承了 InputEventReceiver 的 ViewRootImpl.WindowInputEventReceiver。
所以这里执行的 WindowInputEventReceiver 的 dispachInputEvent():
final class WindowInputEventReceiver extends InputEventReceiver {
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
...
}
ViewRootImpl
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
...
if (processImmediately) {
//关键点:执行 Input 事件
doProcessInputEvents();
} else {
//走一遍 Handler 延迟处理事件
scheduleProcessInputEvents();
}
}
void doProcessInputEvents() {
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
q.mNext = null;
mPendingInputEventCount -= 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
long eventTime = q.mEvent.getEventTimeNano();
long oldestEventTime = eventTime;
if (q.mEvent instanceof MotionEvent) {
MotionEvent me = (MotionEvent)q.mEvent;
if (me.getHistorySize() > 0) {
oldestEventTime = me.getHistoricalEventTimeNano(0);
}
}
mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
//关键点:进一步派发事件处理
deliverInputEvent(q);
}
...
}
private void deliverInputEvent(QueuedInputEvent q) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
q.mEvent.getSequenceNumber());
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
}
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (stage != null) {
//关键点:上面决定将事件派发到那个 InputStage 中处理
stage.deliver(q);
} else {
finishInputEvent(q);
}
}
ViewRootImpl.ViewPostImeInputStage
前面事件会派发到 ViewRootImpl.ViewPostImeInputStage 中处理,它的父类 InputStage.deliver()方法会调用 apply()来处理 Touch 事件:
@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) {
//关键点:执行分发 touch 事件
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;
...
//关键点:mView 分发 Touch 事件,mView 就是 DecorView
boolean handled = mView.dispatchPointerEvent(event);
maybeUpdatePointerIcon(event);
maybeUpdateTooltip(event);
...
}
DecorView
如果你熟悉安卓的 Window,Activity 和 Dialog 对应的 ViewRootImpl 成员 mView 就是 DecorView,View 的 dispatchPointerEvent()代码如下:
//View.java
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
//分发 Touch 事件
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}
因为 DecorView 继承 FrameLayout,上面所以会调用 DecorView 的 dispatchTouchEvent():
@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);
}
上面 Window.Callback 都被 Activity 和 Dialog 实现,所以变量 cb 可能就是 Activity 和 Dialog。
Activity
当上面 cb 是 Activity 时,执行 Activity 的 dispatchTouchEvent():
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {//关键点:getWindow().superDispatchTouchEvent(ev)
return true;
}
return onTouchEvent(ev);
}
如果你熟悉安卓的 Window,Activity 的 getWindow()拿到的就是 PhoneWindow,下面是 PhoneWindow 的代码:
//PhoneWindow.java
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
//调用 DecorView 的 superDispatchTouchEvent
评论