Android中,RILD是RIL(Radio Interface Layer) Deamon的简称。简单的说它下面承接GSM/GPRS Modem(电话通信模块),上面接电话应用相关的Java库(telephony internal)。telephony internal通过socket将请求发送给RILD的消息循环,消息循环则将请求转发给底层通信模块(直接调用底层的库)来实现对通信模块功能的调用。反之,当通信模块有类似于来电的消息时,也会通过RILD的回调,将信息包装成消息,发送到RILD的消息循环中去处理,最后再通过socket回送给telephony internal,以便通知上层。整体结构参见如下:
概述
消息循环(ril_event_loop()函数内)位于单独的线程中,用来处理三种消息,分别对应三个不同的队列,面对的是三种不同的需求:
1.定时列表(timer_list): 此队列中的消息主要用于处理一些延时的操作。比如:从飞信模式切换到通信模式(实际上就是打开通信模块)时,若SIM卡未准备好,那么需要延续一段时间再检查是否准备好,此时就要将消息扔至此队列。
2.侦听列表(watch_list): 此队列中的消息一是作为socket的服务端,用来侦听客户端的请求;另一个是作为本进程的其它线程(如:检查通信模块来电消息的线程)传递过来的消息。
3.挂起列表(pending_list): 之所以叫挂起,实际上指的是在处理上面两中类型的消息时,并不真正的处理消息体,而是将符合条件的消息丢到本队列中。由于消息附带处理函数,所以在处理本队列的消息时,直接触发即可。
消息循环所要做的事就是先等待某个时间间隔(定时消息要求的)或者是客户端(socket或通讯模块的消息)的请求,然后再按次序处理上面三个对列中的消息。
下面还是通过源代码来分析消息循环的处理过程。
ril_eventril_event指代的是消息,它的数据结构如下:
struct ril_event *next; // 下一个消息 struct ril_event *prev; // 前一个消息 int fd; // 开始我以为这里有可能是socket描述符或pipe描述符,但实际上它还被用作消息的回调函数的参数? int index; // 侦听列表(watch_list)中的索引,侦听列表采用的数组而不是链表 bool persist; // 是否常驻侦听列表(watch_list)中。若常驻,则当被转到pending_list中时,不删除。 struct timeval timeout; // 超时,这个为一个时间点。在处理定时消息时,用于和当前的时间比较,以确定是否处理该消息。 ril_event_cb func; // 回调。此消息对应的处理函数。 void *param; // 回调参数。
三种消息列表的定义如下:static struct ril_event * watch_table[MAX_FD_EVENTS]; // 侦听列表 static struct ril_event timer_list; // 定时列表 static struct ril_event pending_list; // 挂起列表
ril_event_init()