【Android FrameWork】第三十九天:DeviceStorageManagerService

DeviceStorageManagerService

在 Android 系统中,存储管理是保障设备稳定运行、用户数据安全及存储资源高效利用的核心模块,而DeviceStorageManagerService(简称 DSMS)作为系统级存储管理的核心服务,承担着存储状态监控、空间阈值管理、存储清理策略执行等关键职责。

本文将从 Framework 层的 Java 源码、Native 层的 C++ 实现入手,深度剖析其核心机制,并探讨 Android 最新系统版本中该服务的演进与变化。

概述

DeviceStorageManagerService 是 Android 系统服务的重要一员,隶属于android.os.storage包,运行在 SystemServer 进程的core_service线程池中。其核心定位是统一管理设备的内部存储(Internal Storage)和外部存储(External Storage)状态,主要职责包括:

  1. 实时监控存储分区的可用空间,触发低存储告警(如"存储空间不足"通知);
  2. 管理存储阈值(如低空间阈值、关键空间阈值),并在阈值触发时执行相应策略;
  3. 提供存储统计、清理建议及应用缓存管理的系统接口;
  4. 协调与StorageManagerServicePackageManagerService等其他系统服务的交互,保障存储相关操作的一致性。

从架构上看,DSMS 采用Java 层封装逻辑 + Native 层底层实现的分层设计:Framework 层的 Java 代码负责服务注册、系统接口暴露和上层逻辑调度;Native 层的 C++ 代码则负责与内核交互、存储分区的实际统计和阈值检测,保证性能和底层兼容性。

Framework 层(Java)源码解析

1 服务的启动与注册

Android 系统服务的启动统一由SystemServer进程管理,DeviceStorageManagerService的启动流程在SystemServerstartOtherServices()方法中完成,核心代码路径为:frameworks/base/services/core/java/com/android/server/SystemServer.java

java 复制代码
// SystemServer.java 中启动 DSMS 的核心代码片段
private void startOtherServices() {
    // ... 其他服务启动代码 ...
    DeviceStorageManagerService deviceStorageManager = null;
    try {
        // 创建 DSMS 实例,依赖 Context 和 StorageManagerService
        deviceStorageManager = new DeviceStorageManagerService(mSystemContext, mStorageManagerService);
        // 注册到 ServiceManager,使上层应用可通过 Context 获取服务
        ServiceManager.addService(Context.DEVICE_STORAGE_SERVICE, deviceStorageManager);
    } catch (Throwable e) {
        reportWtf("starting DeviceStorageManagerService", e);
    }
    // ... 其他初始化操作 ...
}

DeviceStorageManagerService的构造函数会完成初始化工作:初始化存储阈值参数、注册存储状态监听器、启动后台监控线程等。其构造函数核心代码路径为:frameworks/base/services/core/java/com/android/server/DeviceStorageManagerService.java

java 复制代码
public DeviceStorageManagerService(Context context, StorageManagerService sms) {
    mContext = context;
    mStorageManagerService = sms;
    mHandler = new Handler(BackgroundThread.get().getLooper(), null);
    
    // 初始化存储阈值:从系统资源或配置文件中读取低空间阈值(如 100MB)
    mLowStorageThreshold = context.getResources().getInteger(
            com.android.internal.R.integer.config_lowStorageThreshold);
    mCriticalStorageThreshold = context.getResources().getInteger(
            com.android.internal.R.integer.config_criticalStorageThreshold);
    
    // 注册存储分区监听器,监听内部存储的空间变化
    mStorageListener = new StorageListener();
    mStorageManagerService.registerListener(mStorageListener);
    
    // 启动后台监控任务,定期检查存储状态
    scheduleStorageMonitor();
}

2 核心功能的实现逻辑

(1)存储状态监控

DSMS 通过定时任务 + 事件监听两种方式监控存储状态:

  • 定时任务 :通过scheduleStorageMonitor()方法启动周期性任务(默认间隔 1 分钟),调用updateStorageState()方法检测可用空间;
  • 事件监听 :通过StorageListener监听存储分区的挂载、卸载、容量变化等事件,实时触发状态更新。

updateStorageState()是核心方法,其逻辑为:

  1. 调用 Native 层接口获取内部存储的总容量和可用容量;
  2. 对比可用容量与预设阈值(低空间、关键空间),判断存储状态;
  3. 若状态发生变化(如从正常变为低空间),则触发告警、通知或清理策略。
(2)阈值管理与告警触发

