Android6.0的phone应用源码分析(6)——RIL层框架分析

通过之前的分析已经知道,RILJ存在着多个循环结构:1、Ril.cpp中的Event_loop负责接收来自RILJ的Request;2、reference_ril.c中的mainLoop主要是维护AT通道的打开状态,在AT通过出现问题时重启AT通道;3、Atchannel.c中的ReaderLoop负责接收Modem上报的ATResponse。如何让这三个循环正确有序的进行是RIL框架的关键。

首先可以先大致的从Android6.0的文件排布来分析RIL框架。文件夹下的主要如下:

Hardware/ril/rild

Rild.c

Hardware/reference-ril

Atchannel.c 、reference_ril.c

Hardware/libril

Ril.cpp

RILD的上层是Java代码,而一般Android的结构由底层到上层都是C->C++->java。因此可以猜测与RILJ直接交互的应该是Ril.cpp,仔细查看其代码发现 EventLoop就是在Ril.cpp中从而验证了这种猜想。reference_ril.c之前已经知道这是一个链接库,主要将RILRequest转化成AT命令发送带Modem。而Rild.c基本上就是一个main函数,仅仅作为开启三个循环以及构造循环之间的关系的入口。

仔细查看ril.cpp的所在文件夹名字为“Hardware/libril”,因此这个文件夹的编译方式应该是编译成动态共享库。在rild的MK配置文件中还发现,rild.c的编译是依赖于这个共享库的,而且RIL_startEventLoop()函数也是通过extern调用了libril的extern同名函数。因此,通过共享库的方式实现了rild.c对ril.cpp的函数的调用。这里再将rild.main()的代码贴出来:

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

    ……略

    dlHandle = dlopen(rilLibPath, RTLD_NOW);//打开dlrefrence-ril.so

 

    if (dlHandle == NULL) {

        RLOGE("dlopen failed: %s", dlerror());

        exit(EXIT_FAILURE);

    }

 

RIL_startEventLoop();//开启RIL循环,这里调用的是ril.cppextern方法

 

    //从链接库中(也就是reference-ril.c)寻找RIL_Init函数地址 ,注意返回的是函数指针

    rilInit =

        (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))

        dlsym(dlHandle, "RIL_Init");

 

    if (rilInit == NULL) {

        RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath);

        exit(EXIT_FAILURE);

}

……略

//调用reference-ril.c中的RIL_Init函数对驱动进行初始化,同时得到reference-ril的回调函数,参数

//s_rilEnv是一个包含ril.cpp函数指针的结构体,这里通过参数的方法传给了refrence-ril.so

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

    RLOGD("RIL_Init rilInit completed");

     //注册rilInit得到的reference-ril的回调函数,这里调用的依然是ril.cppextern函数。

    //funcs是包含refrence-rill.so的函数集合的结构体,赋值给了rill.cpps_callbacks

    RIL_register(funcs);

     ……略

    RLOGD("RIL_Init starting sleep loop");

    while (true) {

        sleep(UINT32_MAX);

    }

}

而对于reference-ril.so,从rild.main()中可以看出是通过dlopen的方式动态打开的。因此rild.main是持有refrence-ril.so的句柄的。通过dlsym可以找到指向refrence-ril.so中rilInit的函数指针。Rild.main通过调用rilInit(&s_rilEnv,argc,rilArgv)返回了一个指向funcs结构体,此结构体内部存放了需要调用的refrence-ril.so函数的指针,rild.main()接着将此funcs注册进ril.cpp。因此,此时ril.cpp可以通过这个funcs调用的refrence-ril.so的函数。rilInit(&s_rilEnv,argc,rilArgv)同时携带了一个参数s_rilEnv传递给了refrence-ril.so。查看此结构体的内容,发现其存放的都是指向rill.cpp几个函数的函数指针。因此reference-ril.so可以通过s_rilEnv调用ril.cpp的函数。

此时ril.cpp与refrence-ril.so的双向将交互就已经建立好了:ril.cpp通过funcs调用referenc-ril.so的函数,refrence-ril.so可以通过s_rilEnv调用ril.cpp的函数。如下图所示:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值