Android应用程序主要以activity/service/contentprovider/broadcastrecevier四大组件组成,ActivityManagerService根据四大组件的生命周期函数,以及进程的创建,死亡等来动态调节进程自身的状态,影响进程的CPU占用时间,内存IO等资源分配。进程有两个比较重要的状态值,即adj(定义在ProcessList.java)和procState(定义在ActivityManager.java),控制缓存进程和空进程个数上限依赖于procState,控制APP执行handleLowMemory()的触发时机等。
adj值如下:
static final int INVALID_ADJ = -10000;
static final int UNKNOWN_ADJ = 1001;
static final int CACHED_APP_MAX_ADJ = 999;
static final int CACHED_APP_MIN_ADJ = 900;
static final int CACHED_APP_LMK_FIRST_ADJ = 950;
static final int CACHED_APP_IMPORTANCE_LEVELS = 5;
static final int SERVICE_B_ADJ = 800;
static final int PREVIOUS_APP_ADJ = 700;
static final int HOME_APP_ADJ = 600;
static final int SERVICE_ADJ = 500;
static final int HEAVY_WEIGHT_APP_ADJ = 400;
static final int BACKUP_APP_ADJ = 300;
static final int PERCEPTIBLE_LOW_APP_ADJ = 250;
static final int PERCEPTIBLE_APP_ADJ = 200;
static final int VISIBLE_APP_ADJ = 100;
static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
static final int FOREGROUND_APP_ADJ = 0;
static final int PERSISTENT_SERVICE_ADJ = -700;
static final int PERSISTENT_PROC_ADJ = -800;
static final int SYSTEM_ADJ = -900;
static final int NATIVE_ADJ = -1000;
// 定义在ActivityManager.java里的procState值
public static final int PROCESS_STATE_UNKNOWN = -1;
public static final int PROCESS_STATE_PERSISTENT = 0;
public static final int PROCESS_STATE_PERSISTENT_UI = 1;
public static final int PROCESS_STATE_TOP = 2;
public static final int PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3;
public static final int PROCESS_STATE_BOUND_TOP = 4;
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 5;
public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6;
public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 7;
public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 8;
public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 9;
public static final int PROCESS_STATE_BACKUP = 10;
public static final int PROCESS_STATE_SERVICE = 11;
public static final int PROCESS_STATE_RECEIVER = 12;
public static final int PROCESS_STATE_TOP_SLEEPING = 13;
public static final int PROCESS_STATE_HEAVY_WEIGHT = 14;
public static final int PROCESS_STATE_HOME = 15;
public static final int PROCESS_STATE_LAST_ACTIVITY = 16;
public static final int PROCESS_STATE_CACHED_ACTIVITY = 17;
public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18;
public static final int PROCESS_STATE_CACHED_RECENT = 19;
public static final int PROCESS_STATE_CACHED_EMPTY = 20;
public static final int PROCESS_STATE_NONEXISTENT = 21;
OomAdjuster
Android10.0以后将adj相关的处理移到OomAdjuster中,adj的值越大,则进程越容易被杀
updateOomAdjLocked:
更新运行中的进程的adj值
computeOomAdjLocked:
计算adj值
applyOomAdjLocked:
应用adj值,通过调整oom_score_adj来影响进程寿命(Lowmemorykiller杀进程策略);
ProcessRecord涉及到adj成员变量
// 当前进程最大的adj值
int maxAdj;
// 当前进程的原始adj值
int curRawAdj;
// 当前进程上一次的adj值
int setRawAdj;
// 当前进程的adj值
int curAdj;
// 当前进程上一次的adj值
int setAdj;
// 当前进程调度组
int mCurSchedGroup;
// 当前进程上一次调度组
int setSchedGroup;
// adj的类型,便于分辨场景
String adjType;
更新adj值的常见场景:
static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
// activity相关
static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange";
// 广播相关
static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver";
static final String OOM_ADJ_REASON_START_RECEIVER = OOM_ADJ_REASON_METHOD + "_startReceiver";
// 服务相关
static final String OOM_ADJ_REASON_BIND_SERVICE = OOM_ADJ_REASON_METHOD + "_bindService";
static final String OOM_ADJ_REASON_UNBIND_SERVICE = OOM_ADJ_REASON_METHOD + "_unbindService";
static final String OOM_ADJ_REASON_START_SERVICE = OOM_ADJ_REASON_METHOD + "_startService";
// Provider相关
static final String OOM_ADJ_REASON_GET_PROVIDER = OOM_ADJ_REASON_METHOD + "_getProvider";
static final String OOM_ADJ_REASON_REMOVE_PROVIDER = OOM_ADJ_REASON_METHOD + "_removeProvider";
static final String OOM_ADJ_REASON_UI_VISIBILITY = OOM_ADJ_REASON_METHOD + "_uiVisibility";
static final String OOM_ADJ_REASON_WHITELIST = OOM_ADJ_REASON_METHOD + "_whitelistChange";
// 进程相关
static final String OOM_ADJ_REASON_PROCESS_BEGIN = OOM_ADJ_REASON_METHOD + "_processBegin";
static final String OOM_ADJ_REASON_PROCESS_END = OOM_ADJ_REASON_METHOD + "_processEnd";
进程组
在Android中,Process.setProcessGroup(int pid, int group)用来设置进程的调度组。调度组会影响进程的CPU占用时间,内存IO等资源分配
// ProcessList.java
后台进程组
static final int SCHED_GROUP_BACKGROUND = 0;
受限制的组
static final int SCHED_GROUP_RESTRICTED = 1;
默认进程组
static final int SCHED_GROUP_DEFAULT = 2;
top进程组
public static final int SCHED_GROUP_TOP_APP = 3;
static final int SCHED_GROUP_TOP_APP_BOUND = 4;
updateOomAdjLocked函数分析
- 1 获取前台进程
- 2 获取缓存进程的数量
- 3 一些CachedAdj相关变量的初始化, 系统常量获取
- 4 重置mProcessList列表进程中的adj值,以及进程状态
// 获取前台进程
final ProcessRecord TOP_APP = mService.getTopAppLocked();
// 缓存进程的数量
final int N = mProcessList.getLruSizeLocked();
// 避免重复计算设计, 在computeOomAdjLocked中有用到来作为判断依据
mAdjSeq++;
// 最大空进程数量限制
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
// 最大缓存进程数量限制
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
- emptyProcessLimit;
// 进程卡槽数量,android10.0为10
final int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
- ProcessList.CACHED_APP_MIN_ADJ + 1) / 2
/ ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
if (numEmptyProcs > cachedProcessLimit) {
numEmptyProcs = cachedProcessLimit;
}
// cache adj的最小值为ProcessList.CACHED_APP_MIN_ADJ
int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextCachedAdj = curCachedAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
int curCachedImpAdj = 0;
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
int nextEmptyAdj = curEmptyAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
boolean retryCycles = false;
// 重置进程状态
for (int i = N - 1; i >= 0; i--) {
ProcessRecord app = mProcessList.mLruProcesses.get(i);
app.containsCycle = false;
app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
}
- 5 遍历mLruProcesses列表,计算每个进程的adj值 - 6 如果getCurProcState状态为cache相关,则当前进程的adj值在当前的基础上加1或者加ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2中的一个 - 7 设置进程的原始adj值,以及adj值 ```java // 更新mLruProcesses缓存进程的adj值 for (int i = N - 1; i >= 0; i--) { ProcessRecord app = mProcessList.mLruProcesses.get(i); if (!app.killedByAm && app.thread != null) { app.procStateChanged = false; // 计算adj值 computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now, false);
// 稍后需要重新计算adj值
retryCycles |= app.containsCycle;
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
// cache adj 的范围在(CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ)之间
switch (app.getCurProcState()) {
case PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
case ActivityManager.PROCESS_STATE_CACHED_RECENT:
boolean inGroup = false;
if (app.connectionGroup != 0) {
if (lastCachedGroupUid == app.uid
&& lastCachedGroup == app.connectionGroup) {
if (app.connectionImportance > lastCachedGroupImportance) {
lastCachedGroupImportance = app.connectionImportance;
// curCachedAdj的值小于nextCachedAdj,并且小于CACHED_APP_MAX_ADJ
// adj的值将要在现在的基础上增大
if (curCachedAdj < nextCachedAdj
&& curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
curCachedImpAdj++;
}
}
inGroup = true;
} else {
lastCachedGroupUid = app.uid;
lastCachedGroup = app.connectionGroup;
lastCachedGroupImportance = app.connectionImportance;
}
}
if (!inGroup && curCachedAdj != nextCachedAdj) {
stepCached++;
curCachedImpAdj = 0;
if (stepCached >= cachedFactor) {
stepCached = 0;
curCachedAdj = nextCachedAdj;
// 将nextCachedAdj加2个CACHED_APP_IMPORTANCE_LEVELS,移动到下一个等级的值
nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
// cache adj的值最大为ProcessList.CACHED_APP_MAX_ADJ
if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
// 设置app进程的原始adj值
app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
// 调整adj值
app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
break;
default:
if (curEmptyAdj != nextEmptyAdj) {
stepEmpty++;
if (stepEmpty >= emptyFactor) {
stepEmpty = 0;
curEmptyAdj = nextEmptyAdj;
nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
// 设置app进程的原始adj值
app.setCurRawAdj(curEmptyAdj);
// 调整adj值
app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
break;
}
}
}
}
<br>
- 8 是否需要重新计算某些进程的adj值
```java
int cycleCount = 0;
// retryCycles为true, 某些进程需要重新计算adj值
while (retryCycles && cycleCount < 10) {
cycleCount++;
retryCycles = false;
// 重新计算adj值
for (int i = 0; i < N; i++) {
ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
if (computeOomAdjLocked(app, app.getCurRawAdj(), TOP_APP, true, now,
true)) {
retryCycles = true;
}
}
}
}
-9 收尾工作,再次遍历mProcessList列表,cache进程超过限定kill掉,空进程超过系统限定kill掉
for (int i = N - 1; i >= 0; i--) {
ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
switch (app.getCurProcState()) {
case PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
mNumCachedHiddenProcs++;
numCached++;
if (app.connectionGroup != 0) {
if (lastCachedGroupUid == app.info.uid
&& lastCachedGroup == app.connectionGroup) {
numCachedExtraGroup++;
} else {
lastCachedGroupUid = app.info.uid;
lastCachedGroup = app.connectionGroup;
}
} else {
lastCachedGroupUid = lastCachedGroup = 0;
}
// cache进程超过cachedProcessLimit限定, kill掉
if ((numCached - numCachedExtraGroup) > cachedProcessLimit) {
app.kill("cached #" + numCached, true);
}
break;
case PROCESS_STATE_CACHED_EMPTY:
// 超过指定空进程数,kill掉
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++;
if ((numEmpty > emptyProcessLimit)) {
app.kill("empty #" + numEmpty, true);
}
}
break;
default:
mNumNonCachedProcs++;
break;
}
// app.isolated为true,也没有service运行, kill掉
if (app.isolated && app.services.size() <= 0 && app.isolatedEntryPoint == null) {
app.kill("isolated not needed", true);
}
if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
numTrimming++;
}
}
}
computeOomAdjLocked分析
- 1 app.adjSeq等于app.completedAdjSeq则表示已经计算过
- 2 app.containsCycle为true则会在updateOomAdjLocked中重新调用
// 已经计算过,避免重复计算
if (mAdjSeq == app.adjSeq) {
if (app.adjSeq == app.completedAdjSeq) {
// This adjustment has already been computed successfully.
return false;
} else {
// The process is being computed, so there is a cycle. We cannot
// rely on this process's state.
app.containsCycle = true;
return false;
}
}
- 3 空进程处理相关,adj值设置为CACHED_APP_MAX_ADJ返回
// 空进程,直接赋值app.curAdj为ProcessList.CACHED_APP_MAX_ADJ
if (app.thread == null) {
app.adjSeq = mAdjSeq;
app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND);
app.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
app.curAdj = ProcessList.CACHED_APP_MAX_ADJ;
app.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ);
app.completedAdjSeq = app.adjSeq;
return false;
}
- 4 persistent apk的maxAdj为PERSISTENT_PROC_ADJ,常见的persistent apk有Phone, systemUI等, 在AndroidManifest.xml中声明android:persistent="true"的apk,如果是persistent apk, 将adj值赋值为app.maxAdj, persistent apk在AMS中的systemReady中启动
// present apk将adj值赋值为app.maxAdj
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
app.adjType = "fixed";
app.adjSeq = mAdjSeq;
app.setCurRawAdj(app.maxAdj);
app.setHasForegroundActivities(false);
app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
app.systemNoUi = true;
if (app == TOP_APP) {
app.systemNoUi = false;
app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
app.adjType = "pers-top-activity";
} else if (app.hasTopUi()) {
// sched group/proc state adjustment is below
app.systemNoUi = false;
app.adjType = "pers-top-ui";
} else if (wpc.hasVisibleActivities()) {
app.systemNoUi = false;
}
app.setCurRawProcState(app.getCurProcState());
app.curAdj = app.maxAdj;
app.completedAdjSeq = app.adjSeq;
// if curAdj is less than prevAppAdj, then this process was promoted
return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState;
}
- 5 前台进程判断相关处理
boolean foregroundActivities = false;
mTmpBroadcastQueue.clear();
// 是否有前台activity
if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == TOP_APP) {
// The last app on the list is the foreground app.
// 顶部运行的进程,即和用户交互的apk
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.runningRemoteAnimation) {
// 正在执行动画
adj = ProcessList.VISIBLE_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "running-remote-anim";
procState = PROCESS_STATE_CUR_TOP;
} else if (app.getActiveInstrumentation() != null) {
// Don't want to kill running instrumentation.
// 和测试相关
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = PROCESS_STATE_FOREGROUND_SERVICE;
} else if (mService.isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
// 正在接收广播
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = (mTmpBroadcastQueue.contains(mService.mFgBroadcastQueue)
|| mTmpBroadcastQueue.contains(mService.mCtsFgBroadcastQueue))
? 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 = 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 {
// 暂时设置为cache进程,接下来再进行处理
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
adj = cachedAdj;
procState = PROCESS_STATE_CACHED_EMPTY;
app.cached = true;
app.empty = true;
app.adjType = "cch-empty";
}
- 6 不是前台有activity的进程,但apk中存在有效的activity相关处理
// 不是前台有activity的进程, 但apk中存在有效的activity
if (!foregroundActivities && wpc.hasActivities()) {
mTmpComputeOomAdjWindowCallback.initialize(app, adj, foregroundActivities, procState,
schedGroup, appUid, logUid, PROCESS_STATE_CUR_TOP);
final int minLayer = wpc.computeOomAdjFromActivities(
ProcessList.VISIBLE_APP_LAYER_MAX, mTmpComputeOomAdjWindowCallback);
adj = mTmpComputeOomAdjWindowCallback.adj;
foregroundActivities = mTmpComputeOomAdjWindowCallback.foregroundActivities;
procState = mTmpComputeOomAdjWindowCallback.procState;
schedGroup = mTmpComputeOomAdjWindowCallback.schedGroup;
// 根据layer来确定具体的adj值
if (adj == ProcessList.VISIBLE_APP_ADJ) {
adj += minLayer;
}
}
- 7 是否存在前台服务,或者有OverlayUi显示
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > PROCESS_STATE_FOREGROUND_SERVICE_LOCATION) {
// 前台服务
if (app.hasForegroundServices()) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
// 使用了位置的前台服务
if (app.hasLocationForegroundServices()) {
procState = PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
app.adjType = "fg-service-location";
} else {
// 普通前台服务
procState = PROCESS_STATE_FOREGROUND_SERVICE;
app.adjType = "fg-service";
}
app.cached = false;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
} else if (app.hasOverlayUi()) {
// overlay UI.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
app.cached = false;
app.adjType = "has-overlay-ui";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
- 8 前台服务
if (app.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
&& (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now
|| app.setProcState <= PROCESS_STATE_TOP)) {
adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
app.adjType = "fg-service-act";
}
- 9 重量级进程
// heavy-weight process
if(mService.mAtmInternal.isHeavyWeightProcess(app.getWindowProcessController())) {
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 = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "heavy";
}
if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
app.adjType = "heavy";
}
}
- 10 home进程
if (wpc.isHomeProcess()) {
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 = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "home";
}
if (procState > ActivityManager.PROCESS_STATE_HOME) {
procState = ActivityManager.PROCESS_STATE_HOME;
app.adjType = "home";
}
}
- 11 之前启动的进程
if (wpc.isPreviousProcess() && app.hasActivities()) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "previous";
}
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
procState = PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "previous";
}
}
- 12 设置adj
// 设置原始的adj值
app.setCurRawAdj(!cycleReEval ? adj : Math.min(adj, app.getCurRawAdj()));
// 设置原始的进程状态
app.setCurRawProcState(!cycleReEval
? procState
: Math.min(procState, app.getCurRawProcState()));
- 13 根据app进程中的服务来确定adj值
// 遍历app进程下的服务
for (int is = app.services.size() - 1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.services.valueAt(is);
if (s.startRequested) {
// 通过startService启动过服务
app.hasStartedServices = true;
if (procState > PROCESS_STATE_SERVICE) {
procState = PROCESS_STATE_SERVICE;
app.adjType = "started-services";
}
if (app.hasShownUi && !wpc.isHomeProcess()) {
if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-ui-services";
}
} else {
// 小于mConstants.MAX_SERVICE_INACTIVITY时间,服务adj值不变
if (now < (s.lastActivity + mConstants.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";
}
}
}
// bindService方式启动
ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
for (int conni = serviceConnections.size() - 1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
conni--) {
ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
for (int i = 0;
i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
i++) {
ConnectionRecord cr = clist.get(i);
if (cr.binding.client == app) {
// 绑定的进程是当前进程时,跳过
continue;
}
if ((cr.flags& Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client;
// 计算client进程的adj值
computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now, cycleReEval);
// 根据ProcessRecord的containsCycle和client的completedAdjSeq值来确认身份需要跳过
if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
continue;
}
// client进程的adj值
int clientAdj = client.getCurRawAdj();
int clientProcState = client.getCurRawProcState();
String adjType = null;
if (adj > clientAdj) {
if (app.hasShownUi && !wpc.isHomeProcess()
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
adjType = "cch-bound-ui-services";
}
} else {
int newAdj;
// 根据flag和client的adj值来确认newAdj值
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
newAdj = clientAdj;
} else {
// make this service persistent
newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
procState = ActivityManager.PROCESS_STATE_PERSISTENT;
cr.trackProcState(procState, mAdjSeq, now);
trackedProcState = true;
}
} else if ((cr.flags & Context.BIND_NOT_PERCEPTIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
} else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
newAdj = clientAdj;
} else {
if (adj > ProcessList.VISIBLE_APP_ADJ) {
// TODO: Is this too limiting for apps bound from TOP?
newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
} else {
newAdj = adj;
}
}
if (!client.cached) {
app.cached = false;
}
// 从client进程中选择一个最小的adj值来作为当前进程的adj值
if (adj > newAdj) {
adj = newAdj;
app.setCurRawAdj(adj);
adjType = "service";
}
}
}
}
}
}
}
- 14 根据app进程中的Provider来确定adj值
// 遍历当前进程下的Provider
for (int provi = app.pubProviders.size() - 1;
provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > 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 == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
i--) {
ContentProviderConnection conn = cpr.connections.get(i);
ProcessRecord client = conn.client;
if (client == app) {
// 绑定的进程是当前进程时,跳过
continue;
}
// 计算client进程的adj值
computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now, cycleReEval);
// 是否需要跳过当前client进程
if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
continue;
}
// 获取client进程的adj值
int clientAdj = client.getCurRawAdj();
int clientProcState = client.getCurRawProcState();
if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
clientProcState = PROCESS_STATE_CACHED_EMPTY;
}
String adjType = null;
if (adj > clientAdj) {
if (app.hasShownUi && !wpc.isHomeProcess()
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adjType = "cch-ui-provider";
} else {
//选取clientAdj大的进程为当前进程的adj,adj值越大,越容易被杀
adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
app.setCurRawAdj(adj);
adjType = "provider";
}
app.cached &= client.cached;
}
}
- 15 如果有外部程序正在处理, 不能把adj值变大
if (cpr.hasExternalProcessHandles()) {
if (adj > ProcessList.FOREGROUND_APP_ADJ) {
adj = ProcessList.FOREGROUND_APP_ADJ;
app.setCurRawAdj(adj);
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.adjType = "ext-provider";
app.adjTarget = cpr.name;
}
if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) {
procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
app.setCurRawProcState(procState);
}
}
- 16 Provider运行时间小于CONTENT_PROVIDER_RETAIN_TIME不将当前app进程的adj值降低
if (app.lastProviderTime > 0 &&
(app.lastProviderTime + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
// 在mConstants.CONTENT_PROVIDER_RETAIN_TIME时间内不降低当前Provider的进程优先级
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "recent-provider";
}
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
procState = PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "recent-provider";
}
}
- 17 服务达到一定数量后,为了不影响性能的情况, 将三分之一的服务划分为A类,3分之二划分为B类服务,A类服务具有更高的优先级,更不容易被杀
if (adj == ProcessList.SERVICE_ADJ) {
if (doingAll) {
// A服务进程数是否超过了整个服务的3分之一,是则归为B类服务
app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
mNewNumServiceProcs++;
if (!app.serviceb) {
if (mService.mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
&& app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {
// B服务
app.serviceHighRam = true;
app.serviceb = true;
} else {
// A服务
mNewNumAServiceProcs++;
}
} else {
app.serviceHighRam = false;
}
}
if (app.serviceb) {
// 将adj值设置为B类的adj值
adj = ProcessList.SERVICE_B_ADJ;
}
// 设置原始的adj值
app.setCurRawAdj(adj);
// 确保adj的值在合理的范围内
if (adj > app.maxAdj) {
adj = app.maxAdj;
if (app.maxAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
// 调整adj的值,复制给app.curAdj
app.curAdj = app.modifyRawOomAdj(adj);
app.setCurrentSchedulingGroup(schedGroup);
app.setCurProcState(procState);
app.setCurRawProcState(procState);
app.setHasForegroundActivities(foregroundActivities);
// 计算完成标识
app.completedAdjSeq = mAdjSeq;
return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState;
}
applyOomAdjLocked分析
- 1 1设置进程的adj值
// 1设置进程的adj值
if (app.curAdj != app.setAdj) {
ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
app.setAdj = app.curAdj;
app.verifiedAdj = ProcessList.INVALID_ADJ;
}
- 2 mProcessGroupHandler的定义
mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup");
final int pid = msg.arg1;
final int group = msg.arg2;
// 设置进程组
setProcessGroup(pid, group);
});
- 3 设置进程组和线程组
int oldSchedGroup = app.setSchedGroup;
app.setSchedGroup = curSchedGroup;
if (app.waitingToKill != null && app.curReceivers.isEmpty()
&& app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
// 需要kill的进程还没有被kill,现在kill掉
app.kill(app.waitingToKill, true);
success = false;
} else {
int processGroup;
switch (curSchedGroup) {
case ProcessList.SCHED_GROUP_BACKGROUND:
processGroup = THREAD_GROUP_BG_NONINTERACTIVE;
break;
case ProcessList.SCHED_GROUP_TOP_APP:
case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
processGroup = THREAD_GROUP_TOP_APP;
break;
case ProcessList.SCHED_GROUP_RESTRICTED:
processGroup = THREAD_GROUP_RESTRICTED;
break;
default:
processGroup = THREAD_GROUP_DEFAULT;
break;
}
// 设置对应的进程组
mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage(
0 /* unused */, app.pid, processGroup));
try {
if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
app.getWindowProcessController().onTopProcChanged();
// 设置线程优先级
if (mService.mUseFifoUiScheduling) {
// Switch UI pipeline for app to SCHED_FIFO
app.savedPriority = Process.getThreadPriority(app.pid);
mService.scheduleAsFifoPriority(app.pid, /* suppressLogs */true);
if (app.renderThreadTid != 0) {
mService.scheduleAsFifoPriority(app.renderThreadTid,
/* suppressLogs */true);
}
} else {
// 设置线程优先级
setThreadPriority(app.pid, TOP_APP_PRIORITY_BOOST);
if (app.renderThreadTid != 0) {
try {
// 设置线程优先级
setThreadPriority(app.renderThreadTid,
TOP_APP_PRIORITY_BOOST);
} catch (IllegalArgumentException e) {
// thread died, ignore
}
}
}
}
}
}
}
- 4 通知UsageStats状态变化
if (app.setProcState != app.getCurProcState()) {
boolean setImportant = app.setProcState < PROCESS_STATE_SERVICE;
boolean curImportant = app.getCurProcState() < PROCESS_STATE_SERVICE;
if (setImportant && !curImportant) {
// This app is no longer something we consider important enough to allow to use
// arbitrary amounts of battery power. Note its current CPU time to later know to
// kill it if it is not behaving well.
app.setWhenUnimportant(now);
app.lastCpuTime = 0;
}
// 通知UsageStats状态变化
maybeUpdateUsageStatsLocked(app, nowElapsed);
}
uid
用户ID,每个不同的应用程序都有一个uid,uid是你安装应用程序时系统赋予的,是不变的,卸载重新安装有可能会变
pid
进程ID
tid
线程ID
Android中设置进程或线程API,通过使用linux的sched_setscheduler,setpriority函数和操作CGroup文件节点来设置线程优先级和设置调度策略
设置线程优先级
Process.setThreadPriority(int tid, int priority)
Process.setThreadPriority(int priority)
设置线程组
Process.setThreadGroup(int tid, int group)
设置进程组
Process.setProcessGroup(int pid, int group)
设置线程调度器
Process.setThreadScheduler(int tid, int policy, int priority)
线程优先级
// 应用的默认优先级
public static final int THREAD_PRIORITY_DEFAULT = 0;
// 线程的最低优先级
public static final int THREAD_PRIORITY_LOWEST = 19;
// 后台线程的默认优先级
public static final int THREAD_PRIORITY_BACKGROUND = 10;
// 前台进程的优先级
public static final int THREAD_PRIORITY_FOREGROUND = -2;
// 显示功能的优先级
public static final int THREAD_PRIORITY_DISPLAY = -4;
// 紧急显示功能的优先级
public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;
// 视频线程默认优先级
public static final int THREAD_PRIORITY_VIDEO = -10;
// 音频线程默认优先级
public static final int THREAD_PRIORITY_AUDIO = -16;
// 紧急音频线程默认优先级
public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;
线程组
对应sched_policy.h中的SchedPolicy
// 默认线程组
public static final int THREAD_GROUP_DEFAULT = -1;
// 后台非交互组
public static final int THREAD_GROUP_BG_NONINTERACTIVE = 0;
// 前台线程组
private static final int THREAD_GROUP_FOREGROUND = 1;
// 系统组
public static final int THREAD_GROUP_SYSTEM = 2;
// 音频应用程序组
public static final int THREAD_GROUP_AUDIO_APP = 3;
// 系统音频应用程序组
public static final int THREAD_GROUP_AUDIO_SYS = 4;
// 头等app组
public static final int THREAD_GROUP_TOP_APP = 5;
// phone等通讯app组
public static final int THREAD_GROUP_RT_APP = 6;
调度策略
// 默认调度策略
public static final int SCHED_OTHER = 0;
// FIFO调度策略
public static final int SCHED_FIFO = 1;
// RR调度策略
public static final int SCHED_RR = 2;
// 批调度策略
public static final int SCHED_BATCH = 3;
// idle调度策略
public static final int SCHED_IDLE = 5;
linux系统api设置调度器
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
policy:
SCHED_OTHER
SCHED_BATCH
SCHED_IDLE
SCHED_FIFO
SCHED_RR
linux系统api设置线程或进程优先级
int setpriority(int which, int who, int prio);
which:
PRIO_PROCESS
PRIO_PGRP
PRIO_USER
cgroups
cgroups,其名称源自控制组群(control groups)的简写,是Linux内核的一个功能,用来限制、控制与分离一个进程组的资源(如CPU、内存、磁盘输入输出等)
Cgroups提供了以下功能:
- 1.限制进程组可以使用的资源数量(Resource limiting )
- 2.进程组的优先级控制(Prioritization )
- 3.记录进程组使用的资源数量(Accounting )
- 4.进程组隔离(Isolation)
- 5.进程组控制(Control)
libprocessgroup
set_sched_policy和set_cpuset_policy通过操作Cgroups文件节点以达到设置优先级,限制进程CPU资源的目的
int set_cpuset_policy(int tid, SchedPolicy policy);
int set_sched_policy(int tid, SchedPolicy policy);
/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
typedef enum {
SP_DEFAULT = -1,
SP_BACKGROUND = 0,
SP_FOREGROUND = 1,
SP_SYSTEM = 2, // can't be used with set_sched_policy()
SP_AUDIO_APP = 3,
SP_AUDIO_SYS = 4,
SP_TOP_APP = 5,
SP_RT_APP = 6,
SP_RESTRICTED = 7,
SP_CNT,
SP_MAX = SP_CNT - 1,
SP_SYSTEM_DEFAULT = SP_FOREGROUND,
} SchedPolicy;
cgroups.json部分节点如下
{
"Cgroups": [
{
"Controller": "cpu",
"Path": "/dev/cpuctl",
"Mode": "0755",
"UID": "system",
"GID": "system"
},
{
"Controller": "cpuset",
"Path": "/dev/cpuset",
"Mode": "0755",
"UID": "system",
"GID": "system"
},
{
"Controller": "memory",
"Path": "/dev/memcg",
"Mode": "0700",
"UID": "root",
"GID": "system"
},
]
}
https://www.jianshu.com/p/0501bc2bbe7c
https://www.jianshu.com/p/4ee14aa23f07?from=singlemessage
https://baike.baidu.com/item/Cgroup/4988200?fr=aladdin
http://gityuan.com/2018/05/19/android-process-adj/
http://gityuan.com/2016/08/07/android-adj/