Android killPackageProcessesLSP 源码分析

该方法用于终止指定包名/用户ID/应用ID下符合条件的应用进程,涉及多进程管理、资源冻结、进程清理及优先级更新等操作。核心流程分为进程筛选、资源冻结、进程终止与资源恢复三个阶段。

    /*** 从已排序的进程列表中,提取从指定起始索引 startIdx 开始的连续同一 UID 的进程子列表*/private static List<Pair<ProcessRecord, Boolean>> getUIDSublist(List<Pair<ProcessRecord, Boolean>> procs, int startIdx) {final int uid = procs.get(startIdx).first.uid;int endIdx = startIdx + 1;while (endIdx < procs.size() && procs.get(endIdx).first.uid == uid) ++endIdx;return procs.subList(startIdx, endIdx);}// 方法声明:需持有mService和mProcLock锁保证线程安全@GuardedBy({"mService", "mProcLock"})boolean killPackageProcessesLSP(String packageName, int appId,int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,boolean doit, boolean evenPersistent, boolean setRemoved, boolean uninstalling,int reasonCode, int subReason, String reason) {// 获取包管理服务接口final PackageManagerInternal pm = mService.getPackageManagerInternal();// 存储待终止的进程列表,Pair<进程记录, 是否允许重启>final ArrayList<Pair<ProcessRecord, Boolean>> procs = new ArrayList<>();// Remove all processes this package may have touched: all with the// same UID (except for the system or root user), and all whose name// matches the package name.// 移除此软件包可能涉及的所有进程:// 所有具有相同 UID 的进程(除了 system 或 root 用户),以及名称与软件包名称匹配的所有进程。final int NP = mProcessNames.getMap().size();// 此循环的目的就是想找到所有符合条件的进程,将它们添加到procsfor (int ip = 0; ip < NP; ip++) {SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);final int NA = apps.size();for (int ia = 0; ia < NA; ia++) {// 获取所有的进程的ProcessRecord,把符合条件的加入到procs中准备查杀ProcessRecord app = apps.valueAt(ia);// 如果进程标记为持久化且未显式允许终止,跳过处理if (app.isPersistent() && !evenPersistent) {// we don't kill persistent processescontinue;}// 已标记移除// 是否应终止此进程并将其从进程列表中删除。当程序包被强制停止或进程崩溃次数过多时,将设置此参数// mRemoved 标记为trueif (app.isRemoved()) {// 如果需执行终止操作if (doit) {// 检查是否允许重启boolean shouldAllowRestart = false;// 非卸载场景下,检查包依赖关系if (!uninstalling && packageName != null) {// 此包依赖于正在停止的给定包,当它未被冻结或卸载时,允许重新启动它。// This package has a dependency on the given package being stopped,// while it's not being frozen nor uninstalled, allow to restart it.shouldAllowRestart = !app.getPkgList().containsKey(packageName) //该进程不在正在停止的给定包中&& app.getPkgDeps() != null&& app.getPkgDeps().contains(packageName) //该进程依赖正在停止的给定包&& app.info != null&& !pm.isPackageFrozen(app.info.packageName, app.uid, //该进程所在包未被冻结app.userId);}//将进程需要从进程列表中删除,并且需要执行终止操作,那么就记录该进程信息以及该进程是否应该重启procs.add(new Pair<>(app, shouldAllowRestart));}// 如果不需要执行终止就跳过continue;}// 如果它不符合我们的 oom adj 要求,请跳过进程。// Skip process if it doesn't meet our oom adj requirement.if (app.mState.getSetAdj() < minOomAdj) {// 没理解,以后再说// 请注意,在被终止的进程中仍有可能有一个 oom adj 0 的进程,但这并不意味着误判。// 例如,绑定服务进程及其客户端活动进程都在后台,因此它们被收集以被终止。// 如果客户端活动先被终止,则可能会安排服务取消绑定并成为正在执行的服务 (oom adj 0)。// Note it is still possible to have a process with oom adj 0 in the killed// processes, but it does not mean misjudgment. E.g. a bound service process// and its client activity process are both in the background, so they are// collected to be killed. If the client activity is killed first, the service// may be scheduled to unbind and become an executing service (oom adj 0).continue;}// 如果mRemoved标记为false,且adj大于最小adj,那么就检查是否允许重启boolean shouldAllowRestart = false;// 如果未指定 package,则调用给定用户 ID 下的所有进程。// If no package is specified, we call all processes under the// given user id.if (packageName == null) {// 用户ID过滤(USER_ALL表示所有用户)不是指定用户ID,则跳过if (userId != UserHandle.USER_ALL && app.userId != userId) {continue;}// 应用ID过滤(-1表示不限制)不是指定appId,则跳过if (appId >= 0 && UserHandle.getAppId(app.uid) != appId) {continue;}// Package has been specified, we want to hit all processes// that match it.  We need to qualify this by the processes// that are running under the specified app and user ID.// package,我们希望命中与它匹配的所有进程。// 我们需要通过在指定应用程序和用户 ID 下运行的进程来限定此条件。// 有指定包名时的过滤逻辑} else {// 该进程是否依赖待终止的包final boolean isDep = app.getPkgDeps() != null&& app.getPkgDeps().contains(packageName);// 如果不依赖,且应用ID不匹配,则跳过if (!isDep && UserHandle.getAppId(app.uid) != appId) {continue;}// 该进程的userId与待终止的userId不匹配,则跳过if (userId != UserHandle.USER_ALL && app.userId != userId) {continue;}// 检查该进程的包名列表里面是否包含待终止的包名final boolean isInPkgList = app.getPkgList().containsKey(packageName);// 如果该进程的包名列表里面不包含待终止的包名,且该进程不依赖待终止的包,则跳过if (!isInPkgList && !isDep) {continue;}// 如果该进程的包名列表里面不包含待终止的包名,且该进程依赖待终止的包,且不是卸载场景,// 且该进程的包信息不为空,且该进程所在包未被冻结,则允许重启if (!isInPkgList && isDep && !uninstalling && app.info != null&& !pm.isPackageFrozen(app.info.packageName, app.uid, app.userId)) {// This package has a dependency on the given package being stopped,// while it's not being frozen nor uninstalled, allow to restart it.// 此包依赖于正在停止的给定包,当它未被冻结或卸载时,允许重新启动它shouldAllowRestart = true;}}// Process has passed all conditions, kill it!// 如果不需要终止,则返回trueif (!doit) {return true;}// 如果需要终止,需要被移除,则设置相关的flagif (setRemoved) {app.setRemoved(true);}// 记录待终止的进程procs.add(new Pair<>(app, shouldAllowRestart));// MIUI ADD: Performance_ProcessKillPolicyProcessListStub.get().notifyProcessDied(app);// END Performance_ProcessKillPolicy}}// 判断是否属于用户应用(应用ID在应用UID范围内)final boolean killingUserApp = appId >= Process.FIRST_APPLICATION_UID&& appId <= Process.LAST_APPLICATION_UID;// 用户应用按UID排序,保证同UID进程连续处理if (killingUserApp) {procs.sort((o1, o2) -> Integer.compare(o1.first.uid, o2.first.uid));}int idx = 0;while (idx < procs.size()) {// 获取当前UID对应的所有进程子列表final List<Pair<ProcessRecord, Boolean>> uidProcs = getUIDSublist(procs, idx);final int packageUID = uidProcs.get(0).first.uid;// Do not freeze for system apps or for dependencies of the targeted package, but// make sure to freeze the targeted package for all users if called with USER_ALL.// 不要冻结系统应用程序或目标包的依赖项,但请确保在使用 USER_ALL 调用时冻结所有用户的目标包。// 用户应用且当前UID匹配目标应用ID时冻结资源 系统应用或依赖进程不冻结 final boolean doFreeze = killingUserApp && UserHandle.getAppId(packageUID) == appId;// 冻结Binder通信和CPU调度(防止终止过程中产生新请求)if (doFreeze) freezeBinderAndPackageCgroup(uidProcs, packageUID);// 逐进程执行终止操作for (Pair<ProcessRecord, Boolean> proc : uidProcs) {removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second,reasonCode, subReason, reason, !doFreeze /* async */);}// 终止关联的Zygote子进程(防止残留)killAppZygotesLocked(packageName, appId, userId, false /* force */);// 解冻资源限制if (doFreeze) unfreezePackageCgroup(packageUID);idx += uidProcs.size();}// 更新剩余进程的OOM优先级mService.updateOomAdjLocked(OOM_ADJ_REASON_PROCESS_END);// 返回是否终止了至少一个进程return procs.size() > 0;}

