现代Android机保鲜的秘密在这(一)

背景

曾几何时,安卓手机越用越慢的说法不绝于耳,几乎经历过Android 5之前的小伙伴都有过这种感觉。但是近几年的安卓手机这种问题少了很多,更多的是内存不够的问题,还有一些APP或者游戏占用的系统资源越来越多,给人一种手机变卡了的错觉。
对于这种问题,很好验证,现代的手机如果感觉太卡,把手机恢复出厂之后再用,手机基本会焕然一新(当然,电池是不会的),而前几年的手机,则不管恢复几次,都无法回到新机时候的感觉。

问题出现的原因

简单来说,手机用的时间长了,磁盘碎片化严重,磁盘访问变慢,成为了CPU运行的瓶颈,导致整个系统被拖累。

Google解决方案:FSTRIM

简单来说就是这个命令工具就是标记哪些block是无用的,便于操作系统回收。

名词介绍

SS --- SystemServer
PMS --- PackageManagerService
SMS --- StorageManagerService

何时运行

第一种情况,开机时由SS发起

SS startOtherService
-> PMS performFstrimIfNeeded
-> SMS runMaintenance -> fstrim

  1. 取得上次运行时间,上次运行时间是看/data/system/last-fstrim的上次修改时间,如下截图中可看到,该文件没有内容,就是个空文件,其有效信息就是上次修改时间,就是起个标记的作用。


    image
  2. 取得系统规定的fstrim时间间隔,该时间存在SettingProvider中,android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,如果这个值没设置过,则默认为DEFAULT_MANDATORY_FSTRIM_INTERVAL,3天。
final long interval = android.provider.Settings.Global.getLong(
mContext.getContentResolver(), android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                        DEFAULT_MANDATORY_FSTRIM_INTERVAL);
  1. 判断当前时间与上次修改的时间差,如果超出时间间隔,则发起fstrim流程。

第二种启动情况,定时启动

SMS在完成启动之后,会直接启动一个定时任务,定时的fstrim都是由这个定时任务启动的。
SMS.handleSystemReady
-> MountServiceIdler.scheduleIdlePass
这个定时任务是不断被调用的,完成了一次会再调用一次。

    public static void scheduleIdlePass(Context context) {
        JobScheduler tm = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);

        Calendar calendar = tomorrowMidnight(); //凌晨3点
         //计算距离任务启动还有多久
        final long timeToMidnight = calendar.getTimeInMillis() - System.currentTimeMillis();

        JobInfo.Builder builder = new JobInfo.Builder(MOUNT_JOB_ID, sIdleService);
        builder.setRequiresDeviceIdle(true); //该任务执行时设备必须空闲
        builder.setRequiresCharging(true);  //该任务执行时设备必须在充电
        builder.setMinimumLatency(timeToMidnight); //设置任务还有多久启动
        tm.schedule(builder.build()); //启动任务
    }

与第一种情况不同的是,这个定时任务启动fstrim流程后,会有个回调,在回调中会启动下一次的定时任务。

手动运行

adb shell sm fstrim

image.png

你可能感兴趣的:(现代Android机保鲜的秘密在这(一))