Platform: RK3399
OS: Android 7.1
Kernel: v4.4.83
Board: Firefly-RK3399
之前版本sdcard守護程序都是放在init.rc中啟動:
service sdcard /system/bin/sdcard -u -g -l /data/media /mnt/shell/emulated
class late_start
在Android7.1上被放在vold程序中啟動了:
status_t EmulatedVolume::doMount() {
......
dev_t before = GetDevice(mFuseWrite);
//kFusePath就是/system/bin/sdcard即守護程序的可執行檔案
if (!(mFusePid = fork())) {
if (execl(kFusePath, kFusePath,
"-u", "1023", // AID_MEDIA_RW
"-g", "1023", // AID_MEDIA_RW
"-m",
"-w",
mRawPath.c_str(),
label.c_str(),
NULL)) {
PLOG(ERROR) << "Failed to exec";
}
LOG(ERROR) << "FUSE exiting";
_exit();
}
.....
return OK;
}
那麼doMount()是如何調用到的呢? 以下是調用流程:
main -> main.c //vold程序在rc檔案中啟動。
vm->start ->
VolumeManager::start -> VolumeManager.cpp
new android::vold::EmulatedVolume("/data/media")); -> //資料是被存在/data/media路徑的
mInternalEmulated->create -> //VolumeManager繼承了VolumeBase
VolumeBase::create ->
notifyEvent -> //cmd是ResponseCode::VolumeCreated
//vold是socket服務端,用戶端是MountService
onEvent -> MountService.java
onEventLocked -> //cmd是名字改成VoldResponseCode.VOLUME_CREATED,但是值是一樣的。
onVolumeCreatedLocked ->
mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); -> //交由MountServiceHandler類處理
handleMessage ->
mConnector.execute("volume", "mount",...); -> //利用NativeDaemonConnector中socket将消息發送給CommandListener
CommandListener::VolumeCmd::runCommand -> CommandListener.cpp //調用的類是VolumeCmd,cmd是mount
vol->mount -> 調用EmulatedVolume的基類VolumeBase ->
VolumeBase::mount -> VolumeBase.cpp
doMount -> //EmulatedVolume類實作了此虛函數
EmulatedVolume::doMount //啟動sdcard程序
參考:
Android 7.0 Vold工作流程