日期:2014-05-20  浏览次数:20882 次

framework之深入理解Vold和Rild

Vold:用于管理和控制Android平台外部存储设备的后台进程,包括SD卡的插拔检测,挂载、卸载、格式化等等。

Rild:用于智能手机的通信管理和控制的后台进程,所有和手机通信相关的功能,如接打电话、收发短信、GPRS等。

Vold和Rild均为Native层,而MountService为java层。

Vold流程:

Vold的NetlinkManager接收来自Linux kernel层的uevent消息,转发给VolumeManager模块,VM再通过CommandListener发送给MountService。MountService再通过CommandListener发送处理命令给VolumeManager。

这里有四大模块:NetlinkManager、VolumeManager、CommandListener、MountService

NetlinkManager分析:

主要内容在start函数中,首先创建PF_NETLINK的socket,这样NM就能和kernel通信了。收到kernel消息后,处理在NetlinkHandle的start中,NetlinkHandler继承NetlinkListener,继承SocketListener,最终在SocketListener的startListener函数中处理,调用threadstart,调用SocketListener的runListener,无论是客户端还是服务端,最终处理都在NetlinkListener的onDataAvailable函数中处理,将UEvent信息填充到NetlinkEvent中,调用VM来处理这个NetlinkEvent对象。

VolumeManager分析:

主要用process_config函数配置VM,主要解析了/etc/vold.fstab文件,构造出一个DirectVolume对象,该对象从Volume中派生,可以看成是一个SD卡的代表。封装了SD卡的操作,如加载sd卡等。该对象的构造调用了addpath函数,会把和某个存储卡接口相关的设备路径与这个DirectVolume绑定在一起,并且这个设备路径和UEvent中的DEVPATH是对应的。对于block(块)子系统,VM调用handleBlockEvent函数处理NetlinkEvent对象,接着调用DirectVolume的handleBlockEvent函数

CommandListener分析:

继承于socketListener,是Socket的监听端。采用了设计模式中的Command模式,定义了一些和Command相关的内部类,每个命令的处理函数都是runCommand。调用CL的startListener函数,当CL收到数据时,调用FrameworkListener的onDataAvailable函数,dispatchCommand分发命令。会调用该命令对应的runCommand。

MountService分析:

java层的Vold,在插卡后,native的Vold中NM模块收到UEvent消息,最后在DirectVolume的handleBlockEvent中处理,插卡的时候,会调用handleDiskAdded,把UEvent消息做一些转化后发送给MountService,MountService会单独启动一个线程doMountVolume给Vold发送请求。CL收到数据后,调用相应的runCommand处理,先调用VM模块的mountVolume函数处理命令,处理中先看createBindMounts函数,将存储卡上的.android_secure目录挂载到/mnt/secure/asec目录,用来保存安装在SD卡的app信息,可以在sd卡上安装app,节约信息存储空间。将tempfs设备挂载到/mnt/secure/staging/.android_secure,这样.android_secure目录中的内容只能通过/mnt/secure/asec访问,该目录只能root访问,起到一定保护作用。VM端的mountVolume处理完命令后,发送给MountService

Rild原理与机制:

AP:一个处理器用来运行操作系统,上面可以跑应用程序。

BP:该处理器负责喝射频无线通信相关的工作。

AP和BP之间通过串口进行通信,通信协议使用的是AT指令。

AP上的应用程序通过Rild发送AT指令给BP,而BP也通过Rild传送给AP上的应用程序,Rild会加载一个厂商相关的动态库,AP和BP的工作由动态库去完成。

使用android提供的动态库livReference_ril.so分析,先加载该动态库,调用RIL_startEventLoop进行处理,该函数创建eventLoop工作线程,并等待该工作线程创建完毕并且已经运行,工作线程中先调用ril_event_init初始化相关队列和管理结构,ril_event_set函数初始化管道的读端,将匿名管道的读写端加入event队列,再通过往匿名管道写数据触发工作线程,ril_event_loop处理Rild任务,支持定时任务和非定时任务。

动态库必须实现的RIL_init函数,保存Rild传入的RIL_Env结构体,创建一个mainLoop的工作线程,返回一个RIL_RadioFunctions的结构体。RIL_RadioFunctions中有一个onRequest函数,,Rild通过它向动态库提交一个请求,动态库处理这个请求,通过RIL_Env返回,。而mainLoop工作就是初始化AT模块,并且监控AT模块,一旦AT模块被关闭,mainLoop就要重新打开并初始化它。这几项工作由at_open和超时任务的处理函数initalizeCallback完成。AT模块就是对串口通信的封装。

RIL_register函数创建两个监听socket,rild用来监听java层的应用程序,rild-debug用来接收测试程序的测试命令。该函数构造了一个非超时任务,只支持一个客户端的连接,连接后触发eventLoop,对应的listenCallback会被调用,最后处理函数是processCommandsCallback,采用异步请求/响应的知识。