电话(Telephony)部分的主要功能是呼叫(Call)、短信(Sms)、数据连接(Data Connection)以及SIM卡、电话本等功能;主要分为Modem驱动、RIL(Radio Interface Layer)、电话服务框架和应用4层结构;其主体架构如下:
1.Modem驱动
实现电话功能的主要硬件是通信模块(Modem),Modem通过去通信网络进行沟通传输语言及数据,完成呼叫、短信等相关电话功能。一般的Modem模 块装上SIM卡,直接上电即可工作,自动完成初始的找网、网络注册等工作,完成之后即可打电话、发短信等。但独立模块因为体积问题,在手机设计中较少使 用,而是使用chip-on-board的方式。另外也有不少Modem基带与应用处理器共存。Modem硬件上一般提供两个通信渠道:一个用于AT命 令,另一个用于数据传输。
·AT命令通道:一般使用UART或USB方式。AT命令由Hayes公司发明,是调制解调器制造商采用的调制解调器命令语言,每条命令以字母“AT”开头,用于完成调制解调器之间的控制交互。这是电话服务的基础。
·数据传输通道:一般通过USB方式传输网络数据,这个通道是通过通信模块上网的基础。若基带与应用处理器集成,一般通过共享内存等方式传输数据。
Modem驱动比较简单,复杂的AT相关处理一般不放在驱动层,而是通过其上的RIL层完成。主控端一般都支持UART和USB驱动,RIL层直接建立在UART或USB上的几个tty通道,提供与Modem直接的数据交互。
2.本地的RIL代码
在Android中,RIL是电话系统的本地实现。
①简介
RIL是核心部分,负责AT命令的发送及相应解析,这也是电话服务的实现基础。另外,RIL还负责数据的可靠传输。RIL支持的本地代码包括RIL库和守护进程,内容如下:
·hardware/ril/include:RIL头文件
·hardware/ril/libril:RIL库,编译成动态库libril.so
·hardware/ril/rild:RIL守护进程,编译成可执行程序rild,安装在目标系统的/system/bin/目录中
·hardware/ril/reference-ril:RIL参考库,编译成动态库libreference-ril.so
②RILD守护进程
在Android的RIL结构中,libril.so是一个辅助功能库,它被
libreference-ril.so和RILD所使用。RILD是一个可执行程序,作为守护进程进行。执行的过程为:获取参数→打开功能库→建立事件循环(线程)→执行RIL_Init→RIL_register。
③
libril库
libril.so主要提供了用于注册的 RIL_register(),以及RIL_onRequestComplete()、RIL_onUnsolicitedResponse()和 RIL_requestTimedCallback()在RIL处理过程中需要处理的函数,它们的作用相当于回调函数。
④RIL的实现库Reference RIL
libreference-ril.so是RIL功能实现库的一个参考实现,其中,实现RIL_Init()函数,保留RIL_Env传入环境的3个函数指针,在需要处理的场合调用,返回一个RIL_RadioFunctions类型的函数指针用于注册。
libreference-ril.so完成从具体电话服务命令到实际的AT命令之间的转换,也就是负责解释上层的命令。它同时完成对AT端口的监控、读取并解析相应信息,以及主动上报的信息。
⑤Request(请求)流程
对于请求流程,首先从Java层通过Socket将命令发送到RIL层的RILD守护进程,在RILD守护进程中,负责监听的 ril_event_loop信息循环中的Select发现RILD Socket有了请求链接信号,会建立起一个record_stream,打通与上层的数据通道并开始接收请求数据。数据通道的回调函数 processCommandsCallback()会保证收到一个完整的Request后(Request包的完整性由record_stream的机 制保证),将其送达processCommandBuffer()函数。这是命令的下发流程。
processCommandBuffer()函数正式进入了命令的解析流程。
processCommandBuffer() 从Socket中序列化的数据流利还原信息,将其组织到RequestInfo中,这就是一个完整的请求结构。每个命令将以RequestInfo的形式 存在,表示请求消息。在还原出来的信息中,最重要的是Request号,这个号在RIL层和上层之间,定义是统一的,在ril_commands.h中。 RIL层中采用表驱动方式分派请求,而分派的基础正是Request号。CommandInfo结构表示命令信息,关联了Request号和实际的请求函 数,以及相应函数之间的关系。这就是解析流程,接下来是分发流程:
s_callbacks.onRequest()完成这一操作。s_callbacks是获取自libreference-ril的 RIL_RadioFunctions结构指针,Request请求在这里转入底层的libreference-ril处理,handler是 reference-ril.c中的onRequest。
onRequest()根据Request号进行简单的switch分发。
⑥Response(响应)流程
Response有两类:unsolicited表示主动上报的消息,如来电、来短信等;而solicited是AT命令的响应。判断是否是solicited的依据有两点:一是当前有AT命令正在等待响应;二是读取到的响应符合该AT命令的响应格式。对
Response 流程来讲,流程是从Modem设备发回响应数据开始的。RILD通过readerLoop()函数,利用readline逐行读取响应数据,随后通过 processLine进行分析(与短信相关的响应比较独特,要特殊处理)。主动上报一般以+XXXX的形式出现,而AT命令的响应格式则有一行或多行之 分,但最终一定以OK或ERROR结尾。于是ProcessLine有以下几种情形:
·没有AT命令正在等待响应或不符合AT影响格式,一般是主动上报行,由handleUnsolicited处理,handleUnsolicited()→onUnsolicited()→RIL_onUnsolicitedResponse()
·isFinalResponseSuccess/isFinalResponseError是最终响应行,转到handleFinancialResponse处理,handleFinalResponse会发送线程同步信号,激活等待的发送线程
·符合当前AT命令响应格式行,解析并获取数据,这是响应处理的中间过程,然后会继续收到最终响应行
最后的发送动作由sendResponse→sendResponseRaw→blockingWrite通过Socket回传给上层来完成;而最终的响应解析需要上层来完成。
⑦RIL的移植工作
根据各个系统的硬件差别,在移植过程中主要的工作是实现一个类似于libreference-ril.so的库或者应用。当RIL_SHLIB被定义时,将使用库的形式;没有被定义时,将使用守护进程的方式。移植需要考虑的问题如下:
·RIL设备所使用的不同端口
不同的Modem使用的不同端口,实际上也可以在init.rc中作为参数进行配置。
·在RIL_Radiofunctions的onRequest函数中需要处理的不同命令
这是移植方面最主要的部分,大部分AT命令其实是标准的,但不同的Modem之间也会有很多差异。RIL层需要实现具体的AT命令,一般差异比较大的部分在数据连接、呼叫状态查询等方面。
3.Java框架及应用
Android电话部分Java框架的代码路径为frameworks/base/telephony/java/,在这个目录中Java类为:
·android/telephony
·com/android/internal/telephony
前者实现了Java类android.telephony和android.telephony.gsm等,后者实现了内部类 com.android.internal.telephony和com.android.internal.telephony.gsm等。以GSM为 例,内容如下:
①基本架构
Java部分的基本架构是围绕电话服务命令的处理以及对外的接口来构建的,如下:
电话框架部分的基础结构正是由RIL到具体电话的实现,再加上TelephonyManager及其封装的一发一收两个渠道构成。
②呼叫
呼叫(Call)部分的结构如下:
呼叫构建于电话服务的基本架构之上。与呼叫相关的主要用户接口,是基于ITelephony接口实现在Phone应用中的“phone”服务,通过TelephonyManager提供访问接口。
③短信
短信(SMS)部分主要使用的类为SMSManager,其结构如下:
SMSManager实现短信发送以及与SIM卡短信相关的操作,通过ISms接口提供对应的实现。
SMSManager是短信部分的核心,提供发送SMS等操作接口,同时也提供接收SMS和返回报告等接口。
④数据连接
基于数据连接的移动互联网特性,是Android中非常重要乃至标志性的特性。RIL提供的数据连接方式,是移动互联网中最基本、可靠的连接形式。其结构如下:
Android的数据连接通常使用PPP方式提供,Android将pppd移植到ARM平台以支持此特性,生成pppd守护进程供需要时开启。数据连接 主要分两个步骤:首先通过AT命令激活PDP连接,再利用pppd通过数据端口完成拨号连接。数据连接的核心控制类是 DataConnectionTracker,数据连接一般不需要用户太多干预,设置好APN后,在适当的情况下就会自动激活。激活的入口点是 DataConnectionTracker.trySetupData→setupData→PdpConnection.connect→CommandsInterface.setupDefaultPDP。
⑤其它框架部分及其它应用
电话部分比较庞大,除了以上的部分,还有SIM卡、电话本、联系人、USSD、STK、网络选择等众多功能。对于应用部分,除了Phone和Mms,也广泛存在于Contacts、Settings乃至很多用到电话相关服务的应用当中。