【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 的设计理念,而动态阈值和存储健康管理则进一步提升了用户体验。

相关推荐
Gary Studio1 小时前
Android AIDL HAL工程结构示例
android
y = xⁿ1 小时前
MySQL八股知识合集
android·mysql·adb
andr_gale2 小时前
04_rc文件语法规则
android·framework·aosp
祖国的好青年3 小时前
VS Code 搭建 React Native 开发环境(Windows 实战指南)
android·windows·react native·react.js
黄林晴3 小时前
警惕!AGP 9.2 别只改版本号,R8 规则与构建链路全线收紧
android·gradle
小米渣的逆袭4 小时前
Android ADB 完全使用指南
android·adb
儿歌八万首4 小时前
Jetpack Compose Canvas 进阶:结合 animateFloatAsState 让自定义图形动起来
android·动画·compose
zhangphil5 小时前
Android Page 3 Flow读sql数据库媒体文件,Kotlin
android·kotlin
神探小白牙5 小时前
echarts,3d堆叠图
android·3d·echarts