在Android系统的存储管理体系中,StorageManagerService(简称SMS)是核心中枢组件,承担着设备存储全生命周期的管理职责。它作为连接应用层、Framework层与底层存储硬件的重要桥梁,统一管控设备的所有存储资源,包括内部存储、外部SD卡、USB存储设备等,为系统组件和应用提供标准化的存储操作接口,并实现存储安全、存储优化等高级特性。
StorageManagerService采用分层架构设计,各层级职责清晰:
1、应用API接口层 :以StorageManager类为核心,为应用提供存储访问的入口,封装了与StorageManagerService的跨进程通信逻辑。
2、Framework服务层 :StorageManagerService的核心实现层,负责存储管理的业务逻辑处理,与系统其他服务进行交互。
3、底层支撑层 :依赖Vold服务完成存储设备的底层操作,Vold服务通过NetlinkManager与内核进行通信,处理存储设备的硬件事件。
StorageManagerService属于系统服务,启动流程如下:
在SystemServer启动其他服务阶段(startOtherServices()),通过SystemServiceManager启动StorageManagerService。
// frameworks/base/services/java/com/android/server/SystemServer.java
private static final String STORAGE_MANAGER_SERVICE_CLASS =
"com.android.server.StorageManagerService$Lifecycle";
private void startOtherServices() {
// 省略其他服务启动
traceBeginAndSlog("StartStorageManagerService");
try {
// 启动StorageManagerService
mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS);
// 获取服务Binder引用
IStorageManager storageManager = IStorageManager.Stub.asInterface(
ServiceManager.getService("mount"));
} catch (Throwable e) {
reportWtf("starting StorageManagerService", e);
}
traceEnd();
}
1、onStart() :初始化StorageManagerService;发布Binder服务,将服务注册到ServiceManager中,服务名为"mount"。调用StorageManagerService.start启动,连接storaged和vold服务,获取binder对象,并注册IVoldListener监听。
public void onStart() {
mStorageManagerService = new StorageManagerService(getContext());
publishBinderService("mount", mStorageManagerService);
mStorageManagerService.start();
}
//StorageManagerService.java
private void start() {
connectStoraged();
connectVold();
}
storaged服务:**storaged 是 Android 系统中用于收集和发布存储相关指标的原生守护进程(daemon)**,自 Android 8(Oreo)起引入,主要用于监控存储设备的使用情况、健康状态及 I/O 性能。主要功能有:
- 磁盘统计信息采集 :定期读取
/sys/block/mmcblk0/stat(eMMC 设备)或/sys/block/sda/stat(非 eMMC 设备)获取磁盘读写统计。 - eMMC 生命周期监控 :通过解析
/d/mmc0/mmc0:001/ext_csd获取 eMMC 的剩余寿命和磨损情况。 - 应用级 I/O 归因 :遍历
/proc/uid_io/stats,记录每个 UID(应用)的前台/后台读写字节数、字符数、同步操作等,用于识别高 I/O 应用。 - 错误报告支持 :可通过
dumpsys调用,在系统错误报告中包含详细的 I/O 使用数据。
vold服务在《安卓vold服务》一篇中已介绍,本文不加赘述。
2、StorageManagerService 构造初始化:创建各种处理器和控制器、初始化文件系统和维护记录、读取配置设置、注册广播接收器、添加内部存储卷。
// 创建并启动专用的HandlerThread用于处理存储管理任务
HandlerThread hthread = new HandlerThread(TAG);
hthread.start();
// 创建主服务处理器,关联到HandlerThread的Looper 包括volume挂载、volume卸载等处理
mHandler = new StorageManagerServiceHandler(hthread.getLooper());
// 创建OBB(Opaque Binary Blob)操作处理器,使用IO线程的Looper
mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
// 初始化存储会话控制器
mStorageSessionController = new StorageSessionController(mContext);
// 创建安装器服务并启动
mInstaller = new Installer(mContext);
mInstaller.onStart();
// 初始化存储设置文件(原子文件操作,保证数据一致性)
mSettingsFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
// 初始化写记录文件
mWriteRecordFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "storage-write-records"));
// 读取存储设置
synchronized (mLock) {
readSettingsLocked();
}
// 将存储管理内部服务添加到本地服务管理器
LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
// 注册用户相关的广播接收器(用户添加/移除)
final IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_ADDED);
userFilter.addAction(Intent.ACTION_USER_REMOVED);
mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
// 添加内部存储卷
synchronized (mLock) {
addInternalVolumeLocked();
}
// 如果启用了看门狗监控,将当前服务添加到监控列表
if (WATCHDOG_ENABLE) {
Watchdog.getInstance().addMonitor(this);
}
3、onBootPhase:在系统启动的不同阶段执行特定逻辑
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
//核心系统服务已启动
mStorageManagerService.servicesReady();
} else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
//ActivityManagerService 准备就绪
mStorageManagerService.systemReady();
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
//系统启动完成,Home 应用已启动
mStorageManagerService.bootCompleted();
}
}
4、servicesReady():核心系统服务就绪后,获取包管理和AppOps等关键系统服务的接口实例 ;查询并保存三个重要内容提供者的应用信息: MediaStore(媒体存储)、 Downloads(下载管理)、 ExternalStorage(外部存储文档管理);记录这些系统组件的App ID和进程名,用于后续的存储访问权限控制。
// 从本地服务管理器获取包管理内部服务实例
mPmInternal = LocalServices.getService(PackageManagerInternal.class);
// 获取包管理服务的远程接口
mIPackageManager = IPackageManager.Stub.asInterface(
ServiceManager.getService("package"));
// 获取AppOps服务的远程接口,用于应用操作权限管理
mIAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
// 获取MediaStore内容提供者的信息(媒体存储服务)
ProviderInfo provider = getProviderInfo(MediaStore.AUTHORITY);
if (provider != null) {
// 从应用UID中提取App ID(去除用户ID部分)
mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
// 保存MediaStore提供者的进程名称
sMediaStoreAuthorityProcessName = provider.applicationInfo.processName;
}
// 获取下载内容提供者的信息
provider = getProviderInfo(Downloads.Impl.AUTHORITY);
if (provider != null) {
// 保存下载提供者的App ID
mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
}
// 获取外部存储内容提供者的信息(文档存储服务)
provider = getProviderInfo(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY);
if (provider != null) {
// 保存外部存储提供者的App ID
mExternalStorageAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
}
5、 systemReady():系统服务就绪后,调度智能维护任务、fstrim操作;刷新ZRAM设置, 调度ZRAM写回任务,将ZRAM中的冷数据写回到存储设备(如果支持)。
// 准备智能空闲维护,如果准备成功则开始调度智能维护任务
if (prepareSmartIdleMaint()) {
// 按照指定的智能维护周期调度智能空闲维护任务
SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, sSmartIdleMaintPeriod);
}
// 开始调度名义上每日执行的fstrim(文件系统整理)操作
// fstrim用于优化SSD性能,回收未使用的块
MountServiceIdler.scheduleIdlePass(mContext);
// 刷新ZRAM设置,确保系统启动时应用当前设置
refreshZramSettings();
String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
// 检查ZRAM是否启用且系统配置支持ZRAM写回功能
if (!zramPropValue.equals("0") // ZRAM未禁用("0"表示禁用)
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_zramWriteback)) { // 系统配置允许ZRAM写回
// 调度ZRAM写回任务,将ZRAM中的冷数据写回到存储设备
ZramWriteback.scheduleZramWriteback(mContext);
}
// 配置媒体文件转码功能
configureTranscoding();
6、bootCompleted():开机完成后,备份当前系统解锁用户信息、清空磁盘和卷的缓存数据、重启vold守护进程到初始状态、重新注册所有用户信息并恢复解锁状态、通知相关服务重置完成。
// 获取用户管理器服务实例
final UserManager userManager = mContext.getSystemService(UserManager.class);
// 获取系统中所有用户的信息列表
final List<UserInfo> users = userManager.getUsers();
// 通知存储会话控制器执行重置操作
mStorageSessionController.onReset(mVold, () -> {
// 重置完成后移除Handler中的所有回调和消息
mHandler.removeCallbacksAndMessages(null);
});
// 创建系统已解锁用户数组的副本(防止排序改变原始顺序)
systemUnlockedUsers = Arrays.copyOf(mSystemUnlockedUsers,
mSystemUnlockedUsers.length);
// 清空磁盘和卷的缓存信息
mDisks.clear();
mVolumes.clear();
// 重新添加内部存储卷(系统基础卷)
addInternalVolumeLocked();
// 重置vold守护进程,清理现有的磁盘/卷信息,从干净状态重新开始
// 注意:已经解锁的用户存储将保持解锁状态,不受重置影响
//
// TODO(b/135341433): 当FUSE稳定后移除谨慎的日志记录
mVold.reset(); // 执行vold重置
// 通知vold所有已存在和已启动的用户信息
for (UserInfo user : users) {
if (user.isCloneProfile()) {
// 如果是克隆配置文件,传递用户组ID
mVold.onUserAdded(user.id, user.serialNumber, user.profileGroupId);
} else {
// 普通用户,用户组ID设为-1
mVold.onUserAdded(user.id, user.serialNumber, -1);
}
}
// 通知vold所有系统已解锁的用户已启动
for (int userId : systemUnlockedUsers) {
mVold.onUserStarted(userId); // 通知vold用户启动
mStoraged.onUserStarted(userId); // 通知storaged用户启动
}
// 恢复系统解锁用户的存储状态
restoreSystemUnlockedUsers(userManager, users, systemUnlockedUsers);
// 更新安全锁屏状态给vold
mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
// 通知存储管理内部服务重置完成
mStorageManagerInternal.onReset(mVold);
与Vold服务交互 :StorageManagerService作为客户端,通过Binder机制与Vold服务进行通信,Vold服务负责处理存储设备的底层挂载、卸载等操作。
与StorageStatsService协作 :StorageStatsService负责存储统计数据的收集和计算,StorageManagerService通过调用其接口获取存储统计信息。
StorageStatsService核心功能:
- 分区统计:计算内部存储、外部卷的总容量、已用空间、可用空间、缓存空间。 getTotalBytes() 、 getFreeBytes() 。
- 应用统计:遍历 /data/data 、 /storage/emulated/0/Android/data ,统计每个应用的APK大小、数据大小、缓存大小、OBB文件大小、媒体占用。 queryStatsForPackage()
- 订阅与实时更新:支持系统/设置订阅存储变化,定时扫描并回调,更新存储占用视图。
- 垃圾文件扫描:识别残留APK、无效缓存、空目录、冗余媒体,为清理提供数据支撑。
与PackageManagerService交互 :在应用安装、卸载过程中,同步处理应用存储目录的创建、删除和权限配置。
与MediaStore协同 :管理媒体文件的索引和访问,确保媒体文件的存储和访问流程一致。
为了实现更灵活的权限管理,Android引入了FUSE(Filesystem in Userspace)文件系统:
- 用户空间实现 :FUSE的核心逻辑运行在用户空间,而非内核空间,使得存储权限控制可以更灵活地定制。
- 权限拦截 :在应用访问存储文件时,FUSE文件系统可以拦截访问请求,交由StorageManagerService进行权限验证,实现精细化的存储访问控制。
从Android 10开始,StorageManagerService是Scoped Storage(作用域存储)特性的核心实现者:
- 权限划分 :将存储访问权限划分为媒体文件访问、文档访问等不同维度,应用仅能访问自身沙盒目录和授权的外部文件。
- 权限验证 :在应用访问存储资源时,实时验证权限有效性,拦截未授权的访问请求。
- 权限动态调整 :支持应用在运行时申请存储权限,并处理权限授予或拒绝后的状态同步。