android ril开发介绍

上传人:E**** 文档编号:118144325 上传时间:2019-12-11 格式:PDF 页数:14 大小:509.74KB
返回 下载 相关 举报
android ril开发介绍_第1页
第1页 / 共14页
android ril开发介绍_第2页
第2页 / 共14页
android ril开发介绍_第3页
第3页 / 共14页
android ril开发介绍_第4页
第4页 / 共14页
android ril开发介绍_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《android ril开发介绍》由会员分享,可在线阅读,更多相关《android ril开发介绍(14页珍藏版)》请在金锄头文库上搜索。

1、 Android RIL 开发介绍 1 Android RIL 开发开发介绍介绍 -海信海信移动技术移动技术公司公司第三研究所第三研究所 陈泽元陈泽元 20130314 篇前语篇前语 RIL (Radio Interface Layer) 的设计目的, 就是为了将 modem 功能抽象出来, 使其不会因不同的modem而做重大的颠覆性修改和调试。 它提供了AP与modem 之间通讯的桥梁,在保证 AP 与 modem 正常有效通讯的同时,尽可能的简化 AP 与 modem 之间的交互。 RIL 将用户所需要用到的各种功能抽象成对应的 RIL request 和 unsolicited comm

2、and,最终转换成 3GPP 标准的 AT 命令,交由 modem 处理,并将处理结果 返回给 UI。 AT 命令通常被用作与第三方 modem 通讯的一个非常有效的方式, 当第三方 模块无法轻易的移植到某个平台上或仅提供库文件、二进制文件使用时,通常会 使用 AT 命令来与模块进行交互,以实现相应的功能。AT 命令在 3GPP 中都有相 关规定,能够支持 modem 的各种功能,个人理解,实际它上就是 modem 各种 功能的抽象, 提供与外界通讯的接口。(实际上, 我们也可以根据 AT 命令的格式, 自己进行扩展,应用于非无线通讯的第三方交互中,比如 PC 客户端与某模块之 间的通讯,或某

3、两个 PC 应用程序之间的通讯,都是可以的,关键就看你如何理 解,如何定义,如何抽象出你的 AT 命令了) 。 AT 命令按照请求方式分为两种:一种是主动请求命令,称作 request AT command; 另外一种是非请求时的modem上报命令, 称作unsolicited AT command。 在 Android 平台中, RIL 已被模块化, 包含三部分: RILD、 libril 和 Vendor RIL。 本篇的目的就是讲解 Android 平台这三个模块相关的重点概念和关键点,同 时对扩展新的一个 RIL request 的处理和新的 unsolicited AT comman

4、d 的处理做个 介绍,适合于刚接手 RIL 开发的工程师以尽快的熟悉自己的开发工作。 一、一、Android RILD 介绍介绍 RILD 是一个开机启动的后台服务进程, 在 init.rc 中定义。 当系统起来后, init 进程在解析 init.rc 中的 service 时,就会启动并加载 RILD 进程,同时创建两个名 为 rild 和 rild-debug 的 socket。RILD 作为该 socket 的服务器端运行,等待客户端 RILJ 的连接。Android 的 socket 通讯是基于 linux 的 socket,在 linux socket 基础上 做了一层封装,供 J

5、ava 层调用。 RILD 在 init.rc 中的启动: service ril-daemon /system/bin/rild class late_start socket rild stream 660 root radio socket rild-debug stream 660 radio system user root group radio cache inet misc audio sdcard_rw Android RIL 开发介绍 2 RILD 进程启动后,主要做以下几件事情: (1) 依次通过 dlopen()和 dlsym()来找到 Vendor RIL 链接库,并

6、调用 RIL_Init() 来初始化 RIL 和 modem (将在后面 Vendor RIL 中讲解) (2) 调用 RIL_startEventLoop()创建一个独立线程,在该线程中建立一个基于 pipe 的多 I/O 复用的 RIL 消息队列处理机制,并进入 ril_event_loop()循环,select pipe 中的 fd 来处理各个 RIL 消息(将在 libril 中讲解) (3) 调用 RIL_register()监听客户端的 socket 连接,一旦发现有客户端连接成 功,将进入 processCommandsCallback()循环,不断读取来自客户端的 reques

7、t 数 据并分发处理。 其中,(1)将进入 Vendor RIL;(2)和(3)将进入 libril,而 RILD 在处理完这三件 事情后,就没有任何工作了,将在代码 while(1) sleep(0 x00ffffff); 中一直 sleep()下去。 下面对 RILD 所做的三件事情做个较详细的介绍: (1) 加载加载 Vendor RIL 链接库链接库 Vendor RIL 库有两种方式可以指定: 在 init.rc 中通过-l 参数指定,如: service ril-daemon /system/bin/rild -l /system/lib/libreference-ril-gsm.

