关于 vold 的详细分析可以参考这篇文章
此文主要是用来记录工作中添加 NTFS 格式支持时遇到的一些问题。文章是基于 intel 的 CherryTrail T4 平台的 Android 6.0 版本来分析的,其他平台上大致流程应该也差不多。

(由于Ntfs.cpp/Ntfs.h文件是从MTK平台porting过来的,这里就不贴出了)

  • Public Volume & Private Volume
从 6.0 开始,Google 将 Volume 分成了 Public Volume(TF卡,U盘等一系列Mbr分区的disk) 和 Private Volume(Gpt分区的扩展存储)
关于两种 Volume 的区分和创建相关代码逻辑在 vold 源码目录下的 Disk.cpp 中。
if (table == Table::kMbr) {
const char* type = strtok(nullptr, kSgdiskToken);
LOG(ERROR) << "readPartitions disk type is " << type;// add linqihan
switch (strtol(type, nullptr, 16)) {
case 0x06: // FAT16
case 0x07: // add by linqihan, for NTFS or ExFat
case 0x0b: // W95 FAT32 (LBA)
case 0x0c: // W95 FAT32 (LBA)
case 0x0e: // W95 FAT16 (LBA)
createPublicVolume(partDevice);
break;
}
} else if (table == Table::kGpt) {
const char* typeGuid = strtok(nullptr, kSgdiskToken);
const char* partGuid = strtok(nullptr, kSgdiskToken);
if (!strcasecmp(typeGuid, kGptBasicData)) {
createPublicVolume(partDevice);
} else if (!strcasecmp(typeGuid, kGptAndroidExpand)) {
createPrivateVolume(partDevice, partGuid);
}
}
通过添加相应的case,NTFS格式的U盘现在可以被识别并且创建出相应的 Public Volume。
U盘和 TF卡相应的 Block 块文件在设备中的 /dev/block/vold/ 目录下,当且仅当设备识别出该硬件并且创建出相应的 disk 和 volume 时,该路径下才会有相应的文件
以 U 盘为例:
root@tbook16power_m5f6:/dev/block/vold # ls -l
ls -l
brw------- root     root       8,   0 2016-12-01 17:14 disk:8,0
brw------- root     root       8,   1 2016-12-01 17:14 public:8,1
至此,volume 的创建结束。
  • 挂载 volume
在修改完 volume 的创建之后,下一步就到了挂载函数的修改。
由于我们需要修改的是 TF卡和 U盘的NTFS支持,因此需要修改的是 Public Volume,因此NTFS相关的支持最主要的修改就是集中在 PublicVolume.cpp 中。
需要修改的挂载函数为 PublicVolume::doMount(),此函数是继承于 BaseVolume 的 override 函数,PrivateVolume 中也有相应的 doMount()函数,但是我们暂时不需要对 PrivateVolume 作修改。
status_t PublicVolume::doMount() {
// TODO: expand to support mounting other filesystems
readMetadata();
if (mFsType != "vfat" && mFsType != "exfat" && mFsType != "ntfs") {// modify by linqihan,for NTFS & ExFat
LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
return -EIO;
}
// modify by linqihan
if (mFsType == "vfat") {
...//判断是否支持该格式
}
...//ntfs格式和exfat格式是否支持
// end linqihan
// Use UUID as stable name, if available
std::string stableName = getId();
if (!mFsUuid.empty()) {
stableName = mFsUuid;
}
...//获取设备节点相应的path
setInternalPath(mRawPath);
if (getMountFlags() & MountFlags::kVisible) {
setPath(StringPrintf("/storage/%s", stableName.c_str()));
} else {
setPath(mRawPath);
}
// modify by linqihan
...//创建相应的设备节点
// 挂载的关键代码
if (mFsType == "ntfs") {
if (ntfs::Mount(mDevPath, mRawPath, false, false, false,
AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
PLOG(ERROR) << getId() << " ntfs: failed to mount " << mDevPath;
return -EIO;
}
else
LOG(VERBOSE) << "ntfs: mount succeed " << mDevPath;
}
else if (mFsType == "exfat") {
if (exfat::Mount(mDevPath, mRawPath, false, false, false,
AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
PLOG(ERROR) << getId() << " exfat: failed to mount " << mDevPath;
return -EIO;
}
else
LOG(VERBOSE) << "exfat: mount succeed " << mDevPath;
}
else 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;
}
// modify end
}
if (getMountFlags() & MountFlags::kPrimary) {
initAsecStage();
}
// 如果没有kVisible的flag,不会执行下面的fuse相关操作,app无法获取U盘内容
if (!(getMountFlags() & MountFlags::kVisible)) {
// Not visible to apps, so no need to spin up FUSE
LOG(ERROR) << "kVisible is false";// add by linqihan
return OK;
}
...//fuse相关的init操作,将/mnt/media/xxx(volume挂载目录)和/storage/xxx(app访问路径)进行绑定
}
*注意上述代码中的红色标注部分,如果无此flag,挂载后app是无法访问到 U盘和 TF卡的内容的。
在修改完上述代码后,发现NTFS依旧无法挂载,查看aplog,发现如下报错:
11-30 16:54:06.586  2512  2567 I Vold    : ntfs::Mount(/dev/block/vold/public:8,1,/mnt/media_rw/88261D4B261D3C1E,nodev,nosuid,uid=1023,gid=1023,fmask=7,dmask=7noexec) = 5376 No such file or directory
手动执行 ntfs-3g 进行挂载依旧提示无此路径,后来发现是由于 volume 名称中的 "," 字符影响了 ntfs-3g 对于参数的判断,shell下手动将盘符修改为 8:1 后挂载成功。
  • 修改 volume 盘符
