一、概述
1.1 進(jìn)程
Android框架對(duì)進(jìn)程創(chuàng)建與管理進(jìn)行了封裝,對(duì)于APP開發(fā)者只需知道Android四大組件的使用。當(dāng)Activity, Service, ContentProvider, BroadcastReceiver任一組件啟動(dòng)時(shí),當(dāng)其所承載的進(jìn)程存在則直接使用,不存在則由框架代碼自動(dòng)調(diào)用startProcessLocked創(chuàng)建進(jìn)程。一個(gè)APP可以擁有多個(gè)進(jìn)程,多個(gè)APP也可以運(yùn)行在同一個(gè)進(jìn)程,通過配置Android:process屬性來決定。所以說對(duì)APP來說進(jìn)程幾乎是透明的,但了解進(jìn)程對(duì)于深刻理解Android系統(tǒng)是至關(guān)關(guān)鍵的。
1.2 優(yōu)先級(jí)
Android系統(tǒng)的設(shè)計(jì)理念正是希望應(yīng)用進(jìn)程能盡量長(zhǎng)時(shí)間地存活,以提升用戶體驗(yàn)。應(yīng)用首次打開比較慢,這個(gè)過程有進(jìn)程創(chuàng)建以及Application等信息的初始化,所以應(yīng)用在啟動(dòng)之后,即便退到后臺(tái)并非立刻殺死,而是存活一段時(shí)間,這樣下次再使用則會(huì)非???。對(duì)于APP同樣希望自身盡可能存活更長(zhǎng)的時(shí)間,甚至探索各種?;詈诳萍肌N飿O必反,系統(tǒng)處于低內(nèi)存的狀態(tài)下,手機(jī)性能會(huì)有所下降;系統(tǒng)繼續(xù)放任所有進(jìn)程一直存活,系統(tǒng)內(nèi)存很快就會(huì)枯竭而亡,那么需要合理地進(jìn)程回收機(jī)制。
到底該回收哪個(gè)進(jìn)程呢?系統(tǒng)根據(jù)進(jìn)程的組件狀態(tài)來決定每個(gè)進(jìn)程的優(yōu)先級(jí)值A(chǔ)DJ,系統(tǒng)根據(jù)一定策略先殺優(yōu)先級(jí)最低的進(jìn)程,然后逐步殺優(yōu)先級(jí)更低的進(jìn)程,依此類推,以回收預(yù)期的可用系統(tǒng)資源,從而保證系統(tǒng)正常運(yùn)轉(zhuǎn)。
談到優(yōu)先級(jí),可能有些人會(huì)想到Linux進(jìn)程本身有nice值,這個(gè)能決定CPU資源調(diào)度的優(yōu)先級(jí);而本文介紹Android系統(tǒng)中的ADJ,主要決定在什么場(chǎng)景下什么類型的進(jìn)程可能會(huì)被殺,影響的是進(jìn)程存活時(shí)間。ADJ與nice值兩者定位不同,不過也有一定的聯(lián)系,優(yōu)先級(jí)很高的進(jìn)程,往往也是用戶不希望被殺的進(jìn)程,是具有有一定正相關(guān)性。
1.3 ADJ級(jí)別
從Android 7.0開始,ADJ采用100、200、300;在這之前的版本ADJ采用數(shù)字1、2、3,這樣的調(diào)整可以更進(jìn)一步地細(xì)化進(jìn)程的優(yōu)先級(jí),比如在VISIBLE_APP_ADJ(100)與PERCEPTIBLE_APP_ADJ(200)之間,可以有ADJ=101、102級(jí)別的進(jìn)程。
- 省去lmk對(duì)oom_score_adj的計(jì)算過程,Android 7.0之前的版本,oom_score_adj= oom_adj * 1000/17; 而Android 7.0開始,oom_score_adj= oom_adj,不用再經(jīng)過一次轉(zhuǎn)換。
1.4 LMK
為了防止剩余內(nèi)存過低,Android在內(nèi)核空間有l(wèi)owmemorykiller(簡(jiǎn)稱LMK),LMK是通過注冊(cè)shrinker來觸發(fā)低內(nèi)存回收的,這個(gè)機(jī)制并不太優(yōu)雅,可能會(huì)拖慢Shrinkers內(nèi)存掃描速度,已從內(nèi)核4.12中移除,后續(xù)會(huì)采用用戶空間的LMKD + memory cgroups機(jī)制,這里先不展開LMK講解。
進(jìn)程剛啟動(dòng)時(shí)ADJ等于INVALID_ADJ,當(dāng)執(zhí)行完attachApplication(),該該進(jìn)程的curAdj和setAdj不相等,則會(huì)觸發(fā)執(zhí)行setOomAdj()將該進(jìn)程的節(jié)點(diǎn)/proc/pid/oom_score_adj寫入oomadj值。下圖參數(shù)為Android原生閾值,當(dāng)系統(tǒng)剩余空閑內(nèi)存低于某閾值(比如147MB),則從ADJ大于或等于相應(yīng)閾值(比如900)的進(jìn)程中,選擇ADJ值最大的進(jìn)程,如果存在多個(gè)ADJ相同的進(jìn)程,則選擇內(nèi)存最大的進(jìn)程。 如下是64位機(jī)器,LMK默認(rèn)閾值圖:

