专栏名称: Android技术之家
主要分享Android相关技术文章、移动互联网的相关产品和资讯。关注你将学习到更多基础以及框架相关的知识,为您的工作助力!
目录
相关文章推荐
51好读  ›  专栏  ›  Android技术之家

我又发现了Android13的一个bug

Android技术之家  · 公众号  ·  · 2024-05-19 18:36

正文

请到「今天看啥」查看全文


问题回顾

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

流程梳理

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

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

解决方案

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

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

并在提交里找到了该开发者提出的这个问题: 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去了吧。

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

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








请到「今天看啥」查看全文