现在的位置: 首页 > 综合 > 正文

Android的电话功能介绍——整个RIL文件夹的分析

2013年10月13日 ⁄ 综合 ⁄ 共 5505字 ⁄ 字号 评论关闭

 

介绍

本文档对Android RIL部分的内容进行了介绍,其重点放在了Android RIL的原生代码部分。包括四个主题:

1.Android RIL框架介绍

2.Android RILWindowsMobile RIL

3.Android RIL porting

4.Android RILjava框架

在本文档中将Android代码中的重要模块列出进行分析,并给出了相关的程序执行流程介绍,以加深对模块间交互方式的理解。

对于java代码部分,这里仅进行简单的介绍。如果需要深入了解,可以查看相关参考资料。

本文档中还对Android RILPorting部分内容进行了描述和分析。

针对对unix操作系统环境并不熟悉的读者,本文档中所涉及到的相关知识包括:

  Unix file system

  Unix socket

  Unix thread

  Unix
I/O多路转接

以上信息可以在任意一份描述Unix系统调用的文档中找到。

1.Android RIL框架介绍

术语:

fd                       unix文件描述符

pipe                      unix管道

cond                      一般是condition
variable
的缩写

tty                       通常使用tty来简称各种类型的终端设备

unsolicited response         被动请求命令来自baseband

event loop                android的消息队列机制,由unix的系统调用select()实现

init.rc                     init守护进程启动后被执行的启动脚本。

