您的位置:首页 > 移动开发 > Android开发

(1)RIL简析(高通)——RIL如何启动及初始化

2016-08-18 16:39 190 查看
Android设置了RIL层,是上层framework与Modem沟通的桥梁。高通使用qcril作为其vendor-RIL,与modem之间使用QMI机制通讯。

分3篇分析下面的问题:

RIL如何启动及初始化?

RILJ和RILD如何关联?

RILJ的消息如何传递和被处理?

event table的定义

event如何管理

event的处理、返回结果和主动上报(UNSOL)

如何正确地添加一个RIL消息和对应的处理函数?

RILD进程启动

RIL、QCRIL运行在RILD进程,在开机后启动,Rild.c的main函数为入口:

/system/core/rootdir/init.rc

service netd /system/bin/netd
class main
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
socket fwmarkd stream 0660 root inet


RILD2

/device/qcom/common/rootdir/etc/init.qcom.rc

service ril-daemon2 /system/bin/rild -c 2
class main
socket rild2 stream 660 root radio
socket rild-debug2 stream 660 radio system
user root
disabled
group radio cache inet misc audio sdcard_r sdcard_rw qcom_diag diag log


rild主函数入口:

#define LIB_PATH_PROPERTY   "rild.libpath"

int main(int argc, char **argv) {
const char * rilLibPath = NULL;

if (rilLibPath == NULL) {
//这里的property值为:vendor/lib64/libril-qc-qmi-1.so
if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
// No lib sepcified on the command line, and nothing set in props.
// Assume "no-ril" case.
goto done;
} else {
rilLibPath = libPath;
}
}

//获取libril-qc-qmi-1.so库的句柄
dlHandle = dlopen(rilLibPath, RTLD_NOW);

if (dlHandle == NULL) {
RLOGE("dlopen failed: %s", dlerror());
exit(EXIT_FAILURE);
}

RIL_startEventLoop();

//获取RIL_Init函数指针
rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))
dlsym(dlHandle, "RIL_Init");
//调用RIL_Init函数,s_rilEnv定义见后面
funcs = rilInit(&s_rilEnv, argc, rilArgv);
RLOGD("RIL_Init rilInit completed");

RIL_register(funcs);

}
//提供给qcril的回调函数,消息处理完成后调用这些callback函数返回
static struct RIL_Env s_rilEnv = {
RIL_onRequestComplete,
RIL_onUnsolicitedResponse,
RIL_requestTimedCallback
};


RILD入口主要关注这3个函数:

RIL_startEventLoop() —— ril.cpp,线程中开启一个消息循环来监听消息并触发事件处理。

RIL_Init() —— qcril.c初始化工作

RIL_register() —— 注册qcril.c消息函数入口(ril与qcril的关联)

RIL_startEventLoop()

int main(int argc, char **argv) {

RIL_startEventLoop();



ril.cpp

extern "C" void
RIL_startEventLoop(void) {
/* spin up eventLoop thread and wait for it to get started */
s_started = 0;
pthread_mutex_lock(&s_startupMutex);

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
//创建线程,负责执行eventLoop函数
int result = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
if (result != 0) {
RLOGE("Failed to create dispatch thread: %s", strerror(result));
goto done;
}

while (s_started == 0) {
pthread_cond_wait(&s_startupCond, &s_startupMutex);
}

done:
pthread_mutex_unlock(&s_startupMutex);
}


RIL_startEventLoop(void) {

int result = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);



eventloop函数开始在线程中执行,初始化并开始一个消息循环:

static fd_set readFds;
static int nfds = 0;
static struct ril_event * watch_table[MAX_FD_EVENTS];
static struct ril_event timer_list;
static struct ril_event pending_list;

static void *eventLoop(void *param) {
int ret;
int filedes[2];
//初始化watch_table、timer_list、pending_list、readFds
ril_event_init();

pthread_mutex_lock(&s_startupMutex);

s_started = 1;
pthread_cond_broadcast(&s_startupCond);

pthread_mutex_unlock(&s_startupMutex);
//管道
ret = pipe(filedes);
if (ret < 0) {
RLOGE("Error in pipe() errno:%d", errno);
return NULL;
}
s_fdWakeupRead = filedes[0];
s_fdWakeupWrite = filedes[1];
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);

//创建一个event,回调函数为processWakeupCallback
ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
processWakeupCallback, NULL);
//将event加入watchtable,唤醒eventloop
rilEventAddWakeup (&s_wakeupfd_event);

// Only returns on error
//开始event循环
ril_event_loop();
RLOGE ("error in event_loop_base errno:%d", errno);
// kill self to restart on error
kill(0, SIGKILL);

return NULL;
}

static fd_set readFds;
static int nfds = 0;

static struct ril_event * watch_table[MAX_FD_EVENTS];
static struct ril_event timer_list;
static struct ril_event pending_list;

// 初始化消息列表、计时器消息列表、待处理消息列表
void ril_event_init()
{
MUTEX_INIT();

FD_ZERO(&readFds);
init_list(&timer_list);
init_list(&pending_list);
memset(watch_table, 0, sizeof(watch_table));
}

