Android OomAdjuster流程

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 {
    // ...
}

核心职责:

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

处理逻辑:

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

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

参考文献

  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 基于 Android 13/14 AAOS MT8678 平台

相关推荐
河婆墟邓紫棋1 小时前
MIUI中的权限
android·github
我命由我123453 小时前
Java 开发 - CountDownLatch 不需要手动关闭
android·java·开发语言·jvm·kotlin·android studio·android-studio
众少成多积小致巨3 小时前
GNU Make 核心指南
android·c++
凛_Lin~~3 小时前
安卓进程保活方案记录(双重fork+文件锁+手搓parcel)
android·安卓
海天鹰3 小时前
安卓相机:获取最近拍摄的照片缩略图做相册按钮图标
android
tongyiixiaohuang3 小时前
技术案例分享:金蝶云星空客户数据同步到MySQL的实现
android·数据库·mysql
小羊子说4 小时前
Android ANR 原理浅析
android·性能优化·车载系统
Be for thing4 小时前
Android Studio 常用快捷键总结
android·学习
Vect__5 小时前
MySQL的数据类型和约束
android·数据库·mysql