_StriveG Blog

AMS中的进程管理部分-上

1.前言

ActivityManagerService作为一个核心系统服务,除了负责管理四大组件之外,还负责管理进程,对进程的管理有以下方面:

  • 新建进程
  • 调整进程在mLruProcesses的位置
  • 调整进程OomAdj值
  • 杀进程

而新建进程在前面有说到过,今天就来介绍下剩下的三个。

2.调整位置的updateLruProcessLocked方法

代码比较长,分段看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities
|| app.treatLikeActivity;
final boolean hasService = false; // not impl yet. app.services.size() > 0;
if (!activityChange && hasActivity) {
// The process has activities, so we are only allowing activity-based adjustments
// to move it. It should be kept in the front of the list with other
// processes that have activities, and we don't want those to change their
// order except due to activity operations.
return;
}
mLruSeq++;
final long now = SystemClock.uptimeMillis();
app.lastActivityTime = now;
// First a quick reject: if the app is already at the position we will
// put it, then there is nothing to do.
if (hasActivity) {
final int N = mLruProcesses.size();
if (N > 0 && mLruProcesses.get(N-1) == app) {
if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, already top activity: " + app);
return;
}
} else {
if (mLruProcessServiceStart > 0
&& mLruProcesses.get(mLruProcessServiceStart-1) == app) {
if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, already top other: " + app);
return;
}
}
int lrui = mLruProcesses.lastIndexOf(app);
if (app.persistent && lrui >= 0) {
// We don't care about the position of persistent processes, as long as
// they are in the list.
if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, persistent: " + app);
return;
}
  • 如果有activity,并且进程中activity没有发生变化,不需要调整
  • 如果有activity,但是当前进程就是在最后,不需要调整
  • 如果没有activity,但是在合适的位置,不需要调整
  • 如果有persistent标志,不需要调整
  • lrui 为当前进程在list中的索引(最后一个的索引)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (lrui >= 0) {
if (lrui < mLruProcessActivityStart) {
mLruProcessActivityStart--;
}
if (lrui < mLruProcessServiceStart) {
mLruProcessServiceStart--;
}
/*
if (addIndex > lrui) {
addIndex--;
}
if (nextIndex > lrui) {
nextIndex--;
}
*/
mLruProcesses.remove(lrui);
}

如果已经存在,调整mLruProcessActivityStart和mLruProcessServiceStart,并且暂时从列表中移除进程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
if (hasActivity) {
final int N = mLruProcesses.size();
if (app.activities.size() == 0 && mLruProcessActivityStart < (N - 1)) {
// Process doesn't have activities, but has clients with
// activities... move it up, but one below the top (the top
// should always have a real activity).
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Adding to second-top of LRU activity list: " + app);
mLruProcesses.add(N - 1, app);
// To keep it from spamming the LRU list (by making a bunch of clients),
// we will push down any other entries owned by the app.
final int uid = app.info.uid;
for (int i = N - 2; i > mLruProcessActivityStart; i--) {
ProcessRecord subProc = mLruProcesses.get(i);
if (subProc.info.uid == uid) {
// We want to push this one down the list. If the process after
// it is for the same uid, however, don't do so, because we don't
// want them internally to be re-ordered.
if (mLruProcesses.get(i - 1).info.uid != uid) {
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Pushing uid " + uid + " swapping at " + i + ": "
+ mLruProcesses.get(i) + " : " + mLruProcesses.get(i - 1));
ProcessRecord tmp = mLruProcesses.get(i);
mLruProcesses.set(i, mLruProcesses.get(i - 1));
mLruProcesses.set(i - 1, tmp);
i--;
}
} else {
// A gap, we can stop here.
break;
}
}
} else {
// Process has activities, put it at the very tipsy-top.
if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding to top of LRU activity list: " + app);
mLruProcesses.add(app);
}
nextIndex = mLruProcessServiceStart;
} else if (hasService) {
// Process has services, put it at the top of the service list.
if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding to top of LRU service list: " + app);
mLruProcesses.add(mLruProcessActivityStart, app);
nextIndex = mLruProcessServiceStart;
mLruProcessActivityStart++;
} else {
// Process not otherwise of interest, it goes to the top of the non-service area.
int index = mLruProcessServiceStart;
if (client != null) {
// If there is a client, don't allow the process to be moved up higher
// in the list than that client.
int clientIndex = mLruProcesses.lastIndexOf(client);
if (DEBUG_LRU && clientIndex < 0) Slog.d(TAG_LRU, "Unknown client " + client
+ " when updating " + app);
if (clientIndex <= lrui) {
// Don't allow the client index restriction to push it down farther in the
// list than it already is.
clientIndex = lrui;
}
if (clientIndex >= 0 && index > clientIndex) {
index = clientIndex;
}
}
if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding at " + index + " of LRU list: " + app);
mLruProcesses.add(index, app);
nextIndex = index-1;
mLruProcessActivityStart++;
mLruProcessServiceStart++;
}
  • hasActivity为true
    • 没有activities,但是有hasClientActivities,将当前进程插入到列表的最后,从mLruProcessActivityStart到n-2的位置,如果i处的uid和当前进程uid相等,但是上一个却不等的话,交换位置。
    • 直接添加到最后一个
  • hasActivity为false,hasService为true,加入到mLruProcessActivityStart位置
  • 因为client大多为null,所以这里插入到index位置,也就是mLruProcessServiceStart处
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for (int j=app.connections.size()-1; j>=0; j--) {
ConnectionRecord cr = app.connections.valueAt(j);
if (cr.binding != null && !cr.serviceDead && cr.binding.service != null
&& cr.binding.service.app != null
&& cr.binding.service.app.lruSeq != mLruSeq
&& !cr.binding.service.app.persistent) {
nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex,
"service connection", cr, app);
}
}
for (int j=app.conProviders.size()-1; j>=0; j--) {
ContentProviderRecord cpr = app.conProviders.get(j).provider;
if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.persistent) {
nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex,
"provider reference", cpr, app);
}
}

把和这个进程关联的service和contentprovider调整到这个进程之后。

3. 调整OomAdj值的updateOomAdjLocked方法

方法较长,分段看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
final ActivityRecord TOP_ACT = resumedAppLocked();
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
final long now = SystemClock.uptimeMillis();
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();
}
mAdjSeq++;
mNewNumServiceProcs = 0;
mNewNumAServiceProcs = 0;
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.
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.
numEmptyProcs = cachedProcessLimit;
}
int emptyFactor = numEmptyProcs/numSlots;
if (emptyFactor < 1) emptyFactor = 1;
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;

这一部分代码是对一些值进行初始化操作,如空进程、缓存进程的数目,numSlots。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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 we haven't yet assigned the final cached adj
// to the process, do that now.
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.
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;
}
}
applyOomAdjLocked(app, true, now);
// 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++;
}
}
}

上面代码的逻辑是更新进程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.杀进程

杀进程这里就略过了。


最近访客