news 2026/10/16 4:07:39

android Input专题- Q/R/S 10/11/12 InputManager源码分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
android Input专题- Q/R/S 10/11/12 InputManager源码分析

1、SystemServer中InputManagerService创建与启动

base/services/java/com/android/server/SystemServer.java

privatevoidstartOtherServices(){//省略部分traceBeginAndSlog("StartInputManagerService");inputManager=newInputManagerService(context);traceEnd();traceBeginAndSlog("StartWindowManagerService");// WMS needs sensor service readyConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart,START_SENSOR_SERVICE);mSensorServiceStart=null;wm=WindowManagerService.main(context,inputManager,!mFirstBoot,mOnlyCore,newPhoneWindowManager(),mActivityManagerService.mActivityTaskManager);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);traceEnd();//省略部分traceBeginAndSlog("StartInputManager");inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());inputManager.start();//这里再调用starttraceEnd();//省略部分}

这里以前讲过在SystemServer中会对系统中很多service进行启动,这里我们就发现有对InputManagerService进行对应的构造和添加

2、Native层面的InputManager启动

publicInputManagerService(Contextcontext){this.mContext=context;this.mHandler=newInputManagerHandler(DisplayThread.get().getLooper());//省略部分mPtr=nativeInit(this,mContext,mHandler.getLooper().getQueue());//省略部分}

这里InputManagerService构造方法中就是调用了nativeInit,这个方法是native方法
来看看对应的native方法:
base/services/core/jni/com_android_server_input_InputManagerService.cpp

staticjlongnativeInit(JNIEnv*env,jclass/* clazz */,jobject serviceObj,jobject contextObj,jobject messageQueueObj){sp<MessageQueue>messageQueue=android_os_MessageQueue_getMessageQueue(env,messageQueueObj);if(messageQueue==nullptr){jniThrowRuntimeException(env,"MessageQueue is not initialized.");return0;}NativeInputManager*im=newNativeInputManager(contextObj,serviceObj,messageQueue->getLooper());im->incStrong(0);returnreinterpret_cast<jlong>(im);}

这里主要就是构造了一个NativeInputManager:
base/services/core/jni/com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj,constsp<Looper>&looper):mLooper(looper),mInteractive(true){//省略部分mInputManager=newInputManager(this,this);defaultServiceManager()->addService(String16("inputflinger"),mInputManager,false);}

这里主要就是对我们InputManager进行构造,然后把它添加到了servicemanager,而且传递的两个参数都是NativeInputManager类本身
这里它的类结构其实是实现了几个接口方便InputManager里面传递和调用:
base/services/core/jni/com_android_server_input_InputManagerService.cpp

classNativeInputManager:publicvirtualRefBase,publicvirtualInputReaderPolicyInterface,publicvirtualInputDispatcherPolicyInterface,publicvirtualPointerControllerPolicyInterface

那么接下来重点就分析我们的InputManager构造:
native/services/inputflinger/InputManager.cpp

InputManager::InputManager(constsp<InputReaderPolicyInterface>&readerPolicy,constsp<InputDispatcherPolicyInterface>&dispatcherPolicy){mDispatcher=newInputDispatcher(dispatcherPolicy);mClassifier=newInputClassifier(mDispatcher);mReader=createInputReader(readerPolicy,mClassifier);initialize();}

这里首先是进行了new InputDispatcher,再是把构造对象作为InputClassifier的构造参数,然后再是createInputReader,而且把InputClassifier对象也传递给了InputReader,看看createInputReader:

sp<InputReaderInterface>createInputReader(constsp<InputReaderPolicyInterface>&policy,constsp<InputListenerInterface>&listener){returnnewInputReader(newEventHub(),policy,listener);}InputReader::InputReader(constsp<EventHubInterface>&eventHub,constsp<InputReaderPolicyInterface>&policy,constsp<InputListenerInterface>&listener):mContext(this),mEventHub(eventHub),mPolicy(policy),mNextSequenceNum(1),mGlobalMetaState(0),mGeneration(1),mDisableVirtualKeysTimeout(LLONG_MIN),mNextTimeout(LLONG_MAX),mConfigurationChangesToRefresh(0){mQueuedListener=newQueuedInputListener(listener);//listener是作为后面连接InputDispatcher纽带{// acquire lockAutoMutex_l(mLock);//第一次执行时候,一般都是一些初始化的,还没获取到真正一些devices相关信息refreshConfigurationLocked(0);updateGlobalMetaStateLocked();}// release lock}

这里就是构造出了InputReader,而且传递了一个EventHub,也是立即构造的,整个input系统其实就是InputReader和InputDispatcher最为重要。而且二者其实也是间接相连的:

这样才方便后面InputReader读取加工好了数据就传递到InputDispatcher中,让InputDispatcher做下一步的传递工作。

再来看到有new一个EventHub,来看看它是干啥的:
native/services/inputflinger/EventHub.cpp

EventHub::EventHub(void):mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),mNextDeviceId(1),mControllerNumbers(),mOpeningDevices(nullptr),mClosingDevices(nullptr),mNeedToSendFinishedDeviceScan(false),mNeedToReopenDevices(false),mNeedToScanDevices(true),mPendingEventCount(0),mPendingEventIndex(0),mPendingINotify(false){acquire_wake_lock(PARTIAL_WAKE_LOCK,WAKE_LOCK_ID);mEpollFd=epoll_create1(EPOLL_CLOEXEC);//省略部分mINotifyFd=inotify_init();mInputWd=inotify_add_watch(mINotifyFd,DEVICE_PATH,IN_DELETE|IN_CREATE);//省略部分structepoll_eventeventItem;memset(&eventItem,0,sizeof(eventItem));eventItem.events=EPOLLIN;eventItem.data.fd=mINotifyFd;intresult=epoll_ctl(mEpollFd,EPOLL_CTL_ADD,mINotifyFd,&eventItem);//省略部分intwakeFds[2];result=pipe(wakeFds);mWakeReadPipeFd=wakeFds[0];mWakeWritePipeFd=wakeFds[1];result=fcntl(mWakeReadPipeFd,F_SETFL,O_NONBLOCK);result=fcntl(mWakeWritePipeFd,F_SETFL,O_NONBLOCK);eventItem.data.fd=mWakeReadPipeFd;result=epoll_ctl(mEpollFd,EPOLL_CTL_ADD,mWakeReadPipeFd,&eventItem);//省略部分}

我相信看到这里的EventHub,大家应该会有非常非常熟悉的想到getevent源码,二者其实本质的功能都是一样的,这里使用的epoll来监听各个fd的变化,getevent中使用是poll。
这里大概可以看出EventHub职责就是来获取/dev/input/路径设备的,及对数据进行获取,和getevent职责一样,后面再使用到的时候再进行具体分析。

接下来继续分析InputManager构造的最后一个方法initialize:

voidInputManager::initialize(){mReaderThread=newInputReaderThread(mReader);mDispatcherThread=newInputDispatcherThread(mDispatcher);}

这里把mReaderThread和mDispatcherThread构造出来了,它们就是native层面的Thread对象,这里在入门课时候就已经讲解过了,但是这里只是创建了线程并没有启动,那么到这里构造部分就分析完成了,但是还没看到最关键的两个线程启动。其实这个启动是在文章一开始的SystemServer类中startOtherServices触发的,通过调用inputManager.start()方法:
base/services/core/java/com/android/server/input/InputManagerService.java

publicvoidstart(){Slog.i(TAG,"Starting input manager");nativeStart(mPtr);//省略部分}

这里调用是nativeStart方法,有到了我们的native层:
base/services/core/jni/com_android_server_input_InputManagerService.cpp

staticvoidnativeStart(JNIEnv*env,jclass/* clazz */,jlong ptr){NativeInputManager*im=reinterpret_cast<NativeInputManager*>(ptr);status_t result=im->getInputManager()->start();if(result){jniThrowRuntimeException(env,"Input manager could not be started.");}}

这里其实只干了一件关键事情,调用了InputManager的start:
native/services/inputflinger/InputManager.cpp

status_tInputManager::start(){status_t result=mDispatcherThread->run("InputDispatcher",PRIORITY_URGENT_DISPLAY+PRIORITY_MORE_FAVORABLE);//省略部分result=mReaderThread->run("InputReader",PRIORITY_URGENT_DISPLAY+PRIORITY_MORE_FAVORABLE);//省略部分returnOK;}

这里其实就是干了把InputDispatcher和InputReader两个线程启动运行起来,那本节课就先分析到这里,目前就算把InputDispatcher和InputReader开始执行部分引出来了。

更多fw实战干货参考课程:https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 4:07:24

MySQL索引失效排查与治理:从EXPLAIN到慢查询优化实战

1. 先还原一场压测事故&#xff1a;一条DATE()函数让接口延迟翻了20倍90%这个数字多少有点标题党&#xff0c;但换成"九成新手会在索引上至少踩一个坑"&#xff0c;我觉得一点不夸张。先给你讲个真实发生在我身边的压测事故&#xff0c;因为这个例子几乎把所有索引失…

作者头像 李华
网站建设 2026/10/16 4:07:06

三维图纸截图粘贴全攻略:从视图准备到图像导出的工程表达技巧

作为一个常年泡在三维设计软件里的机械工程师&#xff0c;我太清楚“三维图纸截图粘贴”这件小事有多折磨人了。你正赶着出评审报告&#xff0c;或者在微信上给外协加工厂说明一个结构问题&#xff0c;反手一个截图丢过去&#xff0c;结果对方回你一句“看不清”“颜色太暗”“…

作者头像 李华
网站建设 2026/10/16 4:06:31

置信规则库BRB MATLAB代码实战:从规则构建到证据推理融合

简介&#xff1a;这份资源是杨剑波教授置信规则库&#xff08;BRB&#xff09;的MATLAB实现代码包&#xff0c;面向模糊逻辑、不确定性推理与决策优化方向的学习者和研究者&#xff0c;尤其适合希望动手复现BRB建模与参数优化流程的中高级用户。压缩包共9个文件&#xff0c;以8…

作者头像 李华
网站建设 2026/10/16 4:06:28

用Python打造旅游网站数据分析可视化大屏:完整毕设项目实战

每年到毕业季&#xff0c;都会有不少人拿着旅游网站相关的题目来问我——大部分是只做了一个简单的增删改查&#xff0c;景点列表、线路预订、后台管理&#xff0c;学生做得累&#xff0c;导师看了摇头。其实这个方向完全能做出一个很有含金量的毕设项目&#xff0c;关键在于往…

作者头像 李华
网站建设 2026/10/16 4:05:50

项目参考资源整理指南:分类框架、可信度评级与可复现清单构建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/16 4:05:09

ContextCapture实景建模全流程:从照片到三维模型的生产线

简介&#xff1a;ContextCapture 是一款在倾斜摄影实景建模、三维城市重建、工程测量等领域广泛使用的专业软件&#xff0c;适合测绘工程师、三维建模师及相关专业学习者。这份资源包整理了可靠的软件下载地址&#xff0c;并给出实测可用的判断结论&#xff0c;支持 64 位系统&…

作者头像 李华