Android6.0的phone应用源码分析(6)——RIL层框架分析
2016-03-02 15:20
489 查看
通过之前的分析已经知道,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框架。文件夹下的主要如下:
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()的代码贴出来:
而对于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的函数。如下图所示:
首先可以先大致的从Android6.0的文件排布来分析RIL框架。文件夹下的主要如下:
Hardware/ril/rild | Rild.c |
Hardware/reference-ril | Atchannel.c 、reference_ril.c |
Hardware/libril | Ril.cpp |
仔细查看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);//打开dl(refrence-ril.so) if (dlHandle == NULL) { RLOGE("dlopen failed: %s", dlerror()); exit(EXIT_FAILURE); } RIL_startEventLoop();//开启RIL循环,这里调用的是ril.cpp的extern方法 //从链接库中(也就是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.cpp的extern函数。 //funcs是包含refrence-rill.so的函数集合的结构体,赋值给了rill.cpp的s_callbacks RIL_register(funcs); ……略 RLOGD("RIL_Init starting sleep loop"); while (true) { sleep(UINT32_MAX); } } |
此时ril.cpp与refrence-ril.so的双向将交互就已经建立好了:ril.cpp通过funcs调用referenc-ril.so的函数,refrence-ril.so可以通过s_rilEnv调用ril.cpp的函数。如下图所示:
相关文章推荐
- Android Studio ——Service的生命周期
- android浅析1---android系统构架
- Fragment初解
- Android 计时器
- android4.0 以后关于DatePicker的显示问题
- Android AccessibilityService 使用详解
- Android 项目目录结构
- Android drawable 的setBounds(0, 5, dip2px(20), dip2px(20)) 方法
- 记一次EditText设置默认选中setSelection的一个bug
- android:inputType参数类型说明
- Android Studio + JNI 实践~入门第一步
- mac os x上 android apk 反编译
- android修改开机动画和铃声
- Android ListView异步加载图片乱序问题,原因分析及解决方案(二)
- Libgdx仿安卓R文件通过Id访问资源
- Android的bitmap和优化
- android 如何计算PopupWindow宽和高
- android dpi dip px
- [Android] Android开发优化之——从代码角度进行优化
- Android 相机或者相册上传头像