背景
曾几何时,安卓手机越用越慢的说法不绝于耳,几乎经历过Android 5之前的小伙伴都有过这种感觉。但是近几年的安卓手机这种问题少了很多,更多的是内存不够的问题,还有一些APP或者游戏占用的系统资源越来越多,给人一种手机变卡了的错觉。
对于这种问题,很好验证,现代的手机如果感觉太卡,把手机恢复出厂之后再用,手机基本会焕然一新(当然,电池是不会的),而前几年的手机,则不管恢复几次,都无法回到新机时候的感觉。
问题出现的原因
简单来说,手机用的时间长了,磁盘碎片化严重,磁盘访问变慢,成为了CPU运行的瓶颈,导致整个系统被拖累。
Google解决方案:FSTRIM
简单来说就是这个命令工具就是标记哪些block是无用的,便于操作系统回收。
名词介绍
SS --- SystemServer
PMS --- PackageManagerService
SMS --- StorageManagerService
何时运行
第一种情况,开机时由SS发起
SS startOtherService
-> PMS performFstrimIfNeeded
-> SMS runMaintenance -> fstrim
-
取得上次运行时间,上次运行时间是看/data/system/last-fstrim的上次修改时间,如下截图中可看到,该文件没有内容,就是个空文件,其有效信息就是上次修改时间,就是起个标记的作用。
image - 取得系统规定的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);
- 判断当前时间与上次修改的时间差,如果超出时间间隔,则发起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
网友评论