Android RIL学习

tomorrow.cyz@gmail.com

1.Android RIL概念

Android RIL是基于telephony 服务和raido 硬件层的抽象层。Android的rild库是介于HAL接口与baseband modem之间,它提供了语音、数据、短信、SIM卡管理以及STK应用的功能。它把标准的 GSM27.007中常用的如dial这些做主动请求的操作称之为request,一共75个;另外一类GSM模块主动上报的例如信号强度、基站信息等, 称之为unsolicited response,一共17个。开发模式上,需要针对不同的GSM模块进行不同的GSM驱动开发,公用的部分google做 好了,特定的部分需要自己去定制。如下是Android RIL架构图。

2.代码结构

Android2.2中,RIL的代码在hardware目录下,主要包括libril,include,rild,reference-ril,reference-cdma-sms四个目录,编译后生成rild应用程序(守护进程,放在target device的/system/bin下),libril.so(RIL动态链接库,放在device的/system/lib目录下)和libreference-ril.so(RIL参考库,放在device的/system/lib下)。

3.RIL初始化

1)      Init.rc执行rild,并创建两个socket:/dev/socket/rild和/dev/socket/rild-debug

service ril-daemon /system/bin/rild

socket rild stream 660 root radio

socket rild stream 660 radio system

2)      进入rild.cpp的main函数,读取rild.lib的path和rild.libargs系统属性,确定厂商的RIL库和初始化参数。

3)      执行RIL_startEventLoop开启事件队列,进行事件监听。这个函数会建立s_tid_dispatch线程。

4)      加载厂商的RIL库,调用RIL_Init初始化RIL,建立s_tid_mainloop线程。在该线程主循环中会调用at_open建立另一个线程s_tid_reader。

5)      调用RIL_register建立vender ril和ril库之间的联系。获取init.rc中建立的两个socket(rild,rild-debug),进行侦听,并加入消息事件循环中(s_tid_dispatch负责轮询分发)。

4.RIL的事件机制

ril_event.h/cpp对linux常用的select机制进行了简单封装,实现多路复用,以及事件到处理函数的映射。通过阅读rid_event.h的代码就可以理解这个机制所要提供的功能。

ril_event是个带有链表行为的结构体,而且是双向链表,它的主要成员是fd(要轮询的IO,文件,管道,socket等),func(处理事件的回调)。

typedef void (*ril_event_cb)(int fd, short events, void *userdata);

struct ril_event {

struct ril_event *next;

struct ril_event *prev;

int fd;

int index;

bool persist;

struct timeval timeout;

ril_event_cb func;

void *param;

};

提供了六个接口:

// Initialize internal data structs

void ril_event_init();

// Initialize an event

void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param);

// Add event to watch list

void ril_event_add(struct ril_event * ev);

// Add timer event

void ril_timer_add(struct ril_event * ev, struct timeval * tv);

// Remove event from watch list

void ril_event_del(struct ril_event * ev);

// Event loop

void ril_event_loop();

使用之前调用ril_event_init,增加一个io的时候首先初始化事件ril_event_set,然后加入到列表ril_event_add,轮询用ril_event_loop,逻辑非常清晰。关键是在ril_event_set的时候把fd和回调对应上。timer理论上不属于io操作,所以没有所谓的fd,增加timer事件用ril_timer_add,其它的类似,本质上还是事件与回调的对应机制。

至于实现细节,完全可以不关心,有兴趣的话就看代码,很简单,搞清楚readFDS,watch_list,timer_list,pending_list就差不多了。

从这个机制上看,调用event_loop的线程将执行事件分发的任务。因为在add,remove操作中有mutex进行保护,所以这个事件机制支持重入。

在rild的初始化中,会执行RIL_startEventLoop,启动s_tid_dispatch线程来进行事件轮询,所以其它的地方只要考虑事件的增加和删除就可以了。

全局搜索ril_event_set,就可以知道在rild上都有什么事件在跑了。

1)      S_listen_event(s_fdListen,listenCallback):名为rild的socket(init.rc建立的),主要用来监听上层的(RIL-JAVA)客户端连接请求,建立socket连接(s_fdCommand),并新增s_commands_event来监听s_fdCommand。

