文章目录
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是执行挂载命令。
本文很多都是参考网上,这里只是走走过程。
参考文章
《》
《》
《》
