您的位置:首页 > 移动开发 > Android开发

Android Gems — Android的LowMemoryKiller杀进程策略

2016-11-18 00:04 417 查看
Anroid的杀进程策略是基于kernel里的LowMemoryKiller模块,LMK的实现在这里不展开分析,大致的原理就是LMK注册了内核的shrinker(lowmem_shrinker),内核线程kswapd,在linux回收内存分页的时候,通过shrinker回调回来给LMK。LMK根据每个进程的oom_adj值,将大于某个阈值的进程都发送SIGKILL信号杀掉。oom_adj的阈值因内存情况不同而不同,具体的对应关系可以查看/sys/module/lowmemorykiller/parameters/adj和/sys/module/lowmemorykiller/parameters/minfree这两个文件。oom_adj的值从-17到16,值越小,代表越重要,越晚被杀,比如一个应用如果在前台的时候,oom_adj的值就会减到0。也就是说设为负值的那些应用,会比前台应用还晚被杀。于是,系统杀进程的策略就可以通过调整每个进程的oom_adj的值来实现。oom_adj的值有如下类:
// 不可见的Activity
static final int CACHED_APP_MAX_ADJ = 15;
static final int CACHED_APP_MIN_ADJ = 9;

// 比较老的Service
static final int SERVICE_B_ADJ = 8;

// 上一个应用,这样在做任务切换,或者返回的时候,能够快速载入
static final int PREVIOUS_APP_ADJ = 7;

// 桌面 App
static final int HOME_APP_ADJ = 6;

// Service
static final int SERVICE_ADJ = 5;

// 重量级应用,早期版本可以在manifest里加cantSaveState来声明,新版已经注释了,目前没看到哪里可以设置
static final int HEAVY_WEIGHT_APP_ADJ = 4;

// 备份代理应用,manifest里Application标签里可以声明backAgent
static final int BACKUP_APP_ADJ = 3;

// 可感知的App,比如有Pause状态的Activity,Stopping状态的Activity,被一个可见的进程BindService的进程等
static final int PERCEPTIBLE_APP_ADJ = 2;

// 前台可见的Activity,
static final int VISIBLE_APP_ADJ = 1;

// 前台App,包括Top App,Instrumentation Test App,正在接收broadcast的App,正在执行的Service等
static final int FOREGROUND_APP_ADJ = 0;

//  被Persist App BindService的进程
static final int PERSISTENT_SERVICE_ADJ = -11;

//  声明了persist的进程
static final int PERSISTENT_PROC_ADJ = -12;

// 系统进程,比如system server
static final int SYSTEM_ADJ = -16;

// 不被系统管的Native进程,比如/system/bin下运行的那些服务(surfaceflinger etc)
static final int NATIVE_ADJ = -17;
oom_adj的值受很多因素影响:应用是否有activity,activity是否可见,是否有service,service是否被bind的其他进程的oom_adj等等。在Framework里oom_adj的调整主要由ActivityManagerService这个类负责,任何可能会影响到进程oom_adj的值的情况,就会调用updateOomAdjLocked来更新各进程的oom_adj值,比如:
1,Activity切换
2,Service start/stop/bind
3,Broadcast分发处理
updateOomAdjLocked会遍历当前进程列表,对每个进程ProcessRecord都调用computeOomAdjLocked来重新计算oom_adj,最后applyOomAdjLocked来使oom_adj生效。
我们看看updateOomAdjLocked的实现:
final void updateOomAdjLocked() {
final ActivityRecord TOP_ACT = resumedAppLocked();
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
final long now = SystemClock.uptimeMillis();
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
final int N = mLruProcesses.size();

......
......

for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
// 找到最早的一次service活动时间
if (mEnableBServicePropagation && app.serviceb
&& (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
numBServices++;
for (int s = app.services.size() - 1; s >= 0; s--) {
ServiceRecord sr = app.services.valueAt(s);
if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + app.processName
+ " serviceb = " + app.serviceb + " s = " + s + " sr.lastActivity = "
+ sr.lastActivity + " packageName = " + sr.packageName
+ " processName = " + sr.processName);
if (SystemClock.uptimeMillis() - sr.lastActivity
< mMinBServiceAgingTime) {
if (DEBUG_OOM_ADJ) {
Slog.d(TAG,"Not aged enough!!!");
}
continue;
}
if (serviceLastActivity == 0) {
serviceLastActivity = sr.lastActivity;
selectedAppRecord = app;
} else if (sr.lastActivity < serviceLastActivity) {
serviceLastActivity = sr.lastActivity;
selectedAppRecord = app;
}
}
}
if (DEBUG_OOM_ADJ && selectedAppRecord != null) Slog.d(TAG,
"Identified app.processName = " + selectedAppRecord.processName
+ " app.pid = " + selectedAppRecord.pid);
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
// 重新计算进程app的oom_adj
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);

