从源码角度看Android进程保活原理与优先级调度机制

简介

私以为,阅读Android源码必然需要先看看AMS核心组件部分的代码,因为它掌管着和应用打交道最频繁的四大组件生命周期,和应用的联系最为密切。然而,AMS中的集大成者我认为却是进程的管理与调度。阅读过四大组件的源码过后再去读进程的源码,会有一种打通了任督六脉的感觉,对系统的理解不再是停留在某个模块,而是有着更深一层的大局观的感觉。

Android进程管理这块代码中,其中最重要的一块又在进程的优先级调度。阅读这块代码期间你将会看到,系统更新、计算进程的优先级完完全全会根据此时四大组件的状态来完成。

能从进程优先级这块源码汲取出来的知识点很多,其中应用开发者最关心的便是进程保活这块。从近年来国内流氓APP进程霸占系统资源的情况来看,很多大厂的程序员为了自己APP能够长期存活,肯定是殚精竭虑的阅读过各个版本的Android进程源码。

这篇文章里,我将先列举进程被杀场景、保活方法的表格,这些都只停留在表层的知晓阶段;随后我会深入到源码中分析进程优先级调度3个最重要的方法:updateOomAdjLocked, computeOomAdjLocked, applyOomAdjLocked;每段分析中会有一副大致的逻辑图;最后的总结中我会分别列出adj, schedGroup, procState三个重要进程优先级数值与场景对应表格。

进程保活

此章节中列举出了杀进程的场景以及常见的保活方法

杀进程场景

序号 场景
1 被lmk杀死
2 成为空进程,缓存进程后被杀
3 最近任务一键清理
4 最近任务上滑被死
5 使用Setting forceStop
6 第三方应用如猎豹,360杀进程
7 出现FC或者ANR
  • 1,2两种情况属于用户没有察觉的情况下,进程属于”自然死亡”,在内存紧缺或者是用户不再关注的时候被系统杀死的
  • 3,4,5,6的情况属于用户主动去杀死进程;国产的安卓中,一键清理的威力更大,甚至可以杀死前台Service
  • 7的情况属于应用出现异常被系统杀死

以上是原生Android的进程被杀的场景,国外很多如CM等的定制系统差别不大;但是国内安卓系统如小米、华为、乐视这些大厂为了禁止国内流氓应用乱来,往往会定制许多其它杀进程的规则。

保活方法

序号 保活方法 API限制 效果&原理
1 正常的开启前台Servce 无限制 启动前台Service伴随着Notification,如正在播放音乐、正在导航,系统默认给进程高优先级
2 正常弹出悬浮窗 无限制 展示用户可见的窗口,如一键清理火箭,系统默认给进程高优先级
3 设置persistent=true 无限制 成为系统常驻进程
4 启动前台Service传入无意义Notification API<=17 利用系统漏洞,不展示Notification但享受前台Service优先级待遇
5 启动两个相同id前台Service,stop后者 18<=API<=24 同上,享受前台Service优先级待遇
6 native层保活 API<=23 进程互保,通过文件锁监听死亡,如果死亡则拉起
7 桌面放置一像素页面 未知 享受可见进程优先级待遇
8 静态注册系统常用广播 未知 满足权限的前提下,收到广播前进程会被拉起
9 进程Service/Provider互绑 无限制 效果并不好,forceStop下等场景无法存活,只是procState优先级很高
10 AlarmManager/JobScheduler 未知 守护服务,如果被守护进程死亡则拉起
11 账户同步 未知 Android原生机制会定期唤醒账户更新服务

可以看到,除了正常的展示Activity、Notification和浮窗,向用户表示自己的进程正在使用系统的资源之外,其它方法虽然能够在用户不能察觉的情况下使自己的进程相比普通进程存活的更久,但是多多少有着API的限制。在原生Android如果发展到8.0的现在,网络普遍的流行的灰色保活都已经不适用。而且,许多国产的定制xxUI都会对非系统应用进程进行更加严厉的把控,也就是说,即时在原生Android 8.0依然能够使用的漏洞,在国产定制的安卓中很大概率是不可行的。毕竟,进程长期占用,手机的性能、电池使用时间的体验都会下降,这些对用户不友好的灰色手段都应该被直接禁止。

