Android P 储存设备挂载

整体框架设计:
在这里插入图片描述
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继承以及重写的机制,主要重点是描述储存设备的挂载流程,如有错误,麻烦留言纠正。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值