这1篇博客,我们来分析1下AMS进程管理流程中,负责计算进程oom_adj值的computeOomAdjLocked函数。
从难度上来说,computeOomAdjLocked函数比updateOomAdjLocked函数简单,由于它的职责更明确和单1。
但是,由于Android定义的oom_adj种类庞杂,使得这个函数的分支很多,细节显得极为的繁琐。
因此从功利的角度来看,大家知道这个函数的用处和大概脉络便可。
不过对1个框架工程师而言,浏览源码的耐心可能比写代码的能力更重要,因此我们还是耐着性子将代码看完。
“RTFSC”,毕竟大神是这么告知我们的。
computeOomAdjLocked函数的代码很长,
因此在这篇博客中,我们还分段进行研究,然后试着进行总结。
1、computeOomAdjLocked Part-I
private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
boolean doingAll, long now) { //之前的博客中提到过,updateOomAdjLocked函数每次更新oom_adj时,都会分配1个序号 //此处就是根据序号判断是不是已处理过命令 if (mAdjSeq == app.adjSeq) { // This adjustment has already been computed. return app.curRawAdj;
} //ProcessRecord对应的ActivityThread不存在了 //修改其中的1些变量,此时的oom_adj为CACHED_APP_MAX_ADJ, //其意义我们在前1篇博客中已提到过 if (app.thread == null) {
app.adjSeq = mAdjSeq;
app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
} //初始化1些变量 //这些变量的具体用处,在篇博客中我们不关注 //大家只用留意1下ProcessRecord的schedGroup、procState和oom_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(); //这个判断没啥意义,ProcessRecord中只有初始化时为maxAdj赋值 //maxAdj取值为UNKNOWN_ADJ,即最大的1001 if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) { //这部份代码就是修改app的curSchedGroup,并将oom_adj设置为maxAdj //实际进程中,应当是不会履行的的 ...................... } //保存当前TOP Activity的状态 final int PROCESS_STATE_CUR_TOP = mTopProcessState; ...................... }
以上代码就是computeOomAdjLocked函数的第1部份。
从代码不难看出,这部份内容的主要目的是:
1、根据参数及进程的状态,决定是不是需要进行后续的计算;
2、初始化1些变量。
2、computeOomAdjLocked Part-II
在第2部份,computeOomAdjLocked开始干“正事儿”了:
................. // Determine the importance of the process, starting with most // important to least, and assign an appropriate OOM adjustment. // 上面的这段注释为全部computeOomAdjLocked函数“代言” 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; //单独的1种schedGroup schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "top-activity"; //当前处理的是包括前台Activity的进程时,才会将该值置为true foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
} else if (app.instrumentationClass != null) { //处理正在进行测试的进程 // Don't want to kill running instrumentation. adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_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; //根据处理广播的Queue,决定调度策略 schedGroup = (queue == mFgBroadcastQueue) ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
} else if (app.executingServices.size() > 0) { //处理Service正在运行的进程 // An app that is currently executing a service callback also // counts as being in the foreground. adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = app.execServicesFg ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
procState = ActivityManager.PROCESS_STATE_SERVICE;
} else { //其它进程,在后续进程中再进1步处理 // As far as we know the process is empty. We may change our mind later. schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; // At this point we don't actually know the adjustment. Use the cached adj // value that the caller wants us to. // 先将adj临时赋值为cachedAdj,即参数传入的UNKNOW_ADJ adj = cachedAdj;
procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
app.cached = true;
app.empty = true;
app.adjType = "cch-empty";
} ..................
以上代码可以看做是computeOomAdjLocked的第2部份,从这部份代码可以看出:
1、包括前台Activity的进程、运行测试类的进程、处理广播的进程及包括正在运行服务的进程,
其oom_adj均被赋值为FOREGROUND_APP_ADJ,即从LMK的角度来看,它们的重要性是1致的。
但这些进程的procState不同,因而从AMS主动回收内存的角度来看,它们的重要性不同。
另外,这些进程的schedGroup不同。
之前的博客分析过,Process.java中提供了接口,可以调用Linux提供的接口函数设置schedGroup,使得进程具有不同的调度策略。
从获得CPU资源的能力来看,SCHED_GROUP_TOP_APP应当强于SCHED_GROUP_DEFAULT,
最后才轮到SCHED_GROUP_BACKGROUND。
2、对其它种类的进程,这部份代码先将它们的oom_adj设置为UNKNOW_ADJ,
proc_state置为PROCESS_STATE_CACHED_EMPTY,在后续流程中再作进1步处理。
3、computeOomAdjLocked Part-III
这1部份代码主要处理包括Activity,但是Activity不在前台的进程。
注意到这些进程包括之条件到的正在处理广播、服务或测试的进程,和oom_adj暂时为UNKNOW_ADJ的进程。
不过只有UNKNOW_ADJ对应的进程,才有可能进行实际的更新。
.................. // Examine all activities if not already foreground. if (!foregroundActivities && activitiesSize > 0) { //之前分析updateOomAdjLocked的第1部份时,简单提到过rankTaskLayersIfNeeded函数 //该函数会更新包括Activity的Task的rankLayer //依照显示层次从上到下,rankLayer逐步增加,对应的最大值就是VISIBLE_APP_LAYER_MAX int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX; //顺次轮询进程中的Activity for (int j = 0; j < activitiesSize; j++) {
final ActivityRecord r = app.activities.get(j); ................... //如果进程包括可见Activity,即该进程是个可见进程 if (r.visible) { // App has a visible activity; only upgrade adjustment. if (adj > ProcessList.VISIBLE_APP_ADJ) { //adj大于VISIBLE_APP_ADJ时,才更新对应的adj //之条件到的正在处理广播、服务或测试的进程,adj为FOREGROUND,是小于VISIBLE_APP_ADJ //因此不会在此更新 adj = ProcessList.VISIBLE_APP_ADJ;
app.adjType = "visible";
} if (procState > PROCESS_STATE_CUR_TOP) { //与oom_adj类似,在条件满足时,更新procState procState = PROCESS_STATE_CUR_TOP;
} //正在处理广播、服务或测试的进程,如果它们的调度策略为BACKGROUND //但又包括了可见Activity时,调度策略变更加DEFAULT schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true; if (r.task != null && minLayer > 0) {
final int layer = r.task.mLayerRank; if (layer >= 0 && minLayer > layer) { //更新ranklayer minLayer = layer;
}
} //发现可见Activity时,直接可以结束循环 break;
} else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) { //如果进程包括处于PAUSING或PAUSED状态的Activity时 //将其oom_adj调剂为“用户可发觉”的的等级,这个等级还是很高的 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "pausing";
} if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
}
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true; //注意其实不会break } else if (r.state == ActivityState.STOPPING) { //包括处于Stopping状态Activity的进程,其oom_adj也被置为PERCEPTIBLE_APP_ADJ if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "stopping";
} ................ // 这类进程将被看做潜伏的cached或empty进程 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 { //只是含有cached-activity的进程,仅调剂procState if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
app.adjType = "cch-act";
}
} if (adj == ProcessList.VISIBLE_APP_ADJ) { //不同可见进程的oom_adj有1定的差异,处在下层的oom_adj越大 //即越老的Activity所在进程,重要性越低 adj += minLayer;
}
}
} ..................
从上面的代码可以看出,computeOomAdjLocked的第3部份处理包括Activity的进程时,
进程终究的oom_adj将由其中最要的Activity决定。
即进程中存在可见Activity时,进程的oom_adj就为VISIBLE_APP_ADJ;
否则,若进程中存在处于PAUSING、PAUSED或STOPPING状态的Activity时,进程的oom_adj就为PERCEPTIBLE_APP_ADJ;
其余的进程还是UNKNOW_ADJ。
4、computeOomAdjLocked Part-IV
computeOomAdjLocked的第4部份主要用于处理1些特殊的进程。
............... if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { //进程包括前台服务或被强迫在前台运行时 //oom_adj被调剂为PERCEPTIBLE_APP_ADJ,只是procState略有不同 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 = ProcessList.SCHED_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 = ProcessList.SCHED_GROUP_DEFAULT;
}
} //AMS的HeavyWeight进程单独处理 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 = ProcessList.SCHED_GROUP_BACKGROUND;
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 = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "home";
} if (procState > ActivityManager.PROCESS_STATE_HOME) {
procState = ActivityManager.PROCESS_STATE_HOME;
}
} //前台进程之前的1个进程 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 = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "previous";
} if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
}
} // 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工作的进程 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) { .............. 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处理1个进程时,依照重要性由高到底的顺序,
逐渐判断该进程是不是满足对应的条件。
虽然计算1个进程的oom_adj时,会经过上述所有的判断,但当1个进程已满足重要性较高的条件时,
后续的判断实际上不会更改它已取得的oom_adj。
上面4部份的逻辑基本上以下图所示:
大图链接
后续的处理逻辑,依然满足上述规则。
只是在斟酌含有Service和Provider的进程时,整体流程显得极为复杂,
融入上图的本钱太高,因此就不再画图了。
5、computeOomAdjLocked Part-V
computeOomAdjLocked的第5部份,主要是处理包括服务的进程。
这1部份代码写的比较繁琐,复杂度应当超过了前4部份的和,
因此我们进1步分段说明。
1、Unbounded Service的处理
当进程中包括Unbounded Service时,进程的oom_adj先依照Unbounded Service的处理方式进行调剂。
................. //顺次处理进程中的每个Service for (int is = app.services.size()-1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.services.valueAt(is); //Service被已Unbounded Service的方式启动过 if (s.startRequested) {
app.hasStartedServices = true; //调剂procState 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. // 唯一含有服务且显示过UI的进程,由于其占用内存可能较多,因此需要尽早回收 // 故此处不调剂其oom_adj if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "cch-started-ui-services";
}
} else { if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) { //MAX_SERVICE_INACTIVITY为activity启动service后,系统最多保存Service的时间 // This service has seen some activity within // recent memory, so we will keep its process ahead // of the background processes. //此时进程的oom_adj就能够被调剂为后台服务对应的SERVICE_ADJ //adj大于500的进程均会受此判断的影响 if (adj > ProcessList.SERVICE_ADJ) {
adj = ProcessList.SERVICE_ADJ;
app.adjType = "started-services";
app.cached = false;
}
} //处理Service存在超时的情况,可见超时时也不会调剂oom_adj // 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";
}
}
} .................
从上面的代码可以看出,当进程中含有Unbounded Service时,
如果进程之前没有启动过UI,且Unbounded Service存活的时间没有超时,
进程的oom_ad才能被调剂为SERVICE_ADJ;否则进程的oom_adj依然是UNKNOW_ADJ或其它大于500的值。
2、Bounded Service的处理
这部份代码紧接着上述流程。
即进程将先依照Unbounded Service的方式调剂oom_adj,
然后再依照Bounded Service的方式进1步调剂。
固然,若Service仅为Unbounded Service或Bounded Service中的1种时,
computeOomAdjLocked函数的第5部份,只会依照1种方式调剂oom_adj。
Bounded Service的处理方式,远比Unbounded Service复杂,依赖于客户真个oom_adj和绑定服务时使用的flag。
.................... //如果该Service还被客户端Bounded,即是Bounded Service时 for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP);
conni--) {
ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni); //客户端可以通过1个Connection以不同的参数绑定Service //因此,1个Service可以对应多个Connection,1个Connection又对应多个ConnectionRecord //这里顺次处理每个ConnectionRecord for (int i = 0;
i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP);
i++) {
ConnectionRecord cr = clist.get(i); if (cr.binding.client == app) { // Binding to ourself is not interesting. continue;
} //当BIND_WAIVE_PRIORITY为1时,客户端就不会影响服务端 //if中的流程就能够略去;否则,客户端就会影响服务端 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client; //计算出客户端进程的oom_adj //由此可看出Android oom_adj的计算多么麻烦 //要是客户端进程中,又有个服务进程被绑定,那末将再计算其客户端进程的oom_adj?! 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; //BIND_ALLOW_OOM_MANAGEMENT置为1时,先依照通常的处理方式,调剂服务端进程的adjType if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) { //与前面分析Unbounded Service基本1致,若进程显示过UI或Service超时 //会将clientAdj修改成当前进程的adj,即不需要斟酌客户端进程了 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;
}
}
} //根据情况,依照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 { //以下的流程表明,client和flag将同时影响Service进程的adj if ((cr.flags&(Context.BIND_ABOVE_CLIENT |Context.BIND_IMPORTANT)) != 0) { //从这里再次可以看出,Service重要性小于等于Client adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ ? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ; //BIND_NOT_VISIBLE表示不将服务端当作visible进程看待 //因而,即便客户真个adj小于PERCEPTIBLE_APP_ADJ,service也只能取到PERCEPTIBLE_APP_ADJ } 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.PERCEPTIBLE_APP_ADJ) {
adj = clientAdj;
} else { if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
}
} if (!client.cached) {
app.cached = false;
}
adjType = "service";
}
} if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { //进1步更具client调剂当前进程的procState、schedGroup等 ................... } else { ................... } ................. if (procState > clientProcState) {
procState = clientProcState;
} //其它参数的赋值 ................. } if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
app.treatLikeActivity = true;
} //取出ConnectionRecord所在的Activity final ActivityRecord a = cr.activity; //BIND_ADJUST_WITH_ACTIVITY值为1时,表示服务端可以根据客户端Activity的oom_adj作出相应的调剂 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)) { //BIND_ADJUST_WITH_ACTIVITY置为1,且绑定的activity可见或在前台时, //Service进程的oom_adj可以变成FOREGROUND_APP_ADJ adj = ProcessList.FOREGROUND_APP_ADJ; //BIND_NOT_FOREGROUND为0时,才准予调剂Service进程的调度优先级 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
} else {
schedGroup = ProcessList.SCHED_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;
}
}
}
} ....................
以上就是计算含有Service的进程的oom_adj的全部进程。
从代码来看当进程仅含有Unbounded Service时,全部计算进程比较单纯,只要进程没有显示过UI,且Service的存在没有超时时,
进程的oom_adj就被调剂为SERVICE_ADJ。
当进程含有的是Bounded Service时,全部计算的复杂度就飙升了,
它将斟酌到Bound时使用的flag及客户真个情况,综合调剂进程的oom_adj。
不过正由于Bounded Service的处理流程依赖于大量的flag,而这些flag基本很少用到,
因此个人怀疑这些代码都是些实验性质的代码。手机真正运行时,使用的频率可能其实不高。
从另外一个角度来看,这么设计仿佛也是公道的。
当1个进程中的Service被许多客户端需求时,确切应当给这个进程机会,提高自己的重要性。
不知道如此细粒度的处理,Google是如何进行测试,并得到有效结论的?虽不明,但觉厉啊。
6、computeOomAdjLocked Part-VI
computeOomAdjLocked的第6部份主要是处理含有ContentProvider的进程。
由于ContentProvider也有客户端,因此一样需要根据客户端进程调剂当前进程的oom_adj。
....................
//顺次处理进程中的ContentProvider
for (int provi = app.pubProviders.size()-1; provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP); provi--) {
ContentProviderRecord cpr = app.pubProviders.valueAt(provi); //顺次处理ContentProvider的客户端
for (int i = cpr.connections.size()-1; i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| 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; }
//计算客户真个oom_adj
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; }
//与Unbounded Service的处理基本类似
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
app.adjType = "cch-ui-provider"; } else {
//根据c
上一篇 java 场景总结(一)
下一篇 顺丰上市了,王卫身价直追马云