App Standby 学习小结

2019-07-14 02:37发布

standby 流程图:
这里写图片描述 在之前文档“doze模式介绍”的第10点中,我们知道使用adb命令强制使我们的应用进入standby模式,其实用app idle模式更为贴切。具体 命令如下:
adbshelldumpsysbatteryunplug//unplug adb shell am set-inactive false //把对应的app设置为idle状态
$ adb shell am get-inactive //查看对应app是否为idle状态 跟踪到具体的代码,这个用adb set-inactive为false的动作在framework中的调用为:
这里写图片描述
在frameworks/base/cmds/am/src/com/android/commands/am/Am.java中的onRun()方法中,它调用了runSetInactive()方法,继续看下这个方法:
这里写图片描述
方法中拿到对应的包名,需要设置的idle状态后,就调用了UsageStatsManager的setAppInactive方法,该方法调用了UsageStatsService的setAppInactive方法。
这里写图片描述
具体看下该UsageStatsService的setAppInactive方法:
这里写图片描述
方法中拿到了传过来的包名,userId,以及需要设置的idle状态,又调用了setAppIdle方法:
这里写图片描述
通过Handler发MSG_FORCE_IDLE_STATE消息,看下mHandler中的处理:
这里写图片描述
一句话,调用forceIdleState方法:
这里写图片描述
在setBeginIdleTime、setSystemLastTime方法中,调用了notifyStatsChanged
这里写图片描述
这个notifyStatsChanged,会回调StatsUpdatedListener的onStatsUpdated方法,该方法具体实现在UsageStatsService中。
这里写图片描述
看下UsageStatsService中的onStatsUpdated方法:
这里写图片描述
继续回到其Handler中
这里写图片描述 flushToDisk方法:
这里写图片描述
flushToDistLocked方法将所有的状态信息通过UserUsageStatsService持久化到数据库:
这里写图片描述
UserUsageStatsService中的persistActiveStats方法:
这里写图片描述
最后,在NetworkManagementService根据这些数据断网。再看下自然进入app standby的流程。
涉及到的主要的类为:UsageStatsService,继承自SystemService。既然是用户最近很少使用的app才满足app idle的条件,所以先看下ActivityManagerService,会通过updateLruProcessInternalLocked方法将所有进程使用情况存储到ArrayList
mLruProcesses中,详细的算法没作深入研究,有兴趣的同学可以补充。
在AMS中有下面两个方法,至于什么时候这两方法会跑到,能力有限,没作研究了,它们就是通往app idle的桥梁。
这里写图片描述 把对应进程信息传到了UsageStatsService的reportContentProviderUsage、reportEvent。看下reportEvent方法:
这里写图片描述
得到开始idle时间、上次使用时间后调用了UserUsageStatsService的reportEvent方法:
这里写图片描述
具体细节略过,看下notifyStatsChanged方法:
这里写图片描述 又回到UsageStatsService,调用回调方法onStatsUpdated,这样就回到使用adb命令强制进入app idle模式的流程了:
这里写图片描述 上面粗略讲述了从AMS的LUR算法中得到最近使用较少的进程,然后交给了UsageStatsService进行处理。下面说下app idle的策略:
先看下UsageStatsService 的onStart方法:
这里写图片描述
首先是初始化权限管理与用户管理两个系统级的管理类,然后初始化handler,存储使用状态的路径,注册广播。继续看下onBootPhase方法,该方法在系统服务启动的各个阶段都会被回调:
这里写图片描述
初始化SettingsObserver以及与app idle相关的其他系统服务,如果系统启动完成并检测到在充电状态,就关闭app idle.当然DeviceStateReceiver这个BroadcastReceiver也在实时监听设备电池状态:
这里写图片描述
当插拔电源时会释放idle,跟踪下else语句块中方法:
这里写图片描述
像注释中说的,在doze模式中,肯定app idle状态成立,另一种情况看注释。详细看下setAppIdleParoled方法:
这里写图片描述
如果传入的值与当前保存的值不同,就进入实际的操作代码,如果paroled为ture,说明需要释放,看下postParoleEndTimeout方法:
这里写图片描述
继续看handler中对该消息的处理:
这里写图片描述
又回到了setAppIdleParoled方法,但参数置为了false,所以会跑到else代码块中,先调用checkAndGetTimeLocked方法拿到上次释放的时间点,再调用postNextParoleTimeout方法:
这里写图片描述
先获取下次放出来的剩余时间,然后给交给了handler处理。
这里写图片描述
交给了checkParoleTimeout方法:
这里写图片描述
如注释所说,如果自上次放出到现在的时间到了可放出来的点,就直接释放,否则,进入下一轮,又调用postNextParoleTimeout,继续进行判断。 总结:
首先对使用adb命令强制进入app idle模式进行了分析,调用Am的onRun()方法继而调用runSetInactive(),再进入到UsageStatsManager类中,最后到UsageStatsService,通过回调方法onStatsUpdated将数据持久化到指定数据文件。
然后对自然情况下进入app idle模式进行了分析,从AMS中开始,获取到LRU的进程信息,传给UsageStatsService,最后同样通过回调方法onStatsUpdated将数据持久化到指定数据文件。
最后对app idle策略进行了初步的分析,主要粗略讲述了对电池状态、Doze模式下相应的app idle策略。 遗留问题:
1、NetWorkPolicyManager如何通过UsageStatsService持久化的数据进行断网操作?
2、SyncManager如何在app idle时取消同步?
3、JobSchedulerService如何在app idle时挂起对应任务的?
4、App idle释放与囚禁时间算法如何?
5、UsageStatsService持久化的数据与app idle策略是如何联系的? 上面的问题暂时还未弄明白。后续继续学习与更新。不正之处,欢迎拍砖讨论。