1. 引言
在应用AndroidManifest中添加 android:persistent="true" 关键字,并把应用APK预置到system/app目录下,可以给应用实现开机自启动和保活效果。我们带着以下两个疑问去看看是怎么实现的:
- 开机自启动 how?
- adb shell kill -9 杀进程后会自动重启 how?
2. 开机自启动流程
开机后通过adb shell ps -A | grep 包名查看进程号,确实完成了自启。
Desktop psa | grep demo
u0_a61 3329 3329 1753 3600572 83104 ep_poll 7b2c9a4ff34a S e.applicationdemo
查看进程的oom_adj值是-800,优先级非常高,可以看出带persistent的进程很难被系统杀死。
xxx64:/ # cat proc/3329/oom_score_adj
-800
xxx64:/ #
在ActivityManagerService.java的startProcessLocked启进程的方法中打调用栈如下:
private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
app.pendingStart = true;
app.killedByAm = false;
app.removed = false;
app.killed = false;
final long startSeq = app.startSeq = ++mProcStartSeqCounter;
app.setStartParams(uid, hostingType, hostingNameStr, seInfo, startTime);
if (mConstants.FLAG_PROCESS_START_ASYNC) {
if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
"Posting procStart msg for " + app.toShortString());
//Add by QXL
if(null != app && app.processName != null && app.processName.equals("com.example.applicationdemo")) {
android.util.Log.d("qxl","ams startProcessLocked stack:"
+ android.util.Log.getStackTraceString(new Throwable()));
}
重启设备抓开机Log,结果如下:
开机自启动是在ActivityManagerService服务SystemReady后中调用startPersistentApps方法拉起所有persistent应用。
3. kill -9 杀进程后会自动重启
虽然persistent特性的应用进程oom_adj是-800很难被系统杀掉,但不排除其他因素导致应用进程被杀,比如通过adb shell kill -9 xxx命令即可杀掉某个进程。作用于上面的persistent应用试试:
adb shell kill -9 3329
此时打印调用栈信息如下:
由此可以看到persistent进程被杀后,触发了进程启动时和AMS之间的Binder墓碑机制走到cleanUpApplicationRecordLocked方法,针对persistent应用设置restart标记后执行startProcessLock重新拉起进程。
Binder墓碑机制如下图所示:
小结
搞清楚persistent实现应用保活的过程后,我们可以基于这个机制实现一些三方应用的保活个性化需求。在这个基础上应用只需要重写Application的onCreate方法做进程拉起后的业务逻辑即可。