// If we haven't yet assigned the final cached adj
// to the process, do that now.
// 如果没找到对应的oom_adj,那么根据app的进程状态,如果有activity存在,那么oom_adj设为curCachedAdj,
// 否则就是empty进程,讲oom_adj设为curEmptyAdj
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
// This process is a cached process holding activities...
// assign it the next cached value for that type, and then
// step that cached level.
app.curRawAdj = curCachedAdj;
app.curAdj = app.modifyRawOomAdj(curCachedAdj);
if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
+ " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
+ ")");
if (curCachedAdj != nextCachedAdj) {
stepCached++;
if (stepCached >= cachedFactor) {
stepCached = 0;
curCachedAdj = nextCachedAdj;
nextCachedAdj += 2;
if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
break;
default:
// For everything else, assign next empty cached process
// level and bump that up.  Note that this means that
// long-running services that have dropped down to the
// cached level will be treated as empty (since their process
// state is still as a service), which is what we want.
app.curRawAdj = curEmptyAdj;
app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
+ " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
+ ")");
if (curEmptyAdj != nextEmptyAdj) {
stepEmpty++;
if (stepEmpty >= emptyFactor) {
stepEmpty = 0;
curEmptyAdj = nextEmptyAdj;
nextEmptyAdj += 2;
if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
break;
}
}
// 调用applyOomAdjLocked使新的oom_adj生效
applyOomAdjLocked(app, true, now);

// Count the number of process types.
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
mNumCachedHiddenProcs++;
numCached++;
// 计算Cached进程个数,超过cachedProcessLimit即直接kill
if (numCached > cachedProcessLimit) {
app.kill("cached #" + numCached, true);
}
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
//  计算empty进程个数,超过上限即kill
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;
}
......
......
}
}
// 在低内存的情况下,把过老的service的oom_adj的值调大到CACHED_APP_MAX_ADJ,以便可以被优先杀死
if ((numBServices > mBServiceAppThreshold) && (true == mAllowLowerMemLevel)
&& (selectedAppRecord != null)) {
ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
ProcessList.CACHED_APP_MAX_ADJ);
selectedAppRecord.setAdj = selectedAppRecord.curAdj;
if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + selectedAppRecord.processName
+ " app.pid = " + selectedAppRecord.pid + " is moved to higher adj");
}