2)      s_commands_event(s_fdCommand,ProcessCommandsCallback):listen的时候建立的socket,用来从客户端接收StreamRecord(实际上就是Dial,Hang等RIL指令),使用ProcessCommandBuffer处理数据。

3)      s_debug_event(s_fdDebug,debugCallback):名为rild-debug,调试用的request&response通道,用于radiooptions这个调试工具。

4)      s_wakeupfd_event(s_fdWakeupRead,processWakeupCallback):无名管道。仅仅为了开始时wake up这个事件轮询。

5) timer event

5.RIL的交互流程

RIL的通讯分成两种:1)Solicited commands:RIL lib发起的主动调用,比如拨号2)Unsolicited responses:从baseband过来的通知消息,比如新短信到来。前者在类似协议上的request-confirm机制,后者类似Indication-response机制。

5.1 Solicited Commands

1)   RIL.java是FrameWork中Telephony服务的提供者,是Java中电话系统的起点,在这个文件的RIL class中封装了RIL所提供的command,实现了CommandsInterface。

getIccCardStatus

supplyIccPin

supplyIccPuk

changeIccPin

changeBarringPassword

getCurrentCalls

getDataCallList

dial

……

2)    以dial为例,首先调用RILRequest.obtain打包请求,然后再调用RIL::send将消息发送到RILSender的消息队列中。

3)    RILSender是个handler类,会在handleMessage中处理发送消息请求。它会将消息发送到同“RIL”成功建立的socket中。

4)    如6.4节所述,此时rild和JAVA上层建立的socket为s_fdCommand。通过事件轮询机制轮询到有数据来临的时候,会调用processCommandsCallback来处理数据。

5)    调用processCommandBuffer。

6)    在ProcessCommandBuffer中,通过ril_commands.h里面的消息及函数映射,对应于RIL_REQUEST_DIAL的函数为dispatchDial。

7)    在dispatchDial中,调用RIL_Register注册的函数onRequest,也就是reference-ril.c中的onRequest。

8)    调用requestDial。

9)    调用atchannel.c的at_send_command来发送at命令。

10) 调用RIL_onRequestComplete立即回应调用者,不管调用成功还是失败。这时候会调用rild的回调函数RIL_onRequestComplete,该回调在RIL_Init的时候注册,在ril.cpp中实现。

11) 在RIL_onRequestComplete中组装响应,调用sendResponse。

12) 调用sendResponseRaw。

13) 往和JAVA上层建立的socket中写数据。

14) JAVA层RIL.java中,会起一个RILReceiver线程来接收数据。

15) RILReceiver接收到的消息,调用RIL的readRilMessage读取数据。然后调用processResponse处理数据。

16) 调用processSolicited。

5.2 Unsolicited Response

1)    在RIL_Init中传入参数s_device_path,是同modem通讯的设备路径,一般是串口(ttyS),在模拟器中,用qemud 的socket模拟。

2)    RIL_init启动s_tid_mainloop,用于打开通信信道(比如串口,或者模拟器的qemu socket),并启动s_tid_reader接收消息。

3)    S_tid_reader线程从at channel收到Unsolicited reponses,调用Unsolicited handler(在at_open的时候指定为reference-ril.c的onUnsolicited)。

4)    ril.h定义了一系列宏,对应各个Unsolicited response,从RIL_UNSOL_RESPONSE_BASE开始。ril_unsol_commands.h中每个unsolicited repsonse对应一个处理函数。RIL_UNSOL_CALL_STATE_CHANGED对应responseVoid,封装返回给JAVA层的消息。

5)    调用sendResponse给s_fdCommand发消息。

6)    JAVA层的RILReceiver收到消息,调用processResponse。

7)    对应于Unsolicited response,调用processUnsolicited。

6.Radiooptions

这是一个调试程序,可以在控制台启动这个程序,在不开启ui的情况下,调试ril。

# radiooptions

Usage: radiooptions [option] [extra_socket_args]

0 - RADIO_RESET,

1 - RADIO_OFF,

