「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
Framework层传递
InputManagerService是输入系统的起点,所有相关类和线程因此被创建或间接创建。
Android系统启动后,系统进程SystemServer.java会启动系统的各个服务。
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
//创建null对象
InputManagerService inputManager = null;
WindowManagerService wm = null;
//实例化InputManagerService和WindowManagerService
inputManager = new InputManagerService(context);
//将InputManagerService对象传给wm
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
//将服务添加到ServiceManager管理。
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
t.traceBegin("StartInputManager");
//启动服务
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
t.traceEnd();
}
这里就启动了这个服务。
获取输入事件;对事件的处理、存储;分发、传递给应用层;创建注册服务端管道和应用程序客户端管道;应用层接受从fw层接受的按键事件。
我在这里从Java层开始讲解。
传递给应用层
/frameworks/base/core/java/android/view/ViewRootImpl.java
在native层经过一系列处理后,如果所有的事件读取成功后,会根据时间的类型选择相应的执行语句,最终将事件传递给Java层KeyEvent对象。
最终会由WindowInputEventReceiver进行接收,他继承了InputEventReceiver
// Called from native code.
@SuppressWarnings("unused")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
WindowInputEventReceiver中重写了onInputEvent这个方法。最终执行用下面方法,下边直接在源码中进行讲解。
enqueueInputEvent(
processedEvents.get(i), this,
QueuedInputEvent.FLAG_MODIFIED_FOR_COMPATIBILITY, true);
@UnsupportedAppUsage
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
//把输入事件封装成QueuedInputEvent对象
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
// Always enqueue the input event in order, regardless of its time stamp.
// We do this because the application or the IME may inject key events
// in response to touch events and we want to ensure that the injected keys
// are processed in the order they were received and we cannot trust that
// the time stamp of injected events are monotonic.
//将q对象放入QueuedInputEvent对象池中
//QueuedInputEvent对象中有QueuedInputEvent类型的成员变量mNext
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();
}
}
紧接着继续分析doProcessInputEvents()处理流程
doProcessInputEvents()->deliverInputEvent()->deliver(),传递要处理的事件。
public final void deliver(QueuedInputEvent q) {
//QueuedInputEvent.FLAG_FINISHED标识事件已经被处理
if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
forward(q);
} else if (shouldDropInputEvent(q)) {
finish(q, false);
} else {
traceEvent(q, Trace.TRACE_TAG_VIEW);
final int result;
try {
//正常情况下不会丢弃当前事件,因此会走这里。
result = onProcess(q);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
apply(q, result);
}
}
InputStage是抽象基类,这里调用的是ViewPostImeInputStage(表示发送给视图)的onProcess()。在setView()方法中创建了很多InputStage对象,用于处理不同阶段的输入事件,详细请参考源码。
if (q.mEvent instanceof KeyEvent) {
return processKeyEvent(q);
}
processKeyEvent()将按键事件传给了view的跟DecorView做处理,此处开始,将事件交由应用层去处理,下一节继续讲解。