进程优先级的更新:updateOomAdjLocked

更新场景对应表格

序号 代码 场景
1 BroadcastQueue.processNextBroadcast 开始派发广播
2 BroadcastQueue.processNextBroadcast 派发串行广播结束
3 ActivityStackSupervisor.realStartActivityLocked 启动Activity
4 ActivityStack.destroyActivityLocked 进程已无Activity
5 ActivityStack.finishSubActivityLocked finish掉上一个Activity
6 ActivityStack.finishVoiceTask
7 ActivityStack.resumeTopActivityInnerLocked Activity.onResume
8 ActivityManagerService.addAppLocked
9 ActivityManagerService.appDiedLocked 进程死亡后
10 ActivityManagerService.attachApplicationLocked 进程绑定Application
11 ActivityManagerService.foregroundTokenDied
12 ActivityManagerService.killAllBackgroundProcesses
13 ActivityManagerService.killPackageProcessesLocked
14 ActivityManagerService.removeContentProvider ContentProvider被销毁
15 ActivityManagerService.removeContentProviderExternalUnchecked
16 ActivityManagerService.setProcessForeground
17 ActivityManagerService.setSystemProcess 设置系统进程
18 ActivityManagerService.trimApplications trim
19 ActivityManagerService.updateProcessForegroundLocked
20 ActivityManagerService.updateSleepIfNeededLocked
21 ActiveServices.realStartServiceLocked 启动Service

updateOomAdjLocked (1) - 空进程、缓存进程

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
final void updateOomAdjLocked() {
final ActivityRecord TOP_ACT = resumedAppLocked();
// 获取TOP_APP,即前台Activity,这个会在后面的updateOomAdjLocked方法中也会用到
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
...
final int N = mLruProcesses.size();
...
// 重置所有UidRecord
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) {
...
numEmptyProcs = cachedProcessLimit;
}
...
// 计算出当前所有正在运行进程的adj
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;
// 计算单个进程的adj, procState, schedGroup
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
// 如果adj尚未计算出
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
// 计算出当前adj
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
+ ")");
// cachedAdj进行叠加
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:
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, nowElapsed);
// 空进程、缓存进程个数计数
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;
}
// 进程是isolated并且没有在运行Service
if (app.isolated && app.services.size() <= 0) {
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++;
}
}
}
...
  • 获取前台Activity
  • 计算出空进程、缓存进程上限个数
  • 更新所有正在运行的APP的adj并应用
  • 杀死达到上限个数的空进程与缓存进程

updateOomAdjLocked (2) - 对进程内存trim

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
mNumServiceProcs = mNewNumServiceProcs;
// 开始针对后台进程,对内存进行trim
// 初始化memFactor
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;
}
...
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();
// 计算memFactor
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) {
// 如果当前进程memLevel小于当前的level,则需要对进程内存做trim
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) {
}
...
}
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;
}
}
...
// 更新UidRecord变化
for (int i = mActiveUids.size() - 1; i >= 0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
if (uidRec.setProcState != uidRec.curProcState) {
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"Changes in " + uidRec + ": proc state from " + uidRec.setProcState
+ " to " + uidRec.curProcState);
uidRec.setProcState = uidRec.curProcState;
enqueueUidChangeLocked(uidRec, false);
}
}
// 异步记录状态
if (mProcessStats.shouldWriteNowLocked(now)) {
mHandler.post(new Runnable() {
@Override
public void run() {
synchronized (ActivityManagerService.this) {
mProcessStats.writeStateAsyncLocked();
}
}
});
}
...
}

