Android Native Looper机制
在分析Native层代码的时候,很多地方都用到了Looper机制,本文将深入分析一下,方便理解相关机制,在Android系统中,Native层提供了类似于java层的消息循环机制。机制的核心是通过epoll机制,主要就是优化轮询操作,本文不做讲解。Native层的消息Looper机制代码,主要实现位于:
system/core/libutils/Looper.cpp
system/core/include/utils/Looper.h
说明
Looper机制包含两种实现方式,一种是通过sendMessage,另外一种是addFd。
sendMessage
提供如下三个方法:
addFd
Navite Looper 除了提供message机制之外,还提供了监听文件描述符的方式。
通过addFd()接口告之Looper,此文件描述符将要加入轮询之中。
其中:
-fd:为所需要轮询的文件描述符。
-ident:表示为当前发生事件的标识符,必须>=0,或者为POLL_CALLBACK(-2)如果指定了callback。
-events:表示为要监听的文件类型,默认是EVENT_INPUT。
-callback:当有事件发生时,会回调该callback函数。
-data:文件描述符fd里面的数据。
提供了两个addFd函数,一种是传入函数指针Looper_callbackFunc,回调的时候直接调用函数本身。还有一种是传入LooperCallback的子类。回调的时候执行handleMessage。
使用方法
addFd使用方法
使用方法,以inputdispatcher里面的代码举例说明,大致需要四步:
1、创建Looper。
2、启动Looper,并等待消息
3、增加fd到轮询池中
4、请求Looper进行poll操作
sendMessage使用方法
和addFd的区别仅仅存在于第三步。
1、创建Looper
2、启动looper并等待消息。
3、sendMessage,第一个参数的类必须继承了MessageHandler.
4、启动轮询。
原理分析
addFd原理分析
1、创建Looper的过程中,会创建一个mWakeEventFD,然后调用rebuildEpollLocked,重新更新当前被epoll实例监听轮询的fd,并将当前的mWakeEventFD和通过addFd添加的fd添加到创建的epoll实例中,也就是加入监控,当以上fd有处于可读或者可写状态时,则进行相应的操作。
2、接下来调用pollOnce,当系统有时间需要处理的时候,pollOnce的主要代码实现在pollInner。
epoll_wait阻碍当前线程,当mEpollFd上监听的文件描述符有可读或者可写时间则继续执行。epoll机制是native looper的核心。针对Looper来说,当mWakeEventFD或者通过addFd添加的fd有可读可写事件,那么则继续往后执行,否则就阻塞在此处。默认情况会进行阻塞。
3、addFd,如果没有添加过当前fd,那么直接添加进epoll的监听之中,否则修改当前的epoll实例里面的fd。这样后续fd上有任何事件,就可以通过epoll_wait来进行控制了。到目前为止,epoll实例mEpollFd监听了mWakeEventFD和addFd添加的fd.
4、Looper调用wake,如下代码显示。
mWakeEventFd就会有可读事件,那么epoll_wait就会继续往后执行。
epoll_wait会返回所有的事件eventsItems,如果是mWakeEventFd上的事件,那么执行awoken(),如果是通过addFd添加的fd上的事件,那么则通过pushResponse将当前的events添加到mReponse中。后续遍历回调的时候,会用到mResponses.
接下来就会执行callback函数了。
接下来会调用handleEvent。从而直接调用回调函数。
如上分析就完成了。
sendMessage原理分析
刚开始初始化的地方,和addFd一致,区别就是在sendMessage。主要有两个方法,一个是sendMessage,消息及时分发。还有一个sendMessageDelayed,延时分发消息。
都会将当前的消息添加到mMessageEnvelopes里面。消息池里面没有消息,那么i=0,就会调用wake(),唤醒epoll_wait,继续执行epoll_wait后面的内容,处理事件和消息回调。如果还有延迟消息。正常的流程中,
3、接下来会调用pollOnce。
最终调用了handler的handleMessage.
总结
通过addFd方式添加的回调,如果参数是Looper_callbackFunc,那么最终调用function本身。如果参数是LooperCallback的子类,那么调用子类下覆写的handleEvent.如果是通过sendMessage方式来发送消息,那么最终调用的是实现了MessageHandler的子类的handleMessage方法。