问题回顾
之前处理了一个SDCard格式化的问题,最后定位到是底层的原因,让底层同事排查去了,底层同事排查完,没发现什么问题,最近这个问题又转到我的手里了,于是我又深入看了一下
流程梳理
之前已经梳理过了SDCard格式化的代码流程,这里只贴一个简单的流程图
在Settings -> Storage页面点击SDCard格式化,最终请求vold完成格式化。格式化完毕后,再直接访问UnixFileSystem去获取磁盘大小,得到的结果为0。
这里贴一下访问UnixFileSystem获取磁盘大小的核心代码,对上层开发有参考作用,位于
libcore/ojluni/src/main/native/UnixFileSystem_md.c:
#define statvfs64 statvfs
JNIEXPORT jlong JNICALL
Java_java_io_UnixFileSystem_getSpace0(JNIEnv *env, jobject this,
jobject file, jint t)
{
jlong rv = 0L;
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
struct statvfs64 fsstat;
memset(&fsstat, 0, sizeof(fsstat));
if (statvfs64(path, &fsstat) == 0) {
switch(t) {
case java_io_FileSystem_SPACE_TOTAL:
rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
long_to_jlong(fsstat.f_blocks));
break;
case java_io_FileSystem_SPACE_FREE:
rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
long_to_jlong(fsstat.f_bfree));
break;
case java_io_FileSystem_SPACE_USABLE:
rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
long_to_jlong(fsstat.f_bavail));
break;
default:
assert(0);
}
}
} END_PLATFORM_STRING(env, path);
return rv;
}
主要是通过
statvfs
结构体,定义如下:
struct statvfs {
unsigned long f_bsize;
unsigned long f_frsize;
fsblkcnt_t f_blocks;
fsblkcnt_t f_bfree;
fsblkcnt_t f_bavail;
fsfilcnt_t f_files;
fsfilcnt_t f_ffree;
fsfilcnt_t f_favail;
unsigned long f_fsid;
unsigned long f_flag;
unsigned long f_namemax;
};
在使用
statvfs
函数获取文件系统信息时,可以通过访问
statvfs
结构体的成员来获取所需的信息。应用开发者在做文件系统相关需求时,可以考虑使用此API。
深入分析
因为问题复现后,重新切换一下SDCard或者退出重新进入StorageDashboardFragment可以恢复正常,于是,我在进入StorageDashboardFragment、切换SDCard、格式化完毕这三处代码埋下了log,打印当前SDCard的信息,发现了根本原因:
格式化前后,SDCard的路径竟然变了,而SDCard的路径是由SDCard的fsUuid组成的,fsUuid就是磁盘在文件系统中的uuid。正常情况,无论是拔插还是格式化,这个fsUuid应该是不变的。这个变动就导致格式化完之后,Settings拿着旧的路径去文件系统查找磁盘信息,结果找不到。而退出页面重新进入,相当于重新获取了磁盘信息,此时再去文件系统查找就没问题了。
解决方案
好了,上层问题根源定位到了,怎么解决这个问题呢?
显然这两种方案都略显粗暴,不够优雅,因为无论是上层Settings代码,还是底层vold代码,都是Google原生的代码,那么这个问题就很有可能是Android自身的bug。
惊天大坑
带着这个怀疑,我去查阅了AOSP的提交记录,果真被我找到了与此相关的一笔提交:
https://android-review.googlesource.com/c/platform/external/gptfdisk/+/391092%EF%BC%8C%E5%9B%A0%E4%B8%BA%E9%9C%80%E8%A6%81%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91%EF%BC%8C%E8%BF%99%E9%87%8C%E8%B4%B4%E4%B8%80%E4%B8%8B%E7%BD%91%E9%A1%B5%E6%88%AA%E5%9B%BE
并在提交里找到了该开发者提出的这个问题:
https://issuetracker.google.com/issues/37137232
这简直就是一模一样的问题啊,只是这个问题现象是不能显示SDCard的内容,他是在Android7.0上出现的,我是Android13。并且这个哥们儿2017-03-02反馈的这个bug,2017-05-09提交了修改,但Google至今一直没有合入这笔修改,且表示不会修复这个问题
这也就意味着从Android7.0开始,以后每个版本都会有这个问题,坑爹呢这不是。
个人想法
这个bug从一月份,一直解到现在,持续了将近3个月,最终居然是Android的bug,不免让人有些欲哭无泪。不过冷静下来思考,这个问题确实影响也不大,开发者自己也能修复,Android bug那么多,Google那帮大佬们应该都忙着修复紧急bug去了吧。
关注我获取更多知识或者投稿