Android OomAdjuster流程

18 阅读15分钟

Android OomAdjuster 与 computeOomAdjLSP 方法深度解析

源文件路径: frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java


1. OomAdjuster 概述

1.1 类定义与职责

OomAdjuster 是 Android 进程管理的核心组件,负责计算和管理所有应用进程的 OOM 调整值(oom_adj)和进程状态(procState)。

/**
 * All of the code required to compute proc states and oom_adj values.
 */
public class OomAdjuster {
    // ...
}

核心职责:

  1. 进程优先级计算 - 根据进程当前状态计算 oom_adj 值,决定进程被 LMK (Low Memory Killer) 杀死的优先级
  2. 进程状态管理 - 计算 procState,影响进程的能力限制(网络访问、后台限制等)
  3. 调度组分配 - 决定进程的 CPU 调度优先级(schedGroup
  4. 能力传播 - 管理 capability 在绑定关系中的传播

1.2 在 Android 进程管理中的地位

┌─────────────────────────────────────────────────────────────┐
│                    Low Memory Killer (LMK)                   │
│                  根据 oom_adj 值选择杀进程                     │
└─────────────────────────────────────────────────────────────┘
                           │ 使用
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                      OomAdjuster                              │
│                  计算并管理 oom_adj/procState                  │
└─────────────────────────────────────────────────────────────┘
                           │ 服务
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                   ActivityManagerService                      │
│              组件状态变化触发 OOM adj 更新                       │
└─────────────────────────────────────────────────────────────┘
                           │ 触发
                           ▼
┌─────────────────────────────────────────────────────────────┐
│       Activity/Service/Provider/Receiver 状态变化              │
└─────────────────────────────────────────────────────────────┘

1.3 核心数据结构

// 进程记录中存储 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_ADJ0前台应用当前交互的Activity
PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ50最近前台刚离开前台的应用
VISIBLE_APP_ADJ100可见应用可见但非焦点的Activity
PERCEPTIBLE_APP_ADJ200可感知应用前台服务(FGS)、overlay UI
PERCEPTIBLE_MEDIUM_APP_ADJ250中等可感知短时FGS
PERCEPTIBLE_LOW_APP_ADJ300低可感知低优先级感知
BACKUP_APP_ADJ300备份应用正在进行备份的进程
HEAVY_WEIGHT_APP_ADJ400重型应用heavy-weight 进程
SERVICE_ADJ500服务已启动的后台服务
SERVICE_B_ADJ800B类服务内存压力大时降级的服务
HOME_APP_ADJ600主屏幕Launcher 进程
PREVIOUS_APP_ADJ700上一个应用用户刚切换离开的进程
CACHED_APP_MIN_ADJ900缓存最小缓存进程起始值
CACHED_APP_MAX_ADJ999缓存最大最容易被杀的进程

2.2 Adj 值分布图

-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_PERSISTENT0持久化进程全能力
PROCESS_STATE_PERSISTENT_UI1持久化UI进程全能力
PROCESS_STATE_TOP2顶部进程全能力 + TOP调度
PROCESS_STATE_BOUND_TOP3绑定到TOPBFSL能力
PROCESS_STATE_FOREGROUND_SERVICE4前台服务根据FGS类型
PROCESS_STATE_BOUND_FOREGROUND_SERVICE5绑定FGSBFSL能力
PROCESS_STATE_IMPORTANT_FOREGROUND6重要前台受限能力
PROCESS_STATE_IMPORTANT_BACKGROUND7重要后台网络受限
PROCESS_STATE_TRANSIENT_BACKGROUND8短暂后台网络受限
PROCESS_STATE_BACKUP9备份特殊保护
PROCESS_STATE_SERVICE10服务后台限制
PROCESS_STATE_RECEIVER11广播接收器后台限制
PROCESS_STATE_TOP_SLEEPING12顶部睡眠屏幕关闭时
PROCESS_STATE_HEAVY_WEIGHT13重型进程特殊保护
PROCESS_STATE_HOME14主屏幕Home调度
PROCESS_STATE_LAST_ACTIVITY15最后活动切换保护
PROCESS_STATE_CACHED_ACTIVITY16缓存活动可被杀
PROCESS_STATE_CACHED_ACTIVITY_CLIENT17缓存活动客户端可被杀
PROCESS_STATE_CACHED_RECENT18缓存最近可被杀
PROCESS_STATE_CACHED_EMPTY19缓存空最易被杀

3.2 ProcState 与能力关系

// 全能力: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_BACKGROUND0后台最低,THREAD_GROUP_BACKGROUND
SCHED_GROUP_RESTRICTED1受限灭屏时UI进程降级
SCHED_GROUP_DEFAULT2默认正常优先级
SCHED_GROUP_TOP_APP3顶部应用最高,FIFO调度或优先级boost
SCHED_GROUP_TOP_APP_BOUND4绑定顶部高优先级

5. computeOomAdjLSP 方法详解

5.1 方法签名

@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 参数说明

参数类型描述
appProcessRecord要计算 adj 的目标进程
cachedAdjint缓存的 adj 值,用于默认初始值
topAppProcessRecord当前顶部应用进程
doingAllboolean是否为全量更新(遍历所有进程)
nowlong当前时间戳(uptimeMillis)
cycleReEvalboolean是否为循环依赖的重新评估
computeClientsboolean是否递归计算客户端进程

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行)

