Android 2.3 SD卡挂载流程浅析(三) android 分区挂载流程
整个过程从Kernel检测到SD卡插入事件开始,之前的一些硬件中断的触发以及driver的加载这里并不叙述,一直到SD卡挂载消息更新到“Android——系统设置——存储”一项中。
1. Kernel发出SD卡插入uevent。
2. NetlinkHandler::onEvent()接收内核发出的uevent并进行解析。
3. VolumeManager::handlBlockEvent()处理经过第二步处理后的事件。
4. 接下来调用DirectVolume:: handleBlockEvent()。
在该方法中主要有两点需要注意:
第一,程序首先会遍历mPath容器,寻找与event对应的sysfs_path是否存在与mPath容器中。
第二,针对event中的action有4种处理方式:Add,Removed,Change,Noaction 。
例如:在Add action中会有如下操作(因为我们这里所讲的是SD卡的挂载流程,因此以Add来说明),首先创建设备节点,其次对disk和partition两种格式的设备分别进行处理。SD卡属于disk类型。
5. 经过上一步之后会调用DirectVolume::handleDiskAdded()方法,在该方法中会广播disk insert消息。
6. SocketListener::runListener会接收DirectVolume::handleDiskAdded()广播的消息。该方法主要完成对event中数据的获取,通过Socket。(PS:这里的SocketListener.cpp位于Android源码/system/core/libsysutils/src/中,后文的FramworkListener.cpp也是,之前自己找了很久 T_T)
7. 调用FrameworkListener::onDataAvailable()方法处理接收到的消息内容。
8. FrameworkListener::dispatchCommand()该方法用于分发指令。
9.在FrameworkListener::dispatchCommand()方法中,通过runCommand()方法去调用相应的指令。
10. 在/system/vold/CommandListener.cpp中有runCommand()的具体实现。在该类中可以找到这个方法:CommandListener::VolumeCmd::runCommand(),从字面意思上来看这个方法就是对Volume分发指令的解析。该方法中会执行“mount”函数:vm->mountVolume(arg[2])。
11. mountVolume(arg[2])在VolumeManager::mountVolume()中实现,在该方法中调用v->mountVol()。
12. mountVol()方法在Volume::mountVol()中实现,该函数是真正的挂载函数。(在该方法中,后续的处理都在该方法中,在Mount过程中会广播相应的消息给上层,通过setState()函数。)
13. setState(Volume::Checking);广播给上层,正在检查SD卡,为挂载做准备。
14. Fat::check();SD卡检查方法,检查SD卡是否是FAT格式。
15. Fat::doMount()挂载SD卡。
至此,SD的挂载已算初步完成,接下来应该将SD卡挂载后的消息发送给上层,在13中也提到过,在挂载以及检查的过程中其实也有发送消息给上层的。
16. MountService的构造函数中会开启监听线程,用于监听来自vold的socket信息。
Thread thread = new Thread(mConnector,VOLD_TAG); thread.start();
17. mConnector是NativeDaemonConnector的对象,NativeDaemonConnector继承了Runnable并Override了run方法。在run方法中通过一个while(true)调用ListenToSocket()方法来实现实时监听。
18. 在ListenToSocket()中,首先建立与Vold通信的Socket Server端,然后调用MountService中的onDaemonConnected()方法。(PS:Java与Native通信可以通过JNI,那么Native与Java通信就需要通过Socket来实现了。Android中Native与Frameworks通信 这篇文章中有简介,感兴趣的朋友可以参考一下)
19. onDaemonConnected()方法是在接口INativeDaemonConnectorCallbacks中定义的,MountService实现了该接口并Override了onDaemonConnected()方法。该方法开启一个线程用于更新外置存储设备的状态,主要更新状态的方法也在其中实现。
20. 然后回到ListenToSocket中,通过inputStream来获取Vold传递来的event,并存放在队列中。
21. 然后这些event会在onDaemonConnected()通过队列的”队列.take()”方法取出。并根据不同的event调用updatePublicVolumeState()方法,在该方法中调用packageManagerService中的updateExteralState()方法来更新存储设备的状态。(注:这里不太理解packageManagerService中的unloadAllContainers(args)方法)
22. 更新是通过packageHelper.getMountService().finishMediaUpdate()方法来实现的。
23. 在updatePublicVolumeState()方法中,更新后会执行如下代码:
bl.mListener.onStorageStateChanged();
在Android源码/packages/apps/Settings/src/com.android.settings.deviceinfo/Memory.java代码中,实现了StorageEventListener 的匿名内部类,并Override了onStorageStateChanged();方法。因此在updatePublicVolumeState()中调用onStorageStateChanged();方法后,Memory.java中也会收到。在Memory.java中收到以后会在Setting界面进行更新,系统设置——存储中会更新SD卡的状态。从而SD卡的挂载从底层到达了上层。
在经过了上面步骤之后,SD卡的挂载的消息已经从底层到达了上层。这是自己在网上查找资料同时一边跟踪代码后得出的结论,其中可能还有很多不正确的地方,也有很多自己没有理解的地方,希望大家能够帮忙指正,感激不尽。
后续将继续分析SD挂载广播的发出流程,以及SD卡挂载程序调用流程图。转载于:http://blog.csdn.net/yihongyuelan/article/details/6963485,
如有侵权,请告知,谢谢
更多阅读
如何使用大话3新手卡礼包序列号 大话新手礼包序列号
大话3新手卡礼包序列号如何使用,下面我们来详解一下。首先你得有大话3新手卡礼包序列号,没有的话可以到我空间获取。1.打开大话3,输入帐号密码进入游戏2.选择区,接受条款3.创建角色,进入游戏4.点击无限大礼包如何使用大话3新
手机加密SD卡 手机sd卡文件夹加密
手机加密SD卡——简介现在在大家的生活中已经越来越离不开智能手机了,看电影,看微博,看微信,交话费,交水费,等等等等,已经越来越普遍的为大家接受了,但是很多人对于智能手机的操作并不是很熟悉怎么办呢?手机加密SD卡——工具/原料手机手机
如何给SD卡分区 如何给sd卡分区知乎
如何给SD卡分区——简介大家都知道硬盘可以分区,那么,手机上的SD卡可以分区吗?答案是可以。分区之后可以干什么呢?手机SD卡一般都是FAT32格式,不能移动超过4G的文件,比如说电影什么的,只有转成NTFS格式的才可以。但是,手机不识别NTFS的卡,它
Android系统SD卡分区图解教程 安卓系统sd卡分区
最近入手了一部HTC Magic,由于是刚从Symbian系统转到Android系统,还是稍有些不习惯。尤其是相对于Symbian系统来说,Android系统在安装软件的时候只能安装在手机内存,这就给本身内存就不是很大的机器带来了诸多不便。既然有不便,那就要想
如何格式化手机SD卡(内存卡) 如何格式化手机sd卡
1、将SD卡连接上电脑,双击进入我的电脑。、2、进入我的电脑可以看到几个磁盘,【可移动磁盘】就是你的SD卡。3、右击可移动磁盘,【右击 】之后在列表中选择格式化。如何格式化手机SD卡(内存卡)_sd卡格式化