​​一、进程筛选条件​​

​​1. 进程类型过滤​​
​​持久化进程跳过​​:除非显式要求 (evenPersistent=true),否则不终止 isPersistent 标记的进程。
​​预移除进程处理​​:已标记为 isRemoved 的进程直接加入待终止列表,并根据依赖关系决定是否允许重启。
​​2. OOM优先级限制​​
仅终止 OOM_ADJ 值≥指定 minOomAdj 的低优先级进程(如后台进程)。
​​3. 包名与用户ID匹配规则​​
​​未指定包名​​:根据用户ID(userId)和应用ID(appId)过滤所有相关进程。
​​指定包名​​:
终止包名列表中包含该包名或依赖该包的进程(pkgDeps)。
若非卸载场景,依赖此包的进程允许重启(需包未被冻结)。

​​二、进程处理流程​​

  1. 列表排序优化​​
    若目标是用户应用(appId在应用UID范围内),按UID排序进程列表,确保同UID进程连续,便于批量处理。
  2. 资源冻结阶段​​
    冻结条件​​:仅针对普通用户应用且UID匹配应用ID的进程。
    ​​操作内容​​:
    Binder通信冻结​​:阻止进程接收新的Binder请求。
    CGroup限制​​:停止CPU调度,防止进程执行新任务。
    ​​目的​​:确保终止时不会因新请求导致残留问题。
  3. 进程终止与清理​​
    逐进程移除​​:调用 removeProcessLocked 终止进程,设置重启策略(允许依赖进程重启)。
    ​​关联Zygote清理​​:终止产卵该进程的Zygote子进程,避免僵尸进程。
  4. 资源解冻恢复​​
    同批次冻结的进程终止后,解除CGroup限制,恢复资源调度。