当可用容量低于mLowStorageThreshold时,DSMS 会执行以下操作:

  • 发送广播Intent.ACTION_DEVICE_STORAGE_LOW,通知应用和系统组件;
  • 在系统状态栏显示"存储空间不足"通知;
  • 调用StorageManager的接口获取可清理的缓存数据列表,为用户提供清理建议。

当可用容量低于mCriticalStorageThreshold时,系统会执行更严格的策略,如限制应用安装、禁止日志写入等,以保障系统核心功能的运行。

(3)上层接口暴露

DSMS 通过IDeviceStorageManageraidl 接口向上层提供服务,主要接口包括:

  • getStorageState():获取存储状态;
  • getFreeSpace():获取可用空间;
  • clearApplicationCache():清理应用缓存;
  • getLowStorageThreshold():获取低空间阈值。

应用可通过Context.getSystemService(Context.DEVICE_STORAGE_SERVICE)获取DeviceStorageManager实例,调用上述接口。

Native 层(C++)源码解析

DSMS 的 Native 层实现主要依赖Android 系统的存储框架Linux 内核的文件系统接口 ,核心代码路径为:frameworks/base/services/core/jni/com_android_server_DeviceStorageManagerService.cpp

1 JNI 接口的封装

Native 层通过 JNI(Java Native Interface)为 Framework 层提供底层接口,核心 JNI 方法包括:

  • native_getVolumeStats():获取存储分区的统计信息(总容量、可用容量、已用容量);
  • native_getLowStorageThreshold():获取原生的低空间阈值(从内核或文件系统中读取);
  • native_clearCache():清理缓存数据。

native_getVolumeStats()为例,其实现逻辑为:

cpp 复制代码
// com_android_server_DeviceStorageManagerService.cpp
static jobject native_getVolumeStats(JNIEnv* env, jclass clazz, jstring path) {
    const char* pathStr = env->GetStringUTFChars(path, NULL);
    struct statfs stats;
    // 调用 Linux 系统调用 statfs() 获取文件系统信息
    if (statfs(pathStr, &stats) != 0) {
        env->ReleaseStringUTFChars(path, pathStr);
        return NULL;
    }
    env->ReleaseStringUTFChars(path, pathStr);
    
    // 计算总容量和可用容量(单位:字节)
    uint64_t total = (uint64_t)stats.f_blocks * stats.f_bsize;
    uint64_t free = (uint64_t)stats.f_bfree * stats.f_bsize;
    uint64_t avail = (uint64_t)stats.f_bavail * stats.f_bsize;
    
    // 创建 Java 对象返回统计结果
    jclass statsClass = env->FindClass("com/android/server/DeviceStorageManagerService$VolumeStats");
    jmethodID constructor = env->GetMethodID(statsClass, "<init>", "(JJJ)V");
    return env->NewObject(statsClass, constructor, total, free, avail);
}

该方法的核心是调用 Linux 的statfs()系统调用,获取文件系统的块大小、总块数、空闲块数等信息,进而计算出总容量和可用容量。

2 与存储子系统的交互

Native 层不仅直接调用 Linux 系统调用,还与 Android 系统的存储管理子系统(Storage Manager) 交互:

  • 通过libstorage库获取存储分区的挂载信息;
  • 调用vold(Volume Daemon)的接口获取外部存储的状态;
  • 利用libutilslibcutils库进行数据格式化和错误处理。

此外,对于采用 F2FS、EXT4 等不同文件系统的存储分区,Native 层会根据文件系统的特性调整统计逻辑,保证容量计算的准确性。

3 缓存清理的底层实现

native_clearCache()方法的实现逻辑为:

  1. 遍历/data/data/data/cache等目录,获取应用的缓存文件列表;
  2. 调用unlink()系统调用删除缓存文件;
  3. 统计清理的字节数,返回给 Framework 层。

为了保证安全性,该方法会跳过系统应用的核心缓存文件,仅清理第三方应用的非关键缓存。

最新 Android 系统中的变化

随着 Android 版本的迭代(如 Android 12/13/14/15),DeviceStorageManagerService在架构、功能和实现上均发生了若干重要变化,主要集中在存储分层管理、隐私安全、性能优化三个方面。

1 架构层面:与 StorageManagerService 的融合

在早期 Android 版本中,DSMS 与StorageManagerService(SMS)是相对独立的服务,前者负责存储状态监控,后者负责存储分区管理。从 Android 10 开始,Google 逐步将两者的功能融合,DSMS 成为 SMS 的子模块,统一由存储框架(Storage Framework)管理。

变化点:

  • 服务启动不再由SystemServer直接创建,而是由 SMS 通过依赖注入的方式初始化;
  • 存储状态的监控数据不再由 DSMS 单独维护,而是与 SMS 的存储分区信息共享,减少数据冗余。

