Telephony框架设计解析-----version:1.2-----author:***目录一、RIL................................................................................................3二、Telephony中多卡及多运营商设计区分.........................................61.telephony中的多卡.......................................................................71)AP区分多卡.............................................................................72)modem区分多卡...................................................................122.telephony中的多运营商设计......................................................14三、Telephony中AIDL模式设计.........................................................15四、Telephony中观察者模式设计......................................................16五、TelephonyRegistry监听模式设计..................................................201.概述..............................................................................................202.以状态栏信号更新为例分析注册和更新过程【YETIM-1107】.201).注册过程...............................................................................212).RIL上报监听回调更新过程..................................................23六、ServiceStateTracker/DcTracker/CallTracke......................................27七、Telephony分析案例之检测不到SIM卡.......................................27八、手机驻网过程modemlog.............................................................29本篇文档将从如下六个方面讲述telephony框架设计:RIL、多卡及多运营商设计区分、不同运营商的extends继承实现、IDEL的设计、观察者模式设计、TelephonyRegistry监听模式设计、ServiceStateTracker/DcTracker/CallTracker。附上AndroidTelephony框架图PS:AndroidTelephony采用了分层结构,共跨越了4层:1.Telephony应用,包括了Phone、MMS和STK等应用程序2.Telephony框架,提供TelephonyManager,包含数据连接、通话、信息和SIM相关的API3.无线通信接口层(RIL),主要位于UserLibraries层中的HAL层,提供AP(ApplicationProcessor)和BP(BasebandProcessor)之间的通信功能4.Modem,位于BP,主要负责实际的无线通信能力处理一、RILRIL有RILJ和RILC,RILJ是我们所熟悉的java侧RIL.java代码,RILC是hardware/ril目录下C代码,此处我们简单介绍下RILC模块的初始化和运行机理。Android的RIL驱动模块,在hardware/ril目录下,一共分rild,libril.so以及librefrence_ril.so三个部分,另有一radiooptions可供自动或手动调试使用。都依赖于include目录中ril.h头文件。目前cupcake分支上带的是gsm的支持,另有一cdma分支,这里分析的是gsm驱动。GSM模块,由于Modem的历史原因,AP一直是通过基于串口的AT命令与BB交互。包括到了目前的一些edge或3g模块,或像omap这类ap,bp集成的芯片,已经使用了USB或其他等高速总线通信,但大多仍然使用模拟串口机制来使用AT命令。这里的RIL(RadioInterfaceLayer)层,主要也就是基于AT命令的操作,如发命令,response解析等。首先介绍一下rild与libril.so以及librefrence_ril.so的关系:1.rild:仅实现一main函数作为整个ril层的入口点,负责完成初始化。2.libril.so:与rild结合相当紧密,是其共享库,编译时就已经建立了这一关系。组成部分为ril.cpp,ril_event.cpp。libril.so驻留在rild这一守护进程中,主要完成同上层通信的工作,接受ril请求并传递给librefrence_ril.so,同时把来自librefrence_ril.so的反馈回传给调用进程。3.librefrence_ril.so:rild通过手动的dlopen方式加载,结合稍微松散,这也是因为librefrence.so主要负责跟Modem硬件通信的缘故。这样做更方便替换或修改以适配更多的Modem种类。它转换来自libril.so的请求为AT命令,同时监控Modem的反馈信息,并传递回libril.so。在初始化时,rild通过符号RIL_Init获取一组函数指针并以此与之建立联系。4.radiooptions:radiooptiongs通过获取启动参数,利用socket与rild通信,可供调试时配置Modem参数。接下来分析初始化流程:主入口是rild.c中的main函数,主要完成三个任务:1.开启libril.so中的event机制,在RIL_startEventLoop中,是最核心的由多路I/O驱动的消息循环。2.初始化librefrence_ril.so,也就是跟硬件或模拟硬件modem通信的部分(后面统一称硬件),通过RIL_Init函数完成。3.通过RIL_Init获取一组函数指针RIL_RadioFunctions,并通过RIL_register完成注册,并打开接受上层命令的socket通道。第一个任务流程图:图一(RIL_startEventLoop消息循环初始化)rild.c中的main()RIL_startEventLoop()在ril.cpp中开启libril.so中的event机制是最核心的由多路I/O驱动的消息循环pthread_create(&s_tid_dispatch,&attr,eventLoop,NULL)建立一个dispatch线程,入口点在eventLoop()在ril.cpp中ril_event_loop(),ril_event.cpp中建立起消息(event)队列机制ril_event.cpp中包含的方法voidril_event_init();voidril_event_set(structril_event*ev,intfd...);voidril_event_add(structril_event*ev);voidril_timer_add(structril_event*ev,structtimeval*tv);voidril_event_del(structril_event*ev);voidril_event_loop();ril_event_init()在ril_event.cpp中配置一新ril_eventrilEventAddWakeup()ril_event_loop能通过一个多路复用I/O的机制(select)来等待这些fd如果任何一个fd有数据写入,则进入分析流程processTimeouts(),processReadReadies(&rfds,n),firePending()。后面会详细分析这些流程ril_event_add()在ril_event.cpp中将新ril_event加入队列之中add会把队列里所有ril_event的fd,放入一个fd集合readFds中至此第一个初始化任务分析完毕,这样便建立起了基于event队列的消息循环,稍后便可以接受上层发来的的请求了(上层请求的event对象建立,在第三个任务中)。第二个任务流程图:图二(RIL_Init硬件modem通信部分初始化)main(),ril.c中为ril层的入口点RIL_Init(..)在reference_ril.c中首先通过参数获取硬件接口的设备文件或模拟硬件接口的socket.接下来便新开一个线程继续初始化at_open(..)在atchannel.c中建立起这一设备文件上的reader等待循环,这也是通过新建一个线程完成ret=pthread_create(&s_tid_reader,&attr,readerLoop,&attr),即mainLoop(..)在reference_ril.c中主要任务是建立起与硬件的通信,然后通过read方法阻塞等待硬件的主动上报或响应RIL_requestTimedCallback(initializeCallback,NULL,&TIMEVAL_0),跑到initializeCallback中,执行一些Modem的初始化命令,主要都是AT命令的方式。readerLoop(..)在atchannel.c中注册一些基础回调(timeout,readerclose)后,mainLoop首先打开硬件设备文件,建立起与硬件的通信,s_device_path和s_port是前面获取的设备路径参数,将其打开processLine(..)handleFinalResponse(..)第三个任务流程图:图三(RIL_RadioFunctions接受上层命令的socket通道初始化)二、Telephony中多卡及多运营商设计区分以双卡为例,上层是如何区分卡1和卡2在telephony模块中运行,AP发送AT命令后?modem如何区分去执行卡1还是卡2的操作?main(),在ril.c中是ril层的入口点由RIL_Init的返回值开始的,这是一个RIL_RadioFunctions结构的指针在reference_ril.c中指针结构如下:typedefstruct{intversion;/*settoRIL_VERSION*/RIL_RequestFunconRequest;RIL_RadioStateRequestonStateRequest;RIL_Supportssupports;RIL_CancelonCancel;RIL_GetVersiongetVersion;}RIL_RadioFunctions;其中最重要的是onRequest域,上层来的请求都由这个函数进行映射后转换成对应的AT命令发给硬件。rild通过RIL_register注册这一指针。rild通过RIL_register注册这一指针RIL_register中要完成的另外一个任务,就是打开前面提到的跟上层通信的socket接口(s_fdListen是主接口,s_fdDebug供调试时使用)。然后将这两个socket接口使用任务一中实现的机制进行注册