Android系统服务DropBoxManagerService详解与实践应用( 二 )

  • DropBox使用需要预留的存储占总存储的比例(10%);
  • 清除空间时扫描磁盘空间的时间间隔;
  • 需要压缩的最小文件大小 。
  • 根据以上配置,我们可以知道该目录下的日志文件清除策略,触发配置上限后会及时的删除文件 。
    在以下三种情况会执行文件清除策略,防止DropBox占用太多的空间:
    1. 设备低内存;
    2. setting配置发生变更;
    3. 添加文件 。
    同时在添加文件的时候,超过配置的可占用空间,会被丢弃 。
    /** * Trims the files on disk to make sure they aren't using too much space. * @return the overall quota for storage (in bytes) */private synchronized long trimToFit() throws IOException {return mCachedQuotaBlocks * mBlockSize;}2.3.2 文件删除及标记处理策略
    在上述策略不满足后,部分文件会被删除,删除后,会在DropBox添加一个.lost的空文件标记被删除的文件 。
    2.3.3 文件类型管控
    DropBoxMangerService对于可存储的文件类型也有控制,主要是对于TAG的控制 。
    public boolean isTagEnabled(String tag) {}2.3.4 权限管控
    【Android系统服务DropBoxManagerService详解与实践应用】使用DropBox需要READ_LOGS权限和PACKAGE_USAGE_STATS两个权限 。
    2.4 读写策略这块涉及到DBMS几个关键方法和属性,主要涉及到初始化(init),添加文件(addEntry),获取文件(getNextEntry),文件类型(EntryFile) 。
    DBMS作为系统服务会由SystemServer启动,添加文件(addEntry)和获取文件(getNextEntry)在调用时会先进行初始化(init) 。
    其中每个文件都会转换成一个EntryFile类来管理,关系见下图:
    Android系统服务DropBoxManagerService详解与实践应用

    文章插图
    下面了解一下初始化,EntryFile,添加文件和获取文件的具体内容:
    2.4.1 初始化
    初始化会将DropBox文件列表缓存到内存中 。
    /** If never run before, scans disk contents to build in-memory tracking data. */private synchronized void init() throws IOException {// 省略代码......File[] files = mDropBoxDir.listFiles(); // 列出所有文件for (File file : files) {EntryFile entry = new EntryFile(file, mBlockSize); // 一个日志文件对应一个EntryFile对象enrollEntry(entry); // 加入到mAllFiles}}初始化的时机:
    • 设备存储容量低广播回调 
    • 设置配置项修改
    • 添加日志文件
    • 获取日志文件
    • dump 命令行列出DropBox的一些内容
    2.4.2 EntryFile文件属性
    每个文件对应一个EntryFile,用block数来统计大小,DBMS涉及的读写都是根据磁盘的blockSize来进行,效率会更高 。
    static final class EntryFile implements Comparable<EntryFile> {public final String tag; // 日志文件的tag,类型public final long timestampMillis; // 日志文件的时间戳public final int flags; // 日志文件的flag,标志TEXT,EMPTY,GZIPPEDpublic final int blocks; // 存放文件的块数}2.4.3 添加文件
    添加一个日志文件,常见的在Ams中的addErrorToDropBox方法调用 。
    添加文件管控策略
    ① .lost的文件格式不允许添加 。
    // 如果添加.lost的文件,抛异常if ((flags & DropBoxManager.IS_EMPTY) != 0) throw new IllegalArgumentException();② 配置不允许记录的TAG,不会被添加 。
    // 从设置里面读取这个tag是否被允许记录if (!isTagEnabled(tag)) return;③ 根据系统设置的磁盘块大小进行写入,提高写入效率 。
    int bufferSize = mBlockSize;④ 异常时间戳文件矫正:写入文件前会将超过当前时间10s的文件修改时间后重新命名并加入到缓存文件列表中 。
    // 找出当前时间10s之后的所有文件SortedSet<EntryFile> tail = mAllFiles.contents.tailSet(new EntryFile(t + 10000));EntryFile[] future = null;if (!tail.isEmpty()) {future = tail.toArray(new EntryFile[tail.size()]);tail.clear();// 从文件列表中mAllFiles清除掉超过当前时间的}// 省略代码......for (EntryFile late : future) {if ((late.flags & DropBoxManager.IS_EMPTY) == 0) { // 将这些超过当前时间的文件重命名,时间戳依次+1,并且重新加入到mAllFiles中enrollEntry(new EntryFile());}}⑤ 添加文件的顺序,先创建临时文件,然后使用文件的rename方法,rename方法是原子操作,保证并发操作的安全 。


    推荐阅读