当前主线程发送消息H_DAEMON_CONNECTED给线程“MountService”,该线程收到消息后调用MountServiceHandler的handleMessage()相应分支后,进而调用handleDaemonConnected()方法。
private void handleDaemonConnected() {
synchronized (mLock) {
resetIfReadyAndConnectedLocked();
}
//类型为CountDownLatch,用于多线程同步,阻塞await()直到计数器为零
mConnectedSignal.countDown();
if (mConnectedSignal.getCount() != 0) {
return;
}
//调用PMS来加载ASECs
mPms.scanAvailableAsecs();
//用于通知ASEC扫描已完成
mAsecsScanned.countDown();
}
这里的PMS.scanAvailableAsecs()经过层层调用,最终核心工作还是通过MountService.getSecureContainerList。
[-> MountService.java]
public String[] getSecureContainerList() {
enforcePermission(android.Manifest.permission.ASEC_ACCESS);
//等待mConnectedSignal计数锁达到零
waitForReady();
//当没有挂载Primary卷设备,则弹出警告
warnOnNotMounted();
try {
//向vold进程发送asec list命令
return NativeDaemonEvent.filterMessageList(
mConnector.executeForList("asec", "list"), VoldResponseCode.AsecListResult);
} catch (NativeDaemonConnectorException e) {
return new String[0];
}
}
三、Vold
Vold是由开机过程中解析init.rc时启动:
on post-fs-data
start vold
Vold的service定义如下:
service vold /system/bin/vold
class core
socket vold stream 0660 root mount
socket cryptd stream 0660 root mount
ioprio be 2
接下来便进入main()方法:
3.1 main
[-> system/vold/Main.cpp]
int main(int argc, char** argv) {
setenv("ANDROID_LOG_TAGS", "*:v", 1);
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
VolumeManager *vm;
CommandListener *cl;
CryptCommandListener *ccl;
NetlinkManager *nm;
//解析参数,设置contenxt
parse_args(argc, argv);
...
fcntl(android_get_control_socket("vold"), F_SETFD, FD_CLOEXEC);
fcntl(android_get_control_socket("cryptd"), F_SETFD, FD_CLOEXEC);
mkdir("/dev/block/vold", 0755);
//用于cryptfs检查,并mount加密的文件系统
klog_set_level(6);
//创建单例对象VolumeManager 【见小节3.2.1】
if (!(vm = VolumeManager::Instance())) {
exit(1);
}
//创建单例对象NetlinkManager 【见小节3.3.1】
if (!(nm = NetlinkManager::Instance())) {
exit(1);
}
if (property_get_bool("vold.debug", false)) {
vm->setDebug(true);
}
// 创建CommandListener对象 【见小节3.4.1】
cl = new CommandListener();
// 创建CryptCommandListener对象 【见小节3.5.1】
ccl = new CryptCommandListener();
//【见小节3.2.2】
vm->setBroadcaster((SocketListener *) cl);
//【见小节3.3.2】
nm->setBroadcaster((SocketListener *) cl);
if (vm->start()) { //【见小节3.2.3】
exit(1);
}
process_config(vm); //【见小节3.2.4】
if (nm->start()) { //【见小节3.3.3】
exit(1);
}
coldboot("/sys/block");
//启动响应命令的监听器 //【见小节3.4.2】
if (cl->startListener()) {
exit(1);
}
if (ccl->startListener()) {
exit(1);
}
//Vold成为监听线程
while(1) {
sleep(1000);
}
exit(0);
}
该方法的主要功能是创建下面4个对象并启动
VolumeManager
NetlinkManager (NetlinkHandler)
CommandListener
CryptCommandListener
接下来分别说说几个类:
3.2 VolumeManager
3.2.1 创建
[-> VolumeManager.cpp]
VolumeManager *VolumeManager::Instance() {
if (!sInstance)
sInstance = new VolumeManager();
return sInstance;
}
创建单例模式的VolumeManager对象
VolumeManager::VolumeManager() {
mDebug = false;
mActiveContainers = new AsecIdCollection();
mBroadcaster = NULL;
mUmsSharingCount = 0;
mSavedDirtyRatio = -1;
//当UMS获取时,则设置dirty ratio为0
mUmsDirtyRatio = 0;
}
3.2.2 vm->setBroadcaster
void setBroadcaster(SocketListener *sl) {
mBroadcaster = sl;
}
将新创建的 CommandListener 对象sl赋值给vm对象的成员变量 mBroadcaster
3.2.3 vm->start
int VolumeManager::start() {
//卸载所有设备,以提供最干净的环境
unmountAll();
//创建Emulated内部存储
mInternalEmulated = std::shared_ptr<:vold::volumebase>(
new android::vold::EmulatedVolume("/data/media"));
mInternalEmulated->create();
return 0;
}
mInternalEmulated的据类型为 EmulatedVolume ,设备路径为 /data/media ,id和label为“emulated”,mMountFlags=0。 EmulatedVolume 继承于 VolumeBase
3.2.3.1 unmountAll
int VolumeManager::unmountAll() {
std::lock_guard<:mutex> lock(mLock);
//卸载内部存储
if (mInternalEmulated != nullptr) {
mInternalEmulated->unmount();
}
//卸载外部存储
for (auto disk : mDisks) {
disk->unmountAll();
}
FILE* fp = setmntent("/proc/mounts", "r");
if (fp == NULL) {
return -errno;
}
std::list<:string> toUnmount;
mntent* mentry;
while ((mentry = getmntent(fp)) != NULL) {
if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0
|| strncmp(mentry->mnt_dir, "/storage/", 9) == 0) {
toUnmount.push_front(std::string(mentry->mnt_dir));
}
}
endmntent(fp);
for (auto path : toUnmount) {
//强制卸载
android::vold::ForceUnmount(path);
}
return 0;
}
此处打开的”/proc/mounts”每一行内容依次是文件名,目录,类型,操作。例如:
/dev/fuse /mnt/runtime/default/emulated fuse rw,nosuid,nodev,...
该方法的主要工作是卸载:
内部存储mInternalEmulated;
外部存储mDisks,比如sdcard等;
“/proc/mounts”中目录包含mnt或者storage的路径;
(责任编辑:ioter)