




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Reader_Dispatcher 线程启动分析本节主要讲解 reader 线程和 dispatch 线程要分析输入系统,最好先从输入事件系统服务 InputManagerService 入手,这是了解输入系统的起点,所有其他相关类、线程都因此被创建或间接创建。Input 输入子系统起点就是从 java -cpp 的创建过程:系统启动后创建 init 进程(=1),init 进程创建出 Zygote 进程,然后 Zygote 进程孵化出 SystemServer 进程,随后 SystemServer创建了服务 ActivityManagerService、erManagerService、Pa
2、ckageManagerService、InputManagerService 等SystemServer.javaprivate void startOtherServi() 其实在 SystemServer 中做了 2 件事情,第一:创建线程InputManagerService inputManager = new InputManagerService(context);参考:第二:启动线程inputManager.start();那就按照这 2 个步骤,来详细分析一下:分析第一步:创建线程InputManagerService inputManager = new InputMana
3、gerService(context);InputManagerService inputManager= new InputManagerService(context);这个步骤中做了些啥?this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper();创建了一个 InputManagerHandler 对象,参数是 HandlerThread 中创建的 looper 对象;mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue();用 L
4、ooper 中的消息队列作为参数,调用本地方法 nativeInit,返回 C+中的 NativeInputManager 对象地址赋给 mPtr LocalServi.addService(InputManagerernal.class, neLocalService();把 InputManagerernal.class 和 LocalService 对象作为一对添加到 ArrayMapClass, Object中可以看到 Java 层的 IMS 实际上只是对 Native 层的 InputManager 的一层包装;其创建主要是 native 层进行创建,并把 native 层的 Inp
5、utManager 地址赋值给 InputManagerService 的 mPtr 变量;接下来看:mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue();的调用过程:该构造函数中调用了 nativeInit 函数,看到 native就知道了,它是去调用由 c+实现的函数:可以看到首先通过 android_os_MessageQueue_getMessageQueue 函数获取到本地端的 MessageQueue,这个在 Handler 机制中的本地Handler 机制深入中有提到,该 NativeMessageQu
6、eue 对象在 java 层创建 Looper 时创建实例,然后将地址指针赋值为 Looper 对应的 MessageQueue 中的 ptr 变量中,这里根据指针来获取该 NativeMessageQueue 对象;根据 NativeMessageQueue 对象获取其中对应的 Looper(native),用以创建调用了 NativeInputManager 构造得到了 im 对象,其实的东西就在这个 NativeInputManager 的创建过程中:创建了 eventHub 及创建了 InputManagerEventHub 从名字就可以看出,它是用来收集以及外部的输入事件的;而 In
7、putManager 则是对 Event 事件进行处理分发;那么在 eventHub 中其实就是检测设备文件是否有变化,输入设备是否有数据可读首先引入:epoll 的作用EventHub 的构造函数创建流程:概述一下 EventHub 的构造函数:EventHub:EventHub(void) :.mEpollFd = epoll_create(EPOLL_SIZE_H);mINotifyFd = inotify_init();/inotify 监测 DEVICE_PATH 目录 DEVICE_PATH = /dev/input;/并监测删除和创建文件 fd 的事件result = inoti
8、fy_add_watINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);result = pipe(wakeFds);/新建管道mWakeReipeFd = wakeFds0;mWakeWritpeFd = wakeFds1;result = fcntl(mWakeReipeFd, F_SETFL, O_NONBLOCK);/设置管道的读端为非阻塞管道的读端result = epoll_ctl(mEpolld, EPO
9、LL_CTL_ADD, mWakeReipeFd, &eventItem);/.可以看到 EventHub 的构造函数中使用了 inotify 及 epoll 机制来输入设备是否有创建或移除,是否有输入数据可读读到此处,提出 2 个问题:epoll 机制一般有 3 个系统调用接口,而截止到此处,只提到 epoll_create, epoll_ctl,还缺 epoll_wait,猜测在代码某处肯Q1定有 epoll_wait,所以注意在何时调用 epoll_wait 来开启;这里仅进行了初始化,否则 epoll 机制无法工作。发现在 EventHub 的 getEvent 中进行了 epoll_
10、wait 调用如果找到了 epoll_wait,调用进程处于等待状态,那么肯定还有一处用来唤醒调用进程的代码,比如 Looper 的 wake 函Q2数或者其他地方调用了 write 系统调用。发现在:EventHub.cpp 中的 wake 函数中,对 EventHub 构造函数中创建的 fifo 进行了 write因此猜测:是不是当检测到有数据产生时,就把这个数据写个管道,这时候 getEvent 就被唤醒了。是不是这样嗯?答:并不是这样。参考:I:1、6、Anddroid 系统4、Andriod 底层6、子系统研究7、输入子系统7、Reader 线程1、第一件事_获取事件_Reader
11、线程1、Reader 线程_使用 EventHub事件使用 EventHub事件.doc因为在 getEvent 中对/dev/input 下所有的设备文件都进行了读写。EventHub 的原理可参考:inotify_epoll.c,路径6、子系统研究7、输入子系统1、Linux 之监测文件 inotify 和 epollcodeAPP_0006_inotify_epoll-master/inotify_epoll.c中的代码,效果一致:接下来看创建了 InputManager 到底是做了些啥?很明显是创建了:inputDispatcher 和 InputReader 及对应的线程 mRead
12、erThread,mDispatcherThread分析一下这个 InputManager 的构造函数:用这两个传递过去的对象类型作为参数分别创建了 InputDispatcher 和 InputReader 对象,再调用 initialize 方法分别创建了与InputDispatcher 和 InputReader 对应的线程 InputDispatcherThread 和 InputReaderThread 对象;此时注意将 mDispatcher 当作参数传进了 InputReader;在 NativeInputManager 函数中,调用了 InputManager 的构造方法。第一
13、个参数是刚创建的 EventHub 对象,第二、三个参数都是 this。但是 this 是 NativeInputManager 对象,而 InputDispatcher 的构造函数参数需要的是 InputDispatcholicyerface 对象那这个调用为啥没有报错呢?因为NativeInputManager 继承了InputReadolicyerface、InputDispatcherface 类,实际类型还是 NativeInputManager;olicy因此是 ok 的。InputDispatcher 构造函数:mLooper = new Looper(false);创建并初始化
14、了 Looper 对象,在 Looper 构造方法创建了管道并采用 epoll 机制把管道加入到列表中。注意,此处创建的 Looper 对象是在 InputDispatcher 中的,与主线程 ThreadLocal 中的 Looper 没有关系。既然有了 epoll_ctl,那肯定某处会调用 epoll_waitQ3InputReader 构造函数第一个参数是 EventHub 对象,第二个 policy 赋值给 mPolicy,policy 是 InputReadolicyerface 接口类型,实际是NativeInputManager 对象类型。第三个 listener 实际是Inpu
15、tDispatcher 类型,因为 InputDispatcher 实现了InputDispatchererface,InputDispatchererface 又实现了 InputListenererface,因此 policy 也是 InputListenererface 对象类型mQueuedListener = new QueuedInputListener(listener);把 InputListenererface 对象类型 listener 作为参数创建 QueuedInputListener 对象,用以分发事件接下来分析: InputManager.cpp 的 initial
16、ize 函数用 InputReader 对象作为参数创建 InputReaderThread 线程对象,用 InputDispatcher 作为参数创建 InputDispatcherThread 线程对象,InputReaderThread 的构造函数:把 InputReader 对象赋给 mReader 变量,InputReaderThread 的逻辑为调用 InputReader 的 loopOnce 函数;暂且停在这里,因为 Thread 只是创建,并未运行,等分析到具体运行代码时再作分析;InputDispatcherThread 的构造函数:把InputDispatcher 对象赋
17、给mDispatcher 变量,该类同样是一个Thread,其主要运行逻辑即调用InputDispatcher 中的dispatchOnce函数;进程执行到此处,InputManagerService 的初始化就完成,整个过程都是在创建、初始化各种对象。分析第二步:启动线程 inputManager.start();知道对象 inputManager 是属于 InputManagerService 类的第一个调用了 nativeStart第二个调用了 Watchdog.getInstance().addMonitor(this)Watchdog 是看门狗,一个单例类,addMonitor 方法
18、把 InputManagerService 对象添加到 Watchdog,便于回调Q5 :创建了看门狗,用?接下来分析 nativeStart 做了啥? 其实可以而知,这个 native 肯定是又调到了 cpp 中去了看一下 im-getInputManager()-start();做了啥明显是,启动了 dispatch 线程和 reader 线程首先启动分发器线程 InputDispatcherThread,调用 run 方法后,开始执行 Thread 的线程threadLoop 方法,如果 threadLoop返回 true,就再次执行 threadLoop 方法直到 requestExit 方法停止线程;再调用 InputReaderThread 的 run 方法
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025届河北省张家口市高三上学期期末质量检测地理试题及答案
- 2025年度专业车库租赁权转让合同
- 2025年度农村土地承包经营权流转与农业文化遗产保护合同
- 2025年度中小企业流动资金授信借款合同
- 2025年度城市河道治理房屋拆迁补偿合同
- 2025年度人才共享与借用项目合作协议
- 2025年度协商解除劳动合同与员工住房安置合同
- 2025年度公司销售业务员协议书:人工智能赋能下的销售代理合同
- 2025年度子女对父母赡养及社区互助保障协议
- 化妆品店装修合同
- 《大学生安全教育》课件 项目四 军事安全
- 10KV电力配电工程施工方案
- 智能感知工程基础知识单选题100道及答案解析
- 肌肉注射药物不良反应及预防措施研究
- 人教版数学六年级上册第一单元测试卷
- 大型养路机械司机(打磨车)高级工技能鉴定考试题库(含答案)
- 车辆使用不过户免责协议书范文范本
- 自建房-预算表
- DB11T 2033-2022 餐厨垃圾源头减量操作要求
- 合约部年终工作总结
- 【人教版】pep六年级英语下全册教案(表格版)
评论
0/150
提交评论