Rild(RIL Interface Layer Daemon)是Init进程启动的一个本地服务,这个本地服务采用了socket的通讯方式。Android 给出了一个RIL实现框架。由于Android开发者使用的Modem是不一样的,各种指令格式,初始化序列都可能不一样,GSM和CDMA就差别更大 了,所以为了消除这些差别,Android设计者将ril做了一个抽象,使用一个虚拟电话的概念。这个虚拟电话对象就是 GSMPhone(CDMAPhone), Phone对象所提供的功能协议,以及要求下层的支撑环境都有一个统一的描述,这个底层描述的实现就是靠RIL来 完成适配。
Andoid将RIL层分为两个代码空间:RILD管理 框架和具体modem相关的xxxril.so动态链接库。将RIL独立成一个动态链接库的好处就是Android系统适应不同的MODEM,不同的Modem可以有 一个独立的Ril与之对应。从这个层面上看,Rild更多是一个管理框架。
在阐述rild之前,先对整体架构有个初步认识。接下来,将基于prima2平台分析RIL层跟modem是如何进行命令和数据的交互。尽可能的将整个工作流程阐释清楚。
一、RIL层的代码结构
RIL层包括三部分:
- RILD 应用程序: 由init进程启动的服务,是RIL层的入口。
代码位置:/hardware/ril/rild/rild.c
- libril 库: RILD是个框架,具体功能通过调用libril来实现。
代码位置:/hardware/ril/libril/ril.cpp
/hardware/ril/libril/ril_event.cpp 这两个文件实现了跟上层交互的接口和功能
/hardware/ril/libril/ril_commands.h
此文件定义了各个请求命令对应的分发函数和回应函数
/hardware/ril/libril/ril_unsol_commands.h
此文件定义了各个通知对应的回应函数。
Modem既可以接受命令的请求,也会主动上报信息。
- Modem适配的动态链接库
直接与modem进行命令的发送和信息的接受,是与linux驱动进行交互的衔接层。代码位置:
/hardware/csr/libril/sirfril.c
/hardware/csr/libril/atchannel.c
二、RILD启动流程在android系统启动的时候,init.rc脚本将rild守护进程启动起来。接下来进行一系列的初始化工作,具体流程如下图所示:
ril_event_loop 利用select等待在readFDS(fd_set)上,当select设备有数据时,ril_event_loop会从select返回,在 watch_list中相应的Event放置到pend_list,如果Event是持久性的则不从watch_list中删除。然后 ril_event_loop遍历pengding_list处理Event事件,发起事件回调函数。
在 AT通讯的过程中有两类响应:一种是请求后给出应答,一种是通知类,即为不请自来的,例如短信通知达到,我们称该类通知为URC。在Rild中URC和一 般的Response是分开处理的,概念上URC由 handleUnsolicited@Atchannel.c处理,而Response由 handleFinalResponse来处理send_at_command是同步的,命令发送后,send_at_command将等待在s_commandcond,直到有sp_response->finalResponse。
三、Ril-d的整体数据流及其控制流
当我们把rild启动之后的流程按照时间顺序了解后,我们从整体上对数据流和控制流的走向进行一个概览。