保活与杀活一直以来就是应用于系统间的博弈,魔高一尺道高一丈。各种奇奇怪怪的保活方案层中不穷,但是安卓随着系统版本的迭代,各种杀活策略更加严格,已经把流氓软件的可操作保活方法逼到了角落里面了··········

 

作为系统杀活阵营支持者的我由于收到应用大佬们十分过分的要求(需要系统拉活他们的应用或服务),所以不得不帮助他们进行系统保活·········

 

 

 

android系统原生方案

简单的系统保活方案就是防杀和拉活:

1.把要保活的应用加入powersave白名单,这样一般系统在待机模式低电量模式就不会去主动杀应用了。(但是不保证能在lowmemorykiller的屠刀中生存下来)   2020年了,Android后台保活还有戏吗?看我如何优雅的实现!

2.将想要保活的应用设置为特权应用,那么由于特权应用的优先级很高,lowpowerkiller跟影响不到它,并且特权应用系统可以自身拉活它。   Android应用的persistent属性

 

这一套组合拳打下来,系统绝不会去杀它的,即使意外挂掉,系统也能妥妥的将它拉活。 妥妥的保活

 

 

 

然而·········   应用大佬们并不买账,因为他们想要实现远程OTA应用,所以要允许系统被kill掉,然后再被拉活········    并且应用大佬写的各种神奇功能的app被设置为特权应用成为持久男人之后,会和系统原生的应用有so兼容性冲突导致各种崩溃,应用不想放弃使用第三方的so,而且特权应用使用webview也有限制。所以导致应用大佬反对特权应用的实现方式········

 

那么问题就来了,系统自带的保活方案已经无法满足大佬们的要求,就要搞一个曲线救国的方法了。

 

民间大神方案

翻阅网上的帖子发现一个很有想法的保活方案,双进程native层保活方案,Android进程永生技术终极揭秘:进程被杀底层原理、APP应对被杀技巧 

 

感觉为了保活这些大佬无所不用其极······  原理不难理解,由于native调用binder的高效性,通过双进程间的文件锁互相感知,其中有一个被kill掉,另一个进程就要将拉活的intent进行发送出去,以对抗系统5ms一次的查杀。虽然原理简单但是实现很复杂啊········   并且这个是要应用自己实现的,再并且 应用要允许自身OTA被kill掉进程树后被拉起。显然此方案是行不通的······

 

 

自己的方案

既然他人的方案行不通,那只有自己想办法实现了。好在系统代码在自己手中,可以在系统中做一些修改来实现应用保活。

 

起初构想:  实现一个app, 监听开机广播实现自启。然后监测apk被kill状态来拉起被kill的应用。  前提要保证自己开机启动并且自身保活,那么自身要成为特权应用。其次要得到应用被kill的信息,这就犯难了·····  我一个app咋能监测到其他应用被kill的消息?????

 

于是看了一些文章发现在进程挂掉后会有清理程序:

AMS当然会清理掉其对应的ProcessRecord,这就是cleanUpApplicationRecordLocked()的主要工作。然而,对于persistent应用,cleanUpApplicationRecordLocked()会尝试再次启动对应的应用进程。代码截选如下:

 

private final void cleanUpApplicationRecordLocked(ProcessRecord app,
                                                  boolean restarting,
                                                  boolean allowRestart, int index)
{
    . . . . . .
    . . . . . .
    if (!app.persistent || app.isolated)
    {
        . . . . . .
        mProcessNames.remove(app.processName, app.uid);
        mIsolatedProcesses.remove(app.uid);
        . . . . . .
    }
    else if (!app.removed)
    {
        if (mPersistentStartingProcesses.indexOf(app) < 0) {
            mPersistentStartingProcesses.add(app);
            restart = true;
        }
    }
    . . . . . .
    . . . . . .
    if (restart && !app.isolated)
    {
        mProcessNames.put(app.processName, app.uid, app);
        startProcessLocked(app, "restart", app.processName);
    }
    else if (app.pid > 0 && app.pid != MY_PID)
    {
        . . . . . .
    }
    . . . . . .
}

在上面的函数中去将应用被kill的消息发送出去让自己的app去处理,显然发送广播比较简单,但是但觉不是很安全。由于自身应用还要常驻内存,干脆就把它写成系统服务。通过aidl来将kill后的回收event发送到自己实现的服务中,然后根据名单去拉活应用。自己去维护个白名单的话显然沟通成本比较高效率低下,干脆就让应用调用aidl接口自己设置。应用自己设置后白名单保存在xml文件中,应用只需设置一次,终身可以拉活。

 

android 安全保护 安卓系统保护_android 安全保护

 

应用去自己设置白名单,AMS将killevent发送给packagedaemon由其判断是否拉起。同时packagedaemon也向其他服务提供白名单查询接口,这样其他服务的一些权限就可在让应用自己设置了。此服务就是个中转处理,将设置的主导权交还给了应用。

 

 

 

 

 

代码写好了后就开始遇到SElinux这个拦路虎了,好在有现成的方法可以参考: 

Android : 为系统服务添加 SELinux 权限 (Android 9.0)

Android8.1 新增系统自定义服务一 (SELinux权限)

Android 9.0 (P版本) SystemServer中的服务配置se linux权限

android 8.1 安全机制 — SEAndroid & SELinux

 

 

其他参考:

android java进程管理(六)之apk进程的回收