在updateOomLevels()過程,會(huì)根據(jù)手機(jī)屏幕尺寸或內(nèi)存大小來調(diào)整scale,默認(rèn)大多數(shù)手機(jī)內(nèi)存都大于700MB,則scale等于1。對(duì)于64位手機(jī),閾值會(huì)更大些,具體如下。
private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
...
for (int i=0; i<mOomAdj.length; i++) {
int low = mOomMinFreeLow[i];
int high = mOomMinFreeHigh[i];
if (is64bit) {
if (i == 4) high = (high*3)/2;
else if (i == 5) high = (high*7)/4;
}
mOomMinFree[i] = (int)(low + ((high-low)*scale));
}
}
二、解讀ADJ
接下來,解讀每個(gè)ADJ值都對(duì)應(yīng)著怎樣條件的進(jìn)程,包括正在運(yùn)行的組件以及這些組件的狀態(tài)幾何。這里重點(diǎn)介紹上圖標(biāo)紅的ADJ級(jí)別所對(duì)應(yīng)的進(jìn)程。
Android系統(tǒng)中計(jì)算各進(jìn)程ADJ算法的核心方法:
- updateOomAdjLocked:更新adj,當(dāng)目標(biāo)進(jìn)程為空或者被殺則返回false;否則返回true;
- computeOomAdjLocked:計(jì)算adj,返回計(jì)算后RawAdj值;
- applyOomAdjLocked:應(yīng)用adj,當(dāng)需要?dú)⒌裟繕?biāo)進(jìn)程則返回false;否則返回true。
當(dāng)Android四大組件狀態(tài)改變時(shí)會(huì)updateOomAdjLocked()來同步更新相應(yīng)進(jìn)程的ADJ優(yōu)先級(jí)。這里需要說明一下,當(dāng)同一個(gè)進(jìn)程有多個(gè)決定其優(yōu)先級(jí)的組件狀態(tài)時(shí),取優(yōu)先級(jí)最高的ADJ作為最終的ADJ。另外,進(jìn)程會(huì)通過設(shè)置maxAdj來限定ADJ的上限。
關(guān)于分析進(jìn)程ADJ相關(guān)信息,常用命令如下:
- dumpsys meminfo,
- dumpsys activity o
- dumpsys activity p
2.0 ADJ<0的進(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)程
再來說一下其他優(yōu)先級(jí):
- BACKUP_APP_ADJ(300):執(zhí)行bindBackupAgent()過程的進(jìn)程
- HEAVY_WEIGHT_APP_ADJ(400): realStartActivityLocked()過程,當(dāng)應(yīng)用的privateFlags標(biāo)識(shí)PRIVATE_FLAG_CANT_SAVE_STATE的進(jìn)程;
- HOME_APP_ADJ(600):當(dāng)類型為ACTIVITY_TYPE_HOME的應(yīng)用,比如桌面APP
- PREVIOUS_APP_ADJ(700):用戶上一個(gè)使用的APP進(jìn)程
SYSTEM_ADJ(-900)
SYSTEM_ADJ: 僅指system_server進(jìn)程。在執(zhí)行SystemServer的startBootstrapServices()過程會(huì)調(diào)用AMS.setSystemProcess(),將system_server進(jìn)程的maxAdj設(shè)置成SYSTEM_ADJ,源碼如下:
public void setSystemProcess() {
...
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
"android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
synchronized (this) {
ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
app.persistent = true;
app.pid = MY_PID;
app.maxAdj = ProcessList.SYSTEM_ADJ;
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.put(app.pid, app);
}
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
...
}
但system_server的ADJ并非等于-900,而是-800?是由于startPersistentApps()過程直接把其adj重新被設(shè)置為-800,這算是一個(gè)小BUG,但 其實(shí)目前來說對(duì)于ADJ<0的進(jìn)程,LMK不會(huì)殺,兩者沒有什么區(qū)別。
PERSISTENT_PROC_ADJ(-800)
PERSISTENT_PROC_ADJ:在AndroidManifest.xml中申明android:persistent=”true”的系統(tǒng)(即帶有FLAG_SYSTEM標(biāo)記)進(jìn)程,稱之為persistent進(jìn)程。對(duì)于persistent進(jìn)程常規(guī)情況都不會(huì)被殺,一旦被殺或者發(fā)生Crash,進(jìn)程會(huì)立即重啟。
AMS.addAppLocked()或AMS.newProcessRecordLocked()過程會(huì)賦值:
場(chǎng)景1: newProcessRecordLocked
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) {
String proc = customProcess != null ? customProcess : info.processName;
final int userId = UserHandle.getUserId(info.uid);
int uid = info.uid;
...
final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
if (!mBooted && !mBooting
&& userId == UserHandle.USER_SYSTEM
&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
r.persistent = true;
r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
if (isolated && isolatedUid != 0) {
r.maxAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
}
return r;
}
在每一次進(jìn)程啟動(dòng)的時(shí)候都會(huì)判斷該進(jìn)程是否persistent進(jìn)程,如果是則會(huì)設(shè)置maxAdj=PERSISTENT_PROC_ADJ。 system_server進(jìn)程應(yīng)該也是persistent進(jìn)程?
場(chǎng)景2:addAppLocked
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated, String abiOverride) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
info.uid, true);
} else {
app = null;
}
if (app == null) {
app = newProcessRecordLocked(info, customProcess, isolated, 0);
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
...
if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
app.persistent = true;
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
startProcessLocked(app, "added application",
customProcess != null ? customProcess : app.processName, abiOverride);
}
return app;
}
開機(jī)過程會(huì)先啟動(dòng)persistent進(jìn)程,并賦予maxAdj為PERSISTENT_PROC_ADJ,調(diào)用鏈:
startOtherServices()
AMS.systemReady
AMS.startPersistentApps
AMS.addAppLocked
PERSISTENT_SERVICE_ADJ(-700)
PERSISTENT_SERVICE_ADJ: startIsolatedProcess()方式啟動(dòng)的進(jìn)程,或者是由system_server或者persistent進(jìn)程所綁定的服務(wù)進(jìn)程。
場(chǎng)景1:newProcessRecordLocked
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) {
String proc = customProcess != null ? customProcess : info.processName;
final int userId = UserHandle.getUserId(info.uid);
int uid = info.uid;
...
final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
if (!mBooted && !mBooting
&& userId == UserHandle.USER_SYSTEM
&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
r.persistent = true;
r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
if (isolated && isolatedUid != 0) { //startIsolatedProcess
r.maxAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
}
return r;
}
調(diào)用鏈:
startOtherServices
WebViewUpdateService.prepareWebViewInSystemServer
WebViewUpdateServiceImpl.prepareWebViewInSystemServer
WebViewUpdater.prepareWebViewInSystemServer
WebViewUpdater.onWebViewProviderChanged
SystemImpl.onWebViewProviderChanged
WebViewFactory.onWebViewProviderChanged
WebViewLibraryLoader.prepareNativeLibraries
WebViewLibraryLoader.createRelros
WebViewLibraryLoader.createRelroFile
AMS.startIsolatedProcess
BACKUP_APP_ADJ(300)
if (mBackupTarget != null && app == mBackupTarget.app) {
if (adj > ProcessList.BACKUP_APP_ADJ) {
adj = ProcessList.BACKUP_APP_ADJ;
if (procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
}
app.adjType = "backup";
app.cached = false;
}
if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
procState = ActivityManager.PROCESS_STATE_BACKUP;
app.adjType = "backup";
}
}
- 執(zhí)行bindBackupAgent()過程,設(shè)置mBackupTarget值;
- 執(zhí)行clearPendingBackup()或unbindBackupAgent()過程,置空mBackupTarget值;
HEAVY_WEIGHT_APP_ADJ(400)
- realStartActivityLocked()過程,當(dāng)應(yīng)用的privateFlags標(biāo)識(shí)PRIVATE_FLAG_CANT_SAVE_STATE,設(shè)置mHeavyWeightProcess值;
- finishHeavyWeightApp(), 置空mHeavyWeightProcess值;
HOME_APP_ADJ(600)
當(dāng)類型為ACTIVITY_TYPE_HOME的應(yīng)用啟動(dòng)后會(huì)設(shè)置mHomeProcess,比如桌面APP。
PREVIOUS_APP_ADJ(700)
場(chǎng)景1:用戶上一個(gè)使用的包含UI的進(jìn)程,為了給用戶在兩個(gè)APP之間更好的切換體驗(yàn),將上一個(gè)進(jìn)程ADJ設(shè)置到PREVIOUS_APP_ADJ的檔次。 當(dāng)activityStoppedLocked()過程會(huì)更新上一個(gè)應(yīng)用。
if (app == mPreviousProcess && app.activities.size() > 0) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "previous";
}
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "previous";
}
}
場(chǎng)景2: 當(dāng)provider進(jìn)程,上一次使用時(shí)間不超過20S的情況下,優(yōu)先級(jí)不低于PREVIOUS_APP_ADJ。provider進(jìn)程這個(gè)是Android 7.0以后新增的邏輯 ,這樣做的好處是在內(nèi)存比較低的情況下避免擁有provider的進(jìn)程出現(xiàn)顛簸,也就是啟動(dòng)后殺,然后又被拉。
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 (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "recent-provider";
}
}
2.1 FOREGROUND_APP_ADJ(0)
場(chǎng)景1:滿足以下任一條件的進(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)程
源碼如下:
if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) {
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
} else if (app.instr != null) {
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
} else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
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;
} else if (app.executingServices.size() > 0) {
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;
} else if (app == TOP_APP) {
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "top-sleeping";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
} else {
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
adj = cachedAdj;
procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
app.cached = true;
app.empty = true;
app.adjType = "cch-empty";
}
場(chǎng)景2: 當(dāng)客戶端進(jìn)程activity里面調(diào)用bindService()方法時(shí)flags帶有BIND_ADJUST_WITH_ACTIVITY參數(shù),并且該activity處于可見狀態(tài),則當(dāng)前服務(wù)進(jìn)程也屬于前臺(tái)進(jìn)程,源碼如下:
for (int is = app.services.size()-1; is >= 0; is--) {
ServiceRecord s = app.services.valueAt(is);
for (int conni = s.connections.size()-1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
ConnectionRecord cr = clist.get(i);
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
...
}
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.state == ActivityState.RESUMED ||
a.state == 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;
}
}
}
}
}
provider客戶端
場(chǎng)景3: 對(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
for (int provi = app.pubProviders.size()-1; provi >= 0; 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; i--) {
ContentProviderConnection conn = cpr.connections.get(i);
ProcessRecord client = conn.client;
int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
...
} else {
adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
adjType = "provider";
}
app.cached &= client.cached;
}
...
}
//根據(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;
}
}
}
2.2 VISIBLE_APP_ADJ(100)
可見進(jìn)程:當(dāng)ActivityRecord的visible=true,也就是Activity可見的進(jìn)程。
if (!foregroundActivities && activitiesSize > 0) {
int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
for (int j = 0; j < activitiesSize; j++) {
final ActivityRecord r = app.activities.get(j);
if (r.visible) {
if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = ProcessList.VISIBLE_APP_ADJ;
app.adjType = "vis-activity";
}
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
app.adjType = "vis-activity";
}
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
final TaskRecord task = r.getTask();
if (task != null && minLayer > 0) {
final int layer = task.mLayerRank;
if (layer >= 0 && minLayer > layer) {
minLayer = layer;
}
}
break;
}
...
}
if (adj == ProcessList.VISIBLE_APP_ADJ) {
adj += minLayer;
}
}
從Android P開始,進(jìn)一步細(xì)化ADJ級(jí)別,增加了VISIBLE_APP_LAYER_MAX(99),是指VISIBLE_APP_ADJ(100)跟PERCEPTIBLE_APP_ADJ(200)之間有99個(gè)槽,則可見級(jí)別ADJ的取值范圍為[100,199]。 算法會(huì)根據(jù)其所在task的mLayerRank來調(diào)整其ADJ,100加上mLayerRank就等于目標(biāo)ADJ,layer越大,則ADJ越小。
關(guān)于TaskRecord的mLayerRank的計(jì)算方式是在updateOomAdjLocked()過程調(diào)用ASS的rankTaskLayersIfNeeded()方法,如下:
[-> ActivityStackSupervisor.java]
void rankTaskLayersIfNeeded() {
if (!mTaskLayersChanged) {
return;
}
mTaskLayersChanged = false;
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
int baseLayer = 0;
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
baseLayer += stack.rankTaskLayers(baseLayer);
}
}
}
[-> ActivityStack.java]
final int rankTaskLayers(int baseLayer) {
int layer = 0;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
ActivityRecord r = task.topRunningActivityLocked();
if (r == null || r.finishing || !r.visible) {
task.mLayerRank = -1;
} else {
task.mLayerRank = baseLayer + layer++;
}
}
return layer;
}
當(dāng)TaskRecord頂部的ActivityRecord為空或者結(jié)束或者不可見時(shí),則設(shè)置該TaskRecord的mLayerRank等于-1; 每個(gè)ActivityDisplay的baseLayer都是從0開始,從最上面的TaskRecord開始,第一個(gè)ADJ=100,從上至下依次加1,直到199為上限。
service客戶端
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來決定的。
作為工程師很多時(shí)候可能還是想看看源碼,show me the code。但是關(guān)于ADJ計(jì)算這一塊源碼場(chǎng)景computeOomAdjLocked(),Google真心寫得比較亂,為了更清晰地說明客戶端進(jìn)程如何影響服務(wù)進(jìn)程,在保證不失去原意的情況下重寫了這塊部分邏輯:
這個(gè)過程主要根據(jù)service本身、client端情況以及activity狀態(tài)分別來調(diào)整adj和schedGroup
for (int is = app.services.size()-1; is >= 0; is--) {
ServiceRecord s = app.services.valueAt(is);
if (s.startRequested) {
... // 根據(jù)service本身調(diào)整adj和adjType
}
for (int conni = s.connections.size()-1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
ConnectionRecord cr = clist.get(i);
//根據(jù)client端來調(diào)整adj
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
...
} else {
int newAdj = clientAdj;
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
if(clientAdj < ProcessList.PERSISTENT_SERVICE_ADJ) {
newAdj = PERSISTENT_SERVICE_ADJ;
}
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0) {
if(clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ) {
newAdj = PERCEPTIBLE_APP_ADJ;
}
} else {
if (clientAdj < ProcessList.VISIBLE_APP_ADJ) {
newAdj = VISIBLE_APP_ADJ;
}
}
if (adj > newAdj) {
adj = newAdj;
adjType = "service";
}
}
}
}
final ActivityRecord a = cr.activity;
// 根據(jù)client的activity來調(diào)整adj和schedGroup
if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
...
}
}
}
}
上段代碼說明服務(wù)端進(jìn)程優(yōu)先級(jí)(adj)不會(huì)低于客戶端進(jìn)程優(yōu)先級(jí)(newAdj),而newAdj的上限受限于flags,具體服務(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í)。
2.3 PERCEPTIBLE_APP_ADJ(200)
可感知進(jìn)程:當(dāng)該進(jìn)程存在不可見的Activity,但Activity正處于PAUSING、PAUSED、STOPPING狀態(tài),則為PERCEPTIBLE_APP_ADJ
if (!foregroundActivities && activitiesSize > 0) {
int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
for (int j = 0; j < activitiesSize; j++) {
final ActivityRecord r = app.activities.get(j);
if (r.visible) {
...
} else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "pause-activity";
}
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
app.adjType = "pause-activity";
}
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
} else if (r.state == ActivityState.STOPPING) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "stop-activity";
}
if (!r.finishing) {
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "stop-activity";
}
}
app.cached = false;
app.empty = false;
foregroundActivities = true;
}
}
}
滿足以下任一條件的進(jìn)程也屬于可感知進(jìn)程:
- foregroundServices非空:前臺(tái)服務(wù)進(jìn)程,執(zhí)行startForegroundService()方法
- app.forcingToImportant非空:執(zhí)行setProcessImportant()方法,比如Toast彈出過程。
- hasOverlayUi非空:非activity的UI位于屏幕最頂層,比如顯示類型TYPE_APPLICATION_OVERLAY的窗口
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
if (app.foregroundServices) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
app.cached = false;
app.adjType = "fg-service";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
} else if (app.hasOverlayUi) {
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 (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
if (app.forcingToImportant != null) {
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;
}
}
2.4 SERVICE_ADJ(500)
服務(wù)進(jìn)程:沒有啟動(dòng)過Activity,并且30分鐘之內(nèi)活躍過的服務(wù)進(jìn)程。 startRequested為true,則代表執(zhí)行startService()且沒有stop的進(jìn)程。
for (int is = app.services.size()-1; is >= 0; is--) {
ServiceRecord s = app.services.valueAt(is);
if (s.startRequested) {
app.hasStartedServices = true;
if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
procState = ActivityManager.PROCESS_STATE_SERVICE;
app.adjType = "started-services";
}
if (app.hasShownUi && app != mHomeProcess) {
if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-ui-services";
}
} else {
if (now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
if (adj > ProcessList.SERVICE_ADJ) {
adj = ProcessList.SERVICE_ADJ;
app.adjType = "started-services";
app.cached = false;
}
}
}
}
for (int conni = s.connections.size()-1; conni >= 0; conni--) {
... //根據(jù)client情況來調(diào)整adj
}
}
2.5 SERVICE_B_ADJ(800)
進(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)。
源碼如下:
if (adj == ProcessList.SERVICE_ADJ) {
if (doingAll) {
app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
mNewNumServiceProcs++;
if (!app.serviceb) {
if (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
&& app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {
app.serviceHighRam = true;
app.serviceb = true;
} else {
mNewNumAServiceProcs++;
}
} else {
app.serviceHighRam = false;
}
}
if (app.serviceb) {
adj = ProcessList.SERVICE_B_ADJ;
}
}
ADJ_MEM_FACTOR
這里順便一下,內(nèi)存因子ADJ_MEM_FACTOR共有4個(gè)級(jí)別,當(dāng)前處于哪個(gè)內(nèi)存因子級(jí)別,取決于當(dāng)前進(jìn)程中cached進(jìn)程和空進(jìn)程的個(gè)數(shù)。
final int numCachedAndEmpty = numCached + numEmpty;
int memFactor;
if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
&& numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
}
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
}
ADJ內(nèi)存因子:決定允許后臺(tái)運(yùn)行Jobs的最大上限,以及決定TrimMemory的級(jí)別(包括ThreadedRenderer的回收級(jí)別),再進(jìn)一步來看看內(nèi)存因子:
也就是說
默認(rèn)情況取值如下:
- 最大緩存進(jìn)程個(gè)數(shù):CUR_MAX_CACHED_PROCESSES = MAX_CACHED_PROCESSES = 32
- 最大空進(jìn)程個(gè)數(shù): CUR_MAX_EMPTY_PROCESSES = MAX_CACHED_PROCESSES/2 = 16
- Trim空進(jìn)程上限:CUR_TRIM_EMPTY_PROCESSES = MAX_CACHED_PROCESSES/4 = 8
- Trim緩存進(jìn)程上限:CUR_TRIM_CACHED_PROCESSES = MAX_CACHED_PROCESSES/6 = 5
當(dāng)mOverrideMaxCachedProcesses有值的情況下,最大緩存進(jìn)程個(gè)數(shù)和最大空進(jìn)程個(gè)數(shù)上限優(yōu)先取mOverrideMaxCachedProcesses,可通過AMS.setProcessLimit(int max)調(diào)整mOverrideMaxCachedProcesses值;Trim的緩存進(jìn)程和空進(jìn)程上限不受mOverrideMaxCachedProcesses影響。
再來看看cached和empty進(jìn)程:
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit;
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
mNumCachedHiddenProcs++;
numCached++;
//默認(rèn)cachedProcessLimit=16
if (numCached > cachedProcessLimit) {
app.kill("cached #" + numCached, true);
}
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
//默認(rèn)CUR_TRIM_EMPTY_PROCESSES=8, 且滿足30min
if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
&& app.lastActivityTime < oldTime) {
app.kill("empty for "
+ ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
/ 1000) + "s", true);
} else {
numEmpty++;
//默認(rèn)cachedProcessLimit=16
if (numEmpty > emptyProcessLimit) {
app.kill("empty #" + numEmpty, true);
}
}
break;
default:
mNumNonCachedProcs++;
break;
用于限制empty或cached進(jìn)程的上限為16個(gè),并且empty超過8個(gè)時(shí)會(huì)清理掉30分鐘沒有活躍的進(jìn)程。 cached和empty主要是區(qū)別是否有Activity。
2.6 CACHED_APP_MIN_ADJ(900)
緩存進(jìn)程優(yōu)先級(jí)從CACHED_APP_MIN_ADJ(900)到 CACHED_APP_MAX_ADJ(906)。
ADJ的轉(zhuǎn)換算法:
- cached: 900, 901, 903, 905
- empty: 900, 902, 904, 906
final int N = mLruProcesses.size();
//numSlots等于3
int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
- ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
//mNumNonCachedProcs是指empty和cached之外的進(jìn)程, mNumCachedHiddenProcs代表的是cached進(jìn)程個(gè)數(shù)
int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
if (numEmptyProcs > cachedProcessLimit) {
numEmptyProcs = cachedProcessLimit;
}
//emptyFactor和cachedFactor分別代表每個(gè)slot里面包括的進(jìn)程個(gè)數(shù),大于或等于1
int emptyFactor = numEmptyProcs/numSlots;
int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
mNumNonCachedProcs = 0;
mNumCachedHiddenProcs = 0;
int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextCachedAdj = curCachedAdj+1;
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextEmptyAdj = curEmptyAdj+2;
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
case ActivityManager.PROCESS_STATE_CACHED_RECENT:
app.curRawAdj = curCachedAdj;
app.curAdj = app.modifyRawOomAdj(curCachedAdj);
if (curCachedAdj != nextCachedAdj) {
stepCached++;
if (stepCached >= cachedFactor) {
stepCached = 0;
curCachedAdj = nextCachedAdj;
nextCachedAdj += 2; //每次加2
if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
break;
default:
app.curRawAdj = curEmptyAdj;
//ADJ閾值
app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
if (curEmptyAdj != nextEmptyAdj) {
stepEmpty++;
if (stepEmpty >= emptyFactor) {
stepEmpty = 0;
curEmptyAdj = nextEmptyAdj;
nextEmptyAdj += 2; //每次加2
if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
break;
}
}
applyOomAdjLocked(app, true, now, nowElapsed);
...
}
}
numSlots=3, emptyFactor= 空進(jìn)程個(gè)數(shù)/3, cachedFactor= 緩存進(jìn)程個(gè)數(shù)/3,
再來看看PROCESS_STATE_CACHED_ACTIVITY的定義:
if (!foregroundActivities && activitiesSize > 0) {
for (int j = 0; j < activitiesSize; j++) {
final ActivityRecord r = app.activities.get(j);
if (r.visible) {
...
} else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
...
} else if (r.state == ActivityState.STOPPING) {
...
} else {
if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
app.adjType = "cch-act";
}
}
}
}
foregroundActivities代表當(dāng)前不是前臺(tái)(FOREGROUND_APP_ADJ)進(jìn)程,并且存在Activity的進(jìn)程,當(dāng)該Activity窗口不可見,并且不處于PAUSING(正在)、PAUSED(onPause個(gè))、STOPPING的任一狀態(tài)的情況下,則設(shè)置該進(jìn)程為PROCESS_STATE_CACHED_ACTIVITY。
PROCESS_STATE_CACHED_ACTIVITY_CLIENT的定義:
if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
if (app.hasClientActivities) {
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
app.adjType = "cch-client-act";
} else if (app.treatLikeActivity) {
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
app.adjType = "cch-as-act";
}
}
當(dāng)該進(jìn)程Service的客戶端進(jìn)程存在Activity或者是treatLikeActivity的進(jìn)程,其進(jìn)程狀態(tài)都是cached進(jìn)程。
三、查看進(jìn)程優(yōu)先級(jí)
3.1 CPU調(diào)度優(yōu)先級(jí)
bindService或者startService是否前臺(tái)調(diào)用取決于caller進(jìn)程的調(diào)度組。當(dāng)caller屬于SCHED_GROUP_BACKGROUND則認(rèn)為是后臺(tái)調(diào)用,當(dāng)不屬于SCHED_GROUP_BACKGROUND則認(rèn)為是前臺(tái)調(diào)用。callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
關(guān)于CPU調(diào)度組:
THREAD_GROUP_TOP_APP
- SCHED_GROUP_TOP_APP:
- setRenderThread()過程,根據(jù)屬性sys.use_fifo_ui來決定采用SCHED_FIFO,或者設(shè)置當(dāng)前線程的優(yōu)先級(jí)為-10
- TOP_APP或者app.hasTopUi,則設(shè)置為該值
- SCHED_GROUP_TOP_APP_BOUND:
- 對(duì)于ConnectionRecord帶有BIND_ADJUST_WITH_ACTIVITY和BIND_IMPORTANT,并且沒帶有BIND_NOT_FOREGROUND的情況下, 當(dāng)客戶端進(jìn)程的有可見的Activity,或者處于RESUMED/PAUSING狀態(tài)時(shí),則設(shè)置為該值
當(dāng)進(jìn)程調(diào)度級(jí)別由非TOP切換到TOP級(jí)別,則主線程和rendThread可設(shè)置為SCHED_FIFO或者更高優(yōu)先級(jí);當(dāng)由TOP級(jí)別切換回非TOP級(jí)別,則恢復(fù)原來的調(diào)度策略或優(yōu)先級(jí)。
THREAD_GROUP_DEFAULT
- SCHED_GROUP_DEFAULT:
- 默認(rèn)值
- ADJ <= FOREGROUND_APP_ADJ;
- 正在接收來自于mFgBroadcastQueue廣播隊(duì)列的廣播;
- 正在執(zhí)行來自于前臺(tái)調(diào)度進(jìn)程發(fā)起的服務(wù)(execServicesFg=true)
- Activity處于可見狀態(tài)(visible=true)
- 具有fg-service或者設(shè)置forcingToImportant的服務(wù)
- 正在顯示一個(gè)overlay UI(app.hasOverlayUi=true)
- 當(dāng)ConnectionRecord同時(shí)沒有指定BIND_NOT_FOREGROUND和BIND_IMPORTANT_BACKGROUND、BIND_IMPORTANT情況下, 當(dāng)客戶端進(jìn)程的schedGroup高于服務(wù)進(jìn)程,則設(shè)置為該值
- 對(duì)于ConnectionRecord帶有BIND_ADJUST_WITH_ACTIVITY,并且沒帶有BIND_NOT_FOREGROUND和BIND_IMPORTANT的情況下, 當(dāng)客戶端進(jìn)程的有可見的Activity,或者處于RESUMED/PAUSING狀態(tài)時(shí),則設(shè)置為該值
- 當(dāng)ContentProviderConnection所對(duì)應(yīng)的客戶端進(jìn)程的schedGroup高于服務(wù)進(jìn)程,則設(shè)置為該值
- 當(dāng)cpr.hasExternalProcessHandles為true的情況
- 最后,當(dāng)maxAdj <= PERCEPTIBLE_APP_ADJ的情況
THREAD_GROUP_BG_NONINTERACTIVE
- SCHED_GROUP_BACKGROUND:
- 應(yīng)用已結(jié)束(app.thread == null)
- 正在接收來自于mBgBroadcastQueue廣播隊(duì)列的廣播;
- 正在執(zhí)行來自于前臺(tái)調(diào)度進(jìn)程發(fā)起的服務(wù)(execServicesFg=false)
- TOP_APP,且設(shè)備處于睡眠狀態(tài)
- 等等