// 检查是否已计算过
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行)

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行)
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行)
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行)
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行)
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行)
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行)
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行)
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行)

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行)

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行)

// 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行)

这是最复杂的阶段,处理进程间绑定关系对优先级的影响:

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行)

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行)

// 服务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 循环依赖场景

进程A 绑定 服务B
    ↓
服务B 绑定 ProviderC
    ↓
ProviderC 绑定 进程A  ← 形成循环!

7.2 处理策略

// 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;
            }
        }
    }
}

处理逻辑:

  1. 标记循环依赖进程 (containsCycle)
  2. 多次迭代重新计算(最多10次)
  3. 使用部分值进行评估 (cycleReEval=true)
  4. 直到所有进程稳定为止

8. 影响 adj 值的因素总结

8.1 直接因素

因素优先级adj 范围触发条件
顶部Activity最高0 (FOREGROUND)Activity 处于前台焦点
可见Activity100-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_ADJOomAdjuster: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)

// 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 核心调用链

┌─────────────────────────────────────────────────────────────┐
│              组件状态变化(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切换场景:

// ActivityTaskManagerService
void startActivityInner() {
    // ...
    mTaskSupervisor.startActivityResolvedActivity();
    // Activity状态变化,触发 OOM adj 更新
    mService.updateOomAdjLocked(OOM_ADJ_REASON_ACTIVITY);
}

绑定服务场景:

// ActiveServices
int bindServiceLocked(IServiceConnection connection, Intent service, ...) {
    // ...
    bringUpServiceLocked(serviceRecord);
    // 服务绑定,更新相关进程的 adj
    mAm.updateOomAdjLocked(OOM_ADJ_REASON_BIND_SERVICE);
}

10. 关键代码路径标注

10.1 重要方法位置

方法文件位置行号
computeOomAdjLSPOomAdjuster.java1724-2850
updateOomAdjLockedOomAdjuster.java569-573, 609-613
updateOomAdjInnerLSPOomAdjuster.java935-1080
applyOomAdjLSPOomAdjuster.java2986-3100
setOomAdjProcessList.java调用内核写入

10.2 关键决策点

决策点行号说明
循环检测1728-1740检查 adjSeq 避免重复
死亡进程处理1742-1751无线程进程设最低adj
固定优先级处理1774-1819系统进程特殊处理
TOP进程判断1834-1851最高优先级
FGS类型判断1954-1995普通FGS vs 短时FGS
服务绑定传播2248-2597复杂的绑定关系处理
Provider优先级2599-2746Provider客户端影响
最终adj应用2837-2849写入进程状态

11. 实践调试技巧

11.1 查看 OOM adj 状态

# 查看进程 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 调试开关

// 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过高检查是否进入后台限制

参考文献

  1. 源码文件

    • frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
    • frameworks/base/services/core/java/com/android/server/am/ProcessList.java
    • frameworks/base/core/java/android/app/ActivityManager.java
  2. Android官方文档

  3. 相关类

    • ProcessRecord - 进程记录
    • ProcessStateRecord - 进程状态
    • UidRecord - UID记录
    • ServiceRecord - 服务记录
    • ContentProviderRecord - Provider记录
    • ConnectionRecord - 绑定连接记录

文档创建日期: 2026/04/28