// finish所有后台的activity,这个有系统开关可以控制,Settings.Global.ALWAYS_FINISH_ACTIVITIES,也就是开发者选项里的“不保留活动”,
// 也可以通过ActivityManagerNative的setAlwaysFinish来设置,这需要声明权限android.Manifest.permission.SET_ALWAYS_FINISH
if (mAlwaysFinishActivities) {
// Need to do this on its own message because the stack may not
// be in a consistent state at this point.
mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
}
......
......

}
系统将进程分三类:
一, empty process,没有service,也没有activity,空进程没有执行逻辑,可以优先被杀,empty process有数量限制,超过限制之后就马上被kill。
二, cached process,只有不可见的activity,这类进程优先级比empty高些,但也同样可以被杀,用户不会有太明显的感知,表现就是返回到他的activity之后,
进程被重新被创建,Activity也会重新onCreate。
empty和cached进程的上限是ProcessList.MAX_CACHED_APPS=32个,而empty的上限是ProcessList.computeEmptyProcessLimit(ProcessList.MAX_CACHED_APPS),默认是16。
三,其他是第三类,包括有前台可见的Activity的进程,有前台Service的进程等。
三类进程数之和就等于LruProcesses队列的大小。
private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
boolean doingAll, long now) {
if (mAdjSeq == app.adjSeq) {
// This adjustment has already been computed.
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();

// app最大的adj和前台app的adj一样,说明是系统进程,adj就设为maxAdj
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;

// Determine the importance of the process, starting with most
// important to least, and assign an appropriate OOM adjustment.
int adj;
int schedGroup;
int procState;
boolean foregroundActivities = false;
BroadcastQueue queue;
if (app == TOP_APP) {   // App正在系统顶层,adj设为FOREGROUND_APP_ADJ
// 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;
if(app == mHomeProcess) {
mHomeKilled = false;
mHomeProcessName = mHomeProcess.processName;
}
} else if (app.instrumentationClass != null) {  // App正执行Instrumentation,adj设为FOREGROUND_APP_ADJ
// 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) { // App正在接收broadcast,adj设为FOREGROUND_APP_ADJ
// 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;
} else if (app.executingServices.size() > 0) {   // App的Service正在执行,adj设为FOREGROUND_APP_ADJ
// 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;
//  初始状态cached和empty都设为true,根据进程的执行状态再改
app.cached = true;
app.empty = true;
app.adjType = "cch-empty";

// 桌面App,既不是empty也不是cached,adj设为PERSISTENT_PROC_ADJ
if (mHomeKilled && app.processName.equals(mHomeProcessName)) {
adj = ProcessList.PERSISTENT_PROC_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
app.adjType = "top-activity";
}
}

// Examine all activities if not already foreground.
if (!foregroundActivities && activitiesSize > 0) {
// 遍历非前台的activity
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;
}
if (r.visible) {
// 可见的Activity,如果Activity不在最顶层,而且被顶层完全挡住的时候visible状态会被设为false,
// 如果是可见的,那么adj设为VISIBLE_APP_ADJ,cached和empty也设为false
// 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;
} else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
// Pause状态的Activity,adj设为PERCEPTIBLE_APP_ADJ,cached和empty也设为false
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;
} else if (r.state == ActivityState.STOPPING) {
// Stopping状态的app,adj设为PERCEPTIBLE_APP_ADJ,cached和empty也设为false
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 {
// 进这个分支说明进程有不可见的Activity,adj会设为CACHED_APP_MIN_ADJ和CACHED_APP_MAX_ADJ之间的数
if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
app.adjType = "cch-act";
}
}
}
}

if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
// 如果有前台的Service,adj设为PERCEPTIBLE_APP_ADJ,可通过ActivityManagerNative将Service设为foreground
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;
}
}

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;
}
}

if (app == mHomeProcess) {
// 如果桌面App,adj设为HOME_APP_ADJ
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;
}
}

// 如果是刚刚切换出去的App,adj设为PREVIOUS_APP_ADJ
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;
}
}

if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
+ " reason=" + app.adjType);

// By default, we use the computed adjustment.  It may be changed if
// there are applications dependent on our services or providers, but
// this gives us a baseline and makes sure we don't get into an
// infinite recursion.
app.adjSeq = mAdjSeq;
app.curRawAdj = adj;
app.hasStartedServices = false;

// Backup App,adj设为BACKUP_APP_ADJ
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;
}
}

boolean mayBeTop = false;