//唤醒event loop
static void rilEventAddWakeup(struct ril_event *ev) {
//将event加入到watch_table
ril_event_add(ev);
//向s_fdWakeupWrite写入空值,唤醒select
triggerEvLoop();
}


ril_event.cpp::ril_event_set

初始化一个event,fd是监听的设备文件描述,persist指定event是否一直存在于watchtable,以上面代码为例:

ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,

processWakeupCallback, NULL);

s_fdWakeupRead会一直存在于readFds,因此起到长期监听的作用。

//初始化一个event,persist值若为true则此event会一直存在于watchtable
void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
{
dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev);
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);
}


static void *eventLoop(void *param) {

ril_event_loop();



ril_event_loop函数是循环的主体,在获取到消息后触发3个处理函数:

void ril_event_loop()
{
int n;
fd_set rfds;
struct timeval tv;
struct timeval * ptv;

for (;;) {

// make local copy of read fd_set
memcpy(&rfds, &readFds, sizeof(fd_set));
if (-1 == calcNextTimeout(&tv)) {
// no pending timers; block indefinitely
dlog("~~~~ no timers; blocking indefinitely ~~~~");
ptv = NULL;
} else {
dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);
ptv = &tv;
}
printReadies(&rfds);
//select,等待被唤醒
n = select(nfds, &rfds, NULL, NULL, ptv);
printReadies(&rfds);
dlog("~~~~ %d events fired ~~~~", n);
if (n < 0) {
if (errno == EINTR) continue;

RLOGE("ril_event: select error (%d)", errno);
// bail?
return;
}

//处理timer_list中超时的event,加入到pending_list
processTimeouts();
//从watch_table获取event加入到pending_list
processReadReadies(&rfds, n);
//分发pending_list中的事件给对应的处理函数
firePending();
}
}


RIL_INIT

回到rild.c的main函数,继续分析Ril_Init。

