整个过程从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()方法来实现实时监听。
![Android 2.3 SD卡挂载流程浅析(三) android 分区挂载流程](http://img.413yy.cn/images/31101031/31035244t01dab9b6242b387f14.jpg)
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,
如有侵权,请告知,谢谢