这一块代码主要是根据当前的memory level,遍历所有正在运行中的进程,并选择对它们其中的进程内存做trim

查看大图

进程优先级的计算:computeOomAdjLocked

computeOomAdjLocked (1) - 进行特殊检查

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
private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
boolean doingAll, long now) {
// 检查当前adj是否已经被计算
if (mAdjSeq == app.adjSeq) {
return app.curRawAdj;
}
// 检查当前进程是否已经死亡
if (app.thread == null) {
app.adjSeq = mAdjSeq;
app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
return (app.curAdj = app.curRawAdj = ProcessList.CACHED_APP_MAX_ADJ);
}
app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
app.adjSource = null;
app.adjTarget = null;
app.empty = false;
app.cached = false;
final int activitiesSize = app.activities.size();
// 检查当前进程是否被设置了adj下限
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
// The max adjustment doesn't allow this app to be anything
// below foreground, so it is not worth doing work for it.
app.adjType = "fixed";
app.adjSeq = mAdjSeq;
app.curRawAdj = app.maxAdj;
app.foregroundActivities = false;
app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
// System processes can do UI, and when they do we want to have
// them trim their memory after the user leaves the UI. To
// facilitate this, here we need to determine whether or not it
// is currently showing UI.
app.systemNoUi = true;
if (app == TOP_APP) {
app.systemNoUi = false;
} else if (activitiesSize > 0) {
for (int j = 0; j < activitiesSize; j++) {
final ActivityRecord r = app.activities.get(j);
if (r.visible) {
app.systemNoUi = false;
}
}
}
if (!app.systemNoUi) {
app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
}
return (app.curAdj = app.maxAdj);
}
app.systemNoUi = false;
final int PROCESS_STATE_TOP = mTopProcessState;

这一步主要是对进程优先级更新时做一次检查;可以看到adj是进程优先级的主要衡量值

computeOomAdjLocked (2) - 根据四大组件计算

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
115
116
117
118
119
120
121
122
123
124
// 开始计算adj, curProc, schedGroup这些重要指标
// 从最重要的开始计算
// adj, curProc的最终值取值标准是取最小值
int adj;
int schedGroup;
int procState;
boolean foregroundActivities = false;
BroadcastQueue queue;
// 是否有前台Activity
if (app == TOP_APP) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_TOP;
// 是否在运行intrumentation
} else if (app.instrumentationClass != null) {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
// 是否正在接收广播
} else if ((queue = isReceivingBroadcast(app)) != null) {
// An app that is currently receiving a broadcast also
// counts as being in the foreground for OOM killer purposes.
// It's placed in a sched group based on the nature of the
// broadcast as reflected by which queue it's active in.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = (queue == mFgBroadcastQueue)
? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
// 是否正在执行Service
} else if (app.executingServices.size() > 0) {
// An app that is currently executing a service callback also
// counts as being in the foreground.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = app.execServicesFg ?
Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.adjType = "exec-service";
procState = ActivityManager.PROCESS_STATE_SERVICE;
//Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
// 都不符合则暂时为空
} else {
// As far as we know the process is empty. We may change our mind later.
schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
// 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";
}
// 检查进程所有在"后台"的Activity
if (!foregroundActivities && activitiesSize > 0) {
for (int j = 0; j < activitiesSize; j++) {
final ActivityRecord r = app.activities.get(j);
if (r.app != app) {
Slog.w(TAG, "Wtf, activity " + r + " in proc activity list not using proc "
+ app + "?!? Using " + r.app + " instead.");
continue;
}
// 如果Activity可见
if (r.visible) {
// App has a visible activity; only upgrade adjustment.
if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = ProcessList.VISIBLE_APP_ADJ;
app.adjType = "visible";
}
if (procState > PROCESS_STATE_TOP) {
procState = PROCESS_STATE_TOP;
}
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
break;
// 如果在pause状态
} else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "pausing";
}
if (procState > PROCESS_STATE_TOP) {
procState = PROCESS_STATE_TOP;
}
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
// 如果在stop状态
} else if (r.state == ActivityState.STOPPING) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "stopping";
}
// For the process state, we will at this point consider the
// process to be cached. It will be cached either as an activity
// or empty depending on whether the activity is finishing. We do
// this so that we can treat the process as cached for purposes of
// memory trimming (determing current memory level, trim command to
// send to process) since there can be an arbitrary number of stopping
// processes and they should soon all go into the cached state.
if (!r.finishing) {
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
}
}
app.cached = false;
app.empty = false;
foregroundActivities = true;
// 如果都不符合则暂时为空
} else {
if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
app.adjType = "cch-act";
}
}
}
}

