调整进程的oom_adj值
AMS中调整进程oom_adj值的方法是updateOomAdjLocked()方法,如下:
final void updateOomAdjLocked() {
// 获取位于前台的activity和它所在的进程
final ActivityRecord TOP_ACT = resumedAppLocked();
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
final long now = SystemClock.uptimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;// 减去空进程最大保存时间
final int N = mLruProcesses.size();
if (false) {
RuntimeException e = new RuntimeException();
e.fillInStackTrace();
Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
}
// Reset state in all uid records.
for (int i=mActiveUids.size()-1; i>=0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
if (false && DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"Starting update of " + uidRec);
uidRec.reset();
}
mStackSupervisor.rankTaskLayersIfNeeded();
mAdjSeq++;
mNewNumServiceProcs = 0;
mNewNumAServiceProcs = 0;
// 初始化emptyProcessLimit、cachedProcessLimit的值
final int emptyProcessLimit;
final int cachedProcessLimit;
if (mProcessLimit <= 0) {
emptyProcessLimit = cachedProcessLimit = 0;
} else if (mProcessLimit == 1) {
emptyProcessLimit = 1;
cachedProcessLimit = 0;
} else {
emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
cachedProcessLimit = mProcessLimit - emptyProcessLimit;
}
// Let's determine how many processes we have running vs.
// how many slots we have for background processes; we may want
// to put multiple processes in a slot of there are enough of
// them.计算cached进程的slot数,结果为3.
int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
- ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
// 计算空进程的数量;
int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
if (numEmptyProcs > cachedProcessLimit) {
// If there are more empty processes than our limit on cached
// processes, then use the cached process limit for the factor.
// This ensures that the really old empty processes get pushed
// down to the bottom, so if we are running low on memory we will
// have a better chance at keeping around more cached processes
// instead of a gazillion empty processes.
// 如果空进程的数量超过了cached进程的限制值,更新为限制值
numEmptyProcs = cachedProcessLimit;
}
// 计算平均每个slot的空进程数
int emptyFactor = numEmptyProcs/numSlots;
if (emptyFactor < 1) emptyFactor = 1;
// 计算平均每个slot的cached进程数
int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
if (cachedFactor < 1) cachedFactor = 1;
// 初始化一些控制量
int stepCached = 0;
int stepEmpty = 0;
int numCached = 0;
int numEmpty = 0;
int numTrimming = 0;
mNumNonCachedProcs = 0;
mNumCachedHiddenProcs = 0;
// First update the OOM adjustment for each of the
// application processes based on their current state.
int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextCachedAdj = curCachedAdj+1;
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextEmptyAdj = curEmptyAdj+2;// 空进程比cached进程的oom_adj的起始值大1
ProcessRecord selectedAppRecord = null;
long serviceLastActivity = 0;
int numBServices = 0;
for (int i=N-1; i>=0; i--) {// 从mLruProcesses列表的后面先前处理
ProcessRecord app = mLruProcesses.get(i);
if (mEnableBServicePropagation && app.serviceb
&& (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
numBServices++;
for (int s = app.services.size() - 1; s >= 0; s--) {
ServiceRecord sr = app.services.valueAt(s);
if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + app.processName
+ " serviceb = " + app.serviceb + " s = " + s + " sr.lastActivity = "
+ sr.lastActivity + " packageName = " + sr.packageName
+ " processName = " + sr.processName);
if (SystemClock.uptimeMillis() - sr.lastActivity
< mMinBServiceAgingTime) {
if (DEBUG_OOM_ADJ) {
Slog.d(TAG,"Not aged enough!!!");
}
continue;
}
if (serviceLastActivity == 0) {
serviceLastActivity = sr.lastActivity;
selectedAppRecord = app;
} else if (sr.lastActivity < serviceLastActivity) {
serviceLastActivity = sr.lastActivity;
selectedAppRecord = app;
}
}
}
if (DEBUG_OOM_ADJ && selectedAppRecord != null) Slog.d(TAG,
"Identified app.processName = " + selectedAppRecord.processName
+ " app.pid = " + selectedAppRecord.pid);
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
// 计算进程的oom_adj值
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
// If we haven't yet assigned the final cached adj
// to the process, do that now.
// 如果计算后的oom_adj值大于等于系统定义的最大oom_adj的值,则表明他们属于cached进程或空进程
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
switch (app.curProcState) {//进程状态
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
// This process is a cached process holding activities...
// assign it the next cached value for that type, and then
// step that cached level.如果进程属于cached进程类型
app.curRawAdj = curCachedAdj;
app.curAdj = app.modifyRawOomAdj(curCachedAdj);
if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
+ " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
+ ")");
if (curCachedAdj != nextCachedAdj) {
stepCached++;// 统计本级别的进程数
if (stepCached >= cachedFactor) {// 进入下一个级别
stepCached = 0;
curCachedAdj = nextCachedAdj;
nextCachedAdj += 2;
if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
break;
default:// 其他进程都属于空进程
// For everything else, assign next empty cached process
// level and bump that up. Note that this means that
// long-running services that have dropped down to the
// cached level will be treated as empty (since their process
// state is still as a service), which is what we want.
app.curRawAdj = curEmptyAdj;
app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
+ " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
+ ")");
if (curEmptyAdj != nextEmptyAdj) {
stepEmpty++;// 统计本级别的进程数
if (stepEmpty >= emptyFactor) {//进入下一个级别
stepEmpty = 0;
curEmptyAdj = nextEmptyAdj;
nextEmptyAdj += 2;
if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
break;
}
}
// 更新进程中各种oom_adj值
applyOomAdjLocked(app, true, now, nowElapsed);
// Count the number of process types.
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
mNumCachedHiddenProcs++;
numCached++;
if (numCached > cachedProcessLimit) {
app.kill("cached #" + numCached, true);
}
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
if (numEmpty > ProcessList.TRIM_EMPTY_APPS
&& app.lastActivityTime < oldTime) {
app.kill("empty for "
+ ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
/ 1000) + "s", true);
} else {
numEmpty++;
if (numEmpty > emptyProcessLimit) {
app.kill("empty #" + numEmpty, true);
}
}
break;
default:
mNumNonCachedProcs++;
break;
}
if (app.isolated && app.services.size() <= 0) {
// If this is an isolated process, and there are no
// services running in it, then the process is no longer
// needed. We agressively kill these because we can by
// definition not re-use the same process again, and it is
// good to avoid having whatever code was running in them
// left sitting around after no longer needed.
app.kill("isolated not needed", true);
} else {
// Keeping this process, update its uid.
final UidRecord uidRec = app.uidRecord;
if (uidRec != null && uidRec.curProcState > app.curProcState) {
uidRec.curProcState = app.curProcState;
}
}
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
numTrimming++;
}
}
}
if ((numBServices > mBServiceAppThreshold) && (true == mAllowLowerMemLevel)
&& (selectedAppRecord != null)) {
ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
ProcessList.CACHED_APP_MAX_ADJ);
selectedAppRecord.setAdj = selectedAppRecord.curAdj;
if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + selectedAppRecord.processName
+ " app.pid = " + selectedAppRecord.pid + " is moved to higher adj");
}
mNumServiceProcs = mNewNumServiceProcs;
// Now determine the memory trimming level of background processes.
// Unfortunately we need to start at the back of the list to do this
// properly. We only do this if the number of background apps we
// are managing to keep around is less than half the maximum we desire;
// if we are keeping a good number around, we'll let them use whatever
// memory they want.
final int numCachedAndEmpty = numCached + numEmpty;
int memFactor;
if (numCached <= ProcessList.TRIM_CACHED_APPS
&& numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
memFactor = ProcessS