2 - UNSOL_NETWORK_STATE_CHANGE,

3 - QXDM_ENABLE,

4 - QXDM_DISABLE,

5 - RADIO_ON,

6 apn- SETUP_PDP apn,

7 - DEACTIVE_PDP,

8 number - DIAL_CALL number,

9 - ANSWER_CALL,

10 - END_CALL

7.Extend Readings

http://blog.csdn.net/maxleng/archive/2010/05/14/5593759.aspx

http://www.netmite.com/android/mydroid/development/pdk/docs/telephony.html#androidTelephonyRILImplementing

Android RIL学习相关推荐

  1. Android RIL 架构学习总结

    1.Android RIL 概念     (转自http://newfaction.net/2011/03/08/android-ril-structure-learning-summary.html ...

  2. android ril.java_Android RIL学习

    1.Android RIL概念 Android RIL是基于telephony服务和raido硬件层的抽象层.Android的rild库是介于HAL接口与baseband modem之间,它提供了语音 ...

  3. 冰枫论坛android,Android Ril 分析

    引言: 这段时间手中的工作,正好好调试一款3g modem,于是乎就分析了一下Android Ril的代码,做了些总结归纳,阅读时可以先看前后两段以及流程图,这样可能更容易把握: 知识在于分享,文档中 ...

  4. java/android 设计模式学习笔记(1)--- 单例模式

    前段时间公司一些同事在讨论单例模式(我是最渣的一个,都插不上嘴 T__T ),这个模式使用的频率很高,也可能是很多人最熟悉的设计模式,当然单例模式也算是最简单的设计模式之一吧,简单归简单,但是在实际使 ...

  5. Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition

    Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition Property animation系统还提供了对ViewGroup中的View改变 ...

  6. android Fragment 学习资料推荐

    为什么80%的码农都做不了架构师?>>>    android   Fragment 学习资料推荐:android大神 郭霖 http://blog.csdn.net/guolin_ ...

  7. android service 学习(上)

    转载自:http://www.cnblogs.com/allin/archive/2010/05/15/1736458.html Service是android 系统中的一种组件,它跟Activity ...

  8. android service 学习(下)

    android service 学习(下) 通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的service.在android ...

  9. Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

最新文章

  1. saiku执行过程代码跟踪
  2. 利用Python模拟鼠标操作,一键将GIF文件载入CSDN的Markdown编辑器
  3. IAR编译的工程无法正常仿真的问题
  4. gRPC学习记录(四)--官方Demo
  5. SeaJS 与 RequireJS 的差异对比
  6. 对象存储 OSS > 产品简介 > 什么是对象存储OSS
  7. 一个RSS阅读器的开源 ---- 邀请您加入开发队伍
  8. BIM族库下载——塔吊等垂直运输设备族库
  9. 车型代号对照表_车型代号对照表2015Q3
  10. FastAPI获年度第一新兴框架,2021年最受欢迎的TOP 100开发工具出炉
  11. android hid 编程,Android Bluetooth HID完成详解,androidhid
  12. 微信小程序有哪些?401~500
  13. 单向链表的创建与遍历(先进先出和先进后出)
  14. 共识算法比较:Tendermint的BFT与EOS的dPoS
  15. 数字X线透视摄影系统 SONIALVISION SMIT/SONIALVISION C200
  16. 在微信小程序中如何引入iconfont
  17. python 3.x 163邮箱登陆,邮件读取
  18. 从那里进入EI检索号查询入口?
  19. RAMPS1.4 3d打印控制板接线与测试4
  20. 使用传感器和Matrix实现图片随手机晃动而变换

热门文章

  1. 命运赋——原文与译文
  2. 手把手教你50行Python代码,给心目中的女友微博秒评论
  3. leecode做题笔记17————电话号码的字母组合
  4. NDK does not contain any platforms问题解决
  5. PanDownload下载变慢的一个解决办法
  6. 数据库工具——mongostat
  7. 天气预报小程序案例(springboot服务端)
  8. 3-搜索某网站的职位
  9. 安装Goland19.3
  10. Vue项目设置Eslint规则