HAL                    硬件抽象层(Hardware Abstraction LayerHAL

1.1.Android RIL概况:

Android RIL提供了无线硬件设备与电话服务之间的抽象层。

下图展示了RILAndroid体系中的位置。

Android <wbr>RIL结构分析与移植(1)

androidril位于应用程序框架与内核之间,分成了两个部分,一个部分是rild,它负责socket与应用程序框架进行通信。另外一个部分是Vendor
RIL
,这个部分负责向下是通过两种方式与radio进行通信,它们是直接与radio通信的AT指令通道和用于传输包数据的通道,数据通道用于手机的上网功能。 

对于RILjava框架部分,也被分成了两个部分,一个是RIL模块,这个模块主要用于与下层的rild进行通信,另外一个是Phone模块,这个模块直接暴露电话功能接口给应用开发用户,供他们调用以进行电话功能的实现。

 

Android RIL目录结构:

AndroidRIL模块位于Android/hardware/ril文件夹,有三个子模块:rild
, libril , reference-ril

所在目录结构:/hardware/ril/ 

|-- ril     (无线电抽象层)
|   |-- include    (头文件)
|   |-- libril    (库)
|   |-- reference-cdma-sms (cdma短信参考)
|   |-- reference-ril    (ril参考)
|   |-- rild     (ril后台服务程序)

hardware/ril$ ls

include libril reference-cdma-sms reference-ril   rild

 1.hardware/ril/rild$ ls

Android.mk  MODULE_LICENSE_APACHE2  NOTICE radiooptions.c
 rild.c

2.hardware/ril/include/telephony$ ls

ril_cdma_sms.h  ril.h

3.hardware/ril/libril$ ls

Android.mk              NOTICE     ril_event.h       ril.cpp       ril_event.cpp  
ril_commands.h  ril_unsol_commands.h

MODULE_LICENSE_APACHE2  

4.hardware/ril/reference-cdma-sms$ ls

Android.mk  reference-cdma-sms.c  reference-cdma-sms.h

5.hardware/ril/reference-ril$ ls

Android.mk   atchannel.h  at_tok.h  misc.h     NOTICE    atchannel.c at_tok.c   ril_event.h   reference-ril.c 
misc.c    MODULE_LICENSE_APACHE2 

 

第一部分 电话功能概述
     Android的Radio Interface Layer (RIL)提供了电话服务和的radio硬件之间的抽象层。
     Radio Interface Layer RIL(Radio Interface Layer)负责数据的可靠传输、AT命令的发送以及response的解析。应用处理器通过AT命令集与带GPRS功能的无线通讯模块通信。
     AT command由Hayes公司发明,是一个调制解调器制造商采用的一个调制解调器命令语言,每条命令以字母"AT"开头。

JAVA Framework
代码的路径为:
     frameworks/base/telephony/java/android/telephony
     android.telephony以及android.telephony.gsm

Core native:
在hardware/ril目录中,提供了对RIL支持的本地代码,包括4个文件夹:
hardware/ril/include  
hardware/ril/libril  
hardware/ril/reference-ril  
hardware/ril/rild

kernel Driver
     在Linux内核的驱动中,提供了相关的驱动程序的支持,可以建立在UART或者SDIO,USB等高速的串行总线上。

 

第二部分 电话功能各个部分
   
hardware/ril/include/telephony/目录中的ril.h文件是ril部分的基础头文件。
    其中定义的结构体RIL_RadioFunctions如下所示:
typedef struct {
    int version;
    RIL_RequestFunc onRequest;
    RIL_RadioStateRequest onStateRequest;
    RIL_Supports supports;
    RIL_Cancel onCancel;
    RIL_GetVersion getVersion;
} RIL_RadioFunctions;

    RIL_RadioFunctions中包含了几个函数指针的结构体,这实际上是一个移植层的接口,下层的库实现后,由rild守护进程得到这些函数指针,执行对应的函数。
几个函数指针的原型为:
typedef void (*RIL_RequestFunc) (int request, void *data,
                                    size_t datalen, RIL_Token t);
typedef RIL_RadioState (*RIL_RadioStateRequest)();
typedef int (*RIL_Supports)(int requestCode);
typedef void (*RIL_Cancel)(RIL_Token t);
typedef const char * (*RIL_GetVersion) (void);

    其中最为重要的函数是onRequest(),它是一个请求执行的函数。
2.1 rild守护进程
   
rild 守护进程的文件包含在hardware/ril/rild目录中,其中包含了rild.c和radiooptions.c两个文件,这个目录中的文件经过编译后生成一个可执行程序,这个程序在系统的安装路径在:
/system/bin/rild
    rild.c是这个守护进程的入口,它具有一个主函数的入口main,执行的过程是将上层来的请求都由这个函数RIL_RadioFunctions{onReques()}的方法进行映射后转换成对应的AT命令的字符串,发给下层的硬件执行。在运行过程中,使用dlopen 打开路径为/system/lib/中名称为libreference-ril.so的动态库,然后从中取出 RIL_Init符号来运行。
    ril_register()注册:     RIL_Init符号是一个函数指针,执行这个函数后,返回的是一个RIL_RadioFunctions类型的指针。得到这个指针后,调用RIL_register()函数,将这个指针注册到libril库之中,然后进入循环ril_event_loop()。
     事实上,这个守护进程提供了一个申请处理的框架,而具体的功能都是在libril.so和libreference-ril.so中完成的。
附:

RIL守护进程,开机时被init守护进程调用启动,里面仅有main函数作为入口点,负责完成RIL初始化工作。

rild.c文件中,将完成ril的加载过程,它会执行如下操作:

 动态加载Vendor RIL.so文件

 执行RIL_startEventLoop()开启消息队列以进行事件监听

 通过执行Vendor RILrilInit()方法来进行Vendor
RIL
libril的关系建立。

rild文件夹中还包括一个radiooptions.c文件,它的作用是通过串口将一些radio相关的参数直接传给rild来对radio进行配置。

2.2 libreference-ril.so动态库

libreference-ril.so动态库的路径是:
hardware/ril/reference-ril
其中主要的文件是reference-ril.c和atchannel.c。这个库必须实现的是一个名称为RIL_Init的函数,这个函数执行的结果是返回一个RIL_RadioFunctions结构体的指针,指针指向函数指针。
这个库在执行的过程中需要创建一个线程来执行实际的功能。在执行的过程中,这个库将打开一个/dev/ttySXXX的终端(终端的名字是从上层传入的),然后利用这个终端控制硬件执行。
附:

在编译时libril被链入rild,它为rild提供了event处理功能,还提供了在rildVendor
RIL
之间传递请求和响应消息的能力。

Libril提供的主要功能分布在两个主要方法内,一个是RIL_startEventLoop()方法,另一个是RIL_register()方法

RIL_startEventLoop()方法所提供的功能就是启用eventLoop线程,开始执行RIL消息队列。

RIL_register()方法的主要功能是启动名为rild 的监听端口,等待java 端通过socket进行连接。

2.3 libril.so动态库
     libril.so库的目录是:
hardware/ril/libril  
     其中主要的文件为ril.cpp,这个库主要需要实现的以下几个接口为:
RIL_startEventLoop(void);
void RIL_setcallbacks (const RIL_RadioFunctions *callbacks);
RIL_register (const RIL_RadioFunctions *callbacks);
RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen);
void RIL_onUnsolicitedResponse(int unsolResponse, void *data,
                                size_t datalen);
RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,
                                const struct timeval *relativeTime);

    这些函数也是被rild守护进程调用的,不同的vendor可以通过自己的方式实现这几个接口,这样可以保证RIL可以在不同系统的移植。其中 RIL_register()函数把外部的RIL_RadioFunctions结构体注册到这个库之中,在恰当的时候调用相应的函数。在执行的过程中,这个库处理了一些将请求转换成字符串的功能

附:

Android自带的VendorRIL的参考实现。被编译成.so文件,由于本部分是厂商定制的重点所在。所以被设计为松散耦合,且可灵活配置的。在rild中通过opendl()的方式加载。

librefrence.so负责直接与radio通信,这包括将来自libril的指令转换为AT指令,并且将AT指令写入radio中。

reference-ril会接收调用者传来的参数,参数内容为与radio的通信方式。如通过串口连接radio,那么参数为这种形式:-d
/dev/ttySx

抱歉!评论已关闭.