以上代码对进程中的四大组件做了检查;进程优先级的计算秉承着从最重要的开始计算原则,但是如果在后面存在优先级更高的情况,则会取这其中的最小adj与procState作为最终的进程优先级

computeOomAdjLocked (3) - 特殊进程

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
// 检查进程是否为可察觉
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
if (app.foregroundServices) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
app.cached = false;
app.adjType = "fg-service";
schedGroup = Process.THREAD_GROUP_DEFAULT;
} else if (app.forcingToForeground != null) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
app.cached = false;
app.adjType = "force-fg";
app.adjSource = app.forcingToForeground;
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
}
// 是否为heavy-weight进程
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 = Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.cached = false;
app.adjType = "heavy";
}
if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
}
}
// 是否为home进程
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 = Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.cached = false;
app.adjType = "home";
}
if (procState > ActivityManager.PROCESS_STATE_HOME) {
procState = ActivityManager.PROCESS_STATE_HOME;
}
}
// 进程是否之前展示过
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 = Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.cached = false;
app.adjType = "previous";
}
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
}
}
...
app.adjSeq = mAdjSeq;
app.curRawAdj = adj;
app.hasStartedServices = false;
// 是否为备份进程
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_IMPORTANT_BACKGROUND) {
procState = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
}
app.adjType = "backup";
app.cached = false;
}
if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
procState = ActivityManager.PROCESS_STATE_BACKUP;
}
}

计算优先级的过程中特殊判断了一些进程

