概述
每个进程都有自己的优先级adj,但是进程的有显示具体是如何计算的?根据什么条件决定的呢?computeOomAdjLocked方法主要就是来根据当前进程的各种条件分配合适的Adj优先级的.
ADJ优先级介绍
ADJ取值 | 进程类别 | 含义 |
---|---|---|
-1000 | NATIVE_ADJ | native进程 |
-900 | SYSTEM_ADJ | System_server进程 |
-800 | PERSISTENT_PROC_ADJ | 系统persistent进程 |
-700 | PERSISTENT_SERVICE_ADJ | 系统或者persistent进程绑定的进程 |
0 | FOREGROUND_APP_ADJ | 前台进程 :和用户交互的进程,不到万不得已不能杀死 |
100 | VISIBLE_APP_ADJ | 可见进程:该进程的某个UI组件是可以被用户看见的,但是没有和用户进行交互,不能随便杀死,影响用户体验 |
200 | PERCEPTIBLE_APP_ADJ | 可感知进程:该进程的某个组件可以被用户感知到,如后台音乐播放 |
300 | BACKUP_APP_ADJ | 备份进程:不可轻易打断,否则容易引起不可修复的数据错误 |
400 | HEAVY_WEIGHT_APP_ADJ | 重量级进程 |
500 | SERVICE_ADJ | 服务进程 |
600 | HOME_APP_ADJ | Lanucher进程 |
700 | PREVIOUS_APP_ADJ | 上一个访问的进程 |
800 | SERVICE_B_ADJ | B list中的进程 |
900 | CACHED_APP_MIN_ADJ | 不可见进程adj最小值 |
906 | CACHED_APP_MAX_ADJ | 不可见进程adj最大值 |
1001 | UNKNOWN_ADJ | 错误的adj值 |
进程状态介绍
状态值 | 进程状态类别 | 含义 |
---|---|---|
-1 | PROCESS_STATE_UNKNOWN | 错误的进程状态 |
0 | PROCESS_STATE_PERSISTENT | persistent进程 |
1 | PROCESS_STATE_PERSISTENT_UI | 该进程是persistent进程并且有UI界面显示 |
2 | PROCESS_STATE_TOP | 运行Top Activity正在和用户交互的进程 |
3 | PROCESS_STATE_FOREGROUND_SERVICE | 运行了Foreground service的进程 |
4 | PROCESS_STATE_BOUND_FOREGROUND_SERVICE | 运行有系统绑定的前台服务 |
5 | PROCESS_STATE_IMPORTANT_FOREGROUND | 用户可感知的重要进程 |
6 | PROCESS_STATE_IMPORTANT_BACKGROUND | 用户不可感知的重要进程 |
7 | PROCESS_STATE_TRANSIENT_BACKGROUND | |
8 | PROCESS_STATE_BACKUP | 备份进程 |
9 | PROCESS_STATE_SERVICE | 后台运行Service的进程 |
10 | PROCESS_STATE_RECEIVER | 后台运行广播的进程 |
11 | PROCESS_STATE_TOP_SLEEPING | 设备处于Sleep状态时的Top进程 |
12 | PROCESS_STATE_HEAVY_WEIGHT | |
13 | PROCESS_STATE_HOME | Launcher进程 |
14 | PROCESS_STATE_LAST_ACTIVITY | 上一个Activity所处的进程 |
15 | PROCESS_STATE_CACHED_ACTIVITY | 包含Activity且处于缓存状态的进程 |
16 | PROCESS_STATE_CACHED_ACTIVITY_CLIENT | 处于缓存状态且是另一个缓存状态进程的Client进程 |
17 | PROCESS_STATE_CACHED_RECENT | |
18 | PROCESS_STATE_CACHED_EMPTY | 缓存空进程 |
19 | PROCESS_STATE_NONEXISTENT | 不存在的进程 |
如何调整优先级
AMS中将进程分为来这么多个优先级等级,但是AMS是如何给每个进程分配优先级的呢?这个过程主要是在computeOomAdjLocked方法中处理的。
ComputeOomAdjLocked 计算进程的Adj值
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
boolean doingAll, long now) {
// mAdjSeq 是 adj调整的序号,每次进行一轮调整的时候 mAdjSeq 加1,进程ProcessRecord的adjSeq
//代表最后一次计算的mAdjSeq的序号
// 如果当前进程的adjSeq == mAdjSeq说明,当前进程ProcessRecord已经计算adj完成,无需再次计算
if (mAdjSeq == app.adjSeq) {
if (app.adjSeq == app.completedAdjSeq) {
// This adjustment has already been computed successfully.
return false;
} else {
// The process is being computed, so there is a cycle. We cannot
// rely on this process's state.
app.containsCycle = true;
return false;
}
}
//如果当前进程的ActivityThread = NULL, 说明当前进程没有真正运行的实体,是一个缓存的进程
//直接将当前进程设置为缓存进程之后,该进程的adj计算就算完成了
// 当前进程的cured = curRawAdj = 906
if (app.thread == null) {
app.adjSeq = mAdjSeq;
app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ;
app.completedAdjSeq = app.adjSeq;
return false;
}
app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
app.adjSource = null;
app.adjTarget = null;
app.empty = false;
app.cached = false;
final int activitiesSize = app.activities.size();
final int appUid = app.info.uid;
final int logUid = mCurOomAdjUid;
int prevAppAdj = app.curAdj;
int prevProcState = app.curProcState;
//处理某一个进程的maxAdj <= FOREGROUND_APP_ADJ ( 0 )情况�������������������,此类进程属于系统级重要进程
//maxAdj是ProcessRecord在创建的时候设置的一个允许该进程最大的adj值
//搜索系统中maxAdj设置的地方,只有system_server进程启动的时候和系统persistent进程启动的
//时候会进行设置,所以只要maxAdj小于FOREGROUND_APP_ADJ 0的时候,此时是系统的一些重
//要的进程,不需要在调整adj,只需呀设置为maxAdj即可。
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
//初始化进程相关信息
app.adjType = "fixed";
app.adjSeq = mAdjSeq;
app.curRawAdj = app.maxAdj;
app.foregroundActivities = false;
app.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
//判断当前的系统进程是否包含正在显示的UI,根据是否显示UI来设置进程的curProcState以及进程调度策略
app.systemNoUi = true;
if (app == TOP_APP) {
//如果当前系统进程属于TOP_APP, 那这个进程一定含有UI
app.systemNoUi = false;
app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "pers-top-activity";
} else if (app.hasTopUi) {
// 如果当前系统进程有TopUI
app.systemNoUi = false;
app.adjType = "pers-top-ui";
} else if (activitiesSize > 0) {
// 当前进程有正在显示的Activity
for (int j = 0; j < activitiesSize; j++) {
final ActivityRecord r = app.activities.get(j);
if (r.visible) {
app.systemNoUi = false;
}
}
}
if (!app.systemNoUi) {
if (mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) {
// 屏幕显示,且当前进程有UI界面
app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
} else {
// 屏幕休眠,且当前进程有UI界面
app.curProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
app.curSchedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
}
}
app.curAdj = app.maxAdj;
app.completedAdjSeq = app.adjSeq;
// 如果此次的计算的Adj<上次的Adj, 说明adj计算完成了
return app.curAdj < prevAppAdj;
}
第一部分:
- 判断进程在此次调整中是否调整完毕,调整完毕则直接返回
- 如果本进程的ActivityThread已经挂掉了, 则直接设置进程的优先级为CACHED_APP_MAX_ADJ = 906
- 计算maxAdj < FOREGROUND_APP_ADJ的情况, 系统自己创建的系统级进程,设置adj为maxAdj即可,无需对Adj做其他调整
ADJ < 0的进程包括哪些进程?
NATIVE_ADJ(-1000):是由init进程fork出来的Native进程,并不受system管控;
SYSTEM_ADJ(-900):是指system_server进程;
PERSISTENT_PROC_ADJ(-800): 是指在AndroidManifest.xml中申明android:persistent=”true”的系统(即带有FLAG_SYSTEM标记)进程,persistent进程一般情况并不会被杀,即便被杀或者发生Crash系统会立即重新拉起该进程。
PERSISTENT_SERVICE_ADJ(-700):是由startIsolatedProcess()方式启动的进程,或者是由system_server或者persistent进程所绑定(并且带有BIND_ABOVE_CLIENT或者BIND_IMPORTANT)的服务进程
// mTopProcessState 代表运行TopActivity的进程状态,只有两种状态
// 1 : ActivityManager.PROCESS_STATE_TOP 显示状态
// 2 : ActivityManager.PROCESS_STATE_TOP_SLEEPING 休眠状态
final int PROCESS_STATE_CUR_TOP = mTopProcessState;
// 开始遍历并计算普通进程 即adj值 > 0的情况,重要性从高到低进行计算,然后为进程设置一个合适的Adj优先级
int adj;
int schedGroup;
int procState;
int cachedAdjSeq;
boolean foregroundActivities = false;
mTmpBroadcastQueue.clear();
if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) {
// 如果当前进程为TOP_APP进程,即处于和用户交互的进程,并且当前进程不是休眠状态
// 那么先当前进程优先级设置为FOREGROUND_APP_ADJ (0)
// 进程状态 procState 为 PROCESS_STATE_CUR_TOP
// foregroundActivities 为 true, 表明当前进程包含显示的Activity界面
// 设置调度策略为 SCHED_GROUP_TOP_APP
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
}
} else if (app.runningRemoteAnimation) {
// 如果是正在运行动画的进程,则设置Adj = VISIBLE_APP_ADJ = 100
// 进程状态procState 为 PROCESS_STATE_CUR_TOP
// 设置调度策略为 SCHED_GROUP_TOP_APP
adj = ProcessList.VISIBLE_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "running-remote-anim";
procState = PROCESS_STATE_CUR_TOP;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app);
}
} else if (app.instr != null) {
//如果是正在进行测试的进程,设置进程adj = FOREGROUND_APP_ADJ = 0
//设置procState 进程状态为 PROCESS_STATE_FOREGROUND_SERVICE
//设置调度策略为SCHED_GROUP_DEFAULT
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
}
} else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
// 如果是一个正在接受广播的进程,此时我们也要把这个进程看作是前台进程
// adj 设置为 FOREGROUND_APP_ADJ = 0
// 进程状态 procState 设置 PROCESS_STATE_RECEIVER
// 设置调度策略为SCHED_GROUP_DEFAULT或者SCHED_GROUP_BACKGROUND
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = (mTmpBroadcastQueue.contains(mFgBroadcastQueue))
? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
}
} else if (app.executingServices.size() > 0) {
// 如果是正在执行service生命周期回调的进程
// 设置进程adj = FOREGROUND_APP_ADJ = 0
// 设置进程状态 procState = PROCESS_STATE_SERVICE
// 设置调度策略为 SCHED_GROUP_BACKGROUND 或者 SCHED_GROUP_DEFAULT
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = app.execServicesFg ?
ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "exec-service";
procState = ActivityManager.PROCESS_STATE_SERVICE;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
}
//Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
} else if (app == TOP_APP) {
// 如果当前进程是top进程,且系统处于休眠状态
// 设置进程adj = FOREGROUND_APP_ADJ
// 设置进程状态procState = PROCESS_STATE_CUR_TOP
// 设置调度策略为 SCHED_GROUP_BACKGROUND
// foregroundActivities = true 表示当前进程有UI和用户交互
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "top-sleeping";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app);
}
} else {
// 其他进程则默认初始化adj = 1000, 进程state默认初始化为PROCESS_STATE_CACHED_EMPTY
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
// At this point we don't actually know the adjustment. Use the cached adj
// value that the caller wants us to.
adj = cachedAdj;
procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
app.cached = true;
app.empty = true;
app.adjType = "cch-empty";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app);
}
}
第二部分:先处理进程adj应该设置为前台进程FOREGROUND_APP_ADJ的几种情况
满足以下任一条件的进程都属于FOREGROUND_APP_ADJ(0)优先级:
- 正处于resumed状态的Activity
- 正执行一个生命周期回调的Service(比如执行onCreate,onStartCommand,onDestroy等)
- 正执行onReceive()的BroadcastReceiver
- 通过startInstrumentation()启动的进程
把这几种情况的进程adj设置为FOREGROUND_APP_ADJ = 0, 虽然以上几种进程的adj值一样,即对于LowMemorykiller来讲,他们的重要性是相同的,但是这些进程的proceState不同,从AMS角度而言,他们的重要性不一样。此外对不同的进程根据重要情况设置了不同的调度策略schedGroup, 通过linux的接口来使进程有不同的调度策略。
最后其他进程adj都默认设置为1000,进程state 都设置初始化为CACHE_EMPTY。然后在后续的流程里再进行处理。
foregroundActivitys 变量用于表示当前进程是否有处于前台和用户交互的Activity
// 开始处理包含Activity, 但是却不在前台的进程
if (!foregroundActivities && activitiesSize > 0) {
// PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1 = 200 - 100 - 1 = 99
//之前分析updateOomAdjLocked的第一部分时,简单提到过rankTaskLayersIfNeeded函数
//该函数会更新包含Activity的Task的rankLayer
//按照显示层次从上到下,rankLayer逐渐增加,对应的最大值就是VISIBLE_APP_LAYER_MAX
int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
for (int j = 0; j < activitiesSize; j++) {
......
if (r.visible) {
// 如果进程包含可见activity, 设置该进程adj = VISIBLE_APP_ADJ.
if (adj > ProcessList.VISIBLE_APP_ADJ) {
//adj大于VISIBLE_APP_ADJ时,才更新对应的adj
//之前提到的正在处理广播、服务或测试的进程,adj为FOREGROUND,是小于VISIBLE_APP_ADJ
//因此不会在此更新
adj = ProcessList.VISIBLE_APP_ADJ;
app.adjType = "vis-activity";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to vis-activity: " + app);
}
}
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP; //设置可见进程的state = STATE_TOP
app.adjType = "vis-activity";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to vis-activity (top): " + app);
}
}
if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
app.cached = false;
app.empty = false;
foregroundActivities = true; //属于foregroundActivities进程
final TaskRecord task = r.getTask();
if (task != null && minLayer > 0) {
final int layer = task.mLayerRank;
if (layer >= 0 && minLayer > layer) {
//更新rankLayer
minLayer = layer;
}
}
break;
} else if (r.isState(ActivityState.PAUSING, ActivityState.PAUSED)) {
//如果进程包含处于PAUSING或PAUSED状态的Activity时
//将其oom_adj调整为“用户可察觉”的的等级,这个等级还是很高的
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "pause-activity";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to pause-activity: " + app);
}
}
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
app.adjType = "pause-activity";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to pause-activity (top): " + app);
}
}
if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
app.cached = false;
app.empty = false;
foregroundActivities = true;
} else if (r.isState(ActivityState.STOPPING)) {
//包含处于Stopping状态Activity的进程,其oom_adj也被置为PERCEPTIBLE_APP_ADJ
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "stop-activity";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to stop-activity: " + app);
}
}
//处于stoping,但是还没有finish的进程, state设置为PROCESS_STATE_LAST_ACTIVITY
if (!r.finishing) {
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "stop-activity";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to stop-activity: " + app);
}
}
}
app.cached = false;
app.empty = false;
foregroundActivities = true;
} else {
//stop且finish的进程,设置adj为PROCESS_STATE_CACHED_ACTIVITY
if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
app.adjType = "cch-act";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to cached activity: " + app);
}
}
}
}
//不同可见进程的oom_adj有一定的差异,处在下层的oom_adj越大
//即越老的Activity所在进程,重要性越低
if (adj == ProcessList.VISIBLE_APP_ADJ) {
adj += minLayer;
}
}
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
if (app.foregroundServices) {
// oregroundServices非空:前台服务进程,执行startForegroundService()方法, 此时该进程为可感知进程
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
app.cached = false;
app.adjType = "fg-service";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to fg service: " + app);
}
} else if (app.hasOverlayUi) {
// 进程有OverlayUI 该进程为可感知进程.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
app.cached = false;
app.adjType = "has-overlay-ui";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to overlay ui: " + app);
}
}
}
// If the app was recently in the foreground and moved to a foreground service status,
// allow it to get a higher rank in memory for some time, compared to other foreground
// services so that it can finish performing any persistence/processing of in-memory state.
if (app.foregroundServices && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
&& (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now
|| app.setProcState <= ActivityManager.PROCESS_STATE_TOP)) {
adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
app.adjType = "fg-service-act";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
}
}
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
if (app.forcingToImportant != null) {
// app.forcingToImportant非空:执行setProcessImportant()方法,比如Toast弹出过程
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
app.cached = false;
app.adjType = "force-imp";
app.adjSource = app.forcingToImportant;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app);
}
}
}
第三部分:
根据进程的Activity状态和Service状态决定Adj
- VISIBLE_APP_ADJ 可见进程:
进程中存在可见Activity - PERCEPTIBLE_APP_ADJ 可感知进程:
1.进程中存在处于PAUSING、PAUSED或STOPPING状态的Activity时
2.foregroundServices非空:前台服务进程,执行startForegroundService()方法
3.app.forcingToImportant非空:执行setProcessImportant()方法,比如Toast弹出过程。
4.hasOverlayUi非空:非activity的UI位于屏幕最顶层,比如显示类型TYPE_APPLICATION_OVERLAY的窗口进程.
其余的进程仍是UNKNOW_ADJ。
//开始处理一些特殊的进程
//如果进程是heavyWeightProcess进程, 则设置进程adj = HEAVY_WEIGHT_APP_ADJ
if (app == mHeavyWeightProcess) {
if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
// We don't want to kill the current heavy-weight process.
adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "heavy";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app);
}
}
if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
app.adjType = "heavy";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app);
}
}
}
//如果是Home进程, 则设置adj = HOME_APP_ADJ
if (app == mHomeProcess) {
if (adj > ProcessList.HOME_APP_ADJ) {
// This process is hosting what we currently consider to be the
// home app, so we don't want to let it go into the background.
adj = ProcessList.HOME_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "home";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app);
}
}
if (procState > ActivityManager.PROCESS_STATE_HOME) {
procState = ActivityManager.PROCESS_STATE_HOME;
app.adjType = "home";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app);
}
}
}
//如果进程为前一个进程, 则设置adj = PREVIOUS_APP_ADJ
if (app == mPreviousProcess && app.activities.size() > 0) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
// This was the previous process that showed UI to the user.
// We want to try to keep it around more aggressively, to give
// a good experience around switching between two apps.
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "previous";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
}
}
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "previous";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
}
}
}
if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
+ " reason=" + app.adjType);
// By default, we use the computed adjustment. It may be changed if
// there are applications dependent on our services or providers, but
// this gives us a baseline and makes sure we don't get into an
// infinite recursion.
app.curRawAdj = adj;
app.hasStartedServices = false;
app.adjSeq = mAdjSeq;
//如果是备份进程, 则设置adj = BACKUP_APP_ADJ
if (mBackupTarget != null && app == mBackupTarget.app) {
// If possible we want to avoid killing apps while they're being backed up
if (adj > ProcessList.BACKUP_APP_ADJ) {
if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
adj = ProcessList.BACKUP_APP_ADJ;
if (procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
}
app.adjType = "backup";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app);
}
app.cached = false;
}
if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
procState = ActivityManager.PROCESS_STATE_BACKUP;
app.adjType = "backup";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app);
}
}
}
第四部分:
处理了一些特殊的进程,并设置其adj值和processState值
包含前台服务的进程
重量级进程
Home进程
previous进程
Backup进程
//根据Service来调整进程优先级
boolean mayBeTop = false;
String mayBeTopType = null;
Object mayBeTopSource = null;
Object mayBeTopTarget = null;
for (int is = app.services.size()-1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.services.valueAt(is);
//当前进程的Service是startService方式启动的
if (s.startRequested) {
app.hasStartedServices = true;
if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
procState = ActivityManager.PROCESS_STATE_SERVICE;
app.adjType = "started-services";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to started service: " + app);
}
}
if (app.hasShownUi && app != mHomeProcess) {
// If this process has shown some UI, let it immediately
// go to the LRU list because it may be pretty heavy with
// UI stuff. We'll tag it with a label just to help
// debug and understand what is going on.
if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-ui-services";
}
} else {
if (now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
// 30min之内活跃过的Service服务,将该进程的优先级设置为SERVICE_ADJ 500
if (adj > ProcessList.SERVICE_ADJ) {
adj = ProcessList.SERVICE_ADJ;
app.adjType = "started-services";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to started service: " + app);
}
app.cached = false;
}
}
// If we have let the service slide into the background
// state, still have some text describing what it is doing
// even though the service no longer has an impact.
if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-services";
}
}
}
//根据绑定该Service的客户端进程来调整当前进程的优先级
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
conni--) {
ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
for (int i = 0;
i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
i++) {
// XXX should compute this based on the max of
// all connected clients.
ConnectionRecord cr = clist.get(i);
if (cr.binding.client == app) {
// 是自己进程绑定的当前Service服务,无需处理
continue;
}
//BIND_WAIVE_PRIORITY
//是指客户端进程的优先级不会影响目标服务进程的优先级。比如当调用bindService
//又不希望提升目标服务进程的优先级的情况下,可以使用该flags
// 根据Srevise Client进程来调整当前进程的Adj
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client;
computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
if (client.containsCycle) {
// We've detected a cycle. We should retry computeOomAdjLocked later in
// case a later-checked connection from a client would raise its
// priority legitimately.
app.containsCycle = true;
// If the client has not been completely evaluated, skip using its
// priority. Else use the conservative value for now and look for a
// better state in the next iteration.
if (client.completedAdjSeq < mAdjSeq) {
continue;
}
}
int clientAdj = client.curRawAdj;
int clientProcState = client.curProcState;
if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
// If the other app is cached for any reason, for purposes here
// we are going to consider it empty. The specific cached state
// doesn't propagate except under certain conditions.
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
}
String adjType = null;
if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
// Not doing bind OOM management, so treat
// this guy more like a started service.
if (app.hasShownUi && app != mHomeProcess) {
// If this process has shown some UI, let it immediately
// go to the LRU list because it may be pretty heavy with
// UI stuff. We'll tag it with a label just to help
// debug and understand what is going on.
if (adj > clientAdj) {
adjType = "cch-bound-ui-services";
}
app.cached = false;
clientAdj = adj;
clientProcState = procState;
} else {
if (now >= (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
// This service has not seen activity within
// recent memory, so allow it to drop to the
// LRU list if there is no other reason to keep
// it around. We'll also tag it with a label just
// to help debug and undertand what is going on.
if (adj > clientAdj) {
adjType = "cch-bound-services";
}
clientAdj = adj;
}
}
}
if (adj > clientAdj) {
// If this process has recently shown UI, and
// the process that is binding to it is less
// important than being visible, then we don't
// care about the binding as much as we care
// about letting this process get into the LRU
// list to be killed and restarted if needed for
// memory.
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
adjType = "cch-bound-ui-services";
}
} else {
int newAdj;
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
newAdj = clientAdj;
} else {
// make this service persistent
newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
procState = ActivityManager.PROCESS_STATE_PERSISTENT;
}
} else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) {
newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1;
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
} else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
newAdj = clientAdj;
} else {
if (adj > ProcessList.VISIBLE_APP_ADJ) {
newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
} else {
newAdj = adj;
}
}
if (!client.cached) {
app.cached = false;
}
if (adj > newAdj) {
adj = newAdj;
adjType = "service";
}
}
}
if ((cr.flags & (Context.BIND_NOT_FOREGROUND
| Context.BIND_IMPORTANT_BACKGROUND)) == 0) {
// This will treat important bound services identically to
// the top app, which may behave differently than generic
// foreground work.
if (client.curSchedGroup > schedGroup) {
if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
schedGroup = client.curSchedGroup;
} else {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
// Special handling of clients who are in the top state.
// We *may* want to consider this process to be in the
// top state as well, but only if there is not another
// reason for it to be running. Being on the top is a
// special state, meaning you are specifically running
// for the current top app. If the process is already
// running in the background for some other reason, it
// is more important to continue considering it to be
// in the background state.
mayBeTop = true;
mayBeTopType = "service";
mayBeTopSource = cr.binding.client;
mayBeTopTarget = s.name;
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
} else {
// Special handling for above-top states (persistent
// processes). These should not bring the current process
// into the top state, since they are not on top. Instead
// give them the best state after that.
if ((cr.flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
clientProcState =
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
} else if (mWakefulness
== PowerManagerInternal.WAKEFULNESS_AWAKE &&
(cr.flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
!= 0) {
clientProcState =
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
} else {
clientProcState =
ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
}
}
}
} else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
if (clientProcState <
ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
clientProcState =
ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
}
} else {
if (clientProcState <
ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
clientProcState =
ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
}
}
if (procState > clientProcState) {
procState = clientProcState;
if (adjType == null) {
adjType = "service";
}
}
if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
&& (cr.flags&Context.BIND_SHOWING_UI) != 0) {
app.pendingUiClean = true;
}
if (adjType != null) {
app.adjType = adjType;
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
app.adjSource = cr.binding.client;
app.adjSourceProcState = clientProcState;
app.adjTarget = s.name;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
+ ": " + app + ", due to " + cr.binding.client
+ " adj=" + adj + " procState="
+ ProcessList.makeProcStateString(procState));
}
}
}
if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
app.treatLikeActivity = true;
}
//是指当从Activity绑定到该进程时,允许目标服务进程根据该activity的可见性来提升优先级
final ActivityRecord a = cr.activity;
if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && (a.visible
|| a.isState(ActivityState.RESUMED, ActivityState.PAUSING))) {
adj = ProcessList.FOREGROUND_APP_ADJ;
if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
} else {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
app.cached = false;
app.adjType = "service";
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
app.adjSource = a;
app.adjSourceProcState = procState;
app.adjTarget = s.name;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise to service w/activity: " + app);
}
}
}
}
}
}
第五部分:
分为两个部分:
- 根据当前进程的Service来调整当前进程的优先级
- 根据绑定在当前进程Service上的客户端进程来调整优先级
ServiceRecord的成员变量startRequested=true,是指被显式调用了startService()方法。当service被stop或kill会将其置为false。
一般情况下,即便客户端进程处于前台进程(ADJ=0)级别,服务进程只会提升到可见(ADJ=1)级别。以下flags是由调用bindService()过程所传递的flags来决定的。
flag | 含义 |
---|---|
BIND_WAIVE_PRIORITY | 是指客户端进程的优先级不会影响目标服务进程的优先级。比如当调用bindService又不希望提升目标服务进程的优先级的情况下,可以使用该flags |
BIND_ADJUST_WITH_ACTIVITY | 是指当从Activity绑定到该进程时,允许目标服务进程根据该activity的可见性来提升优先级 |
BIND_ABOVE_CLIENT | 当客户端进程绑定到一个服务进程时,则服务进程比客户端进程更重要 |
BIND_IMPORTANT | 标记该服务对于客户端进程很重要,当客户端进程处于前台进程(ADJ=0)级别时,会把服务进程也提升到前台进程级别 |
BIND_NOT_VISIBLE | 当客户端进程处于可见(ADJ=1)级别,也不允许被绑定的服务进程提升到可见级别,该类服务进程的优先级上限为可感知(ADJ=2)级别 |
BIND_NOT_FOREGROUND | 不允许被绑定的服务进程提升到前台调度优先级,但是内存优先级可以提升到前台级别。比如不希望服务进程占用 |
具体服务端进程受客户端进程影响的ADJ上限如下:
BIND_ABOVE_CLIENT或BIND_IMPORTANT的情况下,ADJ上限为PERSISTENT_SERVICE_ADJ;
BIND_NOT_VISIBLE的情况下, ADJ上限为PERCEPTIBLE_APP_ADJ;
否则,一般情况下,ADJ上限为VISIBLE_APP_ADJ;
由此,可见当bindService过程带有BIND_ABOVE_CLIENT或者BIND_IMPORTANT flags的同时,客户端进程ADJ小于或等于PERSISTENT_SERVICE_ADJ的情况下,该进程则为PERSISTENT_SERVICE_ADJ。另外,即便是启动过Activity的进程,当客户端进程ADJ<=200时,还是可以提升该服务进程的优先级。
// 根据 ContentProvider调整进程ADJ
for (int provi = app.pubProviders.size()-1;
provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
provi--) {
ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
//根据client来调整provider进程的adj和procState
for (int i = cpr.connections.size()-1;
i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
i--) {
ContentProviderConnection conn = cpr.connections.get(i);
ProcessRecord client = conn.client;
if (client == app) {
// Being our own client is not interesting.
continue;
}
computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
if (client.containsCycle) {
// We've detected a cycle. We should retry computeOomAdjLocked later in
// case a later-checked connection from a client would raise its
// priority legitimately.
app.containsCycle = true;
// If the client has not been completely evaluated, skip using its
// priority. Else use the conservative value for now and look for a
// better state in the next iteration.
if (client.completedAdjSeq < mAdjSeq) {
continue;
}
}
int clientAdj = client.curRawAdj;
int clientProcState = client.curProcState;
if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
// If the other app is cached for any reason, for purposes here
// we are going to consider it empty.
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
}
String adjType = null;
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adjType = "cch-ui-provider";
} else {
adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
adjType = "provider";
}
app.cached &= client.cached;
}
if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
// Special handling of clients who are in the top state.
// We *may* want to consider this process to be in the
// top state as well, but only if there is not another
// reason for it to be running. Being on the top is a
// special state, meaning you are specifically running
// for the current top app. If the process is already
// running in the background for some other reason, it
// is more important to continue considering it to be
// in the background state.
mayBeTop = true;
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
mayBeTopType = adjType = "provider-top";
mayBeTopSource = client;
mayBeTopTarget = cpr.name;
} else {
// Special handling for above-top states (persistent
// processes). These should not bring the current process
// into the top state, since they are not on top. Instead
// give them the best state after that.
clientProcState =
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
if (adjType == null) {
adjType = "provider";
}
}
}
if (procState > clientProcState) {
procState = clientProcState;
}
if (client.curSchedGroup > schedGroup) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
if (adjType != null) {
app.adjType = adjType;
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_PROVIDER_IN_USE;
app.adjSource = client;
app.adjSourceProcState = clientProcState;
app.adjTarget = cpr.name;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
+ ": " + app + ", due to " + client
+ " adj=" + adj + " procState="
+ ProcessList.makeProcStateString(procState));
}
}
}
// If the provider has external (non-framework) process
// dependencies, ensure that its adjustment is at least
// FOREGROUND_APP_ADJ.
//根据provider外部依赖情况来调整adj和schedGroup
if (cpr.hasExternalProcessHandles()) {
if (adj > ProcessList.FOREGROUND_APP_ADJ) {
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.adjType = "ext-provider";
app.adjTarget = cpr.name;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to external provider: " + app);
}
}
if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to external provider: " + app);
}
}
}
if (app.lastProviderTime > 0 &&
(app.lastProviderTime+mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "recent-provider";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to recent provider: " + app);
}
}
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "recent-provider";
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to recent provider: " + app);
}
}
}
第六部分
对于provider进程,还有以下两个条件能成为前台进程:
- 当Provider的客户端进程ADJ<=FOREGROUND_APP_ADJ时,则Provider进程ADJ等于FOREGROUND_APP_ADJ
- 当Provider有外部(非框架)进程依赖,也就是调用了getContentProviderExternal()方法,则ADJ至少等于FOREGROUND_APP_ADJ
if (adj == ProcessList.SERVICE_ADJ) {
if (doingAll) {
app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
mNewNumServiceProcs++;
//Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb);
if (!app.serviceb) {
// This service isn't far enough down on the LRU list to
// normally be a B service, but if we are low on RAM and it
// is large we want to force it down since we would prefer to
// keep launcher over it.
if (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
&& app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {
app.serviceHighRam = true;
app.serviceb = true;
//Slog.i(TAG, "ADJ " + app + " high ram!");
} else {
mNewNumAServiceProcs++;
//Slog.i(TAG, "ADJ " + app + " not high ram!");
}
} else {
app.serviceHighRam = false;
}
}
if (app.serviceb) {
adj = ProcessList.SERVICE_B_ADJ;
}
}
第七部分
进程由SERVICE_ADJ(500)降低到SERVICE_B_ADJ(800),有以下两种情况:
A类Service占比过高:当A类Service个数 > Service总数的1/3时,则加入到B类Service。换句话说,B Service的个数至少是A Service的2倍。
内存紧张&&A类Service占用内存较高:当系统内存紧张级别(mLastMemoryLevel)高于ADJ_MEM_FACTOR_NORMAL,且该应用所占内存lastPss大于或等于CACHED_APP_MAX_ADJ级别所对应的内存阈值的1/3(默认值阈值约等于110MB)。
app.curRawAdj = adj;
//Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
// " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
if (adj > app.maxAdj) {
adj = app.maxAdj;
if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
// Put bound foreground services in a special sched group for additional
// restrictions on screen off
if (procState >= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE &&
mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE) {
if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) {
schedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
}
}
// Do final modification to adj. Everything we do between here and applying
// the final setAdj must be done in this function, because we will also use
// it when computing the final cached adj later. Note that we don't need to
// worry about this for max adj above, since max adj will always be used to
// keep it out of the cached vaues.
app.curAdj = app.modifyRawOomAdj(adj);
app.curSchedGroup = schedGroup;
app.curProcState = procState;
app.foregroundActivities = foregroundActivities;
app.completedAdjSeq = mAdjSeq;
// if curAdj or curProcState improved, then this process was promoted
return app.curAdj < prevAppAdj || app.curProcState < prevProcState;
}
第八部分:
- adj 变量就是前面7个部分调整后的adj值。调整完成后的adj值保存到了ProcessRecord的curRawAdj中
- 调整后的adj不能大于预设置的maxAdj
- 将调整的调度策略设置到 ProcessRecord的curSchedGroup
- 将调成后的进程状态设置到ProcessRecord的procState中
- 调整完成,记录此次调整到序号到completedAdjSeq中