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设备挂载

相关推荐
木白CPP7 天前
SELinux 介绍和基本使用
嵌入式硬件·安卓·安全架构
物极必反102410 天前
QT使用FFMpeg编译安卓程序.md
qt·ffmpeg·安卓
程序员-珍10 天前
关于协程相关问题
android·安卓
MarkZhou62418 天前
智能蒸烤双核通信架构拆解:从冗余耦合到分层解耦
stm32·单片机·嵌入式硬件·架构·安卓·安全架构
北京自在科技21 天前
谷歌 Find Hub 迎来新版本更新
android·安卓
爱和冰阔落25 天前
【Linux】条件变量为什么必须配合互斥锁:从 pthread_cond_wait 到阻塞队列
linux·运维·c++·缓存·中间件·安卓
爱和冰阔落25 天前
【Linux】手写日志与固定线程池:任务队列、工作线程和安全退出
linux·运维·c++·redis·安卓
凛_Lin~~1 个月前
LiveData 源码解析
android·安卓·livedata
秋不溜啾1 个月前
三星手机网络连接ADB和关闭自动更新
adb·安卓