8、so 在 system.prop 中通过 rild.libpath 来指定,如: rild.libpath=/system/lib/libreference-ril-gsm.so 另外,在 modem 通讯时,必须指定通讯的端口,用于 AT 命令通讯,也有 两种方式可以指定通讯端口: 在 init.rc 中通过-d 参数指定,如: service ril-daemon /system/bin/rild -l /system/lib/libreference-ril-gsm.so - -d /dev/ttyS0 在 system.prop 中通过 rild.libargs 来指定,如: rild

9、.libargs=-d /dev/ttyS0 Vendor RIL 库是通过接口 dlopen()来加载的,dlHandle = dlopen(rilLibPath, RTLD_NOW);加载后, 将通过代码rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char *)dlsym(dlHandle, RIL_Init);来找到接口 RIL_Init(),并在接下 来调用该接口(funcs = rilInit() , 从而让 Vendor RIL 进行 RIL 及 modem 相关的一系列初始化动作,为接

10、下来的 AT 通讯做好准备,这部分 内容将在 Vendor RIL 部分重点讲解。 值得重点提到的一点是,在 RIL_init()调用处理结束后,会返回 RIL_RadioFunctions 的一组函数指针,其中最为核心接口是 onRequest(),用于 AT request 的处理。 该组函数指针将由 RIL_register()传递到libril 中, 在处理 AT request 时, 及时调用 onRequest()将来自 RILJ 的 request 转换成 AT 命令, 并发送给 modem 进行处理。 Android RIL 开发介绍 3 (2) 启动启动 RIL 消息队列处理

11、机制消息队列处理机制 RIL 消息队列机制的启动位于 RIL_startEventLoop(),它内部将启动一个独立 线程并进入 eventLoop(),开始消息的循环处理。 而在 eventLoop()内部,创建了一个 pipe,这是 I/O 多路复用处理 RIL 消息队 列的核心。每种 RIL_event,都将与一个 fd 一一对应,每个 fd 都有一个回调函数 与其绑定,即每一种 RIL_event 都有一个 handler 与其对应,该 handler 就是在添 加 RIL_event 时,调用 ril_event_set()所绑定的回调函数。当有新的一种 RIL_event 需要处理

12、时,会首先调用 ril_event_set()将 event 与回调函数绑定,然后调用 rilEventAddWakeup()将其加入 watch_table 待处理事件链表中,并将其 fd 放入 readfs 集中,等待 pipe 的 select 调度,一旦得到调度,就会依次调用 processReadReadies(;)n = select(nfds, firePending() RIL 消息的循环处理就是在 ril_event_loop()中实现的。它所对应的回调函数 是processWakeupCallback()。 但 processWakeupCallback()内部并没有太多的

13、处理, 目的仅仅是让 pipe 的 select()能够得到一次返回,这样 select()就能够跟踪新的消 息队列了。 从上面流程可知, s_wakeupfd_event 实际上是处理整个 RIL 消息的核心部分, 单独启动了一个 thread,并在 for 循环中循环处理各个消息,当遇到有消息到达 后,将通过 firePending()接口中的语句 ev-func(ev-fd, 0, ev-param),回调 ril_event_set()中该 event 所绑定的回调函数来处理相应的消息。 (ril_event_set() 将各个消息与相应的回调函数做了绑定,保证 ev-func(ev-

14、fd, 0, ev-param)能够 准确的调用 event 所对应的回调函数以处理各个消息) 从 libril 代码看,RIL 消息一共定义了 5 个,那么它们又是如何保证互不干扰 并及时得到处理的呢? 这是由于在 eventLoop()中实现了一个 pipe, (它实现了 I/O 多路复用,以避 免如果只有一个 I/O 时,不管其它 I/O 是否有数据,都会被阻塞,即使采用 I/O 轮询的方式,也会浪费很多的 cpu 时间;该 I/O 多路复用机制带来的好处是:它 会先构造一张有关 I/O 描述符的列表, 然后调用 select 函数, 当 IO 描述符列表中 的一个描述符准备好进行 I/

15、O 时,该函数返回,并告知可以读或写哪个描述符, 而具体的处理来自各 I/O 描述符的数据,则交由各自的回调函数) ,各消息通过 它来统一调度维护, 它包含一个 s_fdWakeupRead 和一个 s_fdWakeupWrite, 分别 对应 pipe 的读操作和写操作,并在 ril_event_loop()中通过 select()来调度到来的 各个 event,得到调度的 event 都交由 firePending()及时处理。 在各个event加入pipe统一管理时, google的牛人也做了一个很巧妙的设计, 即他们并不是直接通过调用 ril_event_add()将 event 加入

16、 RIL 消息队列, 而是调用 了 rilEventAddWakeup()来将 event 加入 RIL 消息队列, rilEventAddWakeup()不仅仅 执行了 ril_event_add()的动作,而且调用了 triggerEvLoop()接口。我们看接口 triggerEvLoop()的实现,该接口代码很简单,就一个核心语句 ret = write (s_fdWakeupWrite, , 1),其作用是向 pipe 写一个空格字符,当向 pipe 写入内容 后,ril_event_loop()中的 select()操作将得到执行,从而将新添加的 event 加入了 RIL 消息队列并得以跟踪,否则如果

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 其它办公文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号