// 如果App有Service,adj设为SERVICE_ADJ
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);
if (s.startRequested) {
app.hasStartedServices = true;
if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
procState = ActivityManager.PROCESS_STATE_SERVICE;
}
if (app.hasShownUi && app != mHomeProcess) {
// If this process has shown some UI, let it immediately
// go to the LRU list because it may be pretty heavy with
// UI stuff.  We'll tag it with a label just to help
// debug and understand what is going on.
if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-ui-services";
}
} else {
if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) {
// This service has seen some activity within
// recent memory, so we will keep its process ahead
// of the background processes.
if (adj > ProcessList.SERVICE_ADJ) {
adj = ProcessList.SERVICE_ADJ;
app.adjType = "started-services";
app.cached = false;
}
}
// If we have let the service slide into the background
// state, still have some text describing what it is doing
// even though the service no longer has an impact.
if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-services";
}
}
}
//  如果App有Service,那么需要检查是否有外部的App在Bind它,如果一个高优先级的App,bind了你的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++) {
// XXX should compute this based on the max of
// all connected clients.
ConnectionRecord cr = clist.get(i);
if (cr.binding.client == app) {
// Binding to ourself is not interesting.
continue;
}
// 只有bind的时候不加BIND_WAIVE_PRIORITY这个flag才会影响对方的adj
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) {
// If the other app is cached for any reason, for purposes here
// we are going to consider it empty.  The specific cached state
// doesn't propagate except under certain conditions.
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
}
String adjType = null;
if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
// Not doing bind OOM management, so treat
// this guy more like a started service.
if (app.hasShownUi && app != mHomeProcess) {
// If this process has shown some UI, let it immediately
// go to the LRU list because it may be pretty heavy with
// UI stuff.  We'll tag it with a label just to help
// debug and understand what is going on.
if (adj > clientAdj) {
adjType = "cch-bound-ui-services";
}
app.cached = false;
clientAdj = adj;
clientProcState = procState;
} else {
if (now >= (s.lastActivity
+ ActiveServices.MAX_SERVICE_INACTIVITY)) {
// This service has not seen activity within
// recent memory, so allow it to drop to the
// LRU list if there is no other reason to keep
// it around.  We'll also tag it with a label just
// to help debug and undertand what is going on.
if (adj > clientAdj) {
adjType = "cch-bound-services";
}
clientAdj = adj;
}
}
}
if (adj > clientAdj) {
// If this process has recently shown UI, and
// the process that is binding to it is less
// important than being visible, then we don't
// care about the binding as much as we care
// about letting this process get into the LRU
// list to be killed and restarted if needed for
// memory.
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adjType = "cch-bound-ui-services";
} else {
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
// 如果Client Bind的时候加了BIND_ABOVE_CLIENT和BIND_IMPORTANT,那么讲client的adj值给Service,最低不小于PERSISTENT_SERVICE_ADJ
adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ;
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
// 如果Client Bind的时候加了BIND_NOT_VISIBLE,并且client的adj比PERCEPTIBLE_APP_ADJ小的时候,将PERCEPTIBLE_APP_ADJ给adj
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
} else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
// 把Client的adj给adj,因为adj是> clientAdj的,所以Service的adj还是得到了提升
adj = clientAdj;
} else {
// 这里client的adj是要小于等于VISIBLE_APP_ADJ的,所以adj将会提升至VISIBLE_APP_ADJ
if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = ProcessList.VISIBLE_APP_ADJ;
}
}
if (!client.cached) {
app.cached = false;
}
adjType = "service";
}
}
......
......
......
}
// ContentProvider的连接也同样会影响到app的adj
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) {
// If the other app is cached for any reason, for purposes here
// we are going to consider it empty.
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 the provider has external (non-framework) process
// dependencies, ensure that its adjustment is at least
// FOREGROUND_APP_ADJ.
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;
}
}
}
......
......
app.curAdj = app.modifyRawOomAdj(adj);
app.curSchedGroup = schedGroup;
app.curProcState = procState;
app.foregroundActivities = foregroundActivities;
return app.curRawAdj;
}
computeOomAdjLocked计算完oom_adj之后,就调用applyOomAdjLocked使之生效,applyOomAdjLocked比较简单,调用ProcessList的setOomAdj,通过LocalSocket连接到
lmkd,通过进程间通信写入。
作者简介:田力,网易彩票Android端创始人,小米视频创始人,现任roobo技术经理、视频云技术总监欢迎关注微信公众号 磨剑石,定期推送技术心得以及源码分析等文章,谢谢

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android framework