概述
每個(gè)進(jìn)程都有自己的優(yōu)先級(jí)adj傻昙,但是進(jìn)程的有顯示具體是如何計(jì)算的?根據(jù)什么條件決定的呢素标?computeOomAdjLocked方法主要就是來根據(jù)當(dāng)前進(jìn)程的各種條件分配合適的Adj優(yōu)先級(jí)的.
ADJ優(yōu)先級(jí)介紹
ADJ取值 | 進(jìn)程類別 | 含義 |
---|---|---|
-1000 | NATIVE_ADJ | native進(jìn)程 |
-900 | SYSTEM_ADJ | System_server進(jìn)程 |
-800 | PERSISTENT_PROC_ADJ | 系統(tǒng)persistent進(jìn)程 |
-700 | PERSISTENT_SERVICE_ADJ | 系統(tǒng)或者persistent進(jìn)程綁定的進(jìn)程 |
0 | FOREGROUND_APP_ADJ | 前臺(tái)進(jìn)程 :和用戶交互的進(jìn)程,不到萬不得已不能殺死 |
100 | VISIBLE_APP_ADJ | 可見進(jìn)程:該進(jìn)程的某個(gè)UI組件是可以被用戶看見的院刁,但是沒有和用戶進(jìn)行交互糯钙,不能隨便殺死,影響用戶體驗(yàn) |
200 | PERCEPTIBLE_APP_ADJ | 可感知進(jìn)程:該進(jìn)程的某個(gè)組件可以被用戶感知到退腥,如后臺(tái)音樂播放 |
300 | BACKUP_APP_ADJ | 備份進(jìn)程:不可輕易打斷任岸,否則容易引起不可修復(fù)的數(shù)據(jù)錯(cuò)誤 |
400 | HEAVY_WEIGHT_APP_ADJ | 重量級(jí)進(jìn)程 |
500 | SERVICE_ADJ | 服務(wù)進(jìn)程 |
600 | HOME_APP_ADJ | Lanucher進(jìn)程 |
700 | PREVIOUS_APP_ADJ | 上一個(gè)訪問的進(jìn)程 |
800 | SERVICE_B_ADJ | B list中的進(jìn)程 |
900 | CACHED_APP_MIN_ADJ | 不可見進(jìn)程adj最小值 |
906 | CACHED_APP_MAX_ADJ | 不可見進(jìn)程adj最大值 |
1001 | UNKNOWN_ADJ | 錯(cuò)誤的adj值 |
進(jìn)程狀態(tài)介紹
狀態(tài)值 | 進(jìn)程狀態(tài)類別 | 含義 |
---|---|---|
-1 | PROCESS_STATE_UNKNOWN | 錯(cuò)誤的進(jìn)程狀態(tài) |
0 | PROCESS_STATE_PERSISTENT | persistent進(jìn)程 |
1 | PROCESS_STATE_PERSISTENT_UI | 該進(jìn)程是persistent進(jìn)程并且有UI界面顯示 |
2 | PROCESS_STATE_TOP | 運(yùn)行Top Activity正在和用戶交互的進(jìn)程 |
3 | PROCESS_STATE_FOREGROUND_SERVICE | 運(yùn)行了Foreground service的進(jìn)程 |
4 | PROCESS_STATE_BOUND_FOREGROUND_SERVICE | 運(yùn)行有系統(tǒng)綁定的前臺(tái)服務(wù) |
5 | PROCESS_STATE_IMPORTANT_FOREGROUND | 用戶可感知的重要進(jìn)程 |
6 | PROCESS_STATE_IMPORTANT_BACKGROUND | 用戶不可感知的重要進(jìn)程 |
7 | PROCESS_STATE_TRANSIENT_BACKGROUND | |
8 | PROCESS_STATE_BACKUP | 備份進(jìn)程 |
9 | PROCESS_STATE_SERVICE | 后臺(tái)運(yùn)行Service的進(jìn)程 |
10 | PROCESS_STATE_RECEIVER | 后臺(tái)運(yùn)行廣播的進(jìn)程 |
11 | PROCESS_STATE_TOP_SLEEPING | 設(shè)備處于Sleep狀態(tài)時(shí)的Top進(jìn)程 |
12 | PROCESS_STATE_HEAVY_WEIGHT | |
13 | PROCESS_STATE_HOME | Launcher進(jìn)程 |
14 | PROCESS_STATE_LAST_ACTIVITY | 上一個(gè)Activity所處的進(jìn)程 |
15 | PROCESS_STATE_CACHED_ACTIVITY | 包含Activity且處于緩存狀態(tài)的進(jìn)程 |
16 | PROCESS_STATE_CACHED_ACTIVITY_CLIENT | 處于緩存狀態(tài)且是另一個(gè)緩存狀態(tài)進(jìn)程的Client進(jìn)程 |
17 | PROCESS_STATE_CACHED_RECENT | |
18 | PROCESS_STATE_CACHED_EMPTY | 緩存空進(jìn)程 |
19 | PROCESS_STATE_NONEXISTENT | 不存在的進(jìn)程 |
如何調(diào)整優(yōu)先級(jí)
AMS中將進(jìn)程分為來這么多個(gè)優(yōu)先級(jí)等級(jí),但是AMS是如何給每個(gè)進(jìn)程分配優(yōu)先級(jí)的呢狡刘?這個(gè)過程主要是在computeOomAdjLocked方法中處理的享潜。
ComputeOomAdjLocked 計(jì)算進(jìn)程的Adj值
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
boolean doingAll, long now) {
// mAdjSeq 是 adj調(diào)整的序號(hào),每次進(jìn)行一輪調(diào)整的時(shí)候 mAdjSeq 加1嗅蔬,進(jìn)程ProcessRecord的adjSeq
//代表最后一次計(jì)算的mAdjSeq的序號(hào)
// 如果當(dāng)前進(jìn)程的adjSeq == mAdjSeq說明剑按,當(dāng)前進(jìn)程ProcessRecord已經(jīng)計(jì)算adj完成疾就,無需再次計(jì)算
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;
}
}
//如果當(dāng)前進(jìn)程的ActivityThread = NULL, 說明當(dāng)前進(jìn)程沒有真正運(yùn)行的實(shí)體艺蝴,是一個(gè)緩存的進(jìn)程
//直接將當(dāng)前進(jìn)程設(shè)置為緩存進(jìn)程之后猬腰,該進(jìn)程的adj計(jì)算就算完成了
// 當(dāng)前進(jìn)程的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;
//處理某一個(gè)進(jìn)程的maxAdj <= FOREGROUND_APP_ADJ ( 0 )情況???????????????????,此類進(jìn)程屬于系統(tǒng)級(jí)重要進(jìn)程
//maxAdj是ProcessRecord在創(chuàng)建的時(shí)候設(shè)置的一個(gè)允許該進(jìn)程最大的adj值
//搜索系統(tǒng)中maxAdj設(shè)置的地方猜敢,只有system_server進(jìn)程啟動(dòng)的時(shí)候和系統(tǒng)persistent進(jìn)程啟動(dòng)的
//時(shí)候會(huì)進(jìn)行設(shè)置姑荷,所以只要maxAdj小于FOREGROUND_APP_ADJ 0的時(shí)候,此時(shí)是系統(tǒng)的一些重
//要的進(jìn)程缩擂,不需要在調(diào)整adj鼠冕,只需呀設(shè)置為maxAdj即可。
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
//初始化進(jìn)程相關(guān)信息
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;
//判斷當(dāng)前的系統(tǒng)進(jìn)程是否包含正在顯示的UI,根據(jù)是否顯示UI來設(shè)置進(jìn)程的curProcState以及進(jìn)程調(diào)度策略
app.systemNoUi = true;
if (app == TOP_APP) {
//如果當(dāng)前系統(tǒng)進(jìn)程屬于TOP_APP, 那這個(gè)進(jìn)程一定含有UI
app.systemNoUi = false;
app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "pers-top-activity";
} else if (app.hasTopUi) {
// 如果當(dāng)前系統(tǒng)進(jìn)程有TopUI
app.systemNoUi = false;
app.adjType = "pers-top-ui";
} else if (activitiesSize > 0) {
// 當(dāng)前進(jìn)程有正在顯示的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) {
// 屏幕顯示胯盯,且當(dāng)前進(jìn)程有UI界面
app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
} else {
// 屏幕休眠懈费,且當(dāng)前進(jìn)程有UI界面
app.curProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
app.curSchedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
}
}
app.curAdj = app.maxAdj;
app.completedAdjSeq = app.adjSeq;
// 如果此次的計(jì)算的Adj<上次的Adj, 說明adj計(jì)算完成了
return app.curAdj < prevAppAdj;
}
第一部分:
- 判斷進(jìn)程在此次調(diào)整中是否調(diào)整完畢,調(diào)整完畢則直接返回
- 如果本進(jìn)程的ActivityThread已經(jīng)掛掉了博脑, 則直接設(shè)置進(jìn)程的優(yōu)先級(jí)為CACHED_APP_MAX_ADJ = 906
- 計(jì)算maxAdj < FOREGROUND_APP_ADJ的情況憎乙, 系統(tǒng)自己創(chuàng)建的系統(tǒng)級(jí)進(jìn)程,設(shè)置adj為maxAdj即可趋厉,無需對(duì)Adj做其他調(diào)整
ADJ < 0的進(jìn)程包括哪些進(jìn)程寨闹?
NATIVE_ADJ(-1000):是由init進(jìn)程fork出來的Native進(jìn)程,并不受system管控君账;
SYSTEM_ADJ(-900):是指system_server進(jìn)程繁堡;
PERSISTENT_PROC_ADJ(-800): 是指在AndroidManifest.xml中申明android:persistent=”true”的系統(tǒng)(即帶有FLAG_SYSTEM標(biāo)記)進(jìn)程,persistent進(jìn)程一般情況并不會(huì)被殺乡数,即便被殺或者發(fā)生Crash系統(tǒng)會(huì)立即重新拉起該進(jìn)程椭蹄。
PERSISTENT_SERVICE_ADJ(-700):是由startIsolatedProcess()方式啟動(dòng)的進(jìn)程,或者是由system_server或者persistent進(jìn)程所綁定(并且?guī)в蠦IND_ABOVE_CLIENT或者BIND_IMPORTANT)的服務(wù)進(jìn)程
// mTopProcessState 代表運(yùn)行TopActivity的進(jìn)程狀態(tài)净赴,只有兩種狀態(tài)
// 1 : ActivityManager.PROCESS_STATE_TOP 顯示狀態(tài)
// 2 : ActivityManager.PROCESS_STATE_TOP_SLEEPING 休眠狀態(tài)
final int PROCESS_STATE_CUR_TOP = mTopProcessState;
// 開始遍歷并計(jì)算普通進(jìn)程 即adj值 > 0的情況绳矩,重要性從高到低進(jìn)行計(jì)算,然后為進(jìn)程設(shè)置一個(gè)合適的Adj優(yōu)先級(jí)
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) {
// 如果當(dāng)前進(jìn)程為TOP_APP進(jìn)程玖翅,即處于和用戶交互的進(jìn)程翼馆,并且當(dāng)前進(jìn)程不是休眠狀態(tài)
// 那么先當(dāng)前進(jìn)程優(yōu)先級(jí)設(shè)置為FOREGROUND_APP_ADJ (0)
// 進(jìn)程狀態(tài) procState 為 PROCESS_STATE_CUR_TOP
// foregroundActivities 為 true, 表明當(dāng)前進(jìn)程包含顯示的Activity界面
// 設(shè)置調(diào)度策略為 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) {
// 如果是正在運(yùn)行動(dòng)畫的進(jìn)程,則設(shè)置Adj = VISIBLE_APP_ADJ = 100
// 進(jìn)程狀態(tài)procState 為 PROCESS_STATE_CUR_TOP
// 設(shè)置調(diào)度策略為 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) {
//如果是正在進(jìn)行測(cè)試的進(jìn)程金度,設(shè)置進(jìn)程adj = FOREGROUND_APP_ADJ = 0
//設(shè)置procState 進(jìn)程狀態(tài)為 PROCESS_STATE_FOREGROUND_SERVICE
//設(shè)置調(diào)度策略為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)) {
// 如果是一個(gè)正在接受廣播的進(jìn)程应媚,此時(shí)我們也要把這個(gè)進(jìn)程看作是前臺(tái)進(jìn)程
// adj 設(shè)置為 FOREGROUND_APP_ADJ = 0
// 進(jìn)程狀態(tài) procState 設(shè)置 PROCESS_STATE_RECEIVER
// 設(shè)置調(diào)度策略為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) {
// 如果是正在執(zhí)行service生命周期回調(diào)的進(jìn)程
// 設(shè)置進(jìn)程adj = FOREGROUND_APP_ADJ = 0
// 設(shè)置進(jìn)程狀態(tài) procState = PROCESS_STATE_SERVICE
// 設(shè)置調(diào)度策略為 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) {
// 如果當(dāng)前進(jìn)程是top進(jìn)程,且系統(tǒng)處于休眠狀態(tài)
// 設(shè)置進(jìn)程adj = FOREGROUND_APP_ADJ
// 設(shè)置進(jìn)程狀態(tài)procState = PROCESS_STATE_CUR_TOP
// 設(shè)置調(diào)度策略為 SCHED_GROUP_BACKGROUND
// foregroundActivities = true 表示當(dāng)前進(jìn)程有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 {
// 其他進(jìn)程則默認(rèn)初始化adj = 1000, 進(jìn)程state默認(rèn)初始化為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);
}
}
第二部分:先處理進(jìn)程adj應(yīng)該設(shè)置為前臺(tái)進(jìn)程FOREGROUND_APP_ADJ的幾種情況
滿足以下任一條件的進(jìn)程都屬于FOREGROUND_APP_ADJ(0)優(yōu)先級(jí):
- 正處于resumed狀態(tài)的Activity
- 正執(zhí)行一個(gè)生命周期回調(diào)的Service(比如執(zhí)行onCreate,onStartCommand,onDestroy等)
- 正執(zhí)行onReceive()的BroadcastReceiver
- 通過startInstrumentation()啟動(dòng)的進(jìn)程
把這幾種情況的進(jìn)程adj設(shè)置為FOREGROUND_APP_ADJ = 0猜极, 雖然以上幾種進(jìn)程的adj值一樣中姜,即對(duì)于LowMemorykiller來講,他們的重要性是相同的跟伏,但是這些進(jìn)程的proceState不同丢胚,從AMS角度而言翩瓜,他們的重要性不一樣。此外對(duì)不同的進(jìn)程根據(jù)重要情況設(shè)置了不同的調(diào)度策略schedGroup, 通過linux的接口來使進(jìn)程有不同的調(diào)度策略携龟。
最后其他進(jìn)程adj都默認(rèn)設(shè)置為1000兔跌,進(jìn)程state 都設(shè)置初始化為CACHE_EMPTY。然后在后續(xù)的流程里再進(jìn)行處理峡蟋。
foregroundActivitys 變量用于表示當(dāng)前進(jìn)程是否有處于前臺(tái)和用戶交互的Activity
// 開始處理包含Activity, 但是卻不在前臺(tái)的進(jìn)程
if (!foregroundActivities && activitiesSize > 0) {
// PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1 = 200 - 100 - 1 = 99
//之前分析updateOomAdjLocked的第一部分時(shí)浮定,簡單提到過rankTaskLayersIfNeeded函數(shù)
//該函數(shù)會(huì)更新包含Activity的Task的rankLayer
//按照顯示層次從上到下,rankLayer逐漸增加层亿,對(duì)應(yīng)的最大值就是VISIBLE_APP_LAYER_MAX
int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
for (int j = 0; j < activitiesSize; j++) {
......
if (r.visible) {
// 如果進(jìn)程包含可見activity, 設(shè)置該進(jìn)程adj = VISIBLE_APP_ADJ.
if (adj > ProcessList.VISIBLE_APP_ADJ) {
//adj大于VISIBLE_APP_ADJ時(shí),才更新對(duì)應(yīng)的adj
//之前提到的正在處理廣播立美、服務(wù)或測(cè)試的進(jìn)程匿又,adj為FOREGROUND,是小于VISIBLE_APP_ADJ
//因此不會(huì)在此更新
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; //設(shè)置可見進(jìn)程的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進(jìn)程
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)) {
//如果進(jìn)程包含處于PAUSING或PAUSED狀態(tài)的Activity時(shí)
//將其oom_adj調(diào)整為“用戶可察覺”的的等級(jí)建蹄,這個(gè)等級(jí)還是很高的
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狀態(tài)Activity的進(jìn)程碌更,其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的進(jìn)程洞慎, state設(shè)置為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的進(jìn)程痛单,設(shè)置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);
}
}
}
}
//不同可見進(jìn)程的oom_adj有一定的差異,處在下層的oom_adj越大
//即越老的Activity所在進(jìn)程劲腿,重要性越低
if (adj == ProcessList.VISIBLE_APP_ADJ) {
adj += minLayer;
}
}
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
if (app.foregroundServices) {
// oregroundServices非空:前臺(tái)服務(wù)進(jìn)程旭绒,執(zhí)行startForegroundService()方法, 此時(shí)該進(jìn)程為可感知進(jìn)程
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) {
// 進(jìn)程有OverlayUI 該進(jìn)程為可感知進(jìn)程.
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非空:執(zhí)行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);
}
}
}
第三部分:
根據(jù)進(jìn)程的Activity狀態(tài)和Service狀態(tài)決定Adj
- VISIBLE_APP_ADJ 可見進(jìn)程:
進(jìn)程中存在可見Activity - PERCEPTIBLE_APP_ADJ 可感知進(jìn)程:
1.進(jìn)程中存在處于PAUSING焦人、PAUSED或STOPPING狀態(tài)的Activity時(shí)
2.foregroundServices非空:前臺(tái)服務(wù)進(jìn)程挥吵,執(zhí)行startForegroundService()方法
3.app.forcingToImportant非空:執(zhí)行setProcessImportant()方法,比如Toast彈出過程花椭。
4.hasOverlayUi非空:非activity的UI位于屏幕最頂層忽匈,比如顯示類型TYPE_APPLICATION_OVERLAY的窗口進(jìn)程.
其余的進(jìn)程仍是UNKNOW_ADJ。
//開始處理一些特殊的進(jìn)程
//如果進(jìn)程是heavyWeightProcess進(jìn)程矿辽, 則設(shè)置進(jìn)程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進(jìn)程丹允, 則設(shè)置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);
}
}
}
//如果進(jìn)程為前一個(gè)進(jìn)程, 則設(shè)置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;
//如果是備份進(jìn)程袋倔, 則設(shè)置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);
}
}
}
第四部分:
處理了一些特殊的進(jìn)程雕蔽,并設(shè)置其adj值和processState值
包含前臺(tái)服務(wù)的進(jìn)程
重量級(jí)進(jìn)程
Home進(jìn)程
previous進(jìn)程
Backup進(jìn)程
//根據(jù)Service來調(diào)整進(jìn)程優(yōu)先級(jí)
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);
//當(dāng)前進(jìn)程的Service是startService方式啟動(dòng)的
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之內(nèi)活躍過的Service服務(wù),將該進(jìn)程的優(yōu)先級(jí)設(shè)置為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";
}
}
}
//根據(jù)綁定該Service的客戶端進(jìn)程來調(diào)整當(dāng)前進(jìn)程的優(yōu)先級(jí)
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) {
// 是自己進(jìn)程綁定的當(dāng)前Service服務(wù)奕污,無需處理
continue;
}
//BIND_WAIVE_PRIORITY
//是指客戶端進(jìn)程的優(yōu)先級(jí)不會(huì)影響目標(biāo)服務(wù)進(jìn)程的優(yōu)先級(jí)萎羔。比如當(dāng)調(diào)用bindService
//又不希望提升目標(biāo)服務(wù)進(jìn)程的優(yōu)先級(jí)的情況下,可以使用該flags
// 根據(jù)Srevise Client進(jìn)程來調(diào)整當(dāng)前進(jìn)程的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;
}
//是指當(dāng)從Activity綁定到該進(jìn)程時(shí)碳默,允許目標(biāo)服務(wù)進(jìn)程根據(jù)該activity的可見性來提升優(yōu)先級(jí)
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);
}
}
}
}
}
}
第五部分:
分為兩個(gè)部分:
- 根據(jù)當(dāng)前進(jìn)程的Service來調(diào)整當(dāng)前進(jìn)程的優(yōu)先級(jí)
- 根據(jù)綁定在當(dāng)前進(jìn)程Service上的客戶端進(jìn)程來調(diào)整優(yōu)先級(jí)
ServiceRecord的成員變量startRequested=true贾陷,是指被顯式調(diào)用了startService()方法缘眶。當(dāng)service被stop或kill會(huì)將其置為false。
一般情況下髓废,即便客戶端進(jìn)程處于前臺(tái)進(jìn)程(ADJ=0)級(jí)別巷懈,服務(wù)進(jìn)程只會(huì)提升到可見(ADJ=1)級(jí)別。以下flags是由調(diào)用bindService()過程所傳遞的flags來決定的慌洪。
flag | 含義 |
---|---|
BIND_WAIVE_PRIORITY | 是指客戶端進(jìn)程的優(yōu)先級(jí)不會(huì)影響目標(biāo)服務(wù)進(jìn)程的優(yōu)先級(jí)顶燕。比如當(dāng)調(diào)用bindService又不希望提升目標(biāo)服務(wù)進(jìn)程的優(yōu)先級(jí)的情況下,可以使用該flags |
BIND_ADJUST_WITH_ACTIVITY | 是指當(dāng)從Activity綁定到該進(jìn)程時(shí)冈爹,允許目標(biāo)服務(wù)進(jìn)程根據(jù)該activity的可見性來提升優(yōu)先級(jí) |
BIND_ABOVE_CLIENT | 當(dāng)客戶端進(jìn)程綁定到一個(gè)服務(wù)進(jìn)程時(shí)涌攻,則服務(wù)進(jìn)程比客戶端進(jìn)程更重要 |
BIND_IMPORTANT | 標(biāo)記該服務(wù)對(duì)于客戶端進(jìn)程很重要,當(dāng)客戶端進(jìn)程處于前臺(tái)進(jìn)程(ADJ=0)級(jí)別時(shí)频伤,會(huì)把服務(wù)進(jìn)程也提升到前臺(tái)進(jìn)程級(jí)別 |
BIND_NOT_VISIBLE | 當(dāng)客戶端進(jìn)程處于可見(ADJ=1)級(jí)別恳谎,也不允許被綁定的服務(wù)進(jìn)程提升到可見級(jí)別,該類服務(wù)進(jìn)程的優(yōu)先級(jí)上限為可感知(ADJ=2)級(jí)別 |
BIND_NOT_FOREGROUND | 不允許被綁定的服務(wù)進(jìn)程提升到前臺(tái)調(diào)度優(yōu)先級(jí)憋肖,但是內(nèi)存優(yōu)先級(jí)可以提升到前臺(tái)級(jí)別因痛。比如不希望服務(wù)進(jìn)程占用 |
具體服務(wù)端進(jìn)程受客戶端進(jìn)程影響的ADJ上限如下:
BIND_ABOVE_CLIENT或BIND_IMPORTANT的情況下,ADJ上限為PERSISTENT_SERVICE_ADJ岸更;
BIND_NOT_VISIBLE的情況下鸵膏, ADJ上限為PERCEPTIBLE_APP_ADJ;
否則怎炊,一般情況下谭企,ADJ上限為VISIBLE_APP_ADJ;
由此评肆,可見當(dāng)bindService過程帶有BIND_ABOVE_CLIENT或者BIND_IMPORTANT flags的同時(shí)赞咙,客戶端進(jìn)程ADJ小于或等于PERSISTENT_SERVICE_ADJ的情況下,該進(jìn)程則為PERSISTENT_SERVICE_ADJ糟港。另外攀操,即便是啟動(dòng)過Activity的進(jìn)程,當(dāng)客戶端進(jìn)程ADJ<=200時(shí)秸抚,還是可以提升該服務(wù)進(jìn)程的優(yōu)先級(jí)速和。
// 根據(jù) ContentProvider調(diào)整進(jìn)程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);
//根據(jù)client來調(diào)整provider進(jìn)程的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.
//根據(jù)provider外部依賴情況來調(diào)整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);
}
}
}
第六部分
對(duì)于provider進(jìn)程,還有以下兩個(gè)條件能成為前臺(tái)進(jìn)程:
- 當(dāng)Provider的客戶端進(jìn)程ADJ<=FOREGROUND_APP_ADJ時(shí)剥汤,則Provider進(jìn)程ADJ等于FOREGROUND_APP_ADJ
- 當(dāng)Provider有外部(非框架)進(jìn)程依賴颠放,也就是調(diào)用了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;
}
}
第七部分
進(jìn)程由SERVICE_ADJ(500)降低到SERVICE_B_ADJ(800)吭敢,有以下兩種情況:
A類Service占比過高:當(dāng)A類Service個(gè)數(shù) > Service總數(shù)的1/3時(shí)碰凶,則加入到B類Service。換句話說,B Service的個(gè)數(shù)至少是A Service的2倍欲低。
內(nèi)存緊張&&A類Service占用內(nèi)存較高:當(dāng)系統(tǒng)內(nèi)存緊張級(jí)別(mLastMemoryLevel)高于ADJ_MEM_FACTOR_NORMAL辕宏,且該應(yīng)用所占內(nèi)存lastPss大于或等于CACHED_APP_MAX_ADJ級(jí)別所對(duì)應(yīng)的內(nèi)存閾值的1/3(默認(rèn)值閾值約等于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個(gè)部分調(diào)整后的adj值砾莱。調(diào)整完成后的adj值保存到了ProcessRecord的curRawAdj中
- 調(diào)整后的adj不能大于預(yù)設(shè)置的maxAdj
- 將調(diào)整的調(diào)度策略設(shè)置到 ProcessRecord的curSchedGroup
- 將調(diào)成后的進(jìn)程狀態(tài)設(shè)置到ProcessRecord的procState中
- 調(diào)整完成瑞筐,記錄此次調(diào)整到序號(hào)到completedAdjSeq中