24、车载存储与文件系统:存储权限、外部存储、分区管理、数据备份与恢复

车载系统的存储,跟手机完全是两码事。

我刚开始接触 Android Automotive OS 时,第一反应是:这不就是车机版 Android 吗?存储能有多大区别?结果被现实狠狠教育了一回。手机没电了可以关机重启,车机存储出问题,轻则导航卡死,重则倒车影像都出不来。嗯,这里面的门道,咱们得好好捋一捋。

24.1 车载存储的特殊性

车载存储,说白了就是「可靠性优先」。手机存储坏了,你换台手机。车机存储坏了,你可能得把整个中控台拆了。我见过某款车型因为 eMMC 寿命耗尽,车主不得不花八千块换整个娱乐主机。

车载存储的几个关键特点:

  • 高可靠性要求:工作温度范围 -40°C 到 85°C,远超消费级
  • 长寿命设计:至少 10 年以上的写入寿命
  • 分区隔离:系统区、用户区、缓存区严格分离
  • 掉电保护:突然断电不能丢数据

核心原则:车载存储的设计目标是「系统不会因为存储问题而崩溃」,而不是「存储空间越大越好」。

24.2 存储权限管理

Android Automotive OS 的权限模型,跟手机版有显著差异。手机上的 READ_EXTERNAL_STORAGE 权限,在车机上基本不适用。为什么?因为车机上的「外部存储」概念跟手机完全不同。

车载应用的存储权限分为三层:

权限级别 访问范围 典型场景
内部私有存储 仅本应用 应用配置、缓存数据
共享存储 多应用共享 音乐下载、地图离线包
系统分区 系统级应用 OTA 升级包、系统日志

我个人习惯的做法是:能用内部私有存储就别碰共享存储。我在项目中遇到过一个问题——两个地图应用同时写入共享存储的离线地图目录,结果互相覆盖了对方的索引文件。排查了整整两天,最后发现是权限设计没做好隔离。

避坑指南:车载应用申请存储权限时,一定要明确告知用户「为什么需要这个权限」。我曾经见过一个音乐播放器,一启动就申请所有存储权限,用户直接给了差评。后来改成按需申请,评分就上来了。

24.3 外部存储管理

车载系统的「外部存储」通常指 USB 设备和 SD 卡。但这里有个坑:车机上的 USB 接口可能同时连接着 CarPlay、Android Auto、U 盘、甚至行车记录仪。你怎么知道哪个是存储设备?

我建议用 StorageManager 来识别:

StorageManager storageManager = getSystemService(StorageManager.class);
StorageVolume[] volumes = storageManager.getStorageVolumes();

for (StorageVolume volume : volumes) {
    if (volume.isRemovable()) {
        // 这是可移除存储设备
        Log.d("Storage", "发现外部存储: " + volume.getDescription());
    }
}

你想想看,如果用户插了个 U 盘,里面存着 500 首无损音乐。你的音乐播放器应该怎么做?直接扫描所有文件?那得卡死。正确的做法是:

  • 先检测存储设备的文件系统类型(FAT32、exFAT、NTFS)
  • 再按目录结构逐层扫描
  • 最后建立索引缓存

注意:车载系统对 USB 设备的读写速度有限制。我曾经测试过,某些车机对 USB 2.0 设备的写入速度只有 8MB/s。如果你要拷贝大文件,一定要在后台线程操作,并且显示进度条。否则用户会以为车机死机了。

24.4 分区管理

车载系统的分区设计,是整车厂最看重的部分。一个典型的分区布局是这样的:

/boot          - 引导分区
/system        - 系统分区(只读)
/vendor        - 厂商分区(只读)
/data          - 用户数据分区(可读写)
/cache         - 缓存分区
/odm           - 原始设备制造商分区
/factory       - 出厂恢复分区

这里我要强调一点:/system 分区必须是只读的。为什么?因为如果系统分区可写,恶意应用就能修改系统文件,后果不堪设想。我见过一个案例,某款车机因为 system 分区被意外写入,导致 OTA 升级后系统无法启动,最后只能返厂刷机。

