谈谈Persistent属性

文章目录

    • 1. 背景
    • 2. 开机自启动流程
    • 3. adb kill -9 杀进程后会自动重启
    • 4. 小结

1. 背景

在应用AndroidManifest文件下添加 android:persistent=“true” 关键字,并把Apk预置到system/app目录下,可以给应用实现开机自启动和保活效果。

从以下两个疑问去找答案:

  1. 开机自启动 how?
  2. adb 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.ecloudapidemo

查看进程的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 QXLif(null != app && app.processName != null && app.processName.equals("com.example.ecloudapidemo")) {android.util.Log.d("qxl","ams startProcessLocked stack:"+ android.util.Log.getStackTraceString(new Throwable()));}

重启设备抓开机Log,结果如下:
02-07 01:09:41.247 1941 1956 D qxl : ams startProcessLocked stack:java.lang.Throwable
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4486)
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4451)
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.am.ActivityManagerService.addAppLocked(ActivityManagerService.java:13289)
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.am.ActivityManagerService.addAppLocked(ActivityManagerService.java:13253)
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.am.ActivityManagerService.startPersistentApps(ActivityManagerService.java:13011)
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.am.UserController$Injector.startPersistentApps(UserController.java:2195)
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.am.UserController.finishUserUnlocked(UserController.java:449)
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.am.UserController.handleMessage(UserController.java:1999)
02-07 01:09:41.247 1941 1956 D qxl : at android.os.Handler.dispatchMessage(Handler.java:102)
02-07 01:09:41.247 1941 1956 D qxl : at android.os.Looper.loop(Looper.java:193)
02-07 01:09:41.247 1941 1956 D qxl : at android.os.HandlerThread.run(HandlerThread.java:65)
02-07 01:09:41.247 1941 1956 D qxl : at com.android.server.ServiceThread.run(ServiceThread.java:44)

开机自启动的流程就比较清楚了。

3. adb kill -9 杀进程后会自动重启

虽然persistent特性的应用进程oom_adj是-800很难被系统杀掉,但不排除其他因素导致应用进程被杀,比如我们通过命令adb shell kill -9 xxx即可杀掉某个进程。

作用于上面的persistent应用试试:

adb shell kill -9 3329

此时打印调用栈信息如下:
02-07 01:10:37.374 1941 2066 D qxl : ams startProcessLocked stack:java.lang.Throwable
02-07 01:10:37.374 1941 2066 D qxl : at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4486)
02-07 01:10:37.374 1941 2066 D qxl : at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4451)
02-07 01:10:37.374 1941 2066 D qxl : at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4266)
02-07 01:10:37.374 1941 2066 D qxl : at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4260)
02-07 01:10:37.374 1941 2066 D qxl : at com.android.server.am.ActivityManagerService.cleanUpApplicationRecordLocked(ActivityManagerService.java:20377)
02-07 01:10:37.374 1941 2066 D qxl : at com.android.server.am.ActivityManagerService.handleAppDiedLocked(ActivityManagerService.java:5968)
02-07 01:10:37.374 1941 2066 D qxl : at com.android.server.am.ActivityManagerService.appDiedLocked(ActivityManagerService.java:6162)
02-07 01:10:37.374 1941 2066 D qxl : at com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied(ActivityManagerService.java:1897)
02-07 01:10:37.374 1941 2066 D qxl : at android.os.BinderProxy.sendDeathNotice(Binder.java:1193)

由此可以看到persistent进程被杀后,触发了进程启动时和AMS之间的binder墓碑机制走到cleanUpApplicationRecordLocked方法,针对persistent应用AMS会重新拉起新的进程。

应用进程启动后如何和AMS绑上这样的关系?可以参考其他人画的流程图:
在这里插入图片描述

4. 小结

大概搞清楚persistent的实现后,我们可以基于这个机制做保活和自启名单的定制需求了。Application这边可以利用重写Application的onCreate方法做进程拉起后的业务逻辑。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注