Rild是Init进程启动的一个本地服务,这个本地服务并没有使用Binder通讯手段,而是采用了socket 通讯方式。

由于Android 开发者使用的Modem 是不一样的,各种指令格式,初始化序列都可能不一样,GSM 和CDMA 就差别更大了,所以为了消除这些差别,Android设计者将ril做了一个抽象,使用一个虚拟电话的概念。这个虚拟电话对象就是GSMPhone(CDMAPhone),底层描述的实现就是靠RIL来完成适配。

Andoid将RIL层分为两个代码空间:RILD管理框架,AT相关的xxxril.so 动态链接库。将ril独立成一个动态链接库的好处就是android系统适应不同的modem,不同的medem有独立的ril与之对应。从这个层面上看,Rild 更多是一个管理框架。


而ril是具体的AT指令合成者和应答解析者。从最基本的功能来讲,ril 建立了一个侦听Socket,等待客户端的连接,然后从该连接上读取RIL-Java 成传递来的命令并转化成AT指令发送到Modem。并等待Modem 的回应,然后将结果通过套接口传回到Ril-Java 层。
下图是Ril-D 的基本框架:


下面的数据流传递描述图表描述了RIL-JAVA 层发出一个电话指令的5步曲。


在AT通讯的过程中有两类响应:一种是请求后给出应答,一种是通知类,即为不请自来的,例如短信通知达到,我们称该类通知为URC。在Rild 中URC 和一般的Response 是分开处理的,概念上URC由handleUnsolicited @Atchannel.c 处理,而Response由handleFinalResponse来处理。

1 Event Loop
Rild管理的真正精髓在ril.cpp,ril_event.cpp 中,在研究的过程中,可以看到设计者在抽象上所下的功夫,设计得很优美。Event Loop 的基本工作就是等待在事件端口(串口,Socket),
一旦有数据到达就根据登记的Event 回调函数进行处理。Ril设计者是如何建立一套管理框架来完成这些工作的?
1.1 Event 对象
Event 对象构成:(fd,index,persist,func,param)
fd 事件相关设备句柄。
index
persist 如果是保持的,则不从watch_list 中删除。
func 回调事件处理函数
param 回调时参数
为了统一管理事件,Android 使用了三个队列:watch_list,timer_list,pending_list,并使用了一个设备句柄池readFDS。
readFDS:是Linux 的fd_set,readFDS 保存了Rild中所有的设备文件句柄,以便利用select函数统一的完成事件的侦听。
watch_list:监测队列。需要检测的事件都放入到该队列中。
timer_list:timer 队列
pending_list:待处理事件队列,事件已经触发,需要回调处理的事件。
事件队列的操作:ril_event_add,ril_event_del, ril_timer_add


在添加操作中,有两个动作:
(1) 加入到watch_list
(2) 将句柄加入到readFDS 事件句柄池。

1.2 ril_event_loop()
对于Linux 设备来讲,我们可以使用select函数等待在FDS上,只要FDS 中记录的设备有数据到来,select就会设置相应的标志位并返回。readFDS 记录了所有的事件相关设备句柄。readFDS 中句柄是在在AddEvent 加入的。所有的事件侦听都是建立在linux 的select readFDS 基础上。


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 事件,发起事件回调函数。

1.3 几个重要的Event
上面分析了ril-d 的框架,在该框架上跑的事件有什么
(1)s_listen_event- (s_fdListen,listenCallback)
listenCallback 处理函数,
接收客户端连接:s_fdCommand=accepte(..)
添加s_commands_event()
重新建立s_listen_event,等待下一次连接
(2)s_command_event(s_fdCommand,ProcessCommandsCallback)
从fdCommand Socket 连接中读取StreamRecord,使用ProcessCommandBufer 处理数据
s_listen_event 在大的功能上处理客户端连接( Ril-JAVA 层发起的connect ) , 并建立s_commands_event 去处理Socket 连接发来的Ril 命令。ProcessCommandBufer 实际上包含了Ril 指令的下行过程。

1.4 下行命令翻译及其组织 @ProcessCommandBuffer
RIL_JAVA传递的命令格式:Parcel,由命令号,令牌,内容组成。RIL_JAVA 到达RIL_C时转为构建本地RequestInfo,并将被翻译成具体的AT指令。由于每条AT命令的参数是不
同的,所以对不同的AT指令,有不同的转换函数,在此Android设计在这里做了一个抽象,做了一个分发框架,通过命令号,利用sCommand数组,获得该命令的处理函数。
sComand[]={
<...>
}
sComand存在于Ril_command.h 中。
&sComand[]=
<
{RIL_REQUEST_GET_IMEI, dispatchVoid, responseString},
{RIL_REQUEST_DIAL, dispatchDial, responseVoid},
{….}
>
dispatchXxx 函数一般都放在在Reference-ril.c 中,Reference-ril.c 这个就是我们需要根据不同的Modem 来修改的文件。

1.5 send_at_command 框架
send_at_command 是同步的,命令发送后,send_at_command 将等待在s_commandcond,直到有sp_response->finalResponse。
2 read loop @Atchannel.c
Read loop 解决的问题是: 解析从Modem 发过来的回应。如果遇到URC 则通过handleUnsolicited上报RIL_JAVA。如果是命令的应答,则通过handleFinalResponse 通知
send_at_command有应答结果。


对于URC,Rild 同样使用一个抽象数组 @Ril.CPP.
static UnsolResponseInfo s_unsolResponses[] = {
#include "ril_unsol_commands.h"
};
并利用RIL_onUnsolicitedResponse 将URC向上层发送。

3.Ril-d的整体数据流及其控制流示意图



更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)之 系统广播机制BroadcastReceiver的使用
  3. android的native开发的重要性
  4. Android(安卓)应用程序
  5. 将Unity3D游戏移植到Android平台上
  6. Android常用之Butterknife使用详解
  7. Android(安卓)init 详细过程分析
  8. android第三天课程 activity生命周期
  9. monkey测试android稳定性

随机推荐

  1. Android(安卓)Progressbar进度条显示
  2. android软键盘问题
  3. Android(安卓)sqlite例子 有外键的使用
  4. android中颜色对应的值
  5. Android(安卓)Studio编译问题:ProcessExce
  6. #Android(安卓)Ticks#Mount a filesystem
  7. Android(安卓)- 插件使用整理 Android(安
  8. Android(安卓)权限管理框架
  9. Android(安卓)全局异常捕捉 + 本地异常日
  10. android 代码混淆总结