computeOomAdjLocked (4) - Service/Provider绑定

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
boolean mayBeTop = false;
// 检查该进程所有已经启动的Service
for (int is = app.services.size() - 1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
|| procState > ActivityManager.PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.services.valueAt(is);
// Service已经启动
if (s.startRequested) {
app.hasStartedServices = true;
if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
procState = ActivityManager.PROCESS_STATE_SERVICE;
}
// 是否展示了ui并且不是home进程
if (app.hasShownUi && app != mHomeProcess) {
if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-ui-services";
}
} else {
if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) {
if (adj > ProcessList.SERVICE_ADJ) {
adj = ProcessList.SERVICE_ADJ;
app.adjType = "started-services";
app.cached = false;
}
}
if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-services";
}
}
}
// 检查Service的绑定情况
for (int conni = s.connections.size() - 1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
|| 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 == Process.THREAD_GROUP_BG_NONINTERACTIVE
|| procState > ActivityManager.PROCESS_STATE_TOP);
i++) {
ConnectionRecord cr = clist.get(i);
// 同进程互相绑定的情况不进行更新
if (cr.binding.client == app) {
// Binding to ourself is not interesting.
continue;
}
// 如果bindService flag没有设置BIND_WAIVE_PRIORITY
if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client;
int clientAdj = computeOomAdjLocked(client, cachedAdj,
TOP_APP, doingAll, now);
int clientProcState = client.curProcState;
if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
}
String adjType = null;
// 如果设置了BIND_ALLOW_OOM_MANAGEMENT flag
if ((cr.flags & Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
if (app.hasShownUi && app != mHomeProcess) {
if (adj > clientAdj) {
adjType = "cch-bound-ui-services";
}
app.cached = false;
clientAdj = adj;
clientProcState = procState;
} else {
if (now >= (s.lastActivity
+ ActiveServices.MAX_SERVICE_INACTIVITY)) {
if (adj > clientAdj) {
adjType = "cch-bound-services";
}
clientAdj = adj;
}
}
}
// 如果此进程的adj大于它的client的adj
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adjType = "cch-bound-ui-services";
} else {
// 如果设置了BIND_ABOVE_CLIENT,BIND_IMPORTANT这些flag
if ((cr.flags & (Context.BIND_ABOVE_CLIENT
| Context.BIND_IMPORTANT)) != 0) {
adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ;
// 设置了BIND_NOT_VISIBLE flag
} else if ((cr.flags & Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
} else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
adj = clientAdj;
} else {
if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = ProcessList.VISIBLE_APP_ADJ;
}
}
if (!client.cached) {
app.cached = false;
}
adjType = "service";
}
}
// 如果没有设置BIND_NOT_FOREGROUND flag
if ((cr.flags & Context.BIND_NOT_FOREGROUND) == 0) {
if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
// service互相绑定可以提升procState优先级
mayBeTop = true;
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
} else {
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 (clientProcState <
ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
clientProcState =
ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
}
}
if (procState > clientProcState) {
procState = clientProcState;
}
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 ((cr.flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
app.treatLikeActivity = true;
}
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) {
schedGroup = Process.THREAD_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绑定情况计算优先级
for (int provi = app.pubProviders.size() - 1;
provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
|| procState > ActivityManager.PROCESS_STATE_TOP);
provi--) {
ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
for (int i = cpr.connections.size() - 1;
i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
|| 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;
}
int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
int clientProcState = client.curProcState;
if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
}
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
app.adjType = "cch-ui-provider";
} else {
adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
app.adjType = "provider";
}
app.cached &= client.cached;
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_PROVIDER_IN_USE;
app.adjSource = client;
app.adjSourceProcState = clientProcState;
app.adjTarget = cpr.name;
}
if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
mayBeTop = true;
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
} else {
clientProcState =
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
}
}
if (procState > clientProcState) {
procState = clientProcState;
}
if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
}
if (cpr.hasExternalProcessHandles()) {
if (adj > ProcessList.FOREGROUND_APP_ADJ) {
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.cached = false;
app.adjType = "provider";
app.adjTarget = cpr.name;
}
if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
}
}
}
// provider与service互相绑定的情况下,可以将procState的优先级提升到3
if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) {
switch (procState) {
case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
case ActivityManager.PROCESS_STATE_SERVICE:
procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
break;
default:
// Otherwise, top is a better choice, so take it.
procState = ActivityManager.PROCESS_STATE_TOP;
break;
}
}
// 缓存进程的情况
if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
if (app.hasClientActivities) {
// This is a cached process, but with client activities. Mark it so.
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
app.adjType = "cch-client-act";
} else if (app.treatLikeActivity) {
// This is a cached process, but somebody wants us to treat it like it has
// an activity, okay!
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
app.adjType = "cch-as-act";
}
}
if (adj == ProcessList.SERVICE_ADJ) {
if (doingAll) {
app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs / 3);
mNewNumServiceProcs++;
//Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb);
if (!app.serviceb) {
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;
}
}
app.curRawAdj = adj;
// 根据maxAdj作出最后的调整
if (adj > app.maxAdj) {
adj = app.maxAdj;
if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
}
// 完成计算,进行赋值
app.curAdj = app.modifyRawOomAdj(adj);
app.curSchedGroup = schedGroup;
app.curProcState = procState;
app.foregroundActivities = foregroundActivities;
return app.curRawAdj;
}
  • 遍历所有运行中的Service,进行计算
  • 对绑定的Service进程优先级进行判断
  • 对绑定的provider进程优先级进行判断
  • 对adj作出最后的调整

