Android OomAdjuster 与 computeOomAdjLSP 方法深度解析
文档基于 Android 13/14 AAOS MediaTek MT8678 平台 源文件路径:
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
1. OomAdjuster 概述
1.1 类定义与职责
OomAdjuster 是 Android 进程管理的核心组件,负责计算和管理所有应用进程的 OOM 调整值(oom_adj)和进程状态(procState)。
java
/**
* All of the code required to compute proc states and oom_adj values.
*/
public class OomAdjuster {
// ...
}
核心职责:
- 进程优先级计算 - 根据进程当前状态计算
oom_adj值,决定进程被 LMK (Low Memory Killer) 杀死的优先级 - 进程状态管理 - 计算
procState,影响进程的能力限制(网络访问、后台限制等) - 调度组分配 - 决定进程的 CPU 调度优先级(
schedGroup) - 能力传播 - 管理
capability在绑定关系中的传播
1.2 在 Android 进程管理中的地位
bash
┌─────────────────────────────────────────────────────────────┐
│ Low Memory Killer (LMK) │
│ 根据 oom_adj 值选择杀进程 │
└─────────────────────────────────────────────────────────────┘
│ 使用
▼
┌─────────────────────────────────────────────────────────────┐
│ OomAdjuster │
│ 计算并管理 oom_adj/procState │
└─────────────────────────────────────────────────────────────┘
│ 服务
▼
┌─────────────────────────────────────────────────────────────┐
│ ActivityManagerService │
│ 组件状态变化触发 OOM adj 更新 │
└─────────────────────────────────────────────────────────────┘
│ 触发
▼
┌─────────────────────────────────────────────────────────────┐
│ Activity/Service/Provider/Receiver 状态变化 │
└─────────────────────────────────────────────────────────────┘
1.3 核心数据结构
java
// 进程记录中存储 adj 相关状态
ProcessStateRecord state = app.mState;
state.setCurAdj(adj); // 当前 adj 值
state.setCurProcState(procState); // 当前进程状态
state.setCurrentSchedulingGroup(schedGroup); // 调度组
state.setCurCapability(capability); // 进程能力
// 用于追踪计算状态的序列号
private int mAdjSeq; // 当前计算轮次序号
state.getAdjSeq(); // 进程最后计算序号
state.getCompletedAdjSeq(); // 完成计算的序号
2. OOM Adj 常量定义
OOM adj 值越小,进程优先级越高,越不容易被 LMK 杀死。
2.1 Adj 值等级表 (ProcessList.java)
| 常量名 | 值 | 描述 | 典型场景 |
|---|---|---|---|
PERSISTENT_SERVICE_ADJ |
-700 | 持久化服务 | 系统核心服务 |
FOREGROUND_APP_ADJ |
0 | 前台应用 | 当前交互的Activity |
PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ |
50 | 最近前台 | 刚离开前台的应用 |
VISIBLE_APP_ADJ |
100 | 可见应用 | 可见但非焦点的Activity |
PERCEPTIBLE_APP_ADJ |
200 | 可感知应用 | 前台服务(FGS)、overlay UI |
PERCEPTIBLE_MEDIUM_APP_ADJ |
250 | 中等可感知 | 短时FGS |
PERCEPTIBLE_LOW_APP_ADJ |
300 | 低可感知 | 低优先级感知 |
BACKUP_APP_ADJ |
300 | 备份应用 | 正在进行备份的进程 |
HEAVY_WEIGHT_APP_ADJ |
400 | 重型应用 | heavy-weight 进程 |
SERVICE_ADJ |
500 | 服务 | 已启动的后台服务 |
SERVICE_B_ADJ |
800 | B类服务 | 内存压力大时降级的服务 |
HOME_APP_ADJ |
600 | 主屏幕 | Launcher 进程 |
PREVIOUS_APP_ADJ |
700 | 上一个应用 | 用户刚切换离开的进程 |
CACHED_APP_MIN_ADJ |
900 | 缓存最小 | 缓存进程起始值 |
CACHED_APP_MAX_ADJ |
999 | 缓存最大 | 最容易被杀的进程 |
2.2 Adj 值分布图
scss
-700 ────────────────────────────────────────────────────────▶ 0
PERSISTENT_SERVICE (系统核心)
0 ──────────────────────────────────────────────────────────▶ 100
FOREGROUND (前台交互)
100 ────────────────────────────────────────────────────────▶ 200
VISIBLE (可见但非焦点)
200 ────────────────────────────────────────────────────────▶ 500
PERCEPTIBLE (FGS, overlay UI, backup)
500 ────────────────────────────────────────────────────────▶ 700
SERVICE (后台服务)
700 ────────────────────────────────────────────────────────▶ 900
HOME/PREVIOUS (Launcher, 切换进程)
900 ────────────────────────────────────────────────────────▶ 999
CACHED (缓存进程,最易被杀)
3. Process State 常量定义
进程状态决定了进程的能力和限制。
3.1 ProcState 等级表 (ActivityManager.java)
| 常量名 | 值 | 描述 | 能力级别 |
|---|---|---|---|
PROCESS_STATE_PERSISTENT |
0 | 持久化进程 | 全能力 |
PROCESS_STATE_PERSISTENT_UI |
1 | 持久化UI进程 | 全能力 |
PROCESS_STATE_TOP |
2 | 顶部进程 | 全能力 + TOP调度 |
PROCESS_STATE_BOUND_TOP |
3 | 绑定到TOP | BFSL能力 |
PROCESS_STATE_FOREGROUND_SERVICE |
4 | 前台服务 | 根据FGS类型 |
PROCESS_STATE_BOUND_FOREGROUND_SERVICE |
5 | 绑定FGS | BFSL能力 |
PROCESS_STATE_IMPORTANT_FOREGROUND |
6 | 重要前台 | 受限能力 |
PROCESS_STATE_IMPORTANT_BACKGROUND |
7 | 重要后台 | 网络受限 |
PROCESS_STATE_TRANSIENT_BACKGROUND |
8 | 短暂后台 | 网络受限 |
PROCESS_STATE_BACKUP |
9 | 备份 | 特殊保护 |
PROCESS_STATE_SERVICE |
10 | 服务 | 后台限制 |
PROCESS_STATE_RECEIVER |
11 | 广播接收器 | 后台限制 |
PROCESS_STATE_TOP_SLEEPING |
12 | 顶部睡眠 | 屏幕关闭时 |
PROCESS_STATE_HEAVY_WEIGHT |
13 | 重型进程 | 特殊保护 |
PROCESS_STATE_HOME |
14 | 主屏幕 | Home调度 |
PROCESS_STATE_LAST_ACTIVITY |
15 | 最后活动 | 切换保护 |
PROCESS_STATE_CACHED_ACTIVITY |
16 | 缓存活动 | 可被杀 |
PROCESS_STATE_CACHED_ACTIVITY_CLIENT |
17 | 缓存活动客户端 | 可被杀 |
PROCESS_STATE_CACHED_RECENT |
18 | 缓存最近 | 可被杀 |
PROCESS_STATE_CACHED_EMPTY |
19 | 缓存空 | 最易被杀 |
3.2 ProcState 与能力关系
java
// 全能力:BFSL允许,网络无限制
case PROCESS_STATE_PERSISTENT:
case PROCESS_STATE_PERSISTENT_UI:
case PROCESS_STATE_TOP:
baseCapabilities = PROCESS_CAPABILITY_ALL;
// BFSL能力:可以从后台启动FGS
case PROCESS_STATE_BOUND_TOP:
baseCapabilities = PROCESS_CAPABILITY_BFSL;
// 前台服务能力:取决于FGS类型
case PROCESS_STATE_FOREGROUND_SERVICE:
baseCapabilities = PROCESS_CAPABILITY_NONE; // 由FGS类型决定
// 默认:无特殊能力
default:
baseCapabilities = PROCESS_CAPABILITY_NONE;
4. Sched Group 常量
调度组控制进程的 CPU 调度优先级。
| 常量名 | 值 | 描述 | CPU 优先级 |
|---|---|---|---|
SCHED_GROUP_BACKGROUND |
0 | 后台 | 最低,THREAD_GROUP_BACKGROUND |
SCHED_GROUP_RESTRICTED |
1 | 受限 | 灭屏时UI进程降级 |
SCHED_GROUP_DEFAULT |
2 | 默认 | 正常优先级 |
SCHED_GROUP_TOP_APP |
3 | 顶部应用 | 最高,FIFO调度或优先级boost |
SCHED_GROUP_TOP_APP_BOUND |
4 | 绑定顶部 | 高优先级 |
5. computeOomAdjLSP 方法详解
5.1 方法签名
java
@GuardedBy({"mService", "mProcLock"})
private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
// 源码位置: OomAdjuster.java:1724
}
5.2 参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
app |
ProcessRecord | 要计算 adj 的目标进程 |
cachedAdj |
int | 缓存的 adj 值,用于默认初始值 |
topApp |
ProcessRecord | 当前顶部应用进程 |
doingAll |
boolean | 是否为全量更新(遍历所有进程) |
now |
long | 当前时间戳(uptimeMillis) |
cycleReEval |
boolean | 是否为循环依赖的重新评估 |
computeClients |
boolean | 是否递归计算客户端进程 |
5.3 返回值
- 返回
true: 进程被提升(adj 或 procState 改善) - 返回
false: 进程未变化或已完成计算
6. computeOomAdjLSP 执行流程
6.1 流程总览图
flowchart TD
A[开始 computeOomAdjLSP] --> B{检查计算序号}
B -->|已计算完成| C[返回 false]
B -->|正在计算| D[标记循环依赖]
B -->|未计算| E{检查进程状态}
E -->|无线程/已死亡| F[设为CACHED_APP_MAX_ADJ]
E -->|有线程| G{检查 maxAdj}
G -->|maxAdj <= FOREGROUND| H[固定优先级处理]
G -->|正常进程| I[开始优先级判断]
I --> J{顶部Activity?}
J -->|是| K[adj=0, procState=TOP]
J -->|否| L{远程动画?}
L -->|是| M[adj=100, schedGroup=TOP]
L -->|否| N{Instrumentation?}
N -->|是| O[adj=0, procState=FGS]
N -->|否| P{接收广播?}
P -->|是| Q[adj=0, procState=RECEIVER]
P -->|否| R{执行服务?}
R -->|是| S[adj=0, procState=SERVICE]
R -->|否| T{顶部睡眠?}
T -->|是| U[adj=0, procState=CUR_TOP]
T -->|否| V[默认空进程]
V --> W[检查Activity状态]
W --> X{有前台服务FGS?}
X -->|普通FGS| Y[adj=200, procState=FGS]
X -->|短时FGS| Z[adj=251]
X -->|overlay UI| AA[adj=200]
AA --> AB{特殊进程类型?}
AB -->|HeavyWeight| AC[adj=400]
AB -->|Home进程| AD[adj=600]
AB -->|Previous进程| AE[adj=700]
AB -->|Backup进程| AF[adj=300]
AF --> AG[处理服务绑定关系]
AG --> AH[处理Provider关系]
AH --> AI[计算capability]
AI --> AJ[设置最终值]
AJ --> AK[返回结果]
6.2 阶段一:初始化检查 (1728-1751行)
java
// 检查是否已计算过
if (mAdjSeq == state.getAdjSeq()) {
if (state.getAdjSeq() == state.getCompletedAdjSeq()) {
// 已完成计算,直接返回
return false;
} else {
// 正在计算中,检测到循环依赖
state.setContainsCycle(true);
mProcessesInCycle.add(app);
return false;
}
}
// 处理已死亡进程
if (app.getThread() == null) {
state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
state.setCurAdj(CACHED_APP_MAX_ADJ); // 999,最易被杀
return false;
}
关键点:
- 使用
adjSeq序列号追踪计算状态,避免重复计算 - 循环依赖检测防止无限递归
- 死亡进程直接设为最低优先级
6.3 阶段二:固定优先级进程处理 (1774-1819行)
java
if (state.getMaxAdj() <= FOREGROUND_APP_ADJ) {
// 系统进程、persistent进程等固定优先级进程
state.setAdjType("fixed");
state.setCurAdj(state.getMaxAdj());
state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
state.setCurrentSchedulingGroup(SCHED_GROUP_DEFAULT);
// 检查是否有UI显示
if (app == topApp) {
state.setCurrentSchedulingGroup(SCHED_GROUP_TOP_APP);
} else if (state.hasTopUi()) {
// 有顶层UI,但不是topApp
state.setSystemNoUi(false);
}
// 根据屏幕状态调整
if (!state.isSystemNoUi()) {
if (isScreenOnOrAnimatingLocked(state)) {
// 屏幕亮起,提升为 UI 进程
state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
state.setCurrentSchedulingGroup(SCHED_GROUP_TOP_APP);
} else {
// 屏幕关闭,降级调度
state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
state.setCurrentSchedulingGroup(SCHED_GROUP_RESTRICTED);
}
}
return state.getCurAdj() < prevAppAdj;
}
关键点:
maxAdj <= 0的进程(如 system_server)有固定优先级- 屏幕状态影响 UI 进程的调度组
- 灭屏时降级为
SCHED_GROUP_RESTRICTED
6.4 阶段三:前台优先级判断 (1825-1917行)
这是最关键的阶段,按优先级从高到低依次检查:
6.4.1 顶部Activity (1834-1851行)
java
if (app == topApp && PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP) {
// 当前前台Activity的进程
adj = FOREGROUND_APP_ADJ; // 0
schedGroup = SCHED_GROUP_TOP_APP; // 最高调度
foregroundActivities = true;
procState = PROCESS_STATE_TOP; // 2
state.setAdjType("top-activity");
}
最高优先级,不会被 LMK 杀死。
6.4.2 远程动画运行 (1852-1859行)
java
else if (state.isRunningRemoteAnimation()) {
// 执行远程动画(如转场动画)
adj = VISIBLE_APP_ADJ; // 100
schedGroup = SCHED_GROUP_TOP_APP;
state.setAdjType("running-remote-anim");
procState = PROCESS_STATE_CUR_TOP;
}
6.4.3 Instrumentation测试 (1860-1869行)
java
else if (app.getActiveInstrumentation() != null) {
// 正在运行Instrumentation测试
adj = FOREGROUND_APP_ADJ; // 0
schedGroup = SCHED_GROUP_DEFAULT;
procState = PROCESS_STATE_FOREGROUND_SERVICE;
capability |= PROCESS_CAPABILITY_BFSL; // 允许后台启动FGS
state.setAdjType("instrumentation");
}
6.4.4 正在接收广播 (1870-1881行)
java
else if (state.getCachedIsReceivingBroadcast(mTmpSchedGroup)) {
// 正在执行BroadcastReceiver.onReceive()
adj = FOREGROUND_APP_ADJ; // 0
schedGroup = mTmpSchedGroup[0]; // 根据广播队列决定
procState = ActivityManager.PROCESS_STATE_RECEIVER; // 11
state.setAdjType("broadcast");
}
广播优先级根据队列类型:
- 前台广播队列 →
SCHED_GROUP_DEFAULT - 后台广播队列 →
SCHED_GROUP_BACKGROUND
6.4.5 正在执行服务回调 (1882-1892行)
java
else if (psr.numberOfExecutingServices() > 0) {
// 正在执行Service的生命周期回调
adj = FOREGROUND_APP_ADJ; // 0
schedGroup = psr.shouldExecServicesFg()
? SCHED_GROUP_DEFAULT : SCHED_GROUP_BACKGROUND;
procState = PROCESS_STATE_SERVICE; // 10
state.setAdjType("exec-service");
}
6.4.6 顶部睡眠进程 (1893-1901行)
java
else if (app == topApp) {
// 是topApp但PROCESS_STATE_CUR_TOP != TOP(屏幕关闭)
adj = FOREGROUND_APP_ADJ; // 0
schedGroup = SCHED_GROUP_BACKGROUND;
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP; // 可能是TOP_SLEEPING
state.setAdjType("top-sleeping");
}
6.4.7 默认空进程 (1902-1917行)
java
else {
// 默认情况:未知重要性
schedGroup = SCHED_GROUP_BACKGROUND;
adj = cachedAdj; // 使用传入的默认值
procState = PROCESS_STATE_CACHED_EMPTY; // 19
state.setCached(true);
state.setEmpty(true);
state.setAdjType("cch-empty");
}
6.5 阶段四:Activity状态检查 (1919-1930行)
java
if (!foregroundActivities && state.getCachedHasActivities()) {
// 如果还没有前台Activity,检查所有Activity的可见性
state.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
adj, foregroundActivities, hasVisibleActivities, procState, schedGroup,
appUid, logUid, PROCESS_STATE_CUR_TOP);
// 使用Activity计算结果
adj = state.getCachedAdj();
foregroundActivities = state.getCachedForegroundActivities();
procState = state.getCachedProcState();
schedGroup = state.getCachedSchedGroup();
}
Activity可见性等级:
VISIBLE_APP_ADJ(100) - Activity可见且有焦点PERCEPTIBLE_APP_ADJ(200) - Activity可见但暂停CACHED_APP_MIN_ADJ(900) - Activity不可见
6.6 阶段五:前台服务(FGS)调整 (1940-2015行)
java
final boolean hasForegroundServices = psr.hasForegroundServices();
final boolean hasNonShortForegroundServices = psr.hasNonShortForegroundServices();
if (adj > PERCEPTIBLE_APP_ADJ || procState > PROCESS_STATE_FOREGROUND_SERVICE) {
if (hasForegroundServices && hasNonShortForegroundServices) {
// 普通前台服务(非短时)
adjType = "fg-service";
newAdj = PERCEPTIBLE_APP_ADJ; // 200
newProcState = PROCESS_STATE_FOREGROUND_SERVICE; // 4
capabilityFromFGS |= PROCESS_CAPABILITY_BFSL;
} else if (hasShortForegroundServices) {
// 短时前台服务(5分钟超时)
adjType = "fg-service-short";
newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 1; // 251
newProcState = PROCESS_STATE_FOREGROUND_SERVICE;
// 短时FGS不获得BFSL能力
} else if (state.hasOverlayUi()) {
// overlay UI(如Toast、悬浮窗)
adjType = "has-overlay-ui";
newAdj = PERCEPTIBLE_APP_ADJ; // 200
newProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
}
}
FGS优先级提升:
- 普通FGS: adj=200, 可获得BFSL能力
- 短时FGS: adj=251, 无BFSL能力,5分钟后超时
6.7 阶段六:特殊进程类型处理 (2055-2129行)
java
// HeavyWeight进程(大型游戏等)
if (state.getCachedIsHeavyWeight()) {
if (adj > HEAVY_WEIGHT_APP_ADJ) {
adj = HEAVY_WEIGHT_APP_ADJ; // 400
state.setAdjType("heavy");
}
if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; // 13
}
}
// Home进程(Launcher)
if (state.getCachedIsHomeProcess()) {
if (adj > HOME_APP_ADJ) {
adj = HOME_APP_ADJ; // 600
state.setAdjType("home");
}
if (procState > ActivityManager.PROCESS_STATE_HOME) {
procState = ActivityManager.PROCESS_STATE_HOME; // 14
}
}
// Previous进程(刚切换离开的进程)
if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
// 保持一段时间的高优先级,方便快速切换回来
if (adj > PREVIOUS_APP_ADJ) {
adj = PREVIOUS_APP_ADJ; // 700
state.setAdjType("previous");
}
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
procState = PROCESS_STATE_LAST_ACTIVITY; // 15
}
}
特殊进程保护:
HeavyWeight: 大型应用,防止频繁重启Home: Launcher必须保持运行Previous: 用户可能快速切换回来
6.8 阶段七:服务绑定关系处理 (2176-2597行)
这是最复杂的阶段,处理进程间绑定关系对优先级的影响:
java
for (int is = psr.numberOfRunningServices() - 1;
is >= 0 && (adj > FOREGROUND_APP_ADJ
|| schedGroup == SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
is--) {
ServiceRecord s = psr.getRunningServiceAt(is);
// 处理服务连接
ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
for (int conni = serviceConnections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
ConnectionRecord cr = clist.get(i);
ProcessRecord client = cr.binding.client;
// 递归计算客户端
if (computeClients) {
computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
cycleReEval, true);
}
int clientAdj = cstate.getCurRawAdj();
int clientProcState = cstate.getCurRawProcState();
// 根据绑定标志调整优先级
if (adj > clientAdj) {
if (cr.hasFlag(Context.BIND_ABOVE_CLIENT | Context.BIND_IMPORTANT)) {
// 服务比客户端更重要
if (clientAdj >= PERSISTENT_SERVICE_ADJ) {
newAdj = clientAdj;
} else {
newAdj = PERSISTENT_SERVICE_ADJ; // -700
}
} else if (cr.hasFlag(Context.BIND_NOT_PERCEPTIBLE)) {
newAdj = PERCEPTIBLE_LOW_APP_ADJ; // 300
} else if (cr.hasFlag(Context.BIND_NOT_VISIBLE)) {
newAdj = PERCEPTIBLE_APP_ADJ; // 200
} else {
// 默认:继承客户端优先级
newAdj = Math.max(clientAdj, VISIBLE_APP_ADJ);
}
}
// 调整 procState
if (clientProcState == PROCESS_STATE_TOP) {
// 绑定到TOP的进程
clientProcState = PROCESS_STATE_BOUND_TOP; // 3
} else if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; // 5
}
}
}
}
关键绑定标志:
| 标志 | 效果 |
|---|---|
BIND_ABOVE_CLIENT |
服务优先级高于客户端 |
BIND_IMPORTANT |
重要绑定,提升调度组 |
BIND_NOT_FOREGROUND |
不提升到前台调度 |
BIND_NOT_PERCEPTIBLE |
不超过感知级别 |
BIND_NOT_VISIBLE |
不超过可见级别 |
BIND_INCLUDE_CAPABILITIES |
传播能力 |
BIND_TREAT_LIKE_ACTIVITY |
视为Activity |
BIND_WAIVE_PRIORITY |
不调整优先级 |
6.9 阶段八:ContentProvider关系处理 (2599-2746行)
java
final ProcessProviderRecord ppr = app.mProviders;
for (int provi = ppr.numberOfProviders() - 1; provi >= 0; provi--) {
ContentProviderRecord cpr = ppr.getProviderAt(provi);
for (int i = cpr.connections.size() - 1; i >= 0; i--) {
ContentProviderConnection conn = cpr.connections.get(i);
ProcessRecord client = conn.client;
// 递归计算客户端
if (computeClients) {
computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
cycleReEval, true);
}
int clientAdj = cstate.getCurRawAdj();
int clientProcState = cstate.getCurRawProcState();
// Provider优先级至少为 FOREGROUND_APP_ADJ
if (adj > clientAdj) {
adj = Math.max(clientAdj, FOREGROUND_APP_ADJ); // 0
state.setAdjType("provider");
}
// Provider procState 调整
if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
if (clientProcState == PROCESS_STATE_TOP) {
clientProcState = PROCESS_STATE_BOUND_TOP;
} else {
clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
}
}
}
// 外部进程依赖(非framework)
if (cpr.hasExternalProcessHandles()) {
adj = FOREGROUND_APP_ADJ; // 0
state.setAdjType("ext-provider");
}
}
6.10 阶段九:最终调整 (2761-2850行)
java
// 服务B类处理(内存压力降级)
if (adj == SERVICE_ADJ) {
if (state.isServiceB()) {
adj = SERVICE_B_ADJ; // 800,降级
}
}
// 应用 maxAdj 限制
if (adj > state.getMaxAdj()) {
adj = state.getMaxAdj();
}
// 计算默认能力
capability |= getDefaultCapability(app, procState);
// BFSL能力限制:procState > BFGS 时移除
if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
capability &= ~PROCESS_CAPABILITY_BFSL;
}
// 设置最终值
state.setCurAdj(adj);
state.setCurCapability(capability);
state.setCurrentSchedulingGroup(schedGroup);
state.setCurProcState(procState);
state.setCompletedAdjSeq(mAdjSeq);
return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
7. 循环依赖处理机制
7.1 循环依赖场景
css
进程A 绑定 服务B
↓
服务B 绑定 ProviderC
↓
ProviderC 绑定 进程A ← 形成循环!
7.2 处理策略
java
// updateOomAdjInnerLSP 中的循环处理
int cycleCount = 0;
while (retryCycles && cycleCount < 10) {
cycleCount++;
retryCycles = false;
// 重置循环进程的计算序号
for (int i = 0; i < numProc; i++) {
ProcessRecord app = activeProcesses.get(i);
if (state.containsCycle()) {
state.decAdjSeq();
state.decCompletedAdjSeq();
}
}
// 重新计算循环进程
for (int i = 0; i < numProc; i++) {
if (state.containsCycle()) {
if (computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, true, now,
true, true)) { // cycleReEval=true
retryCycles = true;
}
}
}
}
处理逻辑:
- 标记循环依赖进程 (
containsCycle) - 多次迭代重新计算(最多10次)
- 使用部分值进行评估 (
cycleReEval=true) - 直到所有进程稳定为止
8. 影响 adj 值的因素总结
8.1 直接因素
| 因素 | 优先级 | adj 范围 | 触发条件 |
|---|---|---|---|
| 顶部Activity | 最高 | 0 (FOREGROUND) | Activity 处于前台焦点 |
| 可见Activity | 高 | 100-200 (VISIBLE/PERCEPTIBLE) | Activity 可见但非焦点 |
| 前台服务(FGS) | 中高 | 200-251 (PERCEPTIBLE) | startForeground() 调用 |
| 后台服务 | 中 | 500 (SERVICE) | startService() 启动 |
| 广播接收 | 中 | 0 (FOREGROUND) | onReceive() 执行中 |
| 主屏幕进程 | 低 | 600 (HOME) | 是 Launcher 进程 |
| 上一个进程 | 低 | 700 (PREVIOUS) | 用户刚切换离开 |
| 缓存进程 | 最低 | 900-999 (CACHED) | 无活动组件 |
8.2 间接因素(绑定关系)
| 因素 | 效果 | 典型场景 |
|---|---|---|
| 绑定高优先级客户端 | 提升服务端adj | 前台Activity绑定后台服务 |
| Provider被高优先级使用 | 提升Provider进程 | 前台应用查询Provider |
| BIND_ABOVE_CLIENT | 服务比客户端更重要 | 系统服务绑定 |
| BIND_NOT_FOREGROUND | 不提升到前台 | 后台绑定 |
| BIND_INCLUDE_CAPABILITIES | 传播能力 | FGS能力传播 |
8.3 其他影响因素
| 因素 | 效果 | 代码位置 |
|---|---|---|
| 屏幕状态(亮屏/灭屏) | UI进程调度组降级 | OomAdjuster:1804-1812 |
| keepWarming服务 | 保持SERVICE_ADJ | OomAdjuster:2201-2215 |
| Instrumentation测试 | 前台优先级保护 | OomAdjuster:1860-1869 |
| 备份状态 | 防止被杀(adj=300) | OomAdjuster:2150-2172 |
| 内存压力 | 服务降级为B类 | OomAdjuster:2761-2786 |
| maxAdj限制 | 上限约束 | OomAdjuster:2791-2796 |
9. OomAdjuster 使用场景
9.1 触发时机 (OOM_ADJ_REASON)
java
// ActivityManagerInternal.java 定义的触发原因
OOM_ADJ_REASON_ACTIVITY // Activity 状态变化
OOM_ADJ_REASON_START_SERVICE // startService()
OOM_ADJ_REASON_STOP_SERVICE // stopService()
OOM_ADJ_REASON_BIND_SERVICE // bindService()
OOM_ADJ_REASON_UNBIND_SERVICE // unbindService()
OOM_ADJ_REASON_START_RECEIVER // BroadcastReceiver 开始
OOM_ADJ_REASON_FINISH_RECEIVER // BroadcastReceiver 结束
OOM_ADJ_REASON_GET_PROVIDER // getContentProvider()
OOM_ADJ_REASON_REMOVE_PROVIDER // removeContentProvider()
OOM_ADJ_REASON_UI_VISIBILITY // Activity 可见性变化
OOM_ADJ_REASON_PROCESS_BEGIN // 进程启动
OOM_ADJ_REASON_PROCESS_END // 进程结束
OOM_ADJ_REASON_SYSTEM_INIT // 系统启动初始化
OOM_ADJ_REASON_BACKUP // 备份开始/结束
OOM_ADJ_REASON_SHORT_FGS_TIMEOUT // 短时FGS超时
OOM_ADJ_REASON_UID_IDLE // UID进入idle
OOM_ADJ_REASON_ALLOWLIST // 白名单变化
OOM_ADJ_REASON_RESTRICTION_CHANGE // 限制策略变化
9.2 核心调用链
scss
┌─────────────────────────────────────────────────────────────┐
│ 组件状态变化(Activity/Service/Provider) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ ActivityManagerService 状态更新 │
│ (如: realStartActivityLocked, bindServiceLocked) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ OomAdjuster.updateOomAdjLocked() │
│ 触发 adj 计算 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ updateOomAdjLSP() │
│ 获取 mProcLock 锁 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ performUpdateOomAdjLSP() │
│ 获取 topApp, 增加 mAdjSeq │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ updateOomAdjInnerLSP() │
│ 遍历 LRU 进程列表 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ computeOomAdjLSP() │
│ 计算每个进程的 adj/procState/schedGroup │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ applyOomAdjLSP() │
│ 应用计算结果到系统 │
├─────────────────────────────────────────────────────────────┤
│ - ProcessList.setOomAdj() → 写入 /proc/pid/oom_score_adj │
│ - setProcessGroup() → 设置调度组 │
│ - setThreadPriority() → 设置线程优先级 │
└─────────────────────────────────────────────────────────────┘
9.3 实际触发示例
Activity切换场景:
java
// ActivityTaskManagerService
void startActivityInner() {
// ...
mTaskSupervisor.startActivityResolvedActivity();
// Activity状态变化,触发 OOM adj 更新
mService.updateOomAdjLocked(OOM_ADJ_REASON_ACTIVITY);
}
绑定服务场景:
java
// ActiveServices
int bindServiceLocked(IServiceConnection connection, Intent service, ...) {
// ...
bringUpServiceLocked(serviceRecord);
// 服务绑定,更新相关进程的 adj
mAm.updateOomAdjLocked(OOM_ADJ_REASON_BIND_SERVICE);
}
10. 关键代码路径标注
10.1 重要方法位置
| 方法 | 文件位置 | 行号 |
|---|---|---|
computeOomAdjLSP |
OomAdjuster.java | 1724-2850 |
updateOomAdjLocked |
OomAdjuster.java | 569-573, 609-613 |
updateOomAdjInnerLSP |
OomAdjuster.java | 935-1080 |
applyOomAdjLSP |
OomAdjuster.java | 2986-3100 |
setOomAdj |
ProcessList.java | 调用内核写入 |
10.2 关键决策点
| 决策点 | 行号 | 说明 |
|---|---|---|
| 循环检测 | 1728-1740 | 检查 adjSeq 避免重复 |
| 死亡进程处理 | 1742-1751 | 无线程进程设最低adj |
| 固定优先级处理 | 1774-1819 | 系统进程特殊处理 |
| TOP进程判断 | 1834-1851 | 最高优先级 |
| FGS类型判断 | 1954-1995 | 普通FGS vs 短时FGS |
| 服务绑定传播 | 2248-2597 | 复杂的绑定关系处理 |
| Provider优先级 | 2599-2746 | Provider客户端影响 |
| 最终adj应用 | 2837-2849 | 写入进程状态 |
11. 实践调试技巧
11.1 查看 OOM adj 状态
bash
# 查看进程 adj 值
adb shell cat /proc/<pid>/oom_score_adj
# 查看所有进程 adj
adb shell ps -eo PID,NAME,OOM_ADJ
# dumpsys 查看 adj 详情
adb shell dumpsys activity oom
# 查看 adj 变化日志
adb logcat -s OOM_ADJ
11.2 调试开关
java
// ActivityManagerDebugConfig.java
static final boolean DEBUG_OOM_ADJ = true;
static final boolean DEBUG_OOM_ADJ_REASON = true;
// 启用后会打印详细日志
// "Set <pid> <processName> adj <value>: <adjType>"
11.3 常见问题排查
| 问题 | 可能原因 | 检查点 |
|---|---|---|
| 进程频繁被杀 | adj 过高 | 检查是否有FGS或绑定关系 |
| 服务无法保持运行 | 缺少绑定 | 检查BIND_AUTO_CREATE |
| 后台无法启动FGS | 缺少BFSL能力 | 检查procState <= BFGS |
| 网络受限 | procState过高 | 检查是否进入后台限制 |
参考文献
-
源码文件
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.javaframeworks/base/services/core/java/com/android/server/am/ProcessList.javaframeworks/base/core/java/android/app/ActivityManager.java
-
Android官方文档
-
相关类
ProcessRecord- 进程记录ProcessStateRecord- 进程状态UidRecord- UID记录ServiceRecord- 服务记录ContentProviderRecord- Provider记录ConnectionRecord- 绑定连接记录
文档创建日期: 2026/04/28 基于 Android 13/14 AAOS MT8678 平台