三、结束处理​​

  1. 系统状态更新​​
    调用 updateOomAdjLocked 更新剩余进程的OOM优先级,优化系统资源分配。
  2. ​​返回值​​
    返回 true 表示至少终止了一个进程(或无需实际终止时符合条件)。

四、​​关键设计逻辑​​

  1. ​​同UID批量处理​​
    按UID分组处理避免资源竞争,同时利用 subList 高效分割连续进程,减少遍历成本。
  2. 依赖进程特殊处理​​
    对依赖被终止包的进程,允许重启以维持系统稳定性,避免级联崩溃。
  3. 冻结-终止-解冻流程​​
    确保进程终止过程中无法接收新任务,提升终止可靠性,防止状态不一致。
  4. 系统进程保护机制​​
    跳过持久化进程及系统UID保护,避免影响系统核心功能。

五、术语解析​​

  • ​​OOM_ADJ​​:Android进程优先级指标,值越小优先级越高(如前台应用为0)。
  • ​​CGroup​​:Linux内核资源控制机制,限制进程组资源使用。
  • ​​Zygote​​:Android应用进程孵化器,清理残留子进程可释放资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903007.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openAICEO山姆奥特曼未来预测雄文之三个观察

《三个观察》 山姆奥特曼 这篇文章主要讲的是关于AGI&#xff08;人工通用智能&#xff09;的未来发展及其对社会的影响&#xff0c;用大白话总结如下&#xff1a; 核心观点&#xff1a; AGI是什么&#xff1f; AGI是一种能像人类一样解决各种复杂问题的智能系统&#xff0c;比…