查看大图

进程优先级的应用: applyOomAdjLocked

applyOomAdjLocked

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
private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
long nowElapsed) {
boolean success = true;
// 应用rawAdj
if (app.curRawAdj != app.setRawAdj) {
app.setRawAdj = app.curRawAdj;
}
int changes = 0;
// 应用adj
if (app.curAdj != app.setAdj) {
ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
app.setAdj = app.curAdj;
}
// 应用schedGroup
if (app.setSchedGroup != app.curSchedGroup) {
app.setSchedGroup = app.curSchedGroup;
if (app.waitingToKill != null && app.curReceiver == null
&& app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
app.kill(app.waitingToKill, true);
success = false;
} else {
if (true) {
long oldId = Binder.clearCallingIdentity();
try {
Process.setProcessGroup(app.pid, app.curSchedGroup);
} catch (Exception e) {
Slog.w(TAG, "Failed setting process group of " + app.pid
+ " to " + app.curSchedGroup);
e.printStackTrace();
} finally {
Binder.restoreCallingIdentity(oldId);
}
} else {
if (app.thread != null) {
try {
// 客户端设置thread group
app.thread.setSchedulingGroup(app.curSchedGroup);
} catch (RemoteException e) {
}
}
}
Process.setSwappiness(app.pid,
app.curSchedGroup <= Process.THREAD_GROUP_BG_NONINTERACTIVE);
}
}
if (app.repForegroundActivities != app.foregroundActivities) {
app.repForegroundActivities = app.foregroundActivities;
changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
}
if (app.repProcState != app.curProcState) {
app.repProcState = app.curProcState;
changes |= ProcessChangeItem.CHANGE_PROCESS_STATE;
if (app.thread != null) {
try {
app.thread.setProcessState(app.repProcState);
} catch (RemoteException e) {
}
}
}
if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT
|| ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) {
app.lastStateTime = now;
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
mTestPssMode, isSleeping(), now);
} else {
if (now > app.nextPssTime || (now > (app.lastPssTime + ProcessList.PSS_MAX_INTERVAL)
&& now > (app.lastStateTime + ProcessList.minTimeFromStateChange(
mTestPssMode)))) {
requestPssLocked(app, app.setProcState);
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
mTestPssMode, isSleeping(), now);
} else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
"Not requesting PSS of " + app + ": next=" + (app.nextPssTime - now));
}
// 设置procState
if (app.setProcState != app.curProcState) {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Proc state change of " + app.processName
+ " to " + app.curProcState);
boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE;
boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE;
if (setImportant && !curImportant) {
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
app.pid, nowElapsed);
}
app.lastCpuTime = app.curCpuTime;
}
maybeUpdateUsageStatsLocked(app, nowElapsed);
app.setProcState = app.curProcState;
if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
app.notCachedSinceIdle = false;
}
if (!doingAll) {
setProcessTrackerStateLocked(app, mProcessStats.getMemFactorLocked(), now);
} else {
app.procStateChanged = true;
}
} else if (app.reportedInteraction && (nowElapsed - app.interactionEventTime)
> USAGE_STATS_INTERACTION_INTERVAL) {
maybeUpdateUsageStatsLocked(app, nowElapsed);
}
...
return success;
}

这块的代码比较简单,无非是对计算过的进程优先级进行应用,同时期间会binder call到客户端对thread group进行设置

查看大图

总结

本篇文章中,我对常见的进程保活场景做了总结,虽然我没有详细讲解它们的实现,但是其中的原理都可以在对进程优先级调度的源码中找到。文章的中代码分析很长并且很枯燥,看不太下去的话可以简单看看逻辑图~

文章的最后附上我对三个重要衡量进程优先级的变量的总结。

adj