分区大小怎么定?我给出一个参考值:

分区 建议大小 说明
/system 2-4 GB 包含 Android 系统和预装应用
/data 16-64 GB 用户数据、应用安装、离线地图
/cache 1-2 GB OTA 升级包、系统缓存
/factory 512 MB 出厂镜像,用于恢复

经验之谈:分区大小不是越大越好。我见过某厂商给 /data 分区分配了 128GB,结果用户根本用不完,反而浪费了宝贵的 eMMC 寿命。合理的做法是根据目标用户的使用习惯来定。比如主打导航的车机,离线地图可能占 20GB,那 /data 给 32GB 就够用了。

24.5 数据备份与恢复

车载系统的数据备份,比手机复杂得多。手机备份大不了恢复联系人、照片。车机要备份什么?

  • 用户账户信息(音乐、视频会员)
  • 导航历史记录和收藏地址
  • 蓝牙配对信息
  • 座椅、空调等车辆设置
  • 驾驶行为数据(部分法规要求)

Android Automotive OS 提供了 BackupManager 机制,但说实话,这个机制在车机上不太够用。为什么?因为车机可能长时间处于休眠状态,BackupManager 的定时备份策略不一定能触发。

我建议的做法是:

// 自定义备份方案
public class VehicleBackupManager {
    private static final String BACKUP_PATH = "/data/backup/";
    
    public void backupUserData() {
        // 1. 序列化用户配置
        // 2. 写入备份分区
        // 3. 校验完整性
        // 4. 记录备份时间戳
    }
    
    public void restoreUserData() {
        // 1. 检查备份文件是否存在
        // 2. 验证签名
        // 3. 恢复数据
        // 4. 重启相关服务
    }
}

避坑指南:我曾经遇到过一个很坑的问题——某款车机在 OTA 升级后,用户的所有蓝牙配对信息都丢了。排查后发现,是升级脚本把 /data/misc/bluetooth 目录给清空了。从那以后,我坚持在 OTA 升级前做一次完整的数据备份,升级后再恢复。虽然多了几步操作,但用户满意度提升了不少。

24.6 存储性能优化

车载存储的性能优化,核心就一句话:减少写入次数

eMMC 和 UFS 的写入寿命是有限的。你想想看,如果某个应用每秒写一次日志,一年下来就是 3150 万次写入。再好的存储芯片也扛不住。

我总结了几条优化原则:

  • 批量写入:把多次小写入合并成一次大写入
  • 延迟写入:非关键数据可以等系统空闲时再写
  • 避免频繁创建和删除文件:这会导致文件系统碎片化
  • 使用 SQLite 替代文件存储:数据库的写入效率远高于文件操作

重要提醒:不要在车载系统上使用 swap 分区。我见过某厂商为了省成本,给车机配了 2GB RAM 加 4GB swap。结果呢?eMMC 的写入寿命在一年内就耗尽了。车载系统就该老老实实做内存管理,别拿存储当内存用。

24.7 知识体系总览

说了这么多,咱们用一张图来总结车载存储的核心知识体系:

车载存储与文件系统知识体系 车载存储系统 存储权限管理 内部私有存储 共享存储 系统分区 外部存储管理 USB设备识别 文件系统兼容 读写速度控制 分区管理 系统分区(只读) 用户数据分区 缓存/恢复分区 数据备份与恢复 用户配置备份 OTA升级保护 存储性能优化 减少写入次数 批量/延迟写入

这张图把车载存储的五个核心模块串起来了。你仔细看就会发现,所有模块都围绕着一个核心目标:可靠性和寿命。权限管理是为了安全,分区管理是为了隔离,备份恢复是为了容错,性能优化是为了延长寿命。外部存储管理则是为了兼容性。

好了,关于车载存储与文件系统,我就讲这么多。记住一句话:在车机上,存储不是用来「装东西」的,而是用来「保证系统稳定运行」的。这个思维转变,是做好车载开发的第一步。


公众号:蓝海资料掘金营,微信deep3321