1.在system/core/rootdir/init.rc中ril-daemon定义
Rild是Init进程启动的一个本地服务,采用了socket通讯这种通讯手段,是具体AT指令合成者与应答解析者
RILD管理框架,AT相关的xxxril.so动态链接库,以便适应不同的modem
RILJ <--socket通信--> RILC <--AT()--> modem
#创建一个名为"ril-daemon"的进程,这个进程要执行的程序是/system/bin/rild
service ril-daemon /system/bin/rild #源码在hardware/ril/rild/rild.c, 在Android中指定该文件编译为模块rild, 仅实现一main函数作为整个ril层的入口点,负责完成初始化
class main #指定分组为main,同一分组的服务,可以统一启动与停止
socket rild stream 660 root radio #创建一个unix域的名为/dev/socket/rild的套接字,并传递它的文件描述符给已启动的进程.
socket rild-debug stream 660 radio system #创建一个unix域的名为/dev/socket/rild-debug的套接字,并传递它的文件描述符给已启动的进程.
user root
group radio cache inet misc audio log qcom_diag
2. rild,libreference-ril.so,libril.so,radiooptions的关系
rild【hardware/ril/rild/rild.c ,ril层的入口点,负责完成初始化,rild的共享库中有一个为libril】
libril【hardware/ril/libril/* ,组成部分为ril.cpp,ril_event.cpp, 主要完成同上层RILJ用socket通信,将ril请求传递给libreference-ril.so,并将其反馈回传给调用进程】
libreference-ril【hardware/ril/libreference-ril/*,libreference-ril的共享库中有一个为libril. 转换libril的请求为AT命令发送给Modem,同时监控Modem的反馈信息,并传递回libril.so】
radiooptions【hardware/ril/rild/radiooptions.c, radiooptiongs通过获取启动参数,利用socket与rild通信,可供调试时配置Modem参数】
3.rild的启动的流程【hardware/ril/rild/rild.c】
........
extern void RIL_register (const RIL_RadioFunctions *callbacks);//【见详解】
........
extern void RIL_startEventLoop();
........
int main(int argc, char **argv) // 被init守护进程调用执行
{
........
//开启EventLoop循环,完成RIL与RILJ层数据交互(通过Socket)
const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
const RIL_RadioFunctions *funcs;
........
rilLibPath = REFERENCE_RIL_PATH; // 连接库地址:/system/lib/libreference-ril.so
........
switchUser(); // 切换UID为AID_RADIO
dlHandle = dlopen(rilLibPath, RTLD_NOW); // 以RTLD_NOW(立即决定,返回前解除所有未决定的符号)模式打开libreference-ril.so的动态连接库文件,并返回一个句柄给调用进程
........
RIL_startEventLoop(); // 开启libril.so共享库中的event机制,由于将上层传入的command内容转换为AT命令发送到modem并将回应发回上层,是由多路I/O驱动的消息循环【见详解】
//打开动态库reference并构建ReaderLoop循环,完成RIL与Modem层数据交互(通过AT)
//dlsym通过句柄和连接符名称获取函数名或者变量名,并强制转换为rilInit函数类型
// 从连接库中寻找RIL_Init函数地址
rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
........
funcs = rilInit(&s_rilEnv, argc, rilArgv); //调用rilInit函数进行初始化INIT,同时得到reference-ril的回调函数【见详解RIL_Init】
RLOGD("RIL_Init rilInit completed");
// 注册reference的回调函数
RIL_register(funcs); // 完成注册rilInit得到的回调函数funcs,并打开接收上层RILJ命令的socket通道【见详解】
........
}
// hardware/ril/libril/ril.cpp 框架和处理方式由ril.cpp管理,差异化的AT命令由reference实现
........
#include <telephony/ril.h>
........
static void * eventLoop(void *param) { //等待在事件端口(串口,socket),一旦有数据到达就根据登记的event回调函数进行处理,
int ret;
int filedes[2];
ril_event_init();// Event的初始化,初始化ril_event.cpp中几个重要的成员变量【见详解】
........
ret = pipe(filedes);//创建匿名管道
s_fdWakeupRead = filedes[0]; //s_fdWakeupRead为管道读端
s_fdWakeupWrite = filedes[1]; //s_fdWakeupWrite为管道写端
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK); //设置管道读端为O_NONBLOCK非阻塞
ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true, processWakeupCallback, NULL);//创建一个Event
// 将上面创建的Event加入到watch_table中,这里起到唤醒LoopEvent的作用,
rilEventAddWakeup (&s_wakeupfd_event);//向监控表watch_table添加一个s_wakeupfd_event事件,通过向管道s_fdWakeupWrite中写入来触发事件循环
Rild是Init进程启动的一个本地服务,采用了socket通讯这种通讯手段,是具体AT指令合成者与应答解析者
RILD管理框架,AT相关的xxxril.so动态链接库,以便适应不同的modem
RILJ <--socket通信--> RILC <--AT()--> modem
#创建一个名为"ril-daemon"的进程,这个进程要执行的程序是/system/bin/rild
service ril-daemon /system/bin/rild #源码在hardware/ril/rild/rild.c, 在Android中指定该文件编译为模块rild, 仅实现一main函数作为整个ril层的入口点,负责完成初始化
class main #指定分组为main,同一分组的服务,可以统一启动与停止
socket rild stream 660 root radio #创建一个unix域的名为/dev/socket/rild的套接字,并传递它的文件描述符给已启动的进程.
socket rild-debug stream 660 radio system #创建一个unix域的名为/dev/socket/rild-debug的套接字,并传递它的文件描述符给已启动的进程.
user root
group radio cache inet misc audio log qcom_diag
2. rild,libreference-ril.so,libril.so,radiooptions的关系
rild【hardware/ril/rild/rild.c ,ril层的入口点,负责完成初始化,rild的共享库中有一个为libril】
libril【hardware/ril/libril/* ,组成部分为ril.cpp,ril_event.cpp, 主要完成同上层RILJ用socket通信,将ril请求传递给libreference-ril.so,并将其反馈回传给调用进程】
libreference-ril【hardware/ril/libreference-ril/*,libreference-ril的共享库中有一个为libril. 转换libril的请求为AT命令发送给Modem,同时监控Modem的反馈信息,并传递回libril.so】
radiooptions【hardware/ril/rild/radiooptions.c, radiooptiongs通过获取启动参数,利用socket与rild通信,可供调试时配置Modem参数】
3.rild的启动的流程【hardware/ril/rild/rild.c】
........
extern void RIL_register (const RIL_RadioFunctions *callbacks);//【见详解】
........
extern void RIL_startEventLoop();
........
int main(int argc, char **argv) // 被init守护进程调用执行
{
........
//开启EventLoop循环,完成RIL与RILJ层数据交互(通过Socket)
const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
const RIL_RadioFunctions *funcs;
........
rilLibPath = REFERENCE_RIL_PATH; // 连接库地址:/system/lib/libreference-ril.so
........
switchUser(); // 切换UID为AID_RADIO
dlHandle = dlopen(rilLibPath, RTLD_NOW); // 以RTLD_NOW(立即决定,返回前解除所有未决定的符号)模式打开libreference-ril.so的动态连接库文件,并返回一个句柄给调用进程
........
RIL_startEventLoop(); // 开启libril.so共享库中的event机制,由于将上层传入的command内容转换为AT命令发送到modem并将回应发回上层,是由多路I/O驱动的消息循环【见详解】
//打开动态库reference并构建ReaderLoop循环,完成RIL与Modem层数据交互(通过AT)
//dlsym通过句柄和连接符名称获取函数名或者变量名,并强制转换为rilInit函数类型
// 从连接库中寻找RIL_Init函数地址
rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
........
funcs = rilInit(&s_rilEnv, argc, rilArgv); //调用rilInit函数进行初始化INIT,同时得到reference-ril的回调函数【见详解RIL_Init】
RLOGD("RIL_Init rilInit completed");
// 注册reference的回调函数
RIL_register(funcs); // 完成注册rilInit得到的回调函数funcs,并打开接收上层RILJ命令的socket通道【见详解】
........
}
// hardware/ril/libril/ril.cpp 框架和处理方式由ril.cpp管理,差异化的AT命令由reference实现
........
#include <telephony/ril.h>
........
static void * eventLoop(void *param) { //等待在事件端口(串口,socket),一旦有数据到达就根据登记的event回调函数进行处理,
int ret;
int filedes[2];
ril_event_init();// Event的初始化,初始化ril_event.cpp中几个重要的成员变量【见详解】
........
ret = pipe(filedes);//创建匿名管道
s_fdWakeupRead = filedes[0]; //s_fdWakeupRead为管道读端
s_fdWakeupWrite = filedes[1]; //s_fdWakeupWrite为管道写端
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK); //设置管道读端为O_NONBLOCK非阻塞
ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true, processWakeupCallback, NULL);//创建一个Event
// 将上面创建的Event加入到watch_table中,这里起到唤醒LoopEvent的作用,
rilEventAddWakeup (&s_wakeupfd_event);//向监控表watch_table添加一个s_wakeupfd_event事件,通过向管道s_fdWakeupWrite中写入来触发事件循环