adj 场景
NATIVE_ADJ -17 native进程,framework中未涉及
SYSTEM_ADJ -16 系统进程,也就是system_server
PERSISTENT_PROC_ADJ -12 系统常驻进程,如telephony, systemui
PERSISTENT_SERVICE_ADJ -11 1) 被系统进程或常驻进程绑定
2) 设置了BIND_ABOVE_CLIENT的flag
FOREGROUND_APP_ADJ 0 1) 当前进程正在显示Activity
2) instrumentation正在运行
3) 正在接收广播
4) 正在运行Service
4) provider被其它进程使用
VISIBLE_APP_ADJ 1 该APP中有可见的Activity
PERCEPTIBLE_APP_ADJ 2 1) Activity正在或已经暂停
2) Activity正在Stop
BACKUP_APP_ADJ 3 备份进程
HEAVY_WEIGHT_APP_ADJ 4 heavy weight进程
SERVICE_ADJ 5 30分钟内Service被启动
HOME_APP_ADJ 6 home进程
PREVIOUS_APP_ADJ 7 运行过上一个显示的Activity
SERVICE_B_ADJ 8 运行Service未显示UI
CACHED_APP_MIN_ADJ 9 空进程最小adj
CACHED_APP_MAX_ADJ 15 app.thread=NULL
UNKNOWN_ADJ 16 adj未知

schedGroup

schedGroup 场景
THREAD_GROUP_DEFAULT -1 1) maxAdj<=FOREGROUND
2) instrumentation正在运行
3) 正在接收前台广播
4) 正在运行前台Service
5) 有可见的Activity
6) Activity正在或已经暂停
7) provider被其它进程使用
THREAD_GROUP_BG_NONINTERACTIVE 0 1) app.thread=NULL
2) 正在接收后台广播
3) 正在执行后台Service
3) heavy weight进程
4) home进程
5) 运行过上一个显示的Activity
6) 空进程
THREAD_GROUP_FOREGROUND 1 前台线程group, framework未涉及
THREAD_GROUP_SYSTEM 2 系统线程,framework未涉及
THREAD_GROUP_AUDIO_APP 3 音频应用线程group
THREAD_GROUP_AUDIO_SYS 4 系统音频应用线程group

procState

procState 场景
PROCESS_STATE_NONEXISTENT -1 未知
PROCESS_STATE_PERSISTENT 0 maxAdj<=FOREGROUND
PROCESS_STATE_PERSISTENT_UI 1 常驻进程并且正在显示UI
PROCESS_STATE_TOP 2 1) 当前进程正在显示Activity
2) 该APP中有可见的Activity
3) Activity正在或已经暂停
PROCESS_STATE_BOUND_FOREGROUND_SERVICE 3 1) instrumentation正在运行
2) 绑定了前台Service
3) 绑定的Service进程为前台
4) 使用的provider进程为前台
PROCESS_STATE_FOREGROUND_SERVICE 4 正在运行前台Service
PROCESS_STATE_TOP_SLEEPING 5 进入睡眠状态
PROCESS_STATE_IMPORTANT_FOREGROUND 6 Notification为Service设置了前台token
PROCESS_STATE_IMPORTANT_BACKGROUND 7 1) 备份进程
2) provider被其它进程使用
PROCESS_STATE_BACKUP 8 备份进程
PROCESS_STATE_HEAVY_WEIGHT 9 heavy weight进程
PROCESS_STATE_SERVICE 10 正在运行Service
PROCESS_STATE_RECEIVER 11 正在等待接收广播
PROCESS_STATE_HOME 12 home进程
PROCESS_STATE_LAST_ACTIVITY 13 运行过上一个显示的Activity
PROCESS_STATE_CACHED_ACTIVITY 14 1) 无Activity活动
2) 空进程但是设置了BIND_TREAT_LIKE_ACTIVITY
PROCESS_STATE_CACHED_ACTIVITY_CLIENT 15 空进程但是有Activity
PROCESS_STATE_CACHED_EMPTY 16 空进程
扫码支持0.99元,您的支持将鼓励我继续创作!