目录
前言
Android P
这里很多都是网上的,我就走走流程。
正文
VolumeManager.cpp
handleBlockEvent()
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) { //申请一个lock std::lock_guard<std::mutex> lock(mLock); //在事件属性参数中查找设备的路径; std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):""); //在事件属性参数中查找设备的类型; std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):""); //判断是否是“disk”类型,磁盘设备,否的话,直接返回不做任何处理 if (devType != "disk") return; //上报的数据中获取主设备号; int major = std::stoi(evt->findParam("MAJOR")); //上报的数据中获取次设备号; int minor = std::stoi(evt->findParam("MINOR")); //makedev()作用是将主次设备号联合得到具体可访问的设备对象索引; dev_t device = makedev(major, minor); //判断事件的动作类型 switch (evt->getAction()) { case NetlinkEvent::Action::kAdd: { //循环判断mDiskSources,这个mDiskSources 在vold的main()函数时就已经配置好的。所以mDiskSources是固定的一些数据。 //在main()函数中调用了process_config()函数对VolumeManager::DiskSource进行赋值。具体是检索配置fstab文件,进行add操作。 for (const auto& source : mDiskSources) { //从mDiskSources表获取的一个成员DiskSource类型的source, //调用该成员的matches函数对 第11行获取的设备路径eventPath,进行匹配字符串比较。 if (source->matches(eventPath)) { // For now, assume that MMC and virtio-blk (the latter is // emulator-specific; see Disk.cpp for details) devices are SD, // and that everything else is USB int flags = source->getFlags(); //判断主设备号是否是mmc的设备; if (major == kMajorBlockMmc //判断是否是模拟器运行的; || (android::vold::IsRunningInEmulator() //判断主设备号必须在 block设备范围内 && major >= (int) kMajorBlockExperimentalMin && major <= (int) kMajorBlockExperimentalMax)) { //将该磁盘Disk的flag标志为kSd flags |= android::vold::Disk::Flags::kSd; } else { //将该磁盘Disk的flag标志为kUsb flags |= android::vold::Disk::Flags::kUsb; } auto disk = new android::vold::Disk(eventPath, device, source->getNickname(), flags); handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk)); break; } } break; } case NetlinkEvent::Action::kChange: { handleDiskChanged(device); break; } case NetlinkEvent::Action::kRemove: { handleDiskRemoved(device); break; } default: { break; } } }
这里是event事件处理中心,主要处理disk类型事件。
以上注册都是摘抄,部分参考文章忘记附上了。
上面分别有三种状态
-
kAdd 挂载
-
kChange
-
kRemove 卸载
这里以分析U盘的挂载流程
handleDiskAdded()
//创建DISK对象 auto disk = new android::vold::Disk(eventPath, device, source->getNickname(), flags); handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) { //锁屏未解锁,需要等待用户解锁 //需要等待user0启动,因为我们需要在mount Fuse daemon处理磁盘前启用用户。 if (mSecureKeyguardShowing) { mPendingDisks.push_back(disk); } else { //调用Disk对象的create()方法创建 //创建一个Disk,并通过notifyEvent()方法通知广播Framework; disk->create(); //将新建的Disk 放到VM管理的一个mDisks表里。 mDisks.push_back(disk); } }
如果锁屏未解锁,添加到mPendingDisks中,等待解锁再处理。如果解锁了,走else,继续看。
Disk.cpp
create()
status_t Disk::create() { //检查是否已经创建过的标志位 CHECK(!mCreated); //第一次创建置位 标志位 mCreated = true; //调用notifyEvent()函数通知到广播中。 auto listener = VolumeManager::Instance()->getListener(); //第一个参数event:ResponseCode::DiskCreated Disk创建; //第二个参数value:mFlags 是new Disk传入的参数。 //只要知道notifyEvent()主要是发送广播给到Framework即可。 if (listener) listener->onDiskCreated(getId(), mFlags); readMetadata(); readPartitions(); return OK; }
这里主要如下内容
-
从VolumeManager中获取listener,并把状态通知到StorageManagerService。
-
readMetadata()
-
readPartitions()
VolumeManager.cpp
getListener()返回的是IVoldListener,其赋值是,在VoldNativeService中。
binder::Status VoldNativeService::setListener( const android::sp<android::os::IVoldListener>& listener) { ENFORCE_UID(AID_SYSTEM); ACQUIRE_LOCK; VolumeManager::Instance()->setListener(listener); return ok(); }
VoldNativeService的setListener,可以看《》,通过IBinder通信,
其中关系,我还不太理解~_~
只知道最后状态进入了StorageManagerService中的private final IVoldListener mListener = new IVoldListener.Stub() {}中。
Disk.cpp
readMetadata()
status_t Disk::readMetadata() { //磁盘大小置为-1 mSize = -1; //清除标签 mLabel.clear(); //以只读的原子操作打开设备 int fd = open(mDevPath.c_str(), O_RDONLY | O_CLOEXEC); //不为1就打开成功 if (fd != -1) { //获取空间大小 if (ioctl(fd, BLKGETSIZE64, &mSize)) { //获取失败 mSize = -1; } close(fd); } //获取主设备号ID unsigned int majorId = major(mDevice); //根据不同的block设备进行分类访问; switch (majorId) { //判断是循环block,则是虚拟设备标签设置为“Virtual”; case kMajorBlockLoop: { mLabel = "Virtual"; break; } //判断是Scsi类型的block设备; case kMajorBlockScsiA: case kMajorBlockScsiB: case kMajorBlockScsiC: case kMajorBlockScsiD: case kMajorBlockScsiE: case kMajorBlockScsiF: case kMajorBlockScsiG: case kMajorBlockScsiH: case kMajorBlockScsiI: case kMajorBlockScsiJ: case kMajorBlockScsiK: case kMajorBlockScsiL: case kMajorBlockScsiM: case kMajorBlockScsiN: case kMajorBlockScsiO: case kMajorBlockScsiP: { //path=mSysPath+“/device/vendor” = “/sys/”+eventPath+“/device/vendor”; std::string path(mSysPath + "/device/vendor"); std::string tmp; //读取对应path路径下的字符串; if (!ReadFileToString(path, &tmp)) { PLOG(WARNING) << "Failed to read vendor from " << path; return -errno; } //将前面读取的字符串 赋值给“mLable”; tmp = android::base::Trim(tmp); mLabel = tmp; break; } //判断是Mmc类型block; case kMajorBlockMmc: { //path=mSysPath+“/device/manfid” = “/sys/”+eventPath+“/device/manfid”; std::string path(mSysPath + "/device/manfid"); std::string tmp; //读取对应path路径下的字符串; if (!ReadFileToString(path, &tmp)) { return -errno; } tmp = android::base::Trim(tmp); //获得得到manfid; int64_t manfid; if (!android::base::ParseInt(tmp, &manfid)) { return -EINVAL; } /* manfid为0x000003 则是"SanDisk"的mmc manfid为0x00001b则是"Samsung"的mmc manfid为0x000028则是"Lexar"的mmc manfid为0x000074则是"Transcend"的mm */ switch (manfid) { case 0x000003: mLabel = "SanDisk"; break; case 0x00001b: mLabel = "Samsung"; break; case 0x000028: mLabel = "Lexar"; break; case 0x000074: mLabel = "Transcend"; break; } break; } //判断为其它类型的设备; default: { if (isVirtioBlkDevice(majorId)) { mLabel = "Virtual"; break; } return -ENOTSUP; } } auto listener = VolumeManager::Instance()->getListener(); /* 发送广播,通知FW,Disk的Size发生变化; 发送广播,通知FW,Disk的Lable发生变化; 发送广播,通知FW,Disk的SysPath发生变化; */ if (listener) listener->onDiskMetadataChanged(getId(), mSize, mLabel, mSysPath); return OK; }
readPartitions()
status_t Disk::readPartitions() { //计算出支持的最大分区设备 //计算出设备支持的最大分区;SCCI和虚拟设备固定默认最大为15,EMMC设备需要动态读取得到。 int maxMinors = getMaxMinors(); if (maxMinors < 0) { return -ENOTSUP; } //销毁所有卷 destroyAllVolumes(); //分析分区表 std::vector<std::string> cmd; cmd.push_back(kSgdiskPath); cmd.push_back("--android-dump"); cmd.push_back(mDevPath); std::vector<std::string> output; //sgdisk扫描 //这里就是调用/system/bin/sgdisk工具读取分区信息 status_t res = ForkExecvp(cmd, output); if (res != OK) { //通知FW扫描Disk auto listener = VolumeManager::Instance()->getListener(); if (listener) listener->onDiskScanned(getId()); //标记我们刚刚分区并应格式化所有卷 mJustPartitioned = false; return res; } Table table = Table::kUnknown; bool foundParts = false; for (const auto& line : output) { auto split = android::base::Split(line, kSgdiskToken); auto it = split.begin(); if (it == split.end()) continue; //比较分解后的字符串是否存在 “DISK” if (*it == "DISK") { if (++it == split.end()) continue; //继续分解 第一次分割 后的字串 if (*it == "mbr") { table = Table::kMbr; } else if (*it == "gpt") {//继续比较是否存在 “gpt” table = Table::kGpt; } else { continue; } } else if (*it == "PART") { //比较分解后的字符串是否存在 “ PART ” foundParts = true; if (++it == split.end()) continue; int i = 0; //将继续分解后的字串 转换为10进制的长整型 if (!android::base::ParseInt(*it, &i, 1, maxMinors)) { continue; } //创建分区设备 dev_t partDevice = makedev(major(mDevice), minor(mDevice) + i); if (table == Table::kMbr) { //继续分解output的字符串 得到类型 if (++it == split.end()) continue; int type = 0; //转换为16进制 if (!android::base::ParseInt("0x" + *it, &type)) { continue; } switch (type) { case 0x06: // FAT16 case 0x07: // HPFS/NTFS/exFAT case 0x0b: // W95 FAT32 (LBA) case 0x0c: // W95 FAT32 (LBA) case 0x0e: // W95 FAT16 (LBA) case 0x83: // Support Linux LBA add by Barton 2019.03.19 createPublicVolume(partDevice); break; } } else if (table == Table::kGpt) { if (++it == split.end()) continue; //继续分解 得到 typeGuid auto typeGuid = *it; if (++it == split.end()) continue; //继续分解 得到 partGuid auto partGuid = *it; //忽略大小写 比较字符串 if (android::base::EqualsIgnoreCase(typeGuid, kGptBasicData)) { ////根据分区设备 创建公用卷 createPublicVolume(partDevice); } else if (android::base::EqualsIgnoreCase(typeGuid, kGptAndroidExpand)) { //根据分区设备 分区ID 创建专用卷 createPrivateVolume(partDevice, partGuid); } } } } // Ugly last ditch effort, treat entire disk as partition if (table == Table::kUnknown || !foundParts) { std::string fsType; std::string unused; //读取元数据不受信任 if (ReadMetadataUntrusted(mDevPath, &fsType, &unused, &unused) == OK) { createPublicVolume(mDevice); } } //通知上层设备开始扫描 auto listener = VolumeManager::Instance()->getListener(); //所有创建完成后 通知FW Disk扫描完成 if (listener) listener->onDiskScanned(getId()); //清除 标记我们刚刚分区并应格式化所有卷 mJustPartitioned = false; return OK; }
上面有几个方法比较重要createPublicVolume()和createPrivateVolume()。
createPublicVolume()
void Disk::createPublicVolume(dev_t device, const int partSeq) { //根据设备好,新建一个公共分区(PublicVolume)对象 auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device, mEventPath, partSeq)); //判断是否标记,我们刚刚分区并格式化所有卷 if (mJustPartitioned) { //设置分区静音 vol->setSilent(true); vol->create(); //设置编码格式为自动 //如果已挂在,则卸载分区,然后在设置分区的fstype; vol->format("auto"); //清理分区内容 vol->destroy(); //取消分区静音 vol->setSilent(false); } //将新建分区对象放到Disk对象的管理队列里 //进行添加,后面会用到 mVolumes.push_back(vol); //设置分区的磁盘ID; mDiskId = diskId; vol->setDiskId(getId()); if (major(mDevice) == android::vold::Disk::kMajorBlockMmc) { if (minor(mDevice) == kMinorBlockEMMC) { vol->setStorageType(android::vold::VolumeBase::StorageType::kPhoneStorage); } else { vol->setStorageType(android::vold::VolumeBase::StorageType::kExternalSD); } } if (major(mDevice) == kMajorBlockLoop && minor(mDevice) == kMinorBlockFon) { vol->setStorageType(android::vold::VolumeBase::StorageType::kPhoneStorage); } //创建分区信息 //VolumeBase.create vol->create(); }
VolumeBase.cpp
status_t VolumeBase::create() { //检查是否重复创建 CHECK(!mCreated); //标记创建 mCreated = true; status_t res = doCreate(); //通知FW创建分区,并上传分区信息 auto listener = getListener(); //通知framework层 if (listener) listener->onVolumeCreated(getId(), static_cast<int32_t>(mType), mDiskId, mPartGuid); //设置kUnmounted setState(State::kUnmounted); return res; }
我们看listener->onVolumeCreated(),通过IBinder通信,进入StorageManagerService中的
private final IVoldListener mListener = new IVoldListener.Stub() { //略,都会走这里 }
StorageManagerService.java
onVolumeCreated()
@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); } }
onVolumeCreatedLocked()
@GuardedBy("mLock") private void onVolumeCreatedLocked(VolumeInfo vol) { if (mPms.isOnlyCoreApps()) { return; } //这里的type是0,也就是TYPE_PUBLIC if (vol.type == VolumeInfo.TYPE_EMULATED) { final StorageManager storage = mContext.getSystemService(StorageManager.class); final VolumeInfo privateVol = storage.findPrivateForEmulated(vol); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid) && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } } else if (vol.type == VolumeInfo.TYPE_PUBLIC) { if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) && vol.disk.isDefaultPrimary()) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; } if (vol.disk.isAdoptable()) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; } vol.mountUserId = mCurrentUserId; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else if (vol.type == VolumeInfo.TYPE_PRIVATE) { mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else { Slog.e(TAG, "Skipping automatic mounting of " + vol); } }
进入了TYPE_PUBLIC分支,最后会发送,H_VOLUME_MOUNT。
handleMessage()
case H_VOLUME_MOUNT: { final VolumeInfo vol = (VolumeInfo) msg.obj; if (isMountDisallowed(vol)) { break; } //根据之前的type=TYPE_PUBLIC,不满足下面if的条件,因此走else if ( (0 == (vol.mountFlags & VolumeInfo.MOUNT_FLAG_PRIMARY)) && (mATCPendigMountFeatureEnable && ( mATCPendigMountAfterFail || mATCPendigMount))) { if (mATCPendigMount) { try { mVold.pending_mount(vol.id, vol.mountFlags, vol.mountUserId); } catch (Exception e) { //Slog.wtf(TAG, e); } } else { try { mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); } catch (Exception e) { //Slog.wtf(TAG, e); } } break; } else { try { //条用mVold的mount()方法 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); } catch (Exception e) { //Slog.wtf(TAG, e); } break; } }
VoldNativeService.cpp
mount()
binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags, int32_t mountUserId) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_ID(volId); ACQUIRE_LOCK; //找到VolumeBase auto vol = VolumeManager::Instance()->findVolume(volId); if (vol == nullptr) { return error("Failed to find volume " + volId); } vol->setMountFlags(mountFlags); vol->setMountUserId(mountUserId); /* 调用VolumeBase的mount方法 */ int res = vol->mount(); if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) { VolumeManager::Instance()->setPrimary(vol); } return translate(res); }
这两个动作:
-
findVolume()找到需要挂载的磁盘
-
mount()进行磁盘挂载
需要注意,findVolume()返回的是PublicVolume对象,因此,调用的mount是PublicVolume->mount(),下面细细道来。
VolumeManager.cpp
findVolume()
std::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) { if (mInternalEmulated != nullptr && mInternalEmulated->getId() == id) { return mInternalEmulated; } for (const auto& disk : mDisks) { auto vol = disk->findVolume(id); if (vol != nullptr) { return vol; } } for (const auto& vol : mObbVolumes) { if (vol->getId() == id) { return vol; } } return nullptr; }
这里调用的是disk的findVolume()
Disk.cpp
findVolume()
std::shared_ptr<VolumeBase> Disk::findVolume(const std::string& id) { for (auto vol : mVolumes) { if (vol->getId() == id) { return vol; } auto stackedVol = vol->findVolume(id); if (stackedVol != nullptr) { return stackedVol; } } return nullptr; }
如果存在,返回的是mVolumes中的对象。
我们之前在createPublicVolume()中添加了PublicVolume的对象。
mVolumes.push_back(vol);
也就是返回的是PublicVolume对象。
因此,第一步的findVolume()结束了,我们看PublicVolume->mount()。
由于PublicVolume没有实现mount(),因此看起父类VolumeBase。
VolumeBase.cpp
mount()
status_t VolumeBase::mount() { if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) { return -EBUSY; } //设置状态kChecking setState(State::kChecking); /* 调用子类PublicVolume的doMount方法 */ /* 注意:该方法是一个虚函数,对于EmulatedVolume,PublicVolume和PrivateVolume有不同的实现 */ status_t res = doMount(); /* 设置挂载成功状态,挂载成功就向上通知onVolumeStateChanged */ if (res == OK) { setState(State::kMounted); } else { setState(State::kUnmountable); } return res; }
改变磁盘状态和doMount()。
doMount()是一个虚函数,加上我们上面调用的是PublicVolume->mount(),这里看PublicVolume->doMount()。
PublicVolume.cpp
doMount()
status_t PublicVolume::doMount() { #ifdef ATC_AOSP_ENHANCEMENT int ret = OK; char fsck_state[PROPERTY_VALUE_MAX] = {0}; bool need_fsck = true; nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);; nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME); dev_t before; std::string res; LOG(ERROR) << "PublicVolume::doMount()"; #endif readMetadata(); #ifdef ATC_AOSP_ENHANCEMENT // Use UUID as stable name, if available std::string stableName = getId(); if (!mFsMountPoint.empty()) { stableName = mFsMountPoint; } else if (!mFsUuid.empty()){ stableName = mFsUuid; } mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str()); LOG(ERROR) << "doMount() mRawPath "<< mRawPath; mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str()); mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str()); mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str()); LOG(ERROR) << "doMount() mFuseDefault "<< mFuseDefault; LOG(ERROR) << "doMount() mFuseRead "<< mFuseRead; LOG(ERROR) << "doMount() mFuseWrite "<< mFuseWrite; setInternalPath(mRawPath); if (getMountFlags() & MountFlags::kVisible) { setPath(StringPrintf("/storage/%s", stableName.c_str())); } else { setPath(mRawPath); } if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT)) { PLOG(ERROR) << getId() << " failed to create mount points"; ret = -errno; goto error_out; } LOG(ERROR) << "doMount() PublicVolume kChecking "; setState(State::kChecking); LOG(ERROR) <<"doMount() PublicVolume getId() : " << getId() << ", mFsType: " << mFsType; if (mFsType != "vfat" && mFsType != "exfat" && mFsType != "ntfs") { LOG(ERROR) << getId() << " unsupported filesystem " << mFsType; ret = -EIO; goto error_mount; } /*for external device fsck or not. false-not do fsck, true or null-do fsck. --atc0128 2017-09-22*/ property_get(kFsckProperty, fsck_state, ""); if (!strcmp(fsck_state, kNotFsck)) { LOG(VERBOSE) << "PublicVolume does not need to do fscking for external device"; need_fsck = false; } else { LOG(ERROR) << stableName<< " start to fsck " << mFsType; } res = StringPrintf("/storage/%s", stableName.c_str()) + " " + StringPrintf("/storage/%s", stableName.c_str()); LOG(ERROR) << "doMount() mFsType : "<< mFsType; if (mFsType == "vfat" && vfat::IsSupported()) { if (need_fsck && vfat::Check(mDevPath)) { LOG(ERROR) << "doMount() " <<getId() << " failed vfat filesystem check, stop mounting"; ret = -EIO; goto error_mount; } } else if (mFsType == "exfat" && exfat::IsSupported()) { if (need_fsck && exfat::Check(mDevPath)) { LOG(ERROR) << "doMount() "<< getId() << " failed exfat filesystem check, stop mounting"; ret = -EIO; goto error_mount; } } else if (mFsType == "ntfs" && ntfs::IsSupported()) { if (need_fsck && ntfs::Check(mDevPath)) { LOG(ERROR) << "doMount() "<< getId() << " failed ntfs filesystem check, stop mounting"; ret = -EIO; goto error_mount; } } #else if (mFsType == "vfat" && vfat::IsSupported()) { if (vfat::Check(mDevPath)) { LOG(ERROR) << "doMount() "<< getId() << " failed filesystem check"; return -EIO; } } else if (mFsType == "exfat" && exfat::IsSupported()) { if (exfat::Check(mDevPath)) { LOG(ERROR) << "doMount() "<< getId() << " failed filesystem check"; return -EIO; } } else { LOG(ERROR) << "doMount() "<< getId() << " unsupported filesystem " << mFsType; return -EIO; } // Use UUID as stable name, if available std::string stableName = getId(); if (!mFsUuid.empty()) { stableName = mFsUuid; } mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str()); mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str()); mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str()); mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str()); setInternalPath(mRawPath); if (getMountFlags() & MountFlags::kVisible) { setPath(StringPrintf("/storage/%s", stableName.c_str())); } else { setPath(mRawPath); } if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT)) { PLOG(ERROR) << "doMount() "<< getId() << " failed to create mount points"; return -errno; } #endif if (mFsType == "vfat") { if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, false)) { PLOG(ERROR) << getId() << " failed to mount " << mDevPath; #ifdef ATC_AOSP_ENHANCEMENT ret = -EIO; goto error_mount; #else return -EIO; #endif } } else if (mFsType == "exfat") { if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) { PLOG(ERROR) << getId() << " failed to mount " << mDevPath; #ifdef ATC_AOSP_ENHANCEMENT ret = -EIO; goto error_mount; #else return -EIO; #endif } #ifdef ATC_AOSP_ENHANCEMENT } else if (mFsType == "ntfs") { if (ntfs::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) { PLOG(ERROR) << getId() << " ntfs: failed to mount " << mDevPath; ret = -EIO; goto error_mount; } #endif } if (getMountFlags() & MountFlags::kPrimary) { initAsecStage(); } if (!(getMountFlags() & MountFlags::kVisible)) { // Not visible to apps, so no need to spin up FUSE return OK; } if (fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) || fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) || fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) { PLOG(ERROR) << getId() << " failed to create FUSE mount points"; #ifdef ATC_AOSP_ENHANCEMENT ret = -errno; goto error_premount_fuse; #else return -errno; #endif } #ifdef ATC_AOSP_ENHANCEMENT before = GetDevice(mFuseWrite); #else dev_t before = GetDevice(mFuseWrite); #endif if (!(mFusePid = fork())) { if (getMountFlags() & MountFlags::kPrimary) { if (execl(kFusePath, kFusePath, "-u", "1023", // AID_MEDIA_RW "-g", "1023", // AID_MEDIA_RW "-U", std::to_string(getMountUserId()).c_str(), "-w", mRawPath.c_str(), stableName.c_str(), NULL)) { PLOG(ERROR) << "Failed to exec"; } } else { if (execl(kFusePath, kFusePath, "-u", "1023", // AID_MEDIA_RW "-g", "1023", // AID_MEDIA_RW "-U", std::to_string(getMountUserId()).c_str(), "-w", mRawPath.c_str(), stableName.c_str(), NULL)) { PLOG(ERROR) << "Failed to exec"; } } LOG(ERROR) << "FUSE exiting"; _exit(1); } if (mFusePid == -1) { PLOG(ERROR) << getId() << " failed to fork"; #ifdef ATC_AOSP_ENHANCEMENT ret = -errno; goto error_premount_fuse; #else return -errno; #endif } #ifdef ATC_AOSP_ENHANCEMENT start = systemTime(SYSTEM_TIME_BOOTTIME); #else nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME); #endif while (before == GetDevice(mFuseWrite)) { LOG(VERBOSE) << "Waiting for FUSE to spin up..."; usleep(50000); // 50ms #ifdef ATC_AOSP_ENHANCEMENT now = systemTime(SYSTEM_TIME_BOOTTIME); #else nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME); #endif if (nanoseconds_to_milliseconds(now - start) > 5000) { LOG(WARNING) << "Timed out while waiting for FUSE to spin up"; #ifdef ATC_AOSP_ENHANCEMENT ret = -ETIMEDOUT; goto error_mount_fuse; #else return -ETIMEDOUT; #endif } } #ifdef ATC_AOSP_ENHANCEMENT TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0)); LOG(INFO) << "sdcard process(" << mFusePid << ") exited!!!"; #else /* sdcardfs will have exited already. FUSE will still be running */ if (TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)) == mFusePid) #endif mFusePid = 0; return OK; #ifdef ATC_AOSP_ENHANCEMENT error_mount_fuse: ForceUnmount(getPath()); ForceUnmount(kAsecPath); ForceUnmount(mFuseDefault); ForceUnmount(mFuseRead); ForceUnmount(mFuseWrite); error_premount_fuse: ForceUnmount(mRawPath); if (mFusePid > 0) { kill(mFusePid, SIGTERM); TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0)); mFusePid = 0; } rmdir(mFuseDefault.c_str()); rmdir(mFuseRead.c_str()); rmdir(mFuseWrite.c_str()); mFuseDefault.clear(); mFuseRead.clear(); mFuseWrite.clear(); error_mount: rmdir(mRawPath.c_str()); mRawPath.clear(); error_out: return ret; #endif }
其中execl是执行挂载命令。
本文很多都是参考网上,这里只是走走过程。
参考文章
-
《》
-
《》
-
《》