2 功能层面:针对折叠屏、多存储设备的适配

(1)多存储分区的支持

随着设备存储形态的多样化(如内置存储 + 可扩展 SD 卡 + 外部 U 盘),最新系统中 DSMS 支持对多个存储分区的独立监控,可分别设置不同的阈值策略。

(2)折叠屏设备的存储优化

针对折叠屏设备的存储特性(如分屏应用的缓存隔离),DSMS 优化了缓存清理策略,可根据应用的运行状态(前台/后台)选择性清理缓存,避免影响用户体验。

3 实现层面:性能与安全的优化

(1)Native 层的性能提升
  • 替换了传统的statfs()调用,采用更高效的statvfs64()系统调用,支持大存储容量(超过 4GB)的准确统计;
  • 引入缓存机制,减少频繁的文件系统查询,降低 CPU 占用率。
(2)隐私安全的增强

从 Android 11 开始,受限于应用沙箱和存储访问框架(Scoped Storage),DSMS 清理应用缓存时需遵循以下规则:

  • 仅能清理应用自身的缓存目录(/data/data/<package>/cache),无法访问其他应用的私有数据;
  • 清理外部存储的缓存时,需通过 MediaStore API 进行,符合 Scoped Storage 的隐私规范。
(3)阈值策略的动态调整

早期系统的存储阈值是固定的(通过资源文件配置),而最新系统中,DSMS 支持动态阈值调整

  • 根据设备的总存储容量自动计算阈值(如总容量 128GB 的设备,低空间阈值为 2GB;总容量 64GB 的设备,阈值为 1GB);
  • 允许用户通过系统设置手动调整存储告警的阈值,增强个性化。

4 API 层面:新增与废弃

(1)新增 API
  • getStorageStatsForPackage():获取指定应用的存储使用详情(缓存、数据、APK 大小);
  • requestClearAppCache():通过权限申请的方式清理应用缓存,符合 Android 13+ 的权限模型。
(2)废弃 API
  • 废弃了clearApplicationCache()的无参版本,改为需要指定应用包名的版本,增强权限控制;
  • 废弃了Intent.ACTION_DEVICE_STORAGE_LOW广播的静态注册,仅允许动态注册,减少不必要的广播开销。

5 Android 15 的最新变化

在 Android 15(Vanadium)中,DSMS 进一步强化了存储健康管理功能:

  • 新增存储健康状态检测,可监控存储设备的坏块、读写速度衰减等硬件问题;
  • 引入"存储压缩"功能,通过压缩不常用的应用数据释放空间,由 DSMS 协调执行;
  • 优化了低内存设备的存储策略,优先保障系统核心服务的内存和存储资源。

总结

DeviceStorageManagerService作为 Android 存储管理的核心服务,其设计体现了 Android 系统分层架构的特点:Framework 层负责上层逻辑和接口暴露,Native 层负责底层交互和性能保障。

从源码层面看,其核心是通过与 Linux 内核的文件系统交互获取存储状态,通过阈值管理实现存储的智能化监控和治理。

在最新的 Android 系统中,DSMS 随着存储技术的发展和用户需求的变化,不断向统一化、智能化、安全化 方向演进:与 StorageManagerService 的融合提升了系统的一致性,多存储设备的适配增强了兼容性,隐私安全的优化符合现代 Android 的设计理念,而动态阈值和存储健康管理则进一步提升了用户体验。

相关推荐
不急不躁1233 小时前
Android16 给应用默认获取权限
android·java
用户41659673693553 小时前
拒绝 Race Condition:深入理解 StateFlow 的取值与更新
android
青莲8433 小时前
Kotlin Flow 深度探索与实践指南——上部:基础与核心篇
android·前端
恋猫de小郭3 小时前
2025 年终醒悟,AI 让我误以为自己很强,未来程序员的转型之路
android·前端·flutter
2501_915918414 小时前
iOS 开发中证书创建与管理中的常见问题
android·ios·小程序·https·uni-app·iphone·webview
00后程序员张4 小时前
IOScer 开发环境证书包括哪些,证书、描述文件与 App ID 的协同管理实践
android·ios·小程序·https·uni-app·iphone·webview
aningxiaoxixi5 小时前
android AV 之 SimpleC2Component
android
TAEHENGV6 小时前
导入导出模块 Cordova 与 OpenHarmony 混合开发实战
android·javascript·数据库
君莫啸ོ6 小时前
Android基础-SwitchCompat自定义样式
android