当前位置:首页 > Android中RIL层详细分析解析
argc = argc -i + 1; } else {
static char * newArgv[MAX_LIB_ARGS]; static char args[PROPERTY_VALUE_MAX]; rilArgv = newArgv;
property_get(LIB_ARGS_PROPERTY, args, \ argc = make_argv(args, rilArgv); }
// Make sure there's a reasonable argv[0] rilArgv[0] = argv[0];
/*利用得到的rilInit函数指针,调用真正的RIL_Init ,实际是动态加载动态库去链接reference-ril.c ,由dlopen()函数加载*/
funcs = rilInit(&s_rilEnv, argc, rilArgv);
/*RIL_register作用一:把vendor RIL(即RIL_init) 注册到reference-ril库去等待,dopen()函数加载链接
附:RIL_init通过是onRequest()方法,将上层来的请求进行映射后转换成对应的AT命令发给硬件,rild通过RIL_register注册这一指针。
RIL_register作用二:创建rild socket主要是等待java层得数据通过,传到下一层,还创建debug socket*/ RIL_register(funcs); done: while(1) {
// sleep(UINT32_MAX) seems to return immediately on bionic sleep(0x00ffffff); }
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 所有文件:
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
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
与rild结合相当紧密,是其共享库,编译时就已经建立了这一关系。组成部分为ril.cpp,ril_event.cpp。libril.so驻留在rild这一守护进程中,主要完成同上层通信的工作,接受ril请求并传递给librefrence_ril.so, 同时把来自librefrence_ril.so的反馈回传给调用进程
在编译时libril被链入rild,它为rild提供了event处理功能,还提供了在rild与Vendor RIL之间传递请求和响应消息的能力。
Libril提供的主要功能分布在两个主要方法内,一个是RIL_startEventLoop()方法,另一个是RIL_register()方法
RIL_startEventLoop()方法所提供的功能就是启用eventLoop线程,开始执行RIL消息队列。
RIL_register()方法的主要功能是启动名为rild 的监听端口,等待java 端通过socket进行连接。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RIL_startEventLoop函数 libril/ril.cpp->RIL_startEventLoop()
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- extern \
RIL_startEventLoop(void) {
int ret;
pthread_attr_t attr;
LOGD(\
/* spin up eventLoop thread and wait for it to get started */ s_started = 0;
pthread_mutex_lock(&s_startupMutex); pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
LOGD(\
ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);//创建线程,为入口函数 LOGD(\ while (s_started == 0) {
pthread_cond_wait(&s_startupCond, &s_startupMutex); }
pthread_mutex_unlock(&s_startupMutex); if (ret < 0) {
LOGE(\ return; } }
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
开启libril.so中的event机制, 在RIL_startEventLoop中,是最核心的由多路I/O驱动的消息循环
RIL_startEventLoop函数。RIL_startEventLoop在ril.cpp中实现, 它的主要目的是通过pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL)建立一个dispatch线程,入口点在eventLoop. 而eventLoop中,会调ril_event.cpp中的ril_event_loop()函数,建立起消息(event)队列机制。
我们来仔细看看这一消息队列的机制,这些代码都在ril_event.cpp中。 void ril_event_init();
void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param); void ril_event_add(struct ril_event * ev);
void ril_timer_add(struct ril_event * ev, struct timeval * tv); void ril_event_del(struct ril_event * ev); void ril_event_loop();
----------------------------------------------- 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; };
-----------------------------------------------------
每个ril_event结构,与一个fd句柄绑定(可以是文件,socket,管道等),并且带一个func指针去执行指定的操作。
具体流程是: ril_event_init完成后,通过ril_event_set来配置一新ril_event,并通过ril_event_add加入队列之中(实际通常用rilEventAddWakeup来添加),add会把队列里所有ril_event的fd,放入一个fd集合readFds中。这样ril_event_loop能通过一个多路复用I/O的机制(select)来等待这些fd, 如果任何一个fd有数据写入,则进入分析流程processTimeouts(),processReadReadies(&rfds, n),firePending()。 后文会详细分析这些流程。另外我们可以看到, 在进入ril_event_loop之前, 已经挂入了一s_wakeupfd_event, 通过pipe的机制实现的, 这个event的目的是可以在一些情况下,能内部唤醒ril_event_loop的多路复用阻塞,比如一些带timeout的命令timeout到期的时候。 至此第一个任务分析完毕,这样便建立起了基于event队列的消息循环,稍后便可以接受上层发来的的请求了(上层请求的event对象建立,在第三个任务中)。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- static void *
eventLoop(void *param) { int ret; int filedes[2];
LOGD(\LOGD(\ ril_event_init();//初始化
LOGD(\ pthread_mutex_lock(&s_startupMutex); s_started = 1;
pthread_cond_broadcast(&s_startupCond); pthread_mutex_unlock(&s_startupMutex); ret = pipe(filedes); if (ret < 0) {
LOGE(\ return NULL; }
s_fdWakeupRead = filedes[0];// 消息循环中侦听
s_fdWakeupWrite = filedes[1];// 用于通知消息循环定义消息已发送
LOGD(\ processWakeupCallback, NULL);--\ fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
/*先执行 processWakeupCallback中的read函数,再把参数,传给ril_event_set进行设置*/
ril_event_set(&s_wakeupfd_event, s_fdWakeupRead, true, processWakeupCallback, NULL); /*在ilEventAddWakeup进行ril_evnet_add事件添加和triggerEvLoop()实现管道写端*/
LOGD(\ rilEventAddWakeup (&s_wakeupfd_event); LOGD(\ // Only returns on error
LOGD(\ ril_event_loop();
LOGD(\ LOGE (\ return NULL; }
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ril_event_init()主要工作是清零和处理三种函数(定时,监听,挂起);
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Initialize internal data structs
void ril_event_init()
{
MUTEX_INIT();
LOGD(\ FD_ZERO(&readFds); init_list(&timer_list); init_list(&pending_list);
memset(watch_table, 0, sizeof(watch_table)); }
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ril_event_set()的作用是:通过管道,对读到的数据进行初始化 ---------注册进程唤醒事件回调
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
{
LOGD(\* param)-\
dlog(\ memset(ev, 0, sizeof(struct ril_event)); ev->fd = fd; ev->index = -1; ev->persist = persist; ev->func = func; ev->param = param;
fcntl(fd, F_SETFL, O_NONBLOCK); }
共分享92篇相关文档