部署yolo到k230教程

训练&#xff1a;K230 借助 AICube部署AI 视觉模型 YOLO等教程_嘉楠 ai cube多标签分类-CSDN博客K230模型训练ai cube报错生成部署文件异常_aicube部署模型显示生成部署文件异常-CSDN博客 部署&#xff1a; # 导入必要的库和模块 import os import ujson # 超快的JS…

Flask 应用封装成 Docker 服务的完整技术指南

一、实现原理 容器化核心逻辑 Docker 通过将应用代码、运行环境和依赖项打包成镜像&#xff0c;实现环境一致性。Flask 应用容器化需包含&#xff1a; Python 基础运行环境项目代码及依赖库&#xff08;requirements.txt&#xff09;WSGI服务器&#xff08;如 Gunicorn&#xf…

windows上的 Vmware Workstation 环境搭建

本文的视频版本&#xff1a;https://www.bilibili.com/video/BV1JhLRzyESh Vmware Workstation 是一款跨平台的桌面级虚拟化软件&#xff0c;可以使用 Vmware 创建虚拟机&#xff0c;我们一般使用 Linux 虚拟机&#xff08;目前主流的 Linux 发行版是 Ubuntu&#xff09;&…

Linux下终端命令行安装常见字体示例

一、准备工作&#xff1a; 准备好要安装的字体文件&#xff0c;如宋体、微软雅黑&#xff08;simsun.ttc、msyh.ttc)。进入字体路径&#xff1a; /usr/share/fonts&#xff0c;使用root权限&#xff0c;新建一个目录shell_fonts。 二、命令行安装字体&#xff1a; 将要安装…

CentOS中在线安装Docker(超详细)

1&#xff09;检查安装docker的基本要求&#xff1a; 64位CPU架构的计算机&#xff0c;目前不支持32为CPU架构的计算机 系统的Linux内核版本为3.10及以上 开启CGroups和namespace功能 2&#xff09;使用命令查看当前系统的内核版本 [rootlocalhost ~]# uname -r 3.10.0-862…

武汉昊衡科技OLI光纤微裂纹检测仪:高密度光器件的精准守护者

随着AI技术应用越来越广&#xff0c;算力需求激增&#xff0c;光通信系统正加速向小型化、高密度、多通道方向演进。硅光芯片、高速光模块等核心器件内部的光纤通道数量成倍增加&#xff0c;波导结构愈发精细&#xff0c;传统检测手段因分辨率不足、效率低下&#xff0c;难以精…

Java数据结构——Stack

Stack 栈的概念和使用栈的概念栈的使用 栈的应用出栈元素序列有效的括号栈的压入、弹出序列逆波兰表达式最小栈 栈的概念和使用 栈的概念 栈(Stack)&#xff1a;一种特殊的线性表&#xff0c;只允许再栈的一端进行插入和删除元素&#xff0c;这一端点被称为栈顶&#xff0c;另…

神经网络与计算机视觉

2016 年,随着 AlphaGo 在围棋比赛中击败李世石,“人工智能”、“神经网络”、“深度 学习”等字眼便越来越多的出现在大众眼前,智能化好像成为一种不可逆转的趋势,带给大家新奇感的同时也带来了一丝忧惧:在不远的未来,机器是否真的拥有思维和情感?《终结者》中天网大战人…

VS2019 与gitcode团队管理

1、安装git 点击下一步安装即可 2、vs2019连接gitcode 然后更改本地的代码添加文件等都可以进行远程同步操作了

