androoid framework学习之 - android RIL
1. RIL简单介绍:
RIL------RadioInterface Layer,RIL是Android 的无线接口层.负责提供电话服务.是上层应用和下层硬件modem之间的中间层。
2.在RIL.Java里如何和HAL层交换数据
交换数据都分为两种:发送和接收,下面先讲下自己今天学习的发送:
以RIL_REQUEST_UDUB(拒接电话)这个事件为例:
l 在RIL.Java中
@Override
public void
rejectCall (Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_UDUB, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
l 在HAL层接收消息:
Reference-ril.c中:
static void
onRequest (int request, void *data, size_t datalen, RIL_Token t)
{
.............................
case RIL_REQUEST_UDUB:
/* user determined user busy */
/* sometimes used: ATH */
at_send_command("ATH", NULL);
/* success or failure is ignored by the upper layer here.
it will call GET_CURRENT_CALLS and determine success that way */
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
break;
.............................
}
那以上就是一个拒绝接电话的建东RIL实现,那看完上面这个肯定会有很多疑问:
1. 一个是.java文件、一个是.c文件,他们是怎么连接消息的?----简单来说是用socket来进行通信的,具体会例外开一篇文章来说。
2. 为什么会调用onRequest函数呢,它是一直在跑还是回调函数呢?
对于这个问题,他是回调函数。那下面来看下整个过程:
1.从Rild.c开始:
int main(int argc, char **argv)
{
.............
RIL_startEventLoop();//创建客户端事件监听线程
..................
rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
//通过dlsym定位到RIL_Init函数的地址,并且强制转换为RIL_RadioFunctions的函数指针
...........................
/*这个地方s_rilEnv虽然名字与RIL_init的一样,但是二者只作用于当前文件,
//目前这个文件对s_rilEnv结构体进行赋值了,也就是对应了
static struct RIL_Env s_rilEnv = {底层-------->上层
RIL_onRequestComplete,
RIL_onUnsolicitedResponse,
RIL_requestTimedCallback
};
然后再将这个结构体指针赋给RIL_init里面的Env,相当于将底层的返回通知的接口注册好
*/
funcs = rilInit(&s_rilEnv, argc, rilArgv);//ril初始化,通过传过来的参数获取硬件接口设备文件,该函数在Reference_ril.c里面
//******调用RIL_Init函数来初始化rild,传入参数s_rilEnv,返回RIL_RadioFunctions地址
RLOGD("RIL_Init rilInit completed"?;
RIL_register(funcs);//将s_fdListen加入消息队列中,开始s_fdListen时间监听,librefrence.so接口就是
//客事件处理接口RIL_RadioFunctions,并创建socket监听事件
/*将上层需要查询、设置的接口注册到底层,上层--------->底层
static const RIL_RadioFunctions s_callbacks = {
RIL_VERSION,
onRequest,AP请求接口
currentState,//BP状态查询
onSupports,
onCancel,
getVersion//动态库版本
};
*/
.......................
}
2.这边先讲下RIL_init函数,在 hardware\ril\reference-ril\reference-ril.c
这里有两个很重要的结构RIL_Env和RIL_RadioFunctions,
//RIL_Env和RIL_RadioFunctions接口就是libril.so与librefrence.so通信的桥梁
//是Rild架构中用于隔离通用代码和厂商代码的接口,RIL_Env由通用代码实现,而RIL_RadioFunctions则是由厂商代码实现
//RIL_Env是libril.so提供的接口包含(完成quest后通知结果,电话来了的接口、延时接口)?
//底层给客户进程的接口
//RIL_Env和RIL_RadioFunctions接口就是libril.so与librefrence.so通信的桥梁
//是Rild架构中用于隔离通用代码和厂商代码的接口,RIL_Env由通用代码实现,而RIL_RadioFunctions则是由厂商代码实现
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
........................
s_rilenv = env;//将ril.cpp中定义的RIL_Env注册到reference-ril.c中的s_rilenv
..........................
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
return &s_callbacks;//返回RIL_RadioFunctions结构
}
这边再看下
RIL_Env(有三种,完成framework时的通知OnRequestComplete、来电通知操作OnUnsolicitedResponse、延时操作RequestTimedCallback,都是由modern往上发的)和
RIL_RadioFunctions(响应framework下下来的消息,比如set/get等,都通过Onrequest来响应)这两个结构体:
在hardware\ril\reference-ril\Rild.c和hardware\ril\reference-ril\Rild.h
struct RIL_Env {
void (*OnRequestComplete)(RIL_Token t, RIL_Errno e, //动态库完成请求后通知处理结果的接口
void *response, size_t responselen);
//动态库unSolicited Response通知接口
void (*OnUnsolicitedResponse)(int unsolResponse, const void *data, size_t datalen, RIL_SOCKET_ID socket_id);
//延时操作
void (*RequestTimedCallback) (RIL_TimedCallback callback,
void *param, const struct timeval *relativeTime);
};
static struct RIL_Env s_rilEnv = {
RIL_onRequestComplete,
RIL_onUnsolicitedResponse,
RIL_requestTimedCallback
};
在hardware\ril\reference-ril\Rild.h
typedef struct {
int version; //Rild版本 /* set to RIL_VERSION */
RIL_RequestFunc onRequest; //AP请求接口
RIL_RadioStateRequest onStateRequest;//BP状态查询
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;//动态库版本
} RIL_RadioFunctions;
在hardware\ril\reference-ril\reference-ril.c
/*** Static Variables ***///变量定义
//客户端向Rild发送请求的接口,由各手机厂商实现。
static const RIL_RadioFunctions s_callbacks = {
RIL_VERSION,
onRequest,AP请求接口
currentState,//BP状态查询
onSupports,
onCancel,
getVersion//动态库版本
};
3.上面RIL_init返回了RIL_RadioFunctions结构体的指针,这个指针会在main函数里的funcs = rilInit(&s_rilEnv, argc, rilArgv); RIL_register(funcs);注册
4.看下RIL_register函数:
RIL_register (const RIL_RadioFunctions *callbacks) {
.......................
//将reference-ril.c中定义的RIL_RadioFunctions注册到ril.cpp中
memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));//注册事件处理接口
............................
这里就将
RIL_RadioFunctions赋给了s_callbacks全局指针
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, /* processCommandsCallback */
NULL /* p_rs */
};
startListen(RIL_SOCKET_1, &s_ril_param_socket);将s_listen_event事件加入到watch_table队列中 唤醒事件处理线程
这里是制定RIL_SOCKET_1的callback函数是processCommandsCallback,并且将其加入watch_table队列中。
5.然后就是startListen函数了:
static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_listen_p) {
......................
fdListen = android_get_control_socket(socket_name);//在init.rc里面找同名的socket
...........................
socket_listen_p->fdListen = fdListen;
/* note: non-persistent so we can accept only one connection at a time */
//创建事件s_listen_event 监听和处理客户端请求
ril_event_set (socket_listen_p->listen_event, fdListen, false,
listenCallback, socket_listen_p);
//将s_listen_event事件加入到watch_table队列中 唤醒事件处理线程
rilEventAddWakeup (socket_listen_p->listen_event);
}
ril_event_set和rilEventAddWakeup二者结合就是将事件加入到watch_table队列中 唤醒事件处理线程。
那这个地方就有个一个疑问了,listenCallback这个callback函数什么时候执行呢?
来我来解释下:
6.在Ril.cpp中:
/*建立多路I/O驱动机制的消息队列,用来接收上层发出的命令以及往Modem发送AT指令的工作,
时整个RIL系统的核心部分。创建一个事件分发线程s_tid_dispatch,线程执行体为eventLoop。
*
*/
RIL_startEventLoop(void) {
/* spin up eventLoop thread and wait for it to get started */
//建eventLoop线程,直到被启动并将s_started置为1返回
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);
//确保函数返回前eventLoop线程启动运行
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);//解锁
}
static void *
eventLoop(void *param) {
int ret;
int filedes[2];
ril_event_init();//初始化请求队列
pthread_mutex_lock(&s_startupMutex);
s_started = 1; //eventLoop线程运行标志位
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_fdWakeupRead为管道读端
s_fdWakeupWrite = filedes[1];//s_fdWakeupWrite为管道写端
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);//设置管道读端为O_NONBLOCK非阻塞
//初始化s_wakeupfd_event结构体的内容,句柄为s_fdWakeupRead,回调函数为 processWakeupCallback
ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
processWakeupCallback, NULL);
rilEventAddWakeup (&s_wakeupfd_event);
// Only returns on error
ril_event_loop();///处理事件
RLOGE ("error in event_loop_base errno:%d", errno);
// kill self to restart on error
kill(0, SIGKILL);
return NULL;
}
void ril_event_loop()//开启ril_event_loop()循环,监听上层发来的request命令
{
int n;
f