我又发现了Android13的一个bug

问题回顾

之前处理了一个SDCard格式化的问题,最后定位到是底层的原因,让底层同事排查去了,底层同事排查完,没发现什么问题,最近这个问题又转到我的手里了,于是我又深入看了一下

流程梳理

之前已经梳理过了SDCard格式化的代码流程,这里只贴一个简单的流程图

在Settings -> Storage页面点击SDCard格式化,最终请求vold完成格式化。格式化完毕后,再直接访问UnixFileSystem去获取磁盘大小,得到的结果为0。

这里贴一下访问UnixFileSystem获取磁盘大小的核心代码,对上层开发有参考作用,位于libcore/ojluni/src/main/native/UnixFileSystem_md.c

c 复制代码
#define statvfs64 statvfs

// Android-changed: Name changed because of added thread policy check
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结构体,定义如下:

c 复制代码
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拿着旧的路径去文件系统查找磁盘信息,结果找不到。而退出页面重新进入,相当于重新获取了磁盘信息,此时再去文件系统查找就没问题了。

解决方案

好了,上层问题根源定位到了,怎么解决这个问题呢?

  • 对于上层来说,很简单,在格式化完毕的代码处重新获取一下磁盘信息不就好了,或者干脆直接初始化StorageDashboardFragment。

  • 对于底层来说,似乎要去更改vold格式化的逻辑,使其fsUuid不随机分配。

显然这两种方案都略显粗暴,不够优雅,因为无论是上层Settings代码,还是底层vold代码,都是Google原生的代码,那么这个问题就很有可能是Android自身的bug。

惊天大坑

带着这个怀疑,我去查阅了AOSP的提交记录,果真被我找到了与此相关的一笔提交:android-review.googlesource.com/c/platform/...

并在提交里找到了该开发者提出的这个问题:issuetracker.google.com/issues/3713...

这简直就是一模一样的问题啊,只是这个问题现象是不能显示SDCard的内容,他是在Android7.0上出现的,我是Android13。并且这个哥们儿2017-03-02反馈的这个bug,2017-05-09提交了修改,但Google至今一直没有合入这笔修改,且表示不会修复这个问题

这也就意味着从Android7.0开始,以后每个版本都会有这个问题,坑爹呢这不是。

个人想法

这个bug从一月份,一直解到现在,持续了将近3个月,最终居然是Android的bug,不免让人有些欲哭无泪。不过冷静下来思考,这个问题确实影响也不大,开发者自己也能修复,Android bug那么多,Google那帮大佬们应该都忙着修复紧急bug去了吧。

相关推荐
幻雨様5 小时前
UE5多人MOBA+GAS 45、制作冲刺技能
android·ue5
Jerry说前后端7 小时前
Android 数据可视化开发:从技术选型到性能优化
android·信息可视化·性能优化
Meteors.8 小时前
Android约束布局(ConstraintLayout)常用属性
android
alexhilton8 小时前
玩转Shader之学会如何变形画布
android·kotlin·android jetpack
whysqwhw13 小时前
安卓图片性能优化技巧
android
风往哪边走13 小时前
自定义底部筛选弹框
android
Yyyy48214 小时前
MyCAT基础概念
android
Android轮子哥14 小时前
尝试解决 Android 适配最后一公里
android
雨白15 小时前
OkHttp 源码解析:enqueue 非同步流程与 Dispatcher 调度
android
风往哪边走16 小时前
自定义仿日历组件弹框
android