Android9~Android13 某些容量SD卡被格式化为内部存储时容量显示错误问题的研究与解决方案

声明:原创文章,禁止转载!

Android9~Android13 某些容量SD卡被格式化为内部存储时容量显示错误问题的研究与解决方案

分析Android11 系统对于EMMC/UFS作为内部存储、SD卡被格式化为内部存储、SD卡/U盘被格式化为便携式存储的不同处理


一.现象描述

实测Android9 Android10 Android11 Android12 Android13系统中某些容量的SD卡在被格式化为内部存储时,在设置中的显示容量与实际容量不符,比如某些16GB容量的SD卡在设置->存储中显示为32GB,但是如果选择“格式化为便携式存储设备”的话可以正常显示容量为16GB。

在Android11系统格式化为内部存储设备和便携式存储设备

同一个SD卡在Android7系统上作为内部存储和便携式存储空间时显示如下


二.源码分析

Android11系统

packages/apps/Settings/src/com/android/settings/deviceinfo/StorageSettings.java

    @Overridepublic void onCreate(Bundle icicle) {super.onCreate(icicle);final Context context = getActivity();mStorageManager = context.getSystemService(StorageManager.class);if (sTotalInternalStorage <= 0) {sTotalInternalStorage = mStorageManager.getPrimaryStorageSize();}addPreferencesFromResource(R.xml.device_info_storage);mInternalCategory = (PreferenceCategory) findPreference("storage_internal");mExternalCategory = (PreferenceCategory) findPreference("storage_external");mInternalSummary = new StorageSummaryPreference(getPrefContext());setHasOptionsMenu(true);}private synchronized void refresh() {final Context context = getPrefContext();getPreferenceScreen().removeAll();mInternalCategory.removeAll();mExternalCategory.removeAll();mInternalCategory.addPreference(mInternalSummary);final StorageManagerVolumeProvider smvp = new StorageManagerVolumeProvider(mStorageManager);final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(smvp);final long privateTotalBytes = info.totalBytes;final long privateUsedBytes = info.totalBytes - info.freeBytes;final List<VolumeInfo> volumes = mStorageManager.getVolumes();Collections.sort(volumes, VolumeInfo.getDescriptionComparator());for (VolumeInfo vol : volumes) {if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {if (vol.getState() == VolumeInfo.STATE_UNMOUNTABLE) {mInternalCategory.addPreference(new StorageVolumePreference(context, vol, 0));} else {final long volumeTotalBytes = PrivateStorageInfo.getTotalSize(vol,sTotalInternalStorage);mInternalCategory.addPreference(new StorageVolumePreference(context, vol, volumeTotalBytes));}} else if (vol.getType() == VolumeInfo.TYPE_PUBLIC|| vol.getType() == VolumeInfo.TYPE_STUB) {mExternalCategory.addPreference(new StorageVolumePreference(context, vol, 0));}}

packages/apps/Settings/src/com/android/settings/deviceinfo/StorageVolumePreference.java

    public StorageVolumePreference(Context context, VolumeInfo volume, long totalBytes) {super(context);mStorageManager = context.getSystemService(StorageManager.class);mVolume = volume;if (volume.isMountedReadable()) {// TODO: move statfs() to background threadfinal File path = volume.getPath();long freeBytes = 0;long usedBytes = 0;if (volume.getType() == VolumeInfo.TYPE_PRIVATE) {final StorageStatsManager stats =context.getSystemService(StorageStatsManager.class);try {//作为TYPE_PRIVATE,调用StorageStatsManager.getTotalBytes接口获取存储总容量大小totalBytes = stats.getTotalBytes(volume.getFsUuid());//作为TYPE_PRIVATE,调用StorageStatsManager.getFreeBytes接口获取存储可用容量大小freeBytes = stats.getFreeBytes(volume.getFsUuid());usedBytes = totalBytes - freeBytes;} catch (IOException e) {Log.w(TAG, e);}} else {// StorageStatsManager can only query private volumes.// Default to previous storage calculation for public volumes.if (totalBytes <= 0) {/*作为便携式存储,调用File.getTotalSpace接口获取存储总容量大小。注意此处并没有调用FileUtils.roundStorageSize接口进行向上整数对齐,那么为什么这个SD卡被格式化为便携式存储设备后在设置中显示的是"16GB"整数呢,下面会有详细解答*/totalBytes = path.getTotalSpace();}freeBytes = path.getFreeSpace();//作为便携式存储,调用File.getFreeSpace接口获取存储可用容量大小usedBytes = totalBytes - freeBytes;}final String used = Formatter.formatFileSize(context, usedBytes);final String total = Formatter.formatFileSize(context, totalBytes);setSummary(context.getString(R.string.storage_volume_summary, used, total));if (totalBytes > 0) {mUsedPercent = (int) ((usedBytes * 100) / totalBytes);}

frameworks/base/core/java/android/app/usage/StorageStatsManager.java

    private final IStorageStatsManager mService;public @BytesLong long getTotalBytes(@NonNull UUID storageUuid) throws IOException {try {return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName());} catch (ParcelableException e) {e.maybeRethrow(IOException.class);throw new RuntimeException(e);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}public @BytesLong long getFreeBytes(@NonNull UUID storageUuid) throws IOException {try {return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName());} catch (ParcelableException e) {e.maybeRethrow(IOException.class);throw new RuntimeException(e);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

frameworks/base/core/java/android/app/usage/IStorageStatsManager.aidl

interface IStorageStatsManager {boolean isQuotaSupported(String volumeU

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/670656.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Aigtek高精度电压源什么作用

高精度电压源是一种能够提供稳定、可靠且精确的电压输出的电子设备。它在科学研究、工程应用和制造业中起着至关重要的作用。以下将详细介绍高精度电压源的作用及其在不同领域的应用。 一、工作原理 稳定性&#xff1a;高精度电压源通常采用精密的电路设计和稳压技术&#xff0…

Java开发IntelliJ IDEA2023

IntelliJ IDEA 2023是一款强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为Java开发人员设计。它提供了许多特色功能&#xff0c;帮助开发人员更高效地编写、测试和调试Java应用程序。以下是一些IntelliJ IDEA 2023的特色功能&#xff1a; 智能代码编辑器&…

软件系统架构的演变历史介绍

个人浅见&#xff0c;不喜勿喷&#xff0c;非常感谢。 软件系统架构的演变历史与计算机技术的发展紧密相连。从最早的单一大型计算机&#xff0c;到个人计算机的兴起&#xff0c;再到互联网和云计算的普及&#xff0c;软件系统架构经历了多次重大的变革。以下是软件系统…

探索回溯算法

前言 回溯算法称之通用解算法&#xff0c;任何问题都可以优先使用回溯算法思考&#xff0c;再进行优化改进。那要问上一句回溯算法是怎样思维方式&#xff1f; 一&#xff0c;回溯算法思想 回溯算法是一个类似枚举的搜索尝试过程&#xff0c;主要是在搜索尝试过程中寻找问题…

Jgit Packfile is truncated解决方案

配置方式解决 这两个配置选项是用于提高 SSH 连接稳定性的 SSH 客户端配置参数&#xff0c;它们被添加到 SSH 配置文件&#xff08;通常是 ~/.ssh/config&#xff09;中。这些参数有助于在网络不稳定或者长时间无数据交换时保持 SSH 连接不被断开。下面是每个参数的具体作用&am…

【并行编程框架】AsyncTool

文章目录 AsyncToolAsyncTool是什么&#xff1f;AsyncTool快速入门1&#xff09;导入依赖2&#xff09;自定义Worker3&#xff09;编排包装类Wrapper4&#xff09;提交任务执行5&#xff09;运行结果 并发编程常见的场景串行并行阻塞等待 - 先串行&#xff0c;后并行阻塞等待 -…

电力负荷预测 | 基于TCN的电力负荷预测(Python)———数据预处理

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 基于TCN的电力负荷预测(Python) python3.8 keras2.6.0 matplotlib3.5.2 numpy1.19.4 pandas1.4.3 tensorflow==2.6.0

浏览器提示ERR_SSL_KEY_USAGE_INCOMPATIBLE解决

ERR_SSL_KEY_USAGE_INCOMPATIBLE报错原因 ERR_SSL_KEY_USAGE_INCOMPATIBLE 错误通常发生在使用 SSL/TLS 连接时,指的是客户端和服务器之间进行安全通信尝试失败,原因是证书中的密钥用途(Key Usage)或扩展密钥用途(Extended Key Usage, EKU)与正在尝试的操作不兼容。这意味…

Unity笔记:相机移动

基础知识 鼠标输入 在Unity中&#xff0c;开发者在“Edit” > “Project Settings” > “Input Manager”中设置输入&#xff0c;如下图所示&#xff1a; 在设置了Mouse X后&#xff0c;Input.GetAxis("Mouse X")返回的是鼠标在X轴上的增量值。这意味着它会…

STM32TIM定时器(3)

文章目录 前言一、介绍部分输入捕获简介频率测量捕获比较通道主从模式输入捕获基本结构PWMI基本结构 二、代码部分使用输入捕获捕获另一个端口的PWM输入线路连接代码内容 PWMI获取频率占空比线路连接与上个案例一致代码实现 总结相关函数PSC、ARR都有1的误差 前言 这部分主要介…

Spring Boot整合新版Spring Security:Lambda表达式配置优雅安全

文章目录 1. 引言2. 项目依赖配置3. 使用Lambda表达式配置Spring Security4. 自定义身份验证逻辑5. 认证与授权注解5.1 Secured注解5.2 PreAuthorize和PostAuthorize注解 6. 总结 &#x1f389;Spring Boot整合新版Spring Security&#xff1a;Lambda表达式配置优雅安全 ☆* o(…

spring cloud stream

背景 主要解决不同消息中间件切换问题。实现不同中间件的代码解耦。 链接: 支持的中间件 后文使用kafka测试。 引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-stream</artifactId></depende…

[EFI]英特尔 猛兽峡谷NUC11BTM电脑 Hackintosh 黑苹果efi引导文件

硬件型号驱动情况主板 猛兽峡谷NUC11BTM 处理器 Intel Core™ i9-11900KB 处理器 已驱动内存英睿达 DDR4 16G 3200MHz*2已驱动硬盘铠侠RC20 1T已驱动显卡AMD Radeon RX 6600 XT已驱动声卡USB音频已驱动网卡以太网控制器 i225-LM已驱动无线网卡蓝牙奋威t919Sonoma以上版本自行安…

Spring Web Body 转化常见错误

在 Spring 中&#xff0c;对于 Body 的处理很多是借助第三方编解码器来完成的。例如常见的 JSON 解析&#xff0c;Spring 都是借助于 Jackson、Gson 等常见工具来完成。所以在 Body 处理中&#xff0c;我们遇到的很多错误都是第三方工具使用中的一些问题。 真正对于 Spring 而…

【C#学习路线——超详细介绍】

C#学习路线——超详细介绍 1. 介绍2. C#基础3. 进阶技术4. .NET框架核心5. 前端和桌面应用开发6. Web 后端开发7. 游戏开发8. 软件开发实践9. 性能调优和最佳实践10. 实战经验11. 持续学习 1. 介绍 C#是由微软开发的一种强类型、面向对象的编程语言&#xff0c;主要用于.NET框…

2024年 复习 HTML5+CSS3+移动web 笔记 之CSS遍 第5天

第 五 天 整个网站例 5.1 准备工作 项目目录与版心 base.css 5.2 网页制作思路 5.3 header 区域-整体布局 5.4 header区域-logo 5.5 header区域-导航 index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…

掌握数据预测的艺术:线性回归模型详解

线性回归是统计学中用于建模两个或多个变量之间线性关系的一种方法,广泛应用于数据分析、机器学习等领域。从数学建模的角度出发,线性回归旨在找到一个线性方程,最好地描述自变量(或称为解释变量、特征变量)和因变量(或称为目标变量)之间的关系。本文将通过Python代码示…

网桥与网关

文章目录 概要网桥网关联系与区别参考文章 概要 网桥和网关的理解 网桥 几个名词的概念 网关 联系与区别 参考文章 如何通俗地解释什么是网桥&#xff1f; 网关到底是什么求通俗易懂讲解? 网桥&#xff1a;网桥也叫桥接器&#xff0c;是连接两个局域网的一种存储/转发…

C语言第十九弹---指针(三)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1、数组名的理解 2、使用指针访问数组 3、⼀维数组传参的本质 4、冒泡排序 5、二级指针 6、指针数组 7、指针数组模拟二维数组 总结 1、数组名的理解…

测试开发体系

软件测试 通过手工或者工具对 “被测对象”进行测试验证实际结果与预期结果之间是否存在差异 软件测试作用 通过测试工作可以发现并修复软件当中存在的缺陷&#xff0c;从而提高用户对产品的使用信心测试可以降低同类型产品开发遇到问题的风险 软件缺陷 软件缺陷被测试工程…