我又发现了Android13的一个bug

问题回顾

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

流程梳理

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

8208bf7ce48fbb06f9ef9b98aa39c9b5.jpeg

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

这里贴一下访问UnixFileSystem获取磁盘大小的核心代码,对上层开发有参考作用,位于

libcore/ojluni/src/main/native/UnixFileSystem_md.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结构体,定义如下:

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的信息,发现了根本原因:

84b4cfb9f9eb8ac7db0cf3b7f011e22c.jpeg

格式化前后,SDCard的路径竟然变了,而SDCard的路径是由SDCard的fsUuid组成的,fsUuid就是磁盘在文件系统中的uuid。正常情况,无论是拔插还是格式化,这个fsUuid应该是不变的。这个变动就导致格式化完之后,Settings拿着旧的路径去文件系统查找磁盘信息,结果找不到。而退出页面重新进入,相当于重新获取了磁盘信息,此时再去文件系统查找就没问题了。

解决方案

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

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

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

显然这两种方案都略显粗暴,不够优雅,因为无论是上层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

77e7b85b280a3f46a243b26f906ca2a1.jpeg

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

1ac0f3180e8bda0c7978de29a25bba17.jpeg

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

6beff3ec19590cb5c9f1757d12dff234.jpeg

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

个人想法

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

作者:小迪vs同学
链接:https://juejin.cn/post/7356772896045645860

关注我获取更多知识或者投稿

7d5a4829d290d4a8fa7bbbf9de6f3651.jpeg

b2d29ee1a410372756dbd99cbb9131e4.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值