Android原生应用保活机制

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.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 QXL
        	if(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应用设置restart标记后执行startProcessLock重新拉起进程。

Binder墓碑机制如下图所示:

4. 小结

搞清楚persistent实现应用保活的过程后,我们可以基于这个机制实现一些三方应用的保活个性化需求。在这个基础上应用只需要重写Application的onCreate方法做进程拉起后的业务逻辑即可。

5. 添加开机自启动注意点

开机自启动执行AMS.stratPersistApplication()方法,分两个阶段:
阶段一(DIRECTORY_BOOT_AWARVE)_DE目录:AMS.systemReady()阶段:启动DIRECTORY_BOOT_AWARVE的persistent应用;
阶段二(DIRECTORY_BOOT_UNAWARVE)_CE目录:UserController.startUser->UserController.finishUserBoot->UserController.mayBeUnlockedUser->UserController.unlockUserCleared->UserManagerService.onBeforeUnlockUser->UserDataPreparer.prepareUserData->UserController.finishUserUnlocked->AMS.stratPersistApplication

做普通应用自启动建议在阶段二拉起做普通应用自启动建议在阶段二拉起,阶段一user的ce目录还没准备好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Quexl189

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值