通过设置 flag,两个普通的进程可以通过互相"攀升"来提升优先级
方式二、监听锁屏广播拉起Activity,监听解锁广播销毁Activity:具体步骤:
- 启动一个Service,通过动态广播receiver接收锁屏、开屏广播
- 灭屏时,启动Activity到前台
- 开屏时,将Activity进行 finish,确保用户无感知
adb shell ps | grep <pacakgeName>ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)All known processes:*APP* UID 10064 ProcessRecord{f59eb2f 30917:com.bytedance.gcsuppression.demo/u0a64}...oom: max=1001 curRaw=100 setRaw=100 cur=100 set=100curSchedGroup=1 setSchedGroup=1 systemNoUi=false trimMemoryLevel=0curProcState=5 repProcState=5 pssProcState=5 setProcState=5 lastStateTime=-23s716ms(该方法在 Android 8.0 上测试过仍有效,更高版本尚未测试;因为是利用了 service 与动态广播的特性,所以 framework 很难对这个逻辑做出应对,除非是在系统侧维护一个 service 黑名单)进程的清理

文章插图
虽然杀进程有这么多的花样,但常见的方式就三种:
清理名称触发场景功能kill粒度最细,用于进程自杀、AMS 查杀单个缓存进程等杀死单个 java 进程killBackground普通应用也可以通过 AM 服务调用杀死系统中 background 进程force-stop以 package 为单位,强力杀死和该包有关联的进程并禁止大部分自启杀死该包下所有进程,关闭并销毁相关组件
普通的查杀方式如kill和killBackground都只是杀死单个或部分进程,当进程死亡后,会因为 binder fd 的释放通过死亡回调通知 AMS 进程已死,这期间 AMS 也有可能因为 Service 等组件重新将进程拉起 。考虑到拉活方案花样多,应用中的其它 java 进程或 c 进程仍然可以通过启动组件的方式重新将进程拉起来 。
在一般的原生机器上,force-stop虽然很少使用,一般只在设置里的"强制停止"按钮触发 。除了杀死进程之外也会销毁组件等信息,同时也会更改 PMS 中对应包名的状态,避免再次拉活 。其主要功能如下:

文章插图
彩蛋:当我们上滑应用卡片时Android在做什么
- systemui 进程中的 com.android.systemui/.recents.RecentsActivity 接收到卡片滑动事件
- systemui 获取到 AMS 服务,再调用 am.removeTask 方法来移除 Task 和杀死显示该界面的进程;注意这个方法普通应用是没有调用权限的 。
- 最后通过 AMS 的 cleanUpRemovedTaskLocked 方法来杀死进程,这个方法的具体实现如下:
void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess, boolean removeFromRecents) { // 1. 在最近任务中移除 Task if (removeFromRecents) { mRecentTasks.remove(tr); } ... // 2. 选择需要查杀的进程 final String pkg = component.getPackageName(); ArrayList<ProcessRecord> procsToKill = new ArrayList<>(); ArrayMap<String, SparseArray<ProcessRecord>> pmap = mService.mProcessNames.getMap(); for (int i = 0; i < pmap.size(); i++) { SparseArray<ProcessRecord> uids = pmap.valueAt(i); for (int j = 0; j < uids.size(); j++) { ProcessRecord proc = uids.valueAt(j); ... // 2.1 如果 Task 所在进程还有别的 Task 在最近任务中显示,那么该进程不会被杀 for (int k = 0; k < proc.activities.size(); k++) { TaskRecord otherTask = proc.activities.get(k).getTask(); if (tr.taskId != otherTask.taskId && otherTask.inRecents) { return; } } // 2.2 进程有前台service的不会被杀,典型的有音乐播放软件 if (proc.foregroundServices) { return; } // Add process to kill list. procsToKill.add(proc); } } // 3. 正式查杀 for (int i = 0; i < procsToKill.size(); i++) { ProcessRecord pr = procsToKill.get(i); // 如果满足这两个条件才会立即被杀 if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND && pr.curReceivers.isEmpty()) { pr.kill("remove task", true); } else { pr.waitingToKill = "remove task"; } }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 昆仑雪菊播种后的管理,雪菊的价格多少
- 一款比phpmyadmin更好用的WEB数据库管理工具
- Android中的三个蓝牙漏洞
- 交换机和路由器的文件管理配置,可以修改设备flash文件
- 安卓|谷歌确认!Android 13最大改进 解决杀后台:CPU/内存使用率暴降
- 项目管理 之“关键路径法 和 关键链法的区别”
- 阿里工程师用 8 张图告诉你如何存储、管理泛内容数据
- 会计学属于什么类别的专业?
- Q Android 10/11(R) 分区存储适配
- 使用微软的 ProcDump 调试 Linux 进程
