1.前言
ActivityManagerService作为一个核心系统服务,除了负责管理四大组件之外,还负责管理进程,对进程的管理有以下方面:
- 新建进程
- 调整进程在mLruProcesses的位置
- 调整进程OomAdj值
- 杀进程
而新建进程在前面有说到过,今天就来介绍下剩下的三个。
2.调整位置的updateLruProcessLocked方法
代码比较长,分段看。
|
|
- 如果有activity,并且进程中activity没有发生变化,不需要调整
- 如果有activity,但是当前进程就是在最后,不需要调整
- 如果没有activity,但是在合适的位置,不需要调整
- 如果有persistent标志,不需要调整
- lrui 为当前进程在list中的索引(最后一个的索引)
|
|
如果已经存在,调整mLruProcessActivityStart和mLruProcessServiceStart,并且暂时从列表中移除进程。
|
|
- hasActivity为true
- 没有activities,但是有hasClientActivities,将当前进程插入到列表的最后,从mLruProcessActivityStart到n-2的位置,如果i处的uid和当前进程uid相等,但是上一个却不等的话,交换位置。
- 直接添加到最后一个
- hasActivity为false,hasService为true,加入到mLruProcessActivityStart位置
- 因为client大多为null,所以这里插入到index位置,也就是mLruProcessServiceStart处
|
|
把和这个进程关联的service和contentprovider调整到这个进程之后。
3. 调整OomAdj值的updateOomAdjLocked方法
方法较长,分段看。
|
|
这一部分代码是对一些值进行初始化操作,如空进程、缓存进程的数目,numSlots。
|
|
上面代码的逻辑是更新进程oomadj值。
- 首先通过computeOomAdjLocked计算oomadj值
- 当进程未分配adj值是,更新adj值(if (app.curAdj >= ProcessList.UNKNOWN_ADJ))
- 当前进程状态为 PROCESS_STATE_CACHED_ACTIVITY_CLIENT,修改adj为9(CACHED_APP_MIN_ADJ),若当前cache adj不等于下一个cache adj的时候, 调整nextCachedAdj和curCachedAdj值
- 不是PROCESS_STATE_CACHED_ACTIVITY和PROCESS_STATE_CACHED_ACTIVITY_CLIENT,修改adj值为curEmptyAdj,当curEmptyAdj不等于nextEmptyAdj的时候,调整这两个值
- applyOomAdjLocked,使更新生效
- 根据进程状态,选择策略
- PROCESS_STATE_CACHED_ACTIVITY_CLIENT,如果,缓存进程数大于最大限制的话,杀掉进程
- PROCESS_STATE_CACHED_EMPTY ,空进程超过数目上线,并且空闲时间大于30分钟,这杀掉进程
- 如果是孤立进程 并且没有service,直接杀掉
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 = ProcessStats.ADJ_MEM_FACTOR_LOW;
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
}
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
}
// We always allow the memory level to go up (better). We only allow it to go
// down if we are in a state where that is allowed, *and* the total number of processes
// has gone down since last time.
if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
+ " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
+ " numProcs=" + mLruProcesses.size() + " last=" + mLastNumProcesses);
if (memFactor > mLastMemoryLevel) {
if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
memFactor = mLastMemoryLevel;
if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
}
}
mLastMemoryLevel = memFactor;
mLastNumProcesses = mLruProcesses.size();
boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
final int trackerMemFactor = mProcessStats.getMemFactorLocked();
if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
if (mLowRamStartTime == 0) {
mLowRamStartTime = now;
}
int step = 0;
int fgTrimLevel;
switch (memFactor) {
case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
break;
case ProcessStats.ADJ_MEM_FACTOR_LOW:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
break;
default:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
break;
}
int factor = numTrimming/3;
int minFactor = 2;
if (mHomeProcess != null) minFactor++;
if (mPreviousProcess != null) minFactor++;
if (factor < minFactor) factor = minFactor;
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
setProcessTrackerStateLocked(app, trackerMemFactor, now);
app.procStateChanged = false;
}
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
if (app.trimMemoryLevel < curLevel && app.thread != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Trimming memory of " + app.processName + " to " + curLevel);
app.thread.scheduleTrimMemory(curLevel);
} catch (RemoteException e) {
}
if (false) {
// For now we won't do this; our memory trimming seems
// to be good enough at this point that destroying
// activities causes more harm than good.
if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
&& app != mHomeProcess && app != mPreviousProcess) {
// Need to do this on its own message because the stack may not
// be in a consistent state at this point.
// For these apps we will also finish their activities
// to help them free memory.
mStackSupervisor.scheduleDestroyAllActivities(app, "trim");
}
}
}
app.trimMemoryLevel = curLevel;
step++;
if (step >= factor) {
step = 0;
switch (curLevel) {
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
break;
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
break;
}
}
} else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
&& app.thread != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Trimming memory of heavy-weight " + app.processName
+ " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
} else {
if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
|| app.systemNoUi) && app.pendingUiClean) {
// If this application is now in the background and it
// had done UI, then give it the special trim level to
// have it free UI resources.
final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
if (app.trimMemoryLevel < level && app.thread != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Trimming memory of bg-ui " + app.processName
+ " to " + level);
app.thread.scheduleTrimMemory(level);
} catch (RemoteException e) {
}
}
app.pendingUiClean = false;
}
if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Trimming memory of fg " + app.processName
+ " to " + fgTrimLevel);
app.thread.scheduleTrimMemory(fgTrimLevel);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = fgTrimLevel;
}
}
} else {
if (mLowRamStartTime != 0) {
mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
mLowRamStartTime = 0;
}
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
setProcessTrackerStateLocked(app, trackerMemFactor, now);
app.procStateChanged = false;
}
if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
|| app.systemNoUi) && app.pendingUiClean) {
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
&& app.thread != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Trimming memory of ui hidden " + app.processName
+ " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
} catch (RemoteException e) {
}
}
app.pendingUiClean = false;
}
app.trimMemoryLevel = 0;
}
}
- 先调整内存因子memFactor
如果内存因子不为0
- 根据内存因子 初始化fgTrimLevel
- 循环处理进程
- curProcState大于12 且没有被am杀掉,若trimMemoryLevel小于curLevel,进行TrimMemory。调整trimMemoryLevel和curLevel
- curProcState等于9,且满足条件,进行TrimMemory
- 其他情况下,根据条件进行TrimMemory操作
内存因子为0,也是根据跳进进行TrimMemory操作
整个过程很复杂,大概就是三个流程,调整oomadj值,清理进程,TrimMemory回收内存。
computeOomAdjLocked和applyOomAdjLocked这里就不介绍了,总之,这部分内容比较复杂。
4.杀进程
杀进程这里就略过了。