Android adj相关简介介绍

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/

上一篇:漫画:深度优先遍历 和 广度优先遍历


下一篇:四级复习资料