1. init.rc里的rild
一般情况下,在init.rc或init.*.rc里面我们都能找到如下的服务启动:
service ril-daemon /system/bin/rild -l libreference-ril.so -- -d /dev/ttyUSB2
class main
socket rild stream 660 root radio
socket rild-debug stream 660 radio system
user root
group radio cache inet misc audio sdcard_rw
主要说明一下参数:
-l:使用指定的ril库;
--:指定的ril库有参数,即为--之后的内容,所以后面的-d /dev/ttyUSB2不是rild的参数,是libreference-ril.so的参数。在rild中读取之后会传到ril库中。
另外注意一下这两行,在init中会解析这个socket,并初始化这个socket,所以我们在rild中是找不到socket建立的代码,这里就已经完成了。
socket rild stream 660 root radio
socket rild-debug stream 660 radio system
2. 在rild中,即rild.c中通过如下调用进入到ril库中,传入了上面说的-d参数,在ril库中,开启一个线程:mainLoop。
funcs = rilInit(&s_rilEnv, argc, rilArgv);
在mainLoop中主要干了两件事,一是打开串口设备并做设置串口,另外就是调用at_open,在at_open中又开启了一个线程:readerLoop, 这是一个循环,会在后台一直运行,功能就很明白了,监听来在modem的消息,并处理。
紧接着上一行代码,调用如下函数,这个函数中获得了rild和rild-debug这两个socket服务端的文件描述符。
RIL_register(funcs);
在RIL_register中调用了 RIL_startEventLoop() 函数,在这个函数中开启了另一个重要的线程:eventLoop。实际的循环是在 ril_event_loop() 中实现。
eventLoop的实现有些复杂,理解它的原理需要理解linux的系统调用select,在RIL_register中把前面获得的两个文件描述符通过如下的代码添加到select监听的rfds中,如果它们有消息到来时,select就能返回,再调用其它函数对消息进一步处理。
ril_event_set (&s_listen_event, s_fdListen, false,
listenCallback, NULL);
rilEventAddWakeup (&s_listen_event);
3. RIL.java,这是在java里和rild相联系的代码,在子类class RILReceiver中开启了一个线程专门来负责接收来自eventLoop的信息。
InputStream is = mSocket.getInputStream();
for (;;) {
Parcel p;
length = readRilMessage(is, buffer);
if (length < 0) {
// End-of-stream reached
break;
}
p = Parcel.obtain();
p.unmarshall(buffer, 0, length);
p.setDataPosition(0);
//Log.v(LOG_TAG, "Read packet: " + length + " bytes");
processResponse(p);
p.recycle();
另一个子类class RILSender负责把请求发向rild。
另一篇写Rild的文章写的很好,推荐:
Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
http://blog.csdn.net/opendroid/article/details/4071149