修改盘符的操作在创建 Public Volume 时修改:
PublicVolume::PublicVolume(dev_t device) :
VolumeBase(Type::kPublic), mDevice(device), mFusePid(0) {
setId(StringPrintf("%u:%u", major(device), minor(device)));// modify by linqihan
mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
}
  • 添加 kVisible flag
在执行完上述改动后,disk 和 volume 都创建成功,在设置中可以看到U盘,但是文件管理器无法读取到相应的内容,U盘内的文件也无法打开。
在网上搜索了一下,发现已经有人将 6.0 的U盘挂载流程分析整理了一遍:
http://blog.csdn.net/kc58236582/article/details/50577333
参照该 bolg 在 doMount() 函数中添加了 log 打印后发现 kVisible 为 false,所以没有执行 fuse 相关操作,app也因此无法获取 U盘内容。
通过 log 打印追踪到 flag 为 8,也就是 USB 设备的 flag,flag相关定义在 Disk.h 中。
enum Flags {
/* Flag that disk is adoptable */
kAdoptable = 1 << 0,
/* Flag that disk is considered primary when the user hasn't
* explicitly picked a primary storage location */
kDefaultPrimary = 1 << 1,
/* Flag that disk is SD card */
kSd = 1 << 2,
/* Flag that disk is USB disk */
kUsb = 1 << 3,
/* Flag that disk is EMMC internal */
kEmmc = 1 << 4,
};
由于 vold 执行 doMount() 函数时的 flag 是由 framework 层的 MountService 传递下来的,而 MountService 则是通过 disk 的flag进行判断的
// TODO: only look at first public partition
if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
&& vol.disk.isDefaultPrimary()) {
Slog.d(TAG, "kangchen UUID_PRIMARY_PHYSICAL");
Slog.v(TAG, "Found primary storage at " + vol);
vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
}
// Adoptable public disks are visible to apps, since they meet
// public API requirement of being in a stable location.
if (vol.disk.isAdoptable()) {//如果有kAdoptable这个flag
vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
}
追踪代码后找到相应的 flag 赋值点:
在 Disk 的 create() 函数中创建 disk 时会发送相应的 event,在 event 中传递 flag 时将 kAdoptable 的 flag 添加上去。
status_t Disk::create() {
CHECK(!mCreated);
mCreated = true;
notifyEvent(ResponseCode::DiskCreated, StringPrintf("%d", mFlags |= 0x01));// modify by linqihan
readMetadata();
readPartitions();
return OK;
}
  • 注意在 Android.mk 文件中添加 Ntfs.cpp
至此,NTFS支持基本添加完成,在关闭 selinux 后上层app可以成功获取到U盘内容。
selinux 相关改动这里就不贴出了,在将 selinux 设置成 permissive 的状态后可以一次性打印出所有被 reject 的权限,一次性添加上去即可。

