整体框架设计:
kernel中会对sd卡以及u盘设备进行检测,当有设备拔插时通过uevent发送给用户空间的vold进程,vold进程接收并解析kernel的uevent信息。vold通过sgdisk与blkid获取设备信息。接着vold会通过某种机制通知到上层framework.上层有设备插入,等待上层framework下发挂载命令给vold。vold接收到挂载命令后调用exfat或者ntfs_3g对设备进行特定格式挂载。
VOLD信息处理UML图:
如图:当uevent有设备插入的时候会最终会在vold创建一个PulicVolume,PublicVolume继承基类VolumeBase,创建一个PulicVolume的时候会调用基类VolumeBase的VolumeBase::create()方法,该方法会通过IVoldListener的onVolumeCreated方法通知上层StorageManagerService.主要是StorageManagerService.java重写了IVoldListener的onVolumeCreated。如代码主要的调用流程为onVolumeCreated–>onVolumeCreatedLocked—(通过handler机制)---->mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);其中mVold来自IVold.Stub.asInterface(binder)。
1 Framework层:
/*代码路径:framework/base/services/core/java/com/android/server/StorageManagerService.java*/
private final IVoldListener mListener = new IVoldListener.Stub() {
......
@Override
public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
synchronized (mLock) {
final DiskInfo disk = mDisks.get(diskId);
final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
mVolumes.put(volId, vol);
onVolumeCreatedLocked(vol);//进行挂载调用
}
}
......
}
@GuardedBy("mLock")
private void onVolumeCreatedLocked(VolumeInfo vol) {
if (mPms.isOnlyCoreApps()) {
Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
return;
}
if (vol.type == VolumeInfo.TYPE_EMULATED) {
.....
} else if (vol.type == VolumeInfo.TYPE_PUBLIC) {//一般来说我们挂载的usb是publicvolume
// TODO: only look at first public partition
....
vol.mountUserId = mCurrentUserId;
/*通过hanlder机制发送H_VOLUME_MOUNT挂载操作*/
mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
} else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
} else {
Slog.d(TAG, "Skipping automatic mounting of " + vol);
}
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
...
case H_VOLUME_MOUNT: {
final VolumeInfo vol = (VolumeInfo) msg.obj;
if (isMountDisallowed(vol)) {
Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
break;
}
try {
mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);//挂载
} catch (Exception e) {
Slog.wtf(TAG, e);
}
break;
}
...
}
}
2 native层代码:
如上面,framework层会通过 mVold.mount来下发挂载命令,这里的mVlod来自IVold.Stub.asInterface(binder),这里调用mVold.mount会再次从framework层调用到native层。调用流程:
VoldNativeService::mount—>VolumeBase::mount()–>PublicVolume::doMount()
代码路径:system/vold/VoldNativeService.cpp
/*代码路径:system/vold/VoldNativeService.cpp*/
binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags,
int32_t mountUserId) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_ID(volId);
ACQUIRE_LOCK;
/*获取之前的PublicVolume信息*/
auto vol = VolumeManager::Instance()->findVolume(volId);
if (vol == nullptr) {
return error("Failed to find volume " + volId);
}
vol->setMountFlags(mountFlags);
vol->setMountUserId(mountUserId);
/**调用PublicVolume的挂载方法,由于PublicVolume继承VolumeBase并没用重写mount
*所以这里调用VolumeBase::mount()
*/
int res = vol->mount();
if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
VolumeManager::Instance()->setPrimary(vol);
}
retur./model/PublicVolume.cppn translate(res);
}
代码路径:/代码路径:system/vold/model/VolumeBase.cpp/
status_t VolumeBase::mount() {
if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
return -EBUSY;
}
setState(State::kChecking);
/*调用各种Volume的doMount挂载,例如:PublicVolume::doMount()*/
status_t res = doMount();
if (res == OK) {
se./model/PublicVolume.cpptState(State::kMounted);
} else {
setState(State::kUnmountable);
}
return res;
}
代码路径:./system/vold/./model/PublicVolume.cpp
status_t PublicVolume::doMount() {
...
/*对具体的设备类型进行挂载,例如vfat*/
if (mFsType == "vfat") {
if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007,
true)) {
PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
return -EIO;
}
} else if (mFsType == "exfat") {
if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
return -EIO;
}
}
...
}
以上是个人的见解,其中忽略一些java如何到native的调用机制以及native如何被java继承以及重写的机制,主要重点是描述储存设备的挂载流程,如有错误,麻烦留言纠正。