int main(int argc, char **argv) {

funcs = rilInit(&s_rilEnv, argc, rilArgv);



RIL_startEventLoop()执行过后,RIL的消息循环已经开始进入工作,接下来RIL_Init负责Qcril的初始化及消息循环的创建。

qcril.c
/*===========================================================================

FUNCTION:  RIL_Init

===========================================================================*/
/*!
@brief
Returns the current state of the RIL

@return
The current state of the RIL
*/
/*=========================================================================*/
const RIL_RadioFunctions *RIL_Init
(
const struct RIL_Env *env,
int argc,
char **argv
)
{

//response函数(ril.cpp)
// o maintain compatibility with data and UIM code which use instance_id and may respond on "second instance" context
qcril_response_api[ QCRIL_DEFAULT_INSTANCE_ID ] = (struct RIL_Env *) env;
qcril_response_api[ QCRIL_SECOND_INSTANCE_ID ] = (struct RIL_Env *) env;

----------

//初始化unsol消息列表 qmi_ril_android_pending_unsol_resp
qmi_ril_init_android_unsol_resp_pending_list();

//在新线程中执行event loop(qcril_event_main())
qcril_event_init();

// 初始化QCRIL(初始化消息函数的table等)
qcril_init(c_argc, c_argv);

//qcril_event_main开始进入循环,等待被唤醒并处理event。
qcril_event_start();

----------

// start bootup if applicable
qmi_ril_initiate_bootup();

//返回RIL_RadioFunctions函数数组给rild.c
return &qcril_request_api[ QCRIL_DEFAULT_INSTANCE_ID ];

}
//qcril的request相关函数接口
static const RIL_RadioFunctions qcril_request_api[] = {
{ RIL_VERSION, onRequest_rid, currentState_rid, onSupports_rid, onCancel_rid, getVersion_rid }
};


RIL_Init(){

qcril_event_init()

}

qcril_event.c
void qcril_event_init(void)
{
qcril_event.started = 0;
//开启线程来执行qcril_event_main
ret = pthread_create(&qcril_event.tid, &attr, qcril_event_main, NULL);

//等待qcril_event_main执行
while (qcril_event.started == 0){
pthread_cond_wait(&qcril_event_startupCond, &qcril_event.startup_mutex);
}
}


qcril_event_init(){

ret = pthread_create(&qcril_event.tid, &attr, qcril_event_main, NULL);

}

qcril_event_main开始一个循环,被唤醒后将event list中的消息分发给qcril_process_event处理。

qcril_event.c

static void *qcril_event_main(void *param)
{
qcril_event.started = 1;
pthread_cond_broadcast(&qcril_event_startupCond);
while (qcril_event.started < 2)
{
//
pthread_cond_wait(&qcril_event_startupCond, &qcril_event.startup_mutex);
}

for (;;)
{
n = select(qcril_event.fdWakeupRead + 1, &rfds, NULL, NULL, NULL);

do
{
ret = read(qcril_event.fdWakeupRead, &buff, sizeof(buff));
if (ret > 0)
{
QCRIL_LOG_DEBUG("%d items on queue", ret);
}
} while (ret > 0 || (ret < 0 && errno == EINTR));

do
{
if ( ( NULL != ( ev = qcril_event.list.next ) && ( ev != &qcril_event.list ) ) )
{
qcril_event_remove_from_list( ev );
//处理消息——qcril_process_event
err_no = qcril_process_event( ev->instance_id, ev->modem_id, ev->event_id, ev->data, ev->datalen, ev->t );

}
}
}
}


RIL_Init(){

qcril_init ()

}

qcril.c

//定义了所有消息和处理函数的对应数组
static qcril_dispatch_table_entry_type qcril_event_table[] =
{
{ QCRIL_REG_ALL_STATES( QCRIL_EVT_UIM_QMI_COMMAND_CALLBACK, qcril_uim_process_qmi_callback ) },
}
//使用hash值来存储qcril_event_table的数据(是实际操作所用的数组)
static qcril_dispatch_table_entry_type *qcril_hash_table[ QCRIL_HT_ENTRIES_MAX ];

void qcril_init
(
int argc,
char **argv
)
{
//qcril_setup_timed_callback 设置timed callback等初始化动作。
qcril_init_state();
//qcril_event_table存储到qcril_hash_table,使用hash id为索引
qcril_init_hash_table();
//初始化qcril_reqlist(qcril_reqlist.c专门用于管理request info,提供添加、查询、删除等函数)
qcril_reqlist_init();
}


RIL_Init(){

qcril_event_start()

开始qcril_event_main中的循环

void qcril_event_start( void )
{
QCRIL_MUTEX_LOCK( &qcril_event.startup_mutex, "[Main Thread] qcril_event.startup_mutex" );

qcril_event.started = 2;

pthread_cond_broadcast(&qcril_event_startupCond);

QCRIL_MUTEX_UNLOCK( &qcril_event.startup_mutex, "[Main Thread] qcril_event.startup_mutex" );

} /* qcril_event_start() */


RIL_Init完成了qcril 初始化,开始eventloop循环,最后返回了qcril_request_api[]

RIL_register

int main(int argc, char **argv) {

funcs = rilInit(&s_rilEnv, argc, rilArgv);

RIL_register(funcs);



监听socket并设置event callback等。

ril.cpp

RIL_RadioFunctions s_callbacks = {0, NULL, NULL, NULL, NULL, NULL};
extern "C" void
RIL_register (const RIL_RadioFunctions *callbacks) {
memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));

//定义socket,双卡项目需要定义2个
/* Initialize socket1 parameters */
s_ril_param_socket = {
RIL_SOCKET_1,             /* socket_id */
-1,                       /* fdListen */
-1,                       /* fdCommand */
PHONE_PROCESS,            /* processName */
&s_commands_event,        /* commands_event */
&s_listen_event,          /* listen_event */
processCommandsCallback,  /* 回调函数 */
NULL                      /* p_rs */
};

#if (SIM_COUNT >= 2)
s_ril_param_socket2 = {
RIL_SOCKET_2,               /* socket_id */
-1,                         /* fdListen */
-1,                         /* fdCommand */
PHONE_PROCESS,              /* processName */
&s_commands_event_socket2,  /* commands_event */
&s_listen_event_socket2,    /* listen_event */
processCommandsCallback,
NULL                        /* p_rs */
};
#endif

//开始监听socket1
startListen(RIL_SOCKET_1, &s_ril_param_socket);

#if (SIM_COUNT >= 2)
//开始监听socket2
startListen(RIL_SOCKET_2, &s_ril_param_socket2);
}

//开始监听
static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_listen_p) {

fdListen = android_get_control_socket(socket_name);
if (fdListen < 0) {
RLOGE("Failed to get socket %s", socket_name);
exit(-1);
}
//监听rild(2)
ret = listen(fdListen, 4);

if (ret < 0) {
RLOGE("Failed to listen on control socket '%d': %s",
fdListen, strerror(errno));
exit(-1);
}
socket_listen_p->fdListen = fdListen;
//唤醒eventloop,回调方法为listenCallback(persist为false)
ril_event_set (socket_listen_p->listen_event, fdListen, false,
listenCallback, socket_listen_p);
rilEventAddWakeup (socket_listen_p->listen_event);
}

//eventloop执行回调,设置对socket的监听
static void listenCallback (int fd, short flags, void *param) {

if(NULL == sapSocket) {

p_info->fdCommand = fdCommand;
p_rs = record_stream_new(p_info->fdCommand, MAX_COMMAND_BYTES);
p_info->p_rs = p_rs;
//event persist属性为true,回调为processCommandsCallback
ril_event_set (p_info->commands_event, p_info->fdCommand, 1,
p_info->processCommandsCallback, p_info);
rilEventAddWakeup (p_info->commands_event);

onNewCommandConnect(p_info->socket_id);
}
}


ril和qcril的event loop及消息函数入口完成了初始化并开始监听消息。

后面的来分析下消息处理和上报。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  高通 框架 android 通讯