Python类和对象四(十三)

魔法方法&#xff1a; 按位运算 按位于运算 只要相同才是1 或运算&#xff1a; 只要某个位是1结果就是1 、 按位非 将结果取反 按位异或&#xff1a; 左移和右移运算符&#xff1a; 右移两位 右移动n位&#xff0c;就是除以2的n次方 左移两位&#xff1a; 左移n位就是乘…

如何设置极狐GitLab 议题截止日?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 截止日期 (BASIC ALL) 可以在议题中使用截止日期&#xff0c;来跟踪截止日期并确保功能按时交付。用户至少需要报告者权限才…

如何在 Conda 环境中降级 Python 版本:详细指南

如何在 Conda 环境中降级 Python 版本&#xff1a;详细指南 Python 版本的管理在开发过程中至关重要&#xff0c;特别是在处理不同项目需求时。对于使用 Conda 环境的 Python 程序员来说&#xff0c;版本管理不仅仅是安装不同的 Python 版本&#xff0c;还涉及到依赖关系的兼容…

【随笔】地理探测器原理与运用

文章目录 一、作者与下载1.1 软件作者1.2 软件下载 二、原理简述2.1 空间分异性与地理探测器的提出2.2 地理探测器的数学模型2.21 分异及因子探测2.22 交互作用探测2.23 风险区与生态探测 三、使用&#xff1a;excel 一、作者与下载 1.1 软件作者 作者&#xff1a; DOI: 10.…

使用达梦官方管理工具SQLark快速生成数据库ER图并导出

在数据库设计与开发中&#xff0c;实体-关系图&#xff08;ER 图&#xff09;作为数据建模的核心工具&#xff0c;能够直观呈现表结构、字段属性及表间关系&#xff0c;是团队沟通和文档维护的重要工具。然而&#xff0c;对于许多使用达梦数据库的开发者来说&#xff0c;可用的…

单精度浮点运算/定点运算下 MATLAB (VS) VIVADO

VIVADO中单精度浮点数IP核计算结果与MATLAB单精度浮点数计算结果的对比 MATLAB定点运算仿真&#xff0c;对比VIVADO计算的结果 目录 前言 一、VIVADO与MATLAB单精度浮点数运算结果对比 二、MATLAB定点运算仿真 总结 前言 本文介绍了怎么在MATLAB中使用单精度浮点数进行运算…

力扣-141.环形链表

题目描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中存在环 &#xff0c;则返回 true 。 否则&#xff0c;返回 false 。 class Solution { public:bool hasCycle(ListNode *head) {ListNode *fast head;ListNode *slow head;while (fast! n…

RESTful学习笔记(一)

Web发展 一、API 程序硬件接口&#xff08;Application Programming Interface&#xff09;&#xff0c;是预先定义好的逻辑函数&#xff0c;软件系统不同组成部分衔接的约定&#xff0c;直接调用函数&#xff0c;无序访问代码细节&#xff0c;分为SDK和Web应用接口两类 SDK…

SD2351核心板:重构AI视觉产业价值链的“超级节点”

在AI视觉技术狂飙突进的当下&#xff0c;一个吊诡的现象正在浮现&#xff1a;一方面&#xff0c;学术界不断刷新着ImageNet等基准测试的精度纪录&#xff1b;另一方面&#xff0c;产业界却深陷“算法有、场景无&#xff0c;技术强、落地难”的怪圈。明远智睿SD2351核心板的问世…

【数据结构】红黑树原理及实现

目录 一. 红黑树的概念1. 红黑树的规则思考 2. 红黑树的效率 二.红黑树的实现1. 红黑树的结构2. 红黑树的插入3. 红黑树的平衡调整情况1&#xff1a;变色情况2&#xff1a;单旋变色情况3&#xff1a;双旋变色 4. 红黑树插入及平衡调整代码实现5.红黑树的验证 一. 红黑树的概念 …