Android Ril库总结

1总体框架    Rild是Init进程启动的一个本地服务,这个本地服务并没有使用Binder之类的通讯手段,而是采用了socket通讯这种方式。Andoid将RIL层分为两个代码空间:RILD管理框架(rild、libril.so),AT相关的xxxril.so动态链接库(libreference-ril.so)。rild把libril.so和libreference-ril.so联系起
摘要由CSDN通过智能技术生成

          

1总体框架

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

Andoid将RIL层分为两个代码空间:RILD管理框架(rild、libril.so),AT相关的xxxril.so动态链接库(libreference-ril.so)。rild把libril.so和libreference-ril.so联系起来,libril.so对上是java的socket通信,对下是把java层的命名分发到libreference-ril.so,而libreference-ril.so则把命名转换层AT的命令,通过串口发送给Modem。将RIL独立成一个动态链接库的好处就是Android系统适应不同的Modem,不同的Mode可以有一个独立的Ril与之对应。

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


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


① JAVA层通过socket发送命令到RILD

② RILD在EventLoop线程监听到socket消息,读取后封装成AT指令,通过串口发送给

     Modem。并等待Modem的回应命令

③ ReaderLoop线程不断读取串口端口数据,得到回应。回应信息分为两种,一种是对

于第二步AT指令的回应,另一种是主动上报信息,即URC消息,例如短信送达的

消息。

④ 判断是回应AT命令的回应信息,将消息传送到ril再次处理

⑤ 通过socket,将AT回应消息发送到JAVA

⑥ URC消息通过socket,通知到JAVA。

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

2初始化流程分析

2.1 初始化流程图

   

2.2 代码分析

Ø        init.XXX.rc                    

Ø        hardware/ril/rild/rild.c            

Ø        hardware/ril/libril/ril.cpp          

Ø        hardware/ril/libril/ril_event.cpp

Ø        hardware/ril/reference-ril/reference-ril.c

Ø        hardware/ril/reference-ril/atchannel.c   

2.2.1 入口 

---1. init.XXX.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 log

在Android配置脚本init.XXX.rc里面,如上所示,定义用于启动RILD的服务ril-daemon,我们可以看到, /system/bin/rild就是该服务的执行文件,即hardware/ril/rild/rild.c文件编译出来的可执行文件。参数如下:

Ø        -l:指定AT相关的动态链接库为libreference-ril.so

Ø        -d:指定modem的端口为/dev/tty/USB2

在ril-daemon服务中,还创建了两个socket端口,分别是rild、rild-debug,我们可以在

小机/dev/socket/目录下看到其节点。rild端口用于Ril库与java代码的socket通信,而rild-debug用于radiooptions(hardware/ril/rild/radiooptions.c)模拟java发送socket命令,起到调试的作用。


2. hardware/ril/rild/rild.c---main

int main(int argc, char **argv)
{
    const char * rilLibPath = NULL;
    void *dlHandle;
    const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
    const RIL_RadioFunctions *funcs;
    unsigned char hasLibArgs = 0;
    dlHandle = dlopen(rilLibPath, RTLD_NOW);//获取动态链接库libreferencer-ril.so
    //入口地址
    ......
    RIL_startEventLoop();//初始化EventLoop
    .......
    rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");//获取libreferencer-ril.so中RIL_Init方法的指针
    .......
    funcs = rilInit(&s_rilEnv, argc, rilArgv);//向libreference-ril.so注册
    RIL_register(funcs);//向libril注册libreference的回调函数,并监听socket端口
    ......
}

通过解析参数获取动态链接库的名字保存在rilLibPath中,调用dlopen()获取动态链接库的入口地址,然后再通过调用dlsym()获取libreference-ril中的RIL_Init()方法的指针。

调用RIL_startEventLoop()初始化EventLoop(),创建线程监听端口(管道、socket)事件。

调用libreference-ril的RIL_Init()方法,所带的参数是s_rilEnv结构体指针及-d指定的Modem端口/dev/ttyUSB2,并返回回调函数给Rild。

Ril_register()将回调函数注册到libril中。

Main()函数解析参数后,依次去做一些初始化工作,详细解析如下分析。

2.2.2  eventLoop

    Event Loop的基本工作就是等待在事件端口(管道,Socket),一旦有数据到达就根据登记的Event回调函数进行处理。

1.ril_event对象 hardware/ril/libril/ril_event.h

struct ril_event {
    struct ril_event *next;
    struct ril_event *prev;
int fd; //事件相关设备句柄,例如socket端口、管道
int index;
    bool persist;//如果是保持的,则不从watch_list中删除。
    struct timeval timeout;
    ril_event_cb func; //回调事件处理函数
    void *param; //回调时参数
};

为了统一管理事件,Android使用了三个队列:watch_table,timer_list,pending_list,并使用了一个设备句柄池readFDS,是Linux的fd_set,readFDS保存了Rild中所有的设备文件句柄,以便利用select函数统一的完成事件的侦听。

Ø        watch_table:监测时间队列。需要检测的事件都放入到该队列中。

Ø        timer_list:timer队列

Ø        pending_list:待处理事件队列,事件已经触发,需要所回调处理的事件。

    事件队列队列的操作:ril_event_add,ril_event_del, ril_timer_add

2. hardware/ril/libril/ril.cpp---RIL_startEventLoop

RIL_startEventLoop(void) {
    ......
    pthread_mutex_lock(&s_startupMutex);
    pthread_attr_init (&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
    ......
}

这个方法很简单,创建新线程,执行eventLoop()方法。

3. hardwar

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值