系列目录第一篇从硬件到应用的事件旅程 | 第二篇EventHub — 原始事件的采集者 | 第三篇InputReader — 原始事件到Android事件的转换引擎 | 第四篇InputDispatcher — 事件分发与ANR超时机制 | 第五篇应用侧 — InputChannel、ViewRootImpl与事件消费一、应用侧在整体架构中的位置InputDispatcher → socket → APP 进程 → View 树 system_server ▲ 本篇聚焦当 InputDispatcher 通过 socket 把InputMessage发送到 APP 进程后一条完整的消费链路开始运转。本篇聚焦于socket 数据如何被 APP 进程感知如何转换为 Java 层的 InputEvent 对象如何与主线程消息队列协作以及最终如何在 View 树中分发。源码位置frameworks/base/core/java/android/view/ViewRootImpl.java // WindowInputEventReceiver frameworks/base/core/java/android/view/InputChannel.java // socket pair 通信 frameworks/base/core/java/android/view/InputEventReceiver.java // 事件接收基类 frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java // WMS frameworks/base/core/jni/android_view_InputEventReceiver.cpp // JNI 桥接层本文中所有 Java 代码块均来自上述文件路径不再逐一标注。二、InputChannel 的创建2.1 ViewRootImpl.setView() 触发通道创建源码路径frameworks/base/core/java/android/view/ViewRootImpl.javapublicvoidsetView(Viewview,...){mViewview;// WMS 在 addWindow 时调用 openInputChannelPair()// server 端 → InputDispatcherclient 端 → 通过 Binder 回传resmWindowSession.addToDisplay(mWindow,...);if(mInputChannel!null){mInputEventReceivernewWindowInputEventReceiver(mInputChannel,Looper.myLooper());}}2.2 WMS 侧创建 socket pair// WindowManagerService.javaInputChannel[]inputChannelsInputChannel.openInputChannelPair(name);// server 端 → 注册到 InputDispatchermInputManager.registerInputChannel(inputChannels[0],...);// client 端 → 通过 Binder 回传给 ViewRootImploutInputChannelinputChannels[1];三、NativeInputEventReceiversocket fd 与 MessageQueue 集成3.1 JNI 初始化// android_view_InputEventReceiver.cppstaticjlongnativeInit(JNIEnv*env,jclass clazz,jobject receiverWeak,jobject inputChannelObj,jobject messageQueueObj){spInputChannelinputChannelandroid_view_InputChannel_getInputChannel(env,inputChannelObj);spMessageQueuemessageQueueandroid_os_MessageQueue_getMessageQueue(env,messageQueueObj);spNativeInputEventReceiverreceivernewNativeInputEventReceiver(env,receiverWeak,inputChannel,messageQueue);receiver-initialize();returnreinterpret_castjlong(receiver.get());}3.2 核心将 socket fd 注册到 MessageQueue 的 LoopervoidNativeInputEventReceiver::setFdEvents(intevents){intfdmInputConsumer.getChannel()-getFd();// socket 的 fd// 将 socket fd 加入 MessageQueue 的 Native Looper 的 epoll 实例mMessageQueue-getLooper()-addFd(fd,0,// identALOOPER_EVENT_INPUT,// 监听可读事件this,// 回调对象handleEvent 方法NULL);}这是整个应用侧最精妙的设计MessageQueue 内部使用 Native Looper epoll 等待消息同一个 epoll 实例同时监听主线程 Message 管道 socket fd当 InputDispatcher 向 socketsend()数据时epoll_wait同时检测到 socket fd 可读在主线程上下文中回调NativeInputEventReceiver::handleEvent()这意味着输入事件和主线程的 Message 共享同一个事件循环。如果主线程在处理耗时 Message输入事件的处理会被延迟——这就是主线程卡顿导致触摸延迟的根本原因。3.3 事件消费与回调 Java 层intNativeInputEventReceiver::handleEvent(intreceiveFd,intevents,void*data){if(events(ALOOPER_EVENT_ERROR|ALOOPER_EVENT_HANGUP)){return0;// 移除回调}if(eventsALOOPER_EVENT_INPUT){JNIEnv*envAndroidRuntime::getJNIEnv();consumeEvents(env,false,-1,NULL);}return1;}status_tNativeInputEventReceiver::consumeEvents(JNIEnv*env,boolconsumeBatches,nsecs_t frameTime,bool*outConsumedBatch){for(;;){uint32_tseq;InputEvent*inputEvent;status_t statusmInputConsumer.consume(mInputEventFactory,consumeBatches,frameTime,seq,inputEvent);if(statusOK){// 回调 Java 层的 dispatchInputEvent()env-CallVoidMethod(receiverObj.get(),gInputEventReceiverClassInfo.dispatchInputEvent,seq,inputEventObj);}elseif(statusWOULD_BLOCK){break;// 没有更多事件}}}3.4 事件消费回复Finished Signalstatus_tNativeInputEventReceiver::sendFinishedSignal(uint32_tseq,boolhandled){// 通过同一 socket 发送 Finished 消息给 InputDispatcherreturnmInputConsumer.sendFinishedSignal(seq,handled);}APP 必须调用sendFinishedSignal来告知 InputDispatcher 事件已被消费。如果长时间不调用就会触发 ANR 超时。四、InputEventReceiverJava 层基类publicabstractclassInputEventReceiver{privatelongmReceiverPtr;// NativeInputEventReceiver 指针publicInputEventReceiver(InputChannelinputChannel,Looperlooper){mInputChannelinputChannel;mReceiverPtrnativeInit(newWeakReference(this),inputChannel,looper.getQueue());}// JNI 回调此方法privatevoiddispatchInputEvent(intseq,InputEventevent){onInputEvent(event);}publicabstractvoidonInputEvent(InputEventevent);// 通知 Dispatcher 事件已消费publicfinalvoidfinishInputEvent(InputEventevent,booleanhandled){nativeFinishInputEvent(mReceiverPtr,seq,handled);}}五、ViewRootImpl窗口事件中枢5.1 WindowInputEventReceiverfinalclassWindowInputEventReceiverextendsInputEventReceiver{OverridepublicvoidonInputEvent(InputEventevent){enqueueInputEvent(event,this,0,true);}}5.2 事件入队与处理voidenqueueInputEvent(InputEventevent,InputEventReceiverreceiver,intflags,booleanprocessImmediately){QueuedInputEventqobtainQueuedInputEvent(event,receiver,flags);// 加入队列尾if(mPendingInputEventTailnull){mPendingInputEventHeadq;}else{mPendingInputEventTail.mNextq;}mPendingInputEventTailq;if(processImmediately){doProcessInputEvents();}else{scheduleProcessInputEvents();// 调度到下一帧}}voiddoProcessInputEvents(){while(mPendingInputEventHead!null){QueuedInputEventqmPendingInputEventHead;mPendingInputEventHeadq.mNext;deliverInputEvent(q);}}5.3 InputStage 责任链流水线ViewRootImpl 用责任链模式处理输入事件依次经过 7 个 Stage// Stage 链顺序从第一个到最后一个abstractclassInputStage{// 1. NativePreImeInputStage → 原生输入法之前处理// 2. ViewPreImeInputStage → View 分发输入法相关事件// 3. ImeInputStage → 输入法IME处理// 4. EarlyPostImeInputStage → 输入法之后、View 之前// 5. NativePostImeInputStage → 原生 View 后处理// 6. ViewPostImeInputStage → View 分发普通事件核心// 7. SyntheticInputStage → 合成事件导航键等}最核心的ViewPostImeInputStagefinalclassViewPostImeInputStageextendsInputStage{OverrideprotectedintonProcess(QueuedInputEventq){if(q.mEventinstanceofKeyEvent){returnprocessKeyEvent(q);}else{returnprocessPointerEvent(q);}}privateintprocessPointerEvent(QueuedInputEventq){MotionEventevent(MotionEvent)q.mEvent;booleanhandledmView.dispatchPointerEvent(event);// → DecorView.dispatchTouchEvent(event)returnhandled?FINISH_HANDLED:FORWARD;}privateintprocessKeyEvent(QueuedInputEventq){KeyEventevent(KeyEvent)q.mEvent;booleanhandledmView.dispatchKeyEvent(event);returnhandled?FINISH_HANDLED:FORWARD;}}六、View 树的事件分发6.1 触摸事件分发ViewGroup// ViewGroup.javaOverridepublicbooleandispatchTouchEvent(MotionEventev){booleanhandledfalse;// 1. 检查是否被拦截finalbooleanintercepted;if(actionMaskedMotionEvent.ACTION_DOWN||mFirstTouchTarget!null){interceptedonInterceptTouchEvent(ev);}else{interceptedtrue;}// 2. 不拦截则分发给子 Viewif(!intercepted){finalView[]childrenmChildren;for(intichildrenCount-1;i0;i--){// 按 Z 序从上层到下层Viewchildchildren[i];if(!canViewReceivePointerEvents(child)||!isTransformedTouchPointInView(x,y,child,null)){continue;}// 坐标转换到子 View 坐标系 递归分发ev.offsetLocation(child.mLeft,child.mTop);if(child.dispatchTouchEvent(ev)){mFirstTouchTargetaddTouchTarget(child,...);handledtrue;break;}}}// 3. 没有子 View 消费自己处理if(mFirstTouchTargetnull){handledsuper.dispatchTouchEvent(ev);// → View.onTouchEvent()}returnhandled;}6.2 View 的事件处理// View.javapublicbooleandispatchTouchEvent(MotionEventevent){// 1. 先回调 OnTouchListenerif(mOnTouchListener!nullmOnTouchListener.onTouch(this,event)){returntrue;}// 2. 再回调 onTouchEventif(onTouchEvent(event)){returntrue;}returnfalse;}publicbooleanonTouchEvent(MotionEventevent){if((viewFlagsCLICKABLE)CLICKABLE){switch(event.getAction()){caseMotionEvent.ACTION_UP:performClick();// 执行点击break;caseMotionEvent.ACTION_DOWN:checkForLongClick(0);// 延迟长按检测break;}returntrue;}returnfalse;}6.3 按键事件分发按键事件优先交给焦点 View// ViewGroup.javapublicbooleandispatchKeyEvent(KeyEventevent){if(mFocused!null){returnmFocused.dispatchKeyEvent(event);}returnsuper.dispatchKeyEvent(event);}// View.javapublicbooleandispatchKeyEvent(KeyEventevent){// 1. 回调 OnKeyListenerif(mOnKeyListener!nullmOnKeyListener.onKey(this,event.getKeyCode(),event)){returntrue;}// 2. 回调 onKeyDown / onKeyUpreturnevent.dispatch(this,...);}七、消费信号回传闭环// ViewRootImpl.javaprivatevoidfinishInputEvent(QueuedInputEventq){if(q.mReceiver!null){booleanhandled(q.mFlagsFLAG_FINISHED_HANDLED)!0;q.mReceiver.finishInputEvent(q.mEvent,handled);}}// → InputEventReceiver.finishInputEvent()// → JNI nativeFinishInputEvent()// → NativeInputEventReceiver::sendFinishedSignal(seq, handled)// → mInputConsumer.sendFinishedSignal()// → socket send(FinishedMessage)// → InputDispatcher 的 fd 变为可读// → handleReceiveCallback() → 从 waitQueue 移除 → ANR 计时器停止八、关键设计总结设计说明socket pair输入通道不经过 Binder降低延迟fd 注册到 MessageQueue epoll输入事件与主线程 Message 共享同一事件循环NativeInputEventReceiverJNI 层桥接读 socket 回调 JavaInputStage 责任链IME 前置 → View 分发 → 合成事件6 级流水线ViewGroup 拦截机制onInterceptTouchEvent mFirstTouchTargetFINISHED 信号闭环APP 消费 → socket 回复 → InputDispatcher 移出 waitQueue → 阻止 ANR系列总结五篇文章涵盖了 Android 7 输入系统从硬件到应用的完整链路总览建立六层架构的宏观认知EventHubinotify epoll 的设备监听与原始事件采集InputReaderInputMapper 体系与事件加工转换InputDispatcher窗口定位、socket 通信与 ANR 超时机制应用侧InputChannel 到 View.onTouchEvent 的完整消费链路每篇文章都是独立的知识模块可以按需查阅。理解这套机制后无论是排查 ANR、处理滑动冲突、还是优化触摸响应延迟都能从源码层面找到根本原因。