Intel-T4-6.0 vold相关分析及添加NTFS支持相关推荐

  1. Intel发布30.0.100.9684显卡驱动:支持Win11

    微软 6 月底发布了 Win11 系统,现在各大厂商都在积极支持新系统了, Intel 今天发布了 30.0.100.9684 显卡驱动,主要升级内容就是增加对 Win11 的支持,同时还优化了两款游 ...

  2. springcloud 组件_SpringCloud组件mica 2.0.5发布,添加对sentinel、undertow指标收集

    一.mica(云母) mica 由如梦技术内部的 lutool(撸秃) 演变而来.lutool 诞生于 2017 年,受 jhipster 启发逐步形成一个微服务的核心集. 因 lutool 名称与功 ...

  3. vim8支持的linux版本,Vim 8.0 版本安装方法及添加Python支持

    利用Git安装 最简单也是最有效的方法 1. 获取Vim仓库: git clone https://github.com/vim/vim.git 2. 升级到最新的版本: cd vim git pul ...

  4. 解决VC++6.0打开文件或添加文件到工程出错的问题

    解决VC++6.0打开文件或添加文件到工程出错的问题 参考文章: (1)解决VC++6.0打开文件或添加文件到工程出错的问题 (2)https://www.cnblogs.com/peter-czha ...

  5. Android 4.0.4-在build.prop中添加属性

    Android 4.0.4-在build.prop中添加属性 2013-10-07 16:40:56|  分类: 默认分类|举报|字号 订阅 1.在*.rc文件中用setprop添加,例如在源码and ...

  6. mysql 给库赋权,MySQL 8.0.18给数据库添加用户和赋权问题

    MySQL 8.0.18给数据库添加用户和赋权问题 1. 首选使用root用户登录数据库 mysql -uroot -p 2. 使用mysql 数据库 USE mysql; 3. 为mysql创建用户 ...

  7. 【Intel RealSense SDK2.0下载】

    做点云的时候需要用到深度相机,目前常用的深度相机是Intel Real Sense.需要去github上下载Intel RealSense SDK2.0,但是经常会因为网速的原因,下载速度慢而且容易失 ...

  8. Java后台开发Tomcat添加https支持小程序开发过程

    文章原文:blog.ouyangsihai.cn >> Java后台开发Tomcat添加https支持小程序开发过程 1 给自己的域名申请证书 注意:申请好了如果不是在腾讯注册的域名,不会 ...

  9. vs2019功能介绍_MFC界面库BCGControlBar v30.0新功能详解:支持VS 2019

    亲爱的BCGSoft用户,我们非常高兴地宣布BCGControlBar Professional for MFC和BCGSuite for MFC v30.0正式发布!新版本添加了对Visual St ...

最新文章

  1. 文巾解题 9 回文数
  2. PHP使用swoole来实现实时异步任务队列
  3. Java黑皮书课后题第1章:1.2(显示五条消息)编写程序,显示以下表格
  4. how does gateway framework treat default system flag in customizing
  5. python schedule运行了一遍说没有任务_python-schedule模块(定时任务)基于官方文档总结...
  6. LeetCode371——Sum of Two Integers(不用+)
  7. IT公司刻板印象合集:程序员都秃头,商务个个是人精
  8. 为什么要用Hibernate框架? 把SessionFactory,Session,Transcational封装成包含crud的工具类并且处理了事务,那不是用不着spring了?...
  9. Python-非关键字参数和关键字参数(*args **kw)
  10. java.lang.OutOfMemoryError: Java heap space错误和方法(集、转)
  11. IDA远程调试Android中so文件
  12. 【emWin】例程二十二:窗口对象——Framewin
  13. 在PHP中开启CURL扩展,使其支持curl()函数
  14. ARM汇编程序设计之--数据搬移
  15. ESP32-cam 初体验 从esp32-cam的购买到局域网监控的实现
  16. Steam Sdk接入
  17. 迅雷插件会导致IE8假死
  18. IPCAM视频数据解码并处理
  19. 荣耀 MagicBook Pro 加装固态硬盘
  20. 【好工具】安利一款优秀的图片浏览器

热门文章

  1. 十年软件测试老司机,感悟!!送给刚入测试行业的萌新!!
  2. WEB数据库管理平台kb-dms:团队管理【四】
  3. 2017暑期实习招聘-产品经理-百度(1)-商业产品经理(群面)
  4. 不知道大二去找公司实习的话,人家要不要??
  5. 计算机量子极限,物理学家:计算机将在七八十年后穷途末路
  6. opencv学习笔记二十一:使用HSV颜色空间实现颜色识别
  7. 国产新冠口服药为什么是治艾滋病的药
  8. Tryhackme-SQL Injection Lab
  9. linux 内核 strftime,linux 下时间函数strftime()的用法
  10. 将海量数据从MySQL数据库导入到Hbase