Android 7.0 ActivityManagerService 进程管理相关流程分析

高斋晓开卷,独共圣人语。这篇文章主要讲述Android 7.0 ActivityManagerService 进程管理相关流程分析相关的知识,希望能为你提供帮助。
前一篇博客进程管理相关流程分析(1)里,
我们介绍了AMS中updateLruProcessLocked函数相关的流程。
updateLruProcessLocked只是按照进程中运行的组件, 粗略地定义了不同进程的优先级。
实际上, android根据进程的oom_adj进行了更加细致的进程分类,
而AMS中的updateOomAdjLocked函数, 就是用于更新进程的oom_adj值。
本篇博客中, 我们来看看AMS中updateOomAdjLocked相关的流程。
一、ProcessList.java中的oom_adj
进程在不同场景下的oom_adj值, 定义于ProcessList.java中。
考虑到updateOomAdjLocked函数极其的复杂, 我们有必要先了解一下不同oom_adj的含义。

final class ProcessList { .............. // OOM adjustments for processes in various states:// Uninitialized value for any major or minor adj fields // 未初始化时, 定义为-10000 static final int INVALID_ADJ = -10000; ..............// Adjustment used in certain places where we don' t know it yet. // (Generally this is something that is going to be cached, but we // don' t know the exact value in the cached range to assign yet.) // 如注释所述, 过渡态的值 static final int UNKNOWN_ADJ = 1001; // This is a process only hosting activities that are not visible, // so it can be killed without any disruption. // 从注释来看, 这里应该是仅持有Activity的background进程对应的值, 最小为900, 最大为906 // 实际上empty进程和background进程均会使用这些值 static final int CACHED_APP_MAX_ADJ = 906; static final int CACHED_APP_MIN_ADJ = 900; // The B list of SERVICE_ADJ -- these are the old and decrepit // services that aren' t as shiny and interesting as the ones in the A list. // 这里应该是对应持有老旧服务的background进程 static final int SERVICE_B_ADJ = 800; // This is the process of the previous application that the user was in. // This process is kept above other things, because it is very common to // switch back to the previous app. // 当前页面对应进程的前一个进程 // 例如, 从A进程的Activity跳转到B进程的Activity // 此时B进程就是当前进程, A进程就是previous进程 // 由于用户可能在A、B Activity之间切换, 因此为previous进程赋予一个单独的oom_adj // 本质上来说, 这仍是background进程 static final int PREVIOUS_APP_ADJ = 700; // This is a process holding the home application -- we want to try // avoiding killing it, even if it would normally be in the background, // because the user interacts with it so much. // 用户经常会和home进程交互, 因此单独为home进程赋予一个oom_adj // 一般情况下, home进程也可以归属到background进程 static final int HOME_APP_ADJ = 600; // This is a process holding an application service -- killing it will not // have much of an impact as far as the user is concerned. // service进程 static final int SERVICE_ADJ = 500; // This is a process with a heavy-weight application.It is in the // background, but we want to try to avoid killing it.Value set in // system/rootdir/init.rc on startup. // 对于heavy_weight进程, 虽是后台进程, 但重要性甚至大于service进程 // 应该是该类型的进程, 重新启动的成本太高了, 因此尽量避免杀掉吧 // 这是所谓的“尾大不掉”吧// 需要指出的是, 这里的注释太老旧了, Android N里的路径已经是system/core/rootdir/init.rc // 同时, 没有看到与heavy_weight相关的配置, 个人觉得注释的意思是: // 可以按照需要自己配置吧, 类似于init进程的写法: // # Set init and its forked children' s oom_adj. // write /proc/1/oom_score_adj -1000 static final int HEAVY_WEIGHT_APP_ADJ = 400; // This is a process currently hosting a backup operation.Killing it // is not entirely fatal but is generally a bad idea. // 正在执行backup的进程 // 与heavy_weight进程一样, android已经不完全按照进程的组件来划分重要性了 // 还考虑了进程当前正在执行的操作 static final int BACKUP_APP_ADJ = 300; // This is a process only hosting components that are perceptible to the // user, and we really want to avoid killing them, but they are not // immediately visible. An example is background music playback. // “perceptible”的意思是: 可察觉到 // 从这里来看, 其实这种进程已经属于visible进程的范畴了, 毕竟用户可以察觉到这种进程的存在 // 不过这种进程属于不包含visible activity, 但包含绑定了Activity的service static final int PERCEPTIBLE_APP_ADJ = 200; // This is a process only hosting activities that are visible to the // user, so we' d prefer they don' t disappear. // visible进程, 侧重于包含visible activity static final int VISIBLE_APP_ADJ = 100; static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1; // This is the process running the current foreground app.We' d really // rather not kill it! // foreground进程 static final int FOREGROUND_APP_ADJ = 0; // This is a process that the system or a persistent process has bound to, // and indicated it is important. // 系统进程或常驻进程绑定的service所在的进程 static final int PERSISTENT_SERVICE_ADJ = -700; // This is a system persistent process, such as telephony.Definitely // don' t want to kill it, but doing so is not completely fatal. // 常驻进程 static final int PERSISTENT_PROC_ADJ = -800; // The system process runs at the default adjustment. // 系统进程 static final int SYSTEM_ADJ = -900; // Special code for native processes that are not being managed by the system (so // don' t have an oom adj assigned by the system). // 框架层无法约束的native进程 static final int NATIVE_ADJ = -1000; .............. // The minimum number of cached apps we want to be able to keep around, // without empty apps being able to push them out of memory. // 从注释来看, min_cached_apps不包含empty进程的数量 static final int MIN_CACHED_APPS = 2; // The maximum number of cached processes we will keep around before killing them. // NOTE: this constant is *only* a control to not let us go too crazy with // keeping around processes on devices with large amounts of RAM.For devices that // are tighter on RAM, the out of memory killer is responsible for killing background // processes as RAM is needed, and we should *never* be relying on this limit to // kill them.Also note that this limit only applies to cached background processes; // we have no limit on the number of service, visible, foreground, or other such // processes and the number of those processes does not count against the cached // process limit. // 这里的注释需要看一看, 这里应该指系统可保留的所有后台和empty进程最大值 // MAX_CACHED_APPS不限制service, visible, foreground, or other such processes的数量 // 仅仅作为参考值, 系统并不会真的保留这么多后台进程, 毕竟LMK将按需看kill them static final int MAX_CACHED_APPS = 32; .............. // The maximum number of empty app processes we will let sit around. //最多保留16个empty进程 private static final int MAX_EMPTY_APPS = computeEmptyProcessLimit(MAX_CACHED_APPS); // The number of empty apps at which we don' t consider it necessary to do // memory trimming. // Android依靠LMK杀死进程来释放内存 // 当empty进程数少于这个门限( 8) 时, 说明LMK已经杀死了一部分empty进程 // 于是AMS主动释放一些应用的内存 static final int TRIM_EMPTY_APPS = MAX_EMPTY_APPS/2; // The number of cached at which we don' t consider it necessary to do // memory trimming. // 与TRIM_EMPTY_APPS的用途类似 // 当后台进程少于该门限(5)时, AMS主动释放一些应用的内存 static final int TRIM_CACHED_APPS = (MAX_CACHED_APPS-MAX_EMPTY_APPS)/3; ................... //以下是之前博客提到过的, LMK预定义的阈值, 这里区分了高内存和低内存的机器 //例如对于低内存机器而言, 当内存小于12288KB时, 就要kill掉oom_adj大于FOREGROUND_APP_ADJ的进程 //对于高内存的机器而言, 当内存小于73728时, 才kill掉oom_adj大于FOREGROUND_APP_ADJ的进程// These are the various interesting memory levels that we will give to // the OOM killer.Note that the OOM killer only supports 6 slots, so we // can' t give it a different value for every possible kind of process. private final int[] mOomAdj = new int[] { FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ, BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ }; // These are the low-end OOM level limits.This is appropriate for an // HVGA or smaller phone with less than 512MB.Values are in KB. private final int[] mOomMinFreeLow = new int[] { 12288, 18432, 24576, 36864, 43008, 49152 }; // These are the high-end OOM level limits.This is appropriate for a // 1280x800 or larger screen with around 1GB RAM.Values are in KB. private final int[] mOomMinFreeHigh = new int[] { 73728, 92160, 110592, 129024, 147456, 184320 }; }

ProcessList.java中定义的oom_adj值较多, 由此可见Android对于进程的管理考虑的很细, 这也意味着对应的工作流程会很复杂。
除去oom_adj的定义外, ProcessList.java中还定义了一些门限值, 决定系统在合适的时候, 主动进行一些内存回收工作, 后文分析具体代码流程时将会遇到。根据自己分析源码的感受, 个人觉得对这些变量有一些了解, 是理解具体流程的必要条件。
这里按照Android对进程的分类, 粗略划分一下不同oom_adj对应的场景, 以便后文的分析:
Android 7.0 ActivityManagerService 进程管理相关流程分析

文章图片

这里唯一要注意的是: CACHED_APP_MIN_ADJ和CACHED_APP_MAX_ADJ的分配,
跨越了后台进程和Empty进程的范畴。
Android并不是kill掉所有Empty进程后, 才kill后台进程。
它是将CACHED_APP_MIN_ADJ和CACHED_APP_MAX_ADJ之间的范围, 分成多个slot。
然后在每个slot中, 分别分配一定量的后台进程和Empty进程。
在单独的slot中, 会先kill掉empty进程, 后kill掉后台进程。
只有当一个slot中的进程kill完毕后, 才会kill掉下一个slot中的进程。
我们将从后面的代码中, 得到对应的分析依据, 这里先有个印象即可。
二、AMS中的updateOomAdjLocked
AMS中有几个重载的updateOomAdjLocked函数, 我们从比较通用的一个入手进行分析。
该updateOomAdjLocked函数较长, 分段进行分析。
1 updateOomAdjLocked Part-I
final void updateOomAdjLocked() { //正常情况下, resumedAppLocked返回当前正处于前台的Activity, 即AMS维护的mResumedActivity //如果没有mResumedActivity, 则返回前台Task中的mPausingActivity或最顶端的Activity final ActivityRecord TOP_ACT = resumedAppLocked(); //得到当前前台Activity对应进程信息 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null; .................. //得到LRU表中, 统计进程的数量 final int N = mLruProcesses.size(); .................. // Reset state in all uid records. // UidRecord用于记录某个用户组中的进程运行状态 // 该对象可以记录用户组中的进程数量, 但只记录最重要进程的状态, // 即优先级最高进程的状态决定了用户组的状态 for (int i= mActiveUids.size()-1; i> = 0; i--) { final UidRecord uidRec = mActiveUids.valueAt(i); ............ //重置 uidRec.reset(); }//更新Task的mLayerRank变量 //Task中无可见Activity时, mLayerRank为-1 //Task有可见Activity时, 按显示的先后, mLayerRank逐渐增加 mStackSupervisor.rankTaskLayersIfNeeded(); //每次调节oom_adj时, 都会有唯一的序号 mAdjSeq+ + ; mNewNumServiceProcs = 0; mNewNumAServiceProcs = 0; final int emptyProcessLimit; final int cachedProcessLimit; //mProcessLimit中记录的是: //系统允许保留的后台进程和empty进程的总和 if (mProcessLimit < = 0) { emptyProcessLimit = cachedProcessLimit = 0; } else if (mProcessLimit = = 1) { //居然优先保证的是empty进程数量 emptyProcessLimit = 1; cachedProcessLimit = 0; } else { //emptyProcess和cachedProcess的数量, 各占mProcessLimit的一半 emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit); cachedProcessLimit = mProcessLimit - emptyProcessLimit; }// Let' s determine how many processes we have running vs. // how many slots we have for background processes; we may want // to put multiple processes in a slot of there are enough of // them. // numSlots等于3 // 后台进程和empty进程对应的oom_adj, 可取的值一共有6个 // 这里划分出3个slot, 后台进程和empty进程将被分配到这3个slot中 // 2代表的是不同slot的oom_adj差异 int numSlots = (ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2; //计算出当前的empty进程数量 //N为LRU表中维护的总进程数量 //mNumNonCachedProcs表示非cached/empty进程的数量 //mNumCachedHiddenProcs表示cachedHidden进程的数量 ( 就是后台进程的数量) int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs; if (numEmptyProcs > cachedProcessLimit) { // If there are more empty processes than our limit on cached // processes, then use the cached process limit for the factor. // This ensures that the really old empty processes get pushed // down to the bottom, so if we are running low on memory we will // have a better chance at keeping around more cached processes // instead of a gazillion empty processes. // 超过门限, 则修改 // 这里有点奇怪, 为什么不用emptyProcessLimit来比较和修改? numEmptyProcs = cachedProcessLimit; }//计算出每个slot中, 可容纳empty进程的数量 int emptyFactor = numEmptyProcs/numSlots; if (emptyFactor < 1) emptyFactor = 1; //计算出每个slot中, 可容纳后台进程的数量 int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots; if (cachedFactor < 1) cachedFactor = 1; //从上面的分配可以看出, Android并不是先kill完所有empty进程, 才去kill后台进程的 //这二者之间按比例分布在不同的slot中 //每kill一个优先级对应的slot时, 都会kill一部分empty进程和后台进程 ......................... //在本次处理前, 重置变量 mNumNonCachedProcs = 0; mNumCachedHiddenProcs = 0; ..................... }

updateOomAdjLocked函数的第一部分, 并没有什么具体的逻辑, 主要是初始化一些变量, 为后续的oom_adj调整做好准备。
个人觉得大致了解即可, 不用太深究每一个变量的含义。
2 updateOomAdjLocked Part-II
这一部分将计算和更新每个进程的oom_adj值。
.................. // First update the OOM adjustment for each of the // application processes based on their current state.//empty进程相对而言, oom_adj的值还是要大于后台进程 int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ; int nextCachedAdj = curCachedAdj+ 1; int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ; int nextEmptyAdj = curEmptyAdj+ 2; for (int i= N-1; i> = 0; i--) { //从后往前, 依次取出LRU中进程对应的ProcessRecord ProcessRecord app = mLruProcesses.get(i); if (!app.killedByAm & & app.thread != null) { app.procStateChanged = false; //计算并更新进程的curProcState, 并得到初步的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. // computeOomAdjLocked没能完成oom_adj的计算时, // 进一步调整oom_adj值 (从代码来看, computeOomAdjLocked应该是无法计算后台进程和empty进程) if (app.curAdj > = ProcessList.UNKNOWN_ADJ) {//根据进程的状态调整oom_adj switch (app.curProcState) {//包含Activity的后台进程, 或其客户端进程 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; //当前进程以BIND_ABOVE_CLIENT绑定一个Service时, modifyRawOomAdj才会生效 //结果是进一步增加oom_adj app.curAdj = app.modifyRawOomAdj(curCachedAdj); ................ //调整curCachedAdj和nextCachedAdj if (curCachedAdj != nextCachedAdj) { stepCached+ + ; //可以看出, 每个slot分配的进程数超过对应门限时 //才会增加curCachedAdj和nextCachedAdj, 即向下个slot分配进程 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. // 如果后台进程不含有Activity等, 将被视为empty进程( 参考注释) //与上面的代码一样, 修改oom_adj //同样按照slot来分配empty进程的oom_adj app.curRawAdj = curEmptyAdj; app.curAdj = app.modifyRawOomAdj(curEmptyAdj); .............. if (curEmptyAdj != nextEmptyAdj) { stepEmpty+ + ; if (stepEmpty > = emptyFactor) { stepEmpty = 0; curEmptyAdj = nextEmptyAdj; nextEmptyAdj + = 2; if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) { nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ; } } } break; } }//更新进程对应的信息 applyOomAdjLocked(app, true, now, nowElapsed); // Count the number of process types. // 更新不同类型进程的数量 switch (app.curProcState) { case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: //更新后台进程的数量( 包含Activity的进程, 或其客户端) mNumCachedHiddenProcs+ + ; numCached+ + ; if (numCached > cachedProcessLimit) { //超过门限时, 直接kill掉 app.kill(" cached #" + numCached, true); } break; case ActivityManager.PROCESS_STATE_CACHED_EMPTY: //更新empty进程的数量//超过trim门限, 同时empty进程存活时间大于30min时, 被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+ + ; //empty进程的数量超过门限后, kill掉 if (numEmpty > emptyProcessLimit) { app.kill(" empty #" + numEmpty, true); } } break; default: //更新其它进程的数量 mNumNonCachedProcs+ + ; break; }//独立进程中没有服务时, 直接kill掉 if (app.isolated & & app.services.size() < = 0) { // If this is an isolated process, and there are no // services running in it, then the process is no longer // needed.We agressively kill these because we can by // definition not re-use the same process again, and it is // good to avoid having whatever code was running in them // left sitting around after no longer needed. app.kill(" isolated not needed" , true); } else { // Keeping this process, update its uid. final UidRecord uidRec = app.uidRecord; //初始时, reset过, 值为PROCESS_STATE_CACHED_EMPTY //这个值越小, 说明uid含有的进程越重要, 最小值为PROCESS_STATE_PERSISTENT if (uidRec != null & & uidRec.curProcState > app.curProcState) { uidRec.curProcState = app.curProcState; } }//home本身就是个后台进程, 若当前进程状态大于home //则该进程是个不重要的后台进程, 或empty进程 if (app.curProcState > = ActivityManager.PROCESS_STATE_HOME & & !app.killedByAm) { numTrimming+ + ; } } } ................

updateOomAdjLocked第二部分没有让我们失望, 可谓是“杀伐果断”。
从上面的代码我们可以看出:
1、该部分代码, 将逆序处理LRU中的每一个进程。
我们可以看到, 当某类进程的数量超过门限时, 将被kill掉。
由于是逆序处理LRU中的进程, 因此不重要的进程( 使用较少、较老) 将先被kill掉。
2、利用computeOomAdjLocked函数, 计算每个进程的oom_adj。
从代码来看, 对于cached process而言, computeOomAdjLocked可能无法计算出其oom_adj,
因此这类进程被单独处理。
computeOomAdjLocked函数较长, 需要单独用一篇博客介绍。
3、上面的代码证明了我们之前的分析:
后台进程和empty进程, 在CACHED_APP_MIN_ADJ和CACHED_APP_MAX_ADJ混合分布。
这段区间被划分为不同的slot, 前一个slot中的位置分配完毕后, 才会分配后一个slot。
由于后一个slot的oom_adj比较大, 将被优先kill掉, 再次和LRU的定义结合起来了。
4、调用applyOomAdjLocked函数, 更新进程相关的信息。
5、对于“隔离”的进程, Android的处理比较严格。
若其中没有运行服务, 则直接kill掉。
此外, 一个用户组的重要性, 由其中最重要的进程决定。
这也符合我们的常识。
6、最后, 该部分代码统计了重要性小于home的后台进程数量。
后面的代码将使用该变量。
这一部分代码的流程基本如下图所示:
Android 7.0 ActivityManagerService 进程管理相关流程分析

文章图片

3 updateOomAdjLocked Part-III
从之前的代码, 我们知道了updateOomAdjLocked的第二部分负责更新进程的oom_adj值,
这些值最终将决定进程何时被LMK kill掉。
同时, 第二部分还会在进程数量超过门限等情况下, 主动kill掉一些进程。
【Android 7.0 ActivityManagerService 进程管理相关流程分析】与第二部分不同的是, 在updateOomAdjLocked的第三部分主要是在不kill进程的前提下,
尽可能地主动回收进程的一些内存。
.......... //computeOomAdjLocked函数中, 更新了mNewNumServiceProcs的值 //将其保存到mNumServiceProcs中 mNumServiceProcs = mNewNumServiceProcs; // 以下代码用于计算内存回收等级 // Now determine the memory trimming level of background processes. // Unfortunately we need to start at the back of the list to do this // properly.We only do this if the number of background apps we // are managing to keep around is less than half the maximum we desire; // if we are keeping a good number around, we' ll let them use whatever // memory they want. // 得到当前后台进程和empty进程的数量 final int numCachedAndEmpty = numCached + numEmpty; // memFactor将用于保存内存回收等级 int memFactor; //后台进程数量小于5, 并且empty进程数量小于8时 if (numCached < = ProcessList.TRIM_CACHED_APPS & & numEmpty < = ProcessList.TRIM_EMPTY_APPS) {//总数小于3时, 内存回收等级为critical if (numCachedAndEmpty < = ProcessList.TRIM_CRITICAL_THRESHOLD) { memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL; //总数小于5时, 内存回收等级为low } else if (numCachedAndEmpty < = ProcessList.TRIM_LOW_THRESHOLD) { memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW; //否则内存回收等级为moderate } else { memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE; } } else { //后台和empty进程足够时, 内存回收等级为normal memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL; }//从上面的代码, 我们可以看出当前后台进程和empty进程数量越少时, 内存的回收等级越高 //个人觉得这么设计的原因是: //在内存足够的情况下, 即当后台进程和empty进程的数量没有超过规定门限时, //系统不会主动去kill掉后台进程和empty进程。 //当LMK察觉到内存不够用时, 才会去主动kill掉进程( 优先kill掉后台进程和empty进程) //因此, 当系统检查到empty和后台进程数量较少时, 就推断出内存不够了// We always allow the memory level to go up (better).We only allow it to go // down if we are in a state where that is allowed, *and* the total number of processes // has gone down since last time. .......... //根据条件判断, 是否需要修改memFactor ( 见注释) //一般情况下, 内存回收等级变高时(即允许尽可能多地回收), 不允许主动降低它 //但mAllowLowerMemLevel为false, 或进程数量变多时, 可以降低 if (memFactor > mLastMemoryLevel) { if (!mAllowLowerMemLevel || mLruProcesses.size() > = mLastNumProcesses) { memFactor = mLastMemoryLevel; ........... } } .......... //保存变量 mLastMemoryLevel = memFactor; mLastNumProcesses = mLruProcesses.size(); //memFactor保存到mProcessStats中, 与之前不等时, 返回true //即内存回收等级与之前不一致时, 返回true boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now); //记录ProcessStats状态 final int trackerMemFactor = mProcessStats.getMemFactorLocked(); //内存状态不等于normal, 表示所有进程都要进行内存回收工作 if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) { if (mLowRamStartTime = = 0) { mLowRamStartTime = now; } int step = 0; //根据内存回收等级, 得到对应的fgTrimLevel (即前台进程的内存回收等级) //ComponentCallbacks2中定义的回收等级, 值越大, 越是会尽可能的回收 int fgTrimLevel; switch (memFactor) { case ProcessStats.ADJ_MEM_FACTOR_CRITICAL: fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL; break; case ProcessStats.ADJ_MEM_FACTOR_LOW: fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; break; default: fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE; break; }//前面已经分析过, numTimming中记录的是重要性低于home的后台进程数量 int factor = numTrimming/3; //决定factor的值 //与之前划分slot的思想相似, factor代表每个slot可以分配进程的数量 int minFactor = 2; if (mHomeProcess != null) minFactor+ + ; if (mPreviousProcess != null) minFactor+ + ; if (factor < minFactor) factor = minFactor; //初始level为TRIM_MEMORY_COMPLETE (回收的最高等级) int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; //开始逆序处理LRU中的每一个进程 // 对应重要性大于home的进程而言, 重要性越高, 内存回收等级越低 // 对于重要性小于home的进程, 排在LRU表越靠后, 即越重要回收等级越高 // 这么安排的理由有两个: 1、此时越不重要的进程, 其中运行的组件越少, 能够回收的内存不多, 不需要高回收等级 // 2、越不重要的进程越有可能被LMK kill掉, 没必要以高等级回收内存 for (int i= N-1; i> = 0; i--) { ProcessRecord app = mLruProcesses.get(i); //更新进程信息 if (allChanged || app.procStateChanged) { setProcessTrackerStateLocked(app, trackerMemFactor, now); app.procStateChanged = false; }//处理重要性小于home的进程 if (app.curProcState > = ActivityManager.PROCESS_STATE_HOME & & !app.killedByAm) { if (app.trimMemoryLevel < curLevel & & app.thread != null) { try { ............. //回调ApplicationThread的scheduleTrimMemory函数, 回收内存 // app.thread.scheduleTrimMemory(curLevel); } catch (RemoteException e) { } ........ } app.trimMemoryLevel = curLevel; //更新trimMemoryLevel, LRU中越有排在前面, trimMemroyLevel越低 step+ + ; //一个slot分配满, 开始下一个slot if (step > = factor) { step = 0; switch (curLevel) { case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE; break; case ComponentCallbacks2.TRIM_MEMORY_MODERATE: curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; break; } } } //处理Heavy weight进程 } else if (app.curProcState = = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { //Heavy weight进程的trimLevel小于background时, 才会以background回收 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND & & app.thread != null) { try { ............... app.thread.scheduleTrimMemory( ComponentCallbacks2.TRIM_MEMORY_BACKGROUND); } catch (RemoteException e) { } } //更新 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; } else { //重要性低于等于IMPROTTANT Background的, 以TRIM_MEMORY_UI_HIDDEN等级回收 if ((app.curProcState > = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND || app.systemNoUi) & & app.pendingUiClean) { // If this application is now in the background and it // had done UI, then give it the special trim level to // have it free UI resources. final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; if (app.trimMemoryLevel < level & & app.thread != null) { try { ............ app.thread.scheduleTrimMemory(level); } catch (RemoteException e) { } } app.pendingUiClean = false; }

    推荐阅读