Vold Bugs(二)---U盘不识别(onVolumeChecking 返回错误码 -5)

背景

查看日志发现 U盘不识别的原因是在 doMount 时报错,错误码为 -5

根据错误码(-EIO)和日志定位到发生错误的位置,发现是在mount fuse的时候报的错误。到这步说明设备能被系统正确的识别到,也已经挂载了,只是 onVolumeChecking 这步发生了错误,随后就把设备卸载了

/android/system/vold/model/PublicVolume.cpp#343

Callback 的实际值是返回的 mMountCallback 这个类成员变量,这个变量并不是由Vold决定的,而是上层StorageManagerService通过setMountCallback 设置的

android/system/vold/VoldNativeService.cpp#280

而且 onVolumeChecking 这个函数也是个虚函数,因此我们需要知道 StorageManagerService 到底重写成了什么样的形式

从C++层的接口映射到 Framework 层的 java 方法的实现如下

上层重写这个函数后所做的主要工作是将卷的两个存储路径进行保存,以及执行mStorageSessionController.onVolumeMount(pfd, vol),重写之后对应的参数:

C++ JAVA 含义
unique_fd fuseFd FileDescriptor fd 文件描述符
std::string path String path 卷的存储路径
std::string internalPath String internalPath 卷的存储路径(内部)
bool* _aidl_return boolean (直接返回值) 返回 bool 指针

因为底层的vold是通过判断_aidl_return这个指针指向的值来判定上层check是否成功,所以我们只需要关注StorageManagerService 的mount函数是否存在异常即可,如果异常就会输出相应log后return false,再看 onVolumeMount 函数具体的实现

android/server/storage/StorageSessionController.java#109

根据log可以看出 connection.startSession(*) 之前的程序都是顺利执行的,理论上来说是走到正确的分支,然后return true,但实际上并没有,底层 vold 的判定仍然是 false ,才会返回-EIO的错误。但是 mount 函数有try...catch 处理,如果有异常情况是会打印对应log的,这个地方非常的费解!!!

方案

采用 onVolumeStateChanged 的方式进行监听,对应vold也可以弃用fuse 的挂载方式,将移动设备作为 portable 设备进行挂载,这样就不会引起上述问题。此外,弃用fuse,一方面可以去掉fuse引起的一些操作,如切换账号时对外部设备的remount,另一方面可以避免Framework卡死的概率性事件

从 fuse 挂载变成 portable 设备挂载具体内容参考:U盘fuse挂载变为portable设备挂载

相关推荐
北京自在科技1 天前
谷歌安卓 Gemini 迎来界面改版,Find Hub 接入 Gemini 支持物品记忆查找
android·安卓
limit00753 天前
三维 WebGIS 工具选型:加载、样式、分析、交付,一套界面能做完什么
android·前端·web3·安卓·webgl
limit00755 天前
三维模型悬空与切片偏移的排查顺序
低代码·3d·arcgis·web3·安卓·webgl
/**书香门第*/11 天前
Cocos Creator 3.8 配置如何直接运行白包到模拟器
安卓·cocos creator·白包
iReachers19 天前
Termux:把安卓手机变成随身的命令行工具箱
python·安卓·termux·命令行·实用工具
木白CPP1 个月前
SELinux 介绍和基本使用
嵌入式硬件·安卓·安全架构
物极必反10241 个月前
QT使用FFMpeg编译安卓程序.md
qt·ffmpeg·安卓
程序员-珍1 个月前
关于协程相关问题
android·安卓
MarkZhou6241 个月前
智能蒸烤双核通信架构拆解:从冗余耦合到分层解耦
stm32·单片机·嵌入式硬件·架构·安卓·安全架构