1.本想从底层开始看看Android的事件是怎么产生的,怎么从底层传到window的,但是 一位网友的总结:Linux Kernel将rawinputevent写入到设备节点后,InputReader会通过EventHub将原始事件读取出来并翻译加工为Android输入事件,而后把它交给InputDispatcher。InputDispatcher根据WMS(WindowManagerService)提供的窗口信息将事件传递给合适的窗口,若窗口为壁纸/SurfaceView等,则到了终点;否则会由该Window的ViewRoot继续分发到合适的View。
2.还是从window开始吧。当原始事件进入InputDispatcher时,已被加工为KeyEvent、MotionEvent(或SwitchEvent)。而后InputDispatcher会对事件进行进一步分发。
将事件放入派发队列
将输入事件加入到派发队列后,会依次执行以下步骤:
- 派发线程开始派发事件;
- 锁定目标窗口,然后向目标Window发送事件。
- InputDispatcher通过InputChannel将event发给Window(InputDispatcher运行于system_server进程中,Window运行于应用进程,两者通过InputChannel通信。);
- Window端的Looper被唤醒,从InputChannel中读取一个InputEvent,而后调用onInputEvent(ev)。具体来说是调用ViewRootImpl的mInputEventReceiver的成员的onInputEvent()方法。
- 调用doProcessInputEvents()
- 调用deliverInputEvent()
在Android系统中,对系统中的所有窗口进行管理是窗口管理服务WindowManagerService的职责(wms)。
在Android中界面的呈现是由Activity完成的
我们知道这个DecorView才是我们看到的显示界面 所以可以理解为用户的触摸按键的消息是由windowManagerService捕捉到然后交给phoneWindow中的DecorView进行相应的处理,而连接两者的桥梁则是一个ViewRoot类,ViewRoot类由windowManagerService创建。
这个ViewRoot可以
- 向DecorView分发收到的用户发起的event事件,如按键,触屏,轨迹球等事件
- 与WindowManagerService交互,完成整个Activity的GUI的绘制。
这里就不去谈Viewrootimpl是如何与WindowManagerService完成GUI的绘制了
在ViewRootImpl中包含有一个WindowInputEventReceiver对象,我们从名字都可以大致的知道它是一个接受用户事件的类,它是Viewrootimpl的一个内部类
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
@Override
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
@Override
public void onBatchedInputEventPending() {
if (mUnbufferedInputDispatch) {
super.onBatchedInputEventPending();
} else {
scheduleConsumeBatchedInput();
}
}
@Override
public void dispose() {
unscheduleConsumeBatchedInput();
super.dispose();
}
}
我们来看看他是如何接受到事件,如何传递给DecorView的。
1 首先看看它老汉的构造方法:
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
//... 省掉判断是否为null的方法
// 用来传递消息
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
我们可以看出接受事件肯定和InputChannel,mMessageQueue相关(具体是什么关系下来在研究一下)
2 看看WindowInputEventReceiver中的方法
onInputEvent(InputEvent event)
该方法中调用了
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
adjustInputEventForCompatibility(event);
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);
if (processImmediately) {
// 立即处理事件
doProcessInputEvents();
} else {
// 将事件放到队列的最后
scheduleProcessInputEvents();
}
}
这俩种方式最后都会调用deliverInputEvent(QueuedInputEvent q)方法传送事件
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
q.mEvent.getSequenceNumber());
if (mInputEventConsistencyVerifier != null) {
//验证事件 根据不同的情况验证 onKeyEvent(keyEvent, nestingLevel);
// onTouchEvent(motionEvent, nestingLevel); onGenericMotionEvent(motionEvent, //nestingLevel);onTrackballEvent(motionEvent, nestingLevel);
mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
}
InputStage stage;
if (q.shouldSendToSynthesizer()) {
//从新输入事件处理输入事件
stage = mSyntheticInputStage;
} else {
//ture?Performs early processing of post-ime input events:Delivers pre-ime //Finput events to a native activity* Does not support pointer events.
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (stage != null) {
stage.deliver(q);
} else {
finishInputEvent(q);
}
各种调用 最后调用InputMethodManager中的dispatchInputEvent方法 或者View.dispatchPointerEvent
终于跑到View上面来了!!!
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}
onBatchedInputEventPending()
dispose()
事件在View上传递网上的资料有点多了 这里就暂时不去分析它了!