androoid framework学习之 - RILd启动过程和如何接收framwork层的消息流程

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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值