源码基于:Android R
0. 前言
通过之前的两篇博文《lmkd 机制详解》和《oom_adj 内存水位算法剖析》中,根据计算出来的 min_score_adj 选择大于该值的 oom_adj 的进程进行 kill 处理。 oom_adj 随着应用状态的不同其值也是伴随着变化的。
本文将通过源码剖析 oom_adj 更新的原理。
1. adj 概念
Android 系统的设计理念希望应用进程尽可能的长时间的存活,以此来提升用户体验。在Android 中,应用首次打开会比较慢,这个过程包含进程的创建、application 初始化、应用其他逻辑等,所以,在应用退出时并非直接exit 进程或被 kill,而是会存活一段时间,这样就保证在下次启动时跟快启动。
当然,物极必反。在大量应用启动后就会造成内存大量使用,手机性能会随着下降。如果放任所有进程存活,系统内存就会枯竭。因此需要合理的回收机制,Android 中通过 adj 和 process state 两个重要的标准来进行衡量。系统根据进程组建的状态来决定每个进程的优先级adj 值,然后再根据一定的策略选择优先级低的进程kill,以此类推,通过回收预期的系统资源来保证系统的正常运转。
2. adj 等级
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
ADJ 等级 | 取值 | 说明 |
UNKNOWN_ADJ | 1001 | 用于特定地方,一般指将要cache进程,不知道确切值 |
CACHED_APP_MAX_ADJ | 999 | 不可见进程的最大值,进程可以无任何干扰的被杀 |
CACHED_APP_LMK_FIRST_ADJ | 950 | oom_adj 等级第一个允许被杀的level,不能等于CACHED_APP_MAX_ADJ |
CACHED_APP_MIN_ADJ | 900 | 不可见进程的最小值 |
SERVICE_B_ADJ | 800 | B List中的Service(较老的、使用可能性更小) |
PREVIOUS_APP_ADJ | 700 | 上一个App的进程(往往通过按返回键) |
HOME_APP_ADJ | 600 | Home进程 |
SERVICE_ADJ | 500 | app service 进程,杀掉它一般不会有太大的影响 |
HEAVY_WEIGHT_APP_ADJ | 400 | 后台的重量级进程,system/rootdir/init.rc文件中startup |
BACKUP_APP_ADJ | 300 | 备份进程,杀掉它不完全致命,但不好 |
PERCEPTIBLE_LOW_APP_ADJ | 250 | 被用户或系统绑定的进程,比service 要重要,但是如果被杀掉,不会立即影响客户的感官 |
PERCEPTIBLE_APP_ADJ | 200 | 可感知的进程,如后台music 播放 |
VISIBLE_APP_ADJ | 100 | 可视进程 |
PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ | 50 | recently TOP 进程 |
FOREGROUND_APP_ADJ | 0 | 前台进程 |
PERSISTENT_SERVICE_ADJ | -700 | 关联系统的进程或一个常驻进程 |
PERSISTENT_PROC_ADJ | -800 | 系统常驻进程,例如telephony 绝对不想杀,但不完全致命 |
SYSTEM_ADJ | -900 | 系统进程 |
NATIVE_ADJ | -1000 | native 进程,不归系统管理,所以没有oom_adj 适配 |
3. 进程状态
状态等级 | 取值 | 说明 |
PROCESS_STATE_CACHED_EMPTY | 19 | 进程将被cached,且是空进程 |
PROCESS_STATE_CACHED_RECENT | 18 | 进程将被cached,而且有个activity与一个recent task 通信 |
PROCESS_STATE_CACHED_ACTIVITY_CLIENT | 17 | 进程将被cached,而且是另外有activities 的cached进程的client端 |
PROCESS_STATE_CACHED_ACTIVITY | 16 | 进程将被cached,且内涵activities |
PROCESS_STATE_LAST_ACTIVITY | 15 | 后台进程,且拥有上一次显示的Activity |
PROCESS_STATE_HOME | 14 | 后台进程,且拥有home Activity |
PROCESS_STATE_HEAVY_WEIGHT | 13 | 后台进程,但无法执行restore,因此尽量避免kill该进程 |
PROCESS_STATE_TOP_SLEEPING | 12 | 与PROCESS_STATE_TOP一样,但此时设备正处于休眠状态 |
PROCESS_STATE_RECEIVER | 11 | 后台进程,且正在运行receiver |
PROCESS_STATE_SERVICE | 10 | 后台进程,且正在运行service |
PROCESS_STATE_BACKUP | 9 | 后台进程,正在运行backup/restore操作 |
PROCESS_STATE_TRANSIENT_BACKGROUND | 8 | 短暂的后台进程,需要keep running |
PROCESS_STATE_IMPORTANT_BACKGROUND | 7 | 对用户重要的进程,但并不能感知到 |
PROCESS_STATE_IMPORTANT_FOREGROUND | 6 | 对用户重要的进程,且可以感知到 |
PROCESS_STATE_BOUND_FOREGROUND_SERVICE | 5 | 进程拥有一个前台Service,且由系统绑定 |
PROCESS_STATE_FOREGROUND_SERVICE | 4 | 进程拥有一个前台service |
PROCESS_STATE_BOUND_TOP | 3 | 被绑定为TOP app 的进程 |
PROCESS_STATE_TOP | 2 | 进程拥有当前top activities,对于用户是可见的 |
PROCESS_STATE_PERSISTENT_UI | 1 | 进程为persisent 系统进程,且doing UI |
PROCESS_STATE_PERSISTENT | 0 | 常驻的系统进程 |
4. 3个核心函数
oom_adj 涉及三个重要函数:
updateOomAdjLocked()
:更新adj,当目标进程为空,或者被杀则返回false;否则返回true;computeOomAdjLocked()
:计算adj,返回计算后RawAdj值;applyOomAdjLocked()
:应用adj,当需要杀掉目标进程则返回 false;否则返回true。
其中 computeOomAdjLocked() 和 applyOomAdjLocked() 都是在 updateOomAdjLocked() 中调用到,代码位于 frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java 中。
当四大组件状态改变时会通过 updateOomAdjLocked() 来同步更新相应进程的 ADJ 优先级。需要注意的是,当同一个进程有多个决定其优先级的组件状态时,取优先级最高的 ADJ 作为最终的 ADJ。另外,进程会通过设置 maxAdj 来限定ADJ 的上限。
5. updateOomAdjLocked() 简析
在上一节中我们得知 oom_adj 涉及三个重要的函数,源头都是 updateOomAdjLocked(),在详细剖析该函数之前先来了解下。
首先该接口的源头都位于 AMS 中,在AMS 中提供了三个接口:
frameworks/base/services/core/java/com/android/server/am/AMS.java
final void updateOomAdjLocked(String oomAdjReason) {
mOomAdjuster.updateOomAdjLocked(oomAdjReason);
}
final void updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
}
final boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll,
String oomAdjReason) {
return mOomAdjuster.updateOomAdjLocked(app, oomAdjAll, oomAdjReason);
}
AMS 中提供的三个接口分别对应 OomAdjuster 中的三个接口,四大组件在更新 ADJ 时都是通过这里的接口。
6. ADJ 更新时机
6.1 activity 中更新 oom_adj
- ASS.realStartActivityLocked():启动Activity
- AS.resumeTopActivityInnerLocked():恢复栈顶Activity
- AS.finishCurrentActivityLocked():结束当前Activity
- AS.destroyActivityLocked():摧毁当前Activity
6.2 service 中更新 oom_adj
- ActiveServices.realStartServiceLocked():启动服务
- ActiveServices.bindServiceLocked():绑定服务(只更新当前app)
- ActiveServices.unbindServiceLocked():解绑服务 (只更新当前app)
- ActiveServices.bringDownServiceLocked():结束服务 (只更新当前app)
- ActiveServices.sendServiceArgsLocked():在bringup或则cleanup服务过程调用 (只更新当前app)
6.3 broadcast 中更新 oom_adj
- BQ.processNextBroadcast():处理下一个广播
- BQ.processCurBroadcastLocked():处理当前广播
- BQ.deliverToRegisteredReceiverLocked():分发已注册的广播 (只更新当前app)
6.4 ContentProvider 中更新 oom_adj
- AMS.removeContentProvider():移除provider
- AMS.publishContentProviders():发布provider (只更新当前app)
- AMS.getContentProviderImpl():获取provider (只更新当前app)
6.5 Process相关
- AMS.setSystemProcess():创建并设置系统进程
- AMS.addAppLocked():创建persistent进程
- AMS.attachApplicationLocked():进程创建后attach到system_server的过程;
- AMS.trimApplications():清除没有使用app
- AMS.appDiedLocked():进程死亡
- AMS.killAllBackgroundProcesses():杀死所有后台进程.即(ADJ>9或removed=true的普通进程)
- AMS.killPackageProcessesLocked():以包名的形式 杀掉相关进程
7. updateOomAdjLocked() 一参
AMS 中一个参数的更新最终会调用到 OomAdjuster.java 中:
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
void updateOomAdjLocked(String oomAdjReason) {
// 前台的app(若无app 处于前台则是TASK栈栈顶的应用)
final ProcessRecord topApp = mService.getTopAppLocked();
// 一参方法最终调用这里
updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true, true);
}
参数是 oomAdjReason,定义在 OomAdjuster.java 文件最开始的地方:
static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
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";
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";
一参的 updateOomAdjLocked() 最终调用的是 updateOomAdjLockedInner(),就是更新 LRU list (所有由 AMS 启动的进程都会保存在这里)中所有的 process 的 oom adj,并且对 cached 进程和 empty进程进行处理,详细看下文第 11 节。
8. updateOomAdjLocked() 二参
在了解完 updateOomAdjLocked() 一参的流程之后,二参函数应该会简单些。相比于一参的函数,这里多了一个参数 app,这个是指定一个进程。该函数用以更新指定进程以及所有绑定(直接/间接)的其他进程的adj。如果该进程中拥有service 或content provider,则其client进程的procState将不会被重新评估。
/*更新指定进程的 adj 等值,如果参数app为null,表示更新所有LRU 进程*/
boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
// 如果传入的app 为null,表示全部 LRU 进程都更新
if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
updateOomAdjLocked(oomAdjReason);
return true;
}
// 从 AMS 中获取topApp
final ProcessRecord topApp = mService.getTopAppLocked();
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
mService.mOomAdjProfiler.oomAdjStarted();
// 用于标识 oom_adj 分配周期的id
// 每次 updateOomAdjLocked() 函数调用都会有 mAdjSeq 序号,用以与进程adjSeq对比
// 用以确认进程是否已经处理
mAdjSeq++;
// 第一步,更新进程自己
// 确认是否处于 cached状态
final boolean wasCached = app.isCached();
// 获取当前 unlimit的adj
final int oldAdj = app.getCurRawAdj();
// 进而确认cached adj
final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ
? oldAdj : ProcessList.UNKNOWN_ADJ;
final boolean wasBackground = ActivityManager.isProcStateBackground(app.setProcState);
app.containsCycle = false;
app.procStateChanged = false;
app.resetCachedInfo();
// 调用 5参的函数,更新adj
boolean success = updateOomAdjLocked(app, cachedAdj, topApp, false,
SystemClock.uptimeMillis());
// 是cached 进程并且background状态未变,但没有5参更新成功(进程被kill了)
if (!success || (wasCached == app.isCached() && oldAdj != ProcessList.INVALID_ADJ
&& wasBackground == ActivityManager.isProcStateBackground(app.setProcState))) {
// Okay, it's unchanged, it won't impact any service it binds to, we're done here.
if (DEBUG_OOM_ADJ) {
Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app);
}
mService.mOomAdjProfiler.oomAdjEnded();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return success; // 返回失败
}
//第二步:找到所有的reachable进程, 更新reachable进程
ArrayList<ProcessRecord> processes = mTmpProcessList;
ActiveUids uids = mTmpUidRecords;
//mTmpQueue:大小是两倍的 CUR_MAX_CACHED_PROCESSES = 32
ArrayDeque<ProcessRecord> queue = mTmpQueue;
processes.clear();
uids.clear();
queue.clear();
// Track if any of them reachables could include a cycle
boolean containsCycle = false;
// Scan downstreams of the process record
app.mReachable = true;
// 循环遍历reachable的进程,其实就是遍历有关联的service和provider
// 第一个for循环执行的是app,此时queue为空,第一个for循环将app的所有相关联service和provider都加入到queue中
// 之后的for循环就是遍历queue,即遍历reachable进程
// poll:检索并移除队列的头部
for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
if (pr != app) {
processes.add(pr);
}
if (pr.uidRecord != null) {
uids.put(pr.uidRecord.uid, pr.uidRecord);
}
// 有连接相关的进程
for (int i = pr.connections.size() - 1; i >= 0; i--) {
ConnectionRecord cr = pr.connections.valueAt(i);
ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
? cr.binding.service.isolatedProc : cr.binding.service.app;
if (service == null || service == pr) {
continue;
}
containsCycle |= service.mReachable;
if (service.mReachable) {
continue;
}
// BIND_WAIVE_PRIORITY: 不会影响服务的进程优先级,像通用的应用进程一样将服务放在一个LRU表中
if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
| Context.BIND_TREAT_LIKE_ACTIVITY
| Context.BIND_ADJUST_WITH_ACTIVITY))
== Context.BIND_WAIVE_PRIORITY) {
continue;
}
// 加入队列尾部
queue.offer(service);
service.mReachable = true;
}
for (int i = pr.conProviders.size() - 1; i >= 0; i--) {
ContentProviderConnection cpc = pr.conProviders.get(i);
ProcessRecord provider = cpc.provider.proc;
if (provider == null || provider == pr || (containsCycle |= provider.mReachable)) {
continue;
}
containsCycle |= provider.mReachable;
if (provider.mReachable) {
continue;
}
queue.offer(provider);
provider.mReachable = true;
}
}
// Reset the flag
app.mReachable = false;
int size = processes.size();
if (size > 0) {
// Reverse the process list, since the updateOomAdjLockedInner scans from the end of it.
for (int l = 0, r = size - 1; l < r; l++, r--) {
ProcessRecord t = processes.get(l);
processes.set(l, processes.get(r));
processes.set(r, t);
}
mAdjSeq--;
// 更新传入的进程列表,然后通过 updateOomAdjLockedInner()来更新这些进程
updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, containsCycle, false);
} else if (app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
// In case the app goes from non-cached to cached but it doesn't have other reachable
// processes, its adj could be still unknown as of now, assign one.
processes.add(app);
assignCachedAdjIfNecessary(processes);
applyOomAdjLocked(app, false, SystemClock.uptimeMillis(),
SystemClock.elapsedRealtime());
}
//统计系统进入计算OomAdj的起始和结束时间,最后计算出OomAdj的运行时间
// mOomAdjProfiler 这个类应该是用来统计所有OomAdj信息的,在AMS中有定义实例
mService.mOomAdjProfiler.oomAdjEnded();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return true;
}
9. updateOomAdjLocked() 三参
三参的函数比较简单,相比于二参函数,多了一个参数 oomAdjAll。如果该值为true,则与二参的流程一样;如果该值为 false,则直接调用五参函数进行直接更新。
boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll,
String oomAdjReason) {
if (oomAdjAll && mConstants.OOMADJ_UPDATE_QUICK) {
return updateOomAdjLocked(app, oomAdjReason);
}
final ProcessRecord TOP_APP = mService.getTopAppLocked();
final boolean wasCached = app.isCached();
mAdjSeq++;
// This is the desired cached adjusment we want to tell it to use.
// If our app is currently cached, we know it, and that is it. Otherwise,
// we don't know it yet, and it needs to now be cached we will then
// need to do a complete oom adj.
final int cachedAdj = app.getCurRawAdj() >= ProcessList.CACHED_APP_MIN_ADJ
? app.getCurRawAdj() : ProcessList.UNKNOWN_ADJ;
boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
SystemClock.uptimeMillis());
if (oomAdjAll
&& (wasCached != app.isCached() || app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ)) {
// Changed to/from cached state, so apps after it in the LRU
// list may also be changed.
updateOomAdjLocked(oomAdjReason);
}
return success;
}
10. updateOomAdjLocked() 五参
该函数是private 函数,会被二参函数和三参的函数调用,该函数只是更新某一个特定进程以及其关联进程,按照逻辑看参数doingAll 都被置为false。
private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord TOP_APP, boolean doingAll, long now) {
if (app.thread == null) {
return false;
}
// 重置cached info
app.resetCachedInfo();
// 获取进程所在用户组的整体状态,UidRecord用于记录某个用户组中进程的运行状态
UidRecord uidRec = app.uidRecord;
if (uidRec != null) {
if (DEBUG_UID_OBSERVERS) {
Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
}
uidRec.reset();
}
// 计算进程相关的adj,最后参数为true,即把client 进程也计算
computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false, true);
// 应用adj
boolean success = applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
// 更新UidRecord
if (uidRec != null) {
// After uidRec.reset() above, for UidRecord that has multiple processes (ProcessRecord)
// , We need to apply all ProcessRecord into UidRecord.
final ArraySet<ProcessRecord> procRecords = app.uidRecord.procRecords;
for (int i = procRecords.size() - 1; i >= 0; i--) {
final ProcessRecord pr = procRecords.valueAt(i);
if (!pr.killedByAm && pr.thread != null) {
if (pr.isolated && pr.numberOfRunningServices() <= 0
&& pr.isolatedEntryPoint == null) {
// No op.
} else {
// Keeping this process, update its uid.
updateAppUidRecLocked(pr);
}
}
}
if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
&& (uidRec.setProcState != uidRec.getCurProcState()
|| uidRec.setCapability != uidRec.curCapability
|| uidRec.setWhitelist != uidRec.curWhitelist)) {
ActiveUids uids = mTmpUidRecords;
uids.clear();
uids.put(uidRec.uid, uidRec);
updateUidsLocked(uids, now);
mProcessList.incrementProcStateSeqAndNotifyAppsLocked(uids);
}
}
return success;
}
主要调用 computeOomAdjLocked() 和 applyOomAdjLocked(),详细可以查看《更新原理(二)》
11. updateOomAdjLockedInner()
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
boolean startProfiling) {
if (startProfiling) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
mService.mOomAdjProfiler.oomAdjStarted();
}
final long now = SystemClock.uptimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
// 这里有个30mins的限制,如果activity 30分钟内没有活跃,后面会被kill掉
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
final boolean fullUpdate = processes == null;
ActiveUids activeUids = uids;
// 确定是否使用参数中传入的进程list,如果参数为NULL,则使用LRU processes
ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.mLruProcesses
: processes;
final int numProc = activeProcesses.size();
// 确认传入的uid是否为NULL,如果是则用 mActiveUids初始化
if (activeUids == null) {
final int numUids = mActiveUids.size();
activeUids = mTmpUidRecords;
activeUids.clear();
for (int i = 0; i < numUids; i++) {
UidRecord r = mActiveUids.valueAt(i);
activeUids.put(r.uid, r);
}
}
// 重置用户组中所有进程的状态
for (int i = activeUids.size() - 1; i >= 0; i--) {
final UidRecord uidRec = activeUids.valueAt(i);
if (DEBUG_UID_OBSERVERS) {
Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
}
uidRec.reset();
}
if (mService.mAtmInternal != null) {
mService.mAtmInternal.rankTaskLayersIfNeeded();
}
// 用于标识 oom_adj 分配周期的id
// 每次 updateOomAdjLocked() 函数调用都会有 mAdjSeq 序号,用以与进程adjSeq对比
// 用以确认进程是否已经处理
mAdjSeq++;
if (fullUpdate) {
mNewNumServiceProcs = 0;
mNewNumAServiceProcs = 0;
}
boolean retryCycles = false;
boolean computeClients = fullUpdate || potentialCycles;
// 先进行一些 reset 工作
for (int i = numProc - 1; i >= 0; i--) {
ProcessRecord app = activeProcesses.get(i);
//所有进程的reachable都改为false
app.mReachable = false;
// app.adjSeq会记录进程上一次的更新序号,如果已经评估过,后面就不会在计算
if (app.adjSeq != mAdjSeq) {
app.containsCycle = false;
//设为 empty 进程
app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
//adj 设为UNKNOWN_ADJ
app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
app.setCapability = PROCESS_CAPABILITY_NONE;
app.resetCachedInfo();
}
}
// 进入compute 阶段
for (int i = numProc - 1; i >= 0; i--) {
ProcessRecord app = activeProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
computeClients); // It won't enter cycle if not computing clients.
// if any app encountered a cycle, we need to perform an additional loop later
retryCycles |= app.containsCycle;
// Keep the completedAdjSeq to up to date.
app.completedAdjSeq = mAdjSeq;
}
}
//将 cache 进程和 empty 进程均匀分散到slot中去
assignCachedAdjIfNecessary(mProcessList.mLruProcesses);
//是否需要计算进程绑定的client的adj,同时一参调用是需要计算的
if (computeClients) { // There won't be cycles if we didn't compute clients above.
// Cycle strategy:
// - Retry computing any process that has encountered a cycle.
// - Continue retrying until no process was promoted.
// - Iterate from least important to most important.
int cycleCount = 0;
while (retryCycles && cycleCount < 10) {
cycleCount++;
retryCycles = false;
for (int i = 0; i < numProc; i++) {
ProcessRecord app = activeProcesses.get(i);
if (!app.killedByAm && app.thread != null && app.containsCycle) {
app.adjSeq--;
app.completedAdjSeq--;
}
}
for (int i = 0; i < numProc; i++) {
ProcessRecord app = activeProcesses.get(i);
if (!app.killedByAm && app.thread != null && app.containsCycle) {
if (computeOomAdjLocked(app, app.getCurRawAdj(), topApp, true, now,
true, true)) {
retryCycles = true;
}
}
}
}
}
// 非cached或empty进程数置0
mNumNonCachedProcs = 0;
// cached hidden进程数置0
mNumCachedHiddenProcs = 0;
// 杀掉超过限额的empty进程和cached进程,这个函数很重要
boolean allChanged = updateAndTrimProcessLocked(now, nowElapsed, oldTime, activeUids);
mNumServiceProcs = mNewNumServiceProcs;
if (mService.mAlwaysFinishActivities) {
// Need to do this on its own message because the stack may not
// be in a consistent state at this point.
mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
}
if (allChanged) {
mService.requestPssAllProcsLocked(now, false,
mService.mProcessStats.isMemFactorLowered());
}
updateUidsLocked(activeUids, nowElapsed);
if (mService.mProcessStats.shouldWriteNowLocked(now)) {
mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
mService.mProcessStats));
}
// Run this after making sure all procstates are updated.
mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
if (DEBUG_OOM_ADJ) {
final long duration = SystemClock.uptimeMillis() - now;
if (false) {
Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
new RuntimeException("here").fillInStackTrace());
} else {
Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
}
}
if (startProfiling) {
mService.mOomAdjProfiler.oomAdjEnded();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
11.1 assignCachedAdjIfNecessary()
/*
*该函数是将lru list中的cache的进程按照一定的跨距逐个分配到[CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ]区间中
*根据proc_state为empty和其他cached,对其进行分配
*/
private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
final int numLru = lruList.size();
// 首先,根据进程当前状态为每个进程更新oom 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);
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
- emptyProcessLimit;
//计算出槽的数量,再将cache进程和empty进程分别平均分配到这些槽中(slots)
// CACHED_APP_MIN_ADJ ~ CACHED_APP_MAX_ADJ 之间交错分配cached和empty进程
// mNumNonCachedProcs 是除cached进程外的进程数,mNumCachedHiddenProcs是cached进程个数
int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
if (numEmptyProcs > cachedProcessLimit) { //空进程数大于cache进程阈值
//确保低内存杀进程的时候以杀empty为主,尽可能保留cache
numEmptyProcs = cachedProcessLimit;
}
//cachedFactor和emptyFactor分别表示每个slot中包括的进程个数
int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
/ mNumSlots;
if (cachedFactor < 1) cachedFactor = 1;
int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
if (emptyFactor < 1) emptyFactor = 1;
int stepCached = -1;
int stepEmpty = -1;
int lastCachedGroup = 0;
int lastCachedGroupImportance = 0;
int lastCachedGroupUid = 0;
//遍历lru列表,为每一个app进程更新cache状态
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
// If we haven't yet assigned the final cached adj
// to the process, do that now.
if (!app.killedByAm && app.thread != null && app.curAdj
>= ProcessList.UNKNOWN_ADJ) {
switch (app.getCurProcState()) { //三种非empty cache进程
case PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
case ActivityManager.PROCESS_STATE_CACHED_RECENT:
// Figure out the next cached level, taking into account groups.
boolean inGroup = false;
if (app.connectionGroup != 0) {
if (lastCachedGroupUid == app.uid
&& lastCachedGroup == app.connectionGroup) {
// This is in the same group as the last process, just tweak
// adjustment by importance.
if (app.connectionImportance > lastCachedGroupImportance) {
lastCachedGroupImportance = app.connectionImportance;
if (curCachedAdj < nextCachedAdj
&& curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
curCachedImpAdj++;
}
}
inGroup = true;
} else {
lastCachedGroupUid = app.uid;
lastCachedGroup = app.connectionGroup;
lastCachedGroupImportance = app.connectionImportance;
}
}
//当前slot数大于factor,分配下一个slot,更新cur和next的cachedadj
if (!inGroup && curCachedAdj != nextCachedAdj) {
stepCached++;
curCachedImpAdj = 0;
if (stepCached >= cachedFactor) {
stepCached = 0;
curCachedAdj = nextCachedAdj;
nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
// This process is a cached process holding activities...
// assign it the next cached value for that type, and then
// step that cached level.
app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
if (DEBUG_LRU) {
Slog.d(TAG_LRU, "Assigning activity LRU #" + i
+ " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
+ " curCachedImpAdj=" + curCachedImpAdj + ")");
}
break;
default: //empty进程
// Figure out the next cached level.
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;
}
}
}
// 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.setCurRawAdj(curEmptyAdj);
app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
if (DEBUG_LRU) {
Slog.d(TAG_LRU, "Assigning empty LRU #" + i
+ " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
+ ")");
}
break;
}
}
}
}
AMS将所有cache和empty按照一定的机制均分到[900,999]区间中;在这个区间中,每一个分配给cache/empty进程的adj值都被称为一个槽点(slot),实际上是将LRU列表中的所有cache进程按照一定的跨距均分到这些槽点中;
在这个机制里面,cache进程的adj分配起点为900,而empty进程的分配起点为905,两者都是以跨距为10进行均匀分配的;这样就能够将empty进程和cache进程分开,彼此间隔相同的距离。当内存不足时,lmkd进程就会从adj最大值开始,逐步往下查杀进程,不会出现集体被杀或者都不被杀导致内存占用过高的问题。
注意:
临时变量 emptyProcessLimit 记录系统中empty进程的最大值,通常为 cached 最大值的一半,即默认值为32/2 = 16;
临时变量 cachedProcessLimit 记录系统中cached 进程的最大值,即mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit,CUR_MAX_CACHED_PROCESSES 默认为32,减去 emptyProcessLimit,剩余也是16个;
11.2 updateAndTrimProcessLocked()
private boolean updateAndTrimProcessLocked(final long now, final long nowElapsed,
final long oldTime, final ActiveUids activeUids) {
ArrayList<ProcessRecord> lruList = mProcessList.mLruProcesses;
final int numLru = lruList.size();
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
- emptyProcessLimit;
int lastCachedGroup = 0;
int lastCachedGroupUid = 0;
int numCached = 0;
int numCachedExtraGroup = 0;
int numEmpty = 0;
int numTrimming = 0;
/*******针对 B service 优化的地方 1*******/
ProcessRecord selectedAppRecord = null;
long serviceLastActivity = 0;
int numBServices = 0;
/*******针对 B service 优化的地方 1 end*******/
// 反向遍历 LRU
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
/*******针对 B service 优化的地方 2*******/
if (mEnableBServicePropagation && app.serviceb
&& (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
numBServices++;
// 遍历正在运行的服务
for (int s = app.numberOfRunningServices() - 1; s >= 0; s--) {
ServiceRecord sr = app.getRunningServiceAt(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);
// 当前时间与上一次activity运行该服务的时间差,lastActivity在创建services时更新
// mMinBServiceAgingTime = 5000ms,B_service的最小老化时间阈值
if (SystemClock.uptimeMillis() - sr.lastActivity
< mMinBServiceAgingTime) {
if (DEBUG_OOM_ADJ) {
Slog.d(TAG,"Not aged enough!!!");
}
continue;
}
// 更新距上一次运行service 的时间最久的app
// 当进程为 B_service,在B_service进程数超过阈值(5个)时,
// 如果该进程相关联的service 中,有最久未被调用的service,则将该进程设置
// 为SelectedAppRecord,将其adj设置为800,lmkd中存储的是900
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);
/*******针对 B service 优化的地方 2 end*******/
if (!app.killedByAm && app.thread != null) {
// 不需要为没有计算的进程应用更新
if (app.completedAdjSeq == mAdjSeq) {
applyOomAdjLocked(app, true, now, nowElapsed);
}
// 根据procState 确定进程类型数量
switch (app.getCurProcState()) {
case PROCESS_STATE_CACHED_ACTIVITY: //处理cached 且函数activity的进程
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
mNumCachedHiddenProcs++; //统计cached进程个数
numCached++;
if (app.connectionGroup != 0) {
if (lastCachedGroupUid == app.info.uid
&& lastCachedGroup == app.connectionGroup) {
// 如果与上一个进程同一个进程组,
// 不希望它与cached 进程数量限制相冲突,只是
// 额外增加group count来统计
numCachedExtraGroup++;
} else {
lastCachedGroupUid = app.info.uid;
lastCachedGroup = app.connectionGroup;
}
} else {
lastCachedGroupUid = lastCachedGroup = 0;
}
// 除掉额外计数的cached进程,扔超过limit的,kill
if ((numCached - numCachedExtraGroup) > cachedProcessLimit) {
app.kill("cached #" + numCached,
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
true);
}
break;
case PROCESS_STATE_CACHED_EMPTY: //处理被cached 的empty进程
//当empty进程超过CUR_TRIM_EMPTY_PROCESSES(默认8个),
// 并且activity上次活跃超过了30min,kill
if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
&& app.lastActivityTime < oldTime) {
app.kill("empty for "
+ ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
/ 1000) + "s",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TRIM_EMPTY,
true);
} else {
numEmpty++;
// empty 进程中activity虽然没有超过30min,但总的数量超过了16(默认值),kill
if (numEmpty > emptyProcessLimit) {
app.kill("empty #" + numEmpty,
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
true);
}
}
break;
default:
mNumNonCachedProcs++;
break;
}
// 如果该进程是isolated,其中没有运行service,并且它不是具有自定义入口点的特殊
// 进程,那么该进程就不再需要了。
// 我们强烈地杀掉这些进程因为我们可以根据定义不再重复使用相同的进程,这样能够很好
// 地避免在不再需要的情况下让代码中的任何代码在它们中运行。
if (app.isolated && app.numberOfRunningServices() <= 0
&& app.isolatedEntryPoint == null) {
// If this is an isolated process, there are no services
// running in it, and it's not a special process with a
// custom entry point, 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", ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
} else {
// 否则就保留这些进程,
//更新进程的 uidRecord
updateAppUidRecLocked(app);
}
if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
numTrimming++;
}
}
}
/*******针对 B service 优化的地方 3*******/
// 当B_Service 的数量超过上面(mBServiceAppThreshold=5),
// 且mAllowLowerMemLevel 为true,即为低内存lmkd 杀过进程
if ((numBServices > mBServiceAppThreshold) && (true == mService.mAllowLowerMemLevel)
&& (selectedAppRecord != null)) {
// setOomAdj() 方法是将更新后的 adj通知给 lmkd
ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
ProcessList.CACHED_APP_MAX_ADJ);
//将最久没运行过的appRecord的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");
}
/*******针对 B service 优化的地方 3 end*******/
mProcessList.incrementProcStateSeqAndNotifyAppsLocked(activeUids);
//本方法根据cached和empty进程的数量,确定 memFactor;根据memFactor是否为NORMAL等级分别进行处理
return mService.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
}
updateAndTrimProcessLocked() 包含了很多 app.kill() 方法,是 AMS 除了lmkd 之外的一个查杀进程机制。该函数中遍历 LRU 列表,分别统计 cached 和 empty 进程,并进行trim 处理。对超过限定的 cached 和 empty 进程进行查杀,回收内存。
其中临时变量 emptyProcessLimit 和 cachedProcessLimit 分别记录empty 进程和 cached 进程个数的上限,同 assignCachedAdjIfNecessary() 函数中,这里两个值默认都是 16.
另外,该函数中在源生的基础上添加了针对 B_services 优化点,共 3 处,如代码中的注释。其中涉及到的变量mMinBServiceAgingTime、mBServiceAppThreshold、mEnableBServicePropagation 都是在 OomAdjuster.java 中定义的成员变量。详细的patch,可以下载。
11.2.1 updateLowMemStateLocked()
frameworks/base/services/core/java/com/android/server/am/AMS.java
/**
*本方法根据cached和empty进程的数量,确定 memFactor;根据memFactor是否为NORMAL等级分别进行处理
* 1、非NORMAL:将memFactor转换为trim level等级,根据当前进程的进程级别分等级处理,确定最新的trim level
* 2、NORMAL:对于重要性比IMPORTANT_BACKGROUND小或没有运行UI的system进程,关闭其从showing UI回收内存的权利,并且将trimlevel提升到不低于UI_HIDDEN
*/
final boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) {
final int N = mProcessList.getLruSizeLocked();//lru大小
final long now = SystemClock.uptimeMillis();
//内存因子,值越大,级别越高,内存资源越紧张
int memFactor;
if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
//获取memfactor,此函数根据PSI event返回对应的内存因子级别,通过监听/proc/pressure/memory实现
// waitforPressure方法是一个jni调用
memFactor = mLowMemDetector.getMemFactor();
} else {
// R上不在使用
// 根据cache进程和empty进程的个数得出memfactor,memfactor越大,内存压力越大
if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES//32/6=5
&& numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {//8
final int numCachedAndEmpty = numCached + numEmpty;
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {//3
memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {//5
memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
}
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
}
}
// 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.
if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
+ " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
+ " numProcs=" + mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses);
//现在的等级比之前还高,说明内存紧张,不主动降低等级
if (memFactor > mLastMemoryLevel) {
//当不允许LowerMemLevel或者LRU进程数有增加时,可以降低等级
if (!mAllowLowerMemLevel || mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
memFactor = mLastMemoryLevel;
if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
}
}
//内存因子更新了
if (memFactor != mLastMemoryLevel) {
EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
}
//更新最近一次memorylevel的等级
mLastMemoryLevel = memFactor;
mLastNumProcesses = mProcessList.getLruSizeLocked();
//将内存等级保存到processstats中,如果与之前不等(更新了),返回true
boolean allChanged = mProcessStats.setMemFactorLocked(
memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
//更新后获取factor
final int trackerMemFactor = mProcessStats.getMemFactorLocked();
//下面为两个大判断,memFactor 为NORMAL和不为NORMAL两种情况
//memFactor 不等于NORMAL时的处理
if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
if (mLowRamStartTime == 0) {
//进入lowRam状态,记录进入的时间点
mLowRamStartTime = now;
}
int step = 0;
int fgTrimLevel;
//将内存因子memFactor转换为ComponentCallbacks2中定义的变量名,
//就是从memFactor等级转换到 TrimMemlevel
//TrimMemlevel 值越大越容易被回收
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;
}
//factor为每个槽可以容纳的进程数
// 三个LowRam状态各自放多少Trimming进程
int factor = numTrimming/3;
int minFactor = 2;
if (mAtmInternal.getHomeProcess() != null) minFactor++;
if (mAtmInternal.getPreviousProcess() != null) minFactor++;
if (factor < minFactor) factor = minFactor;
//80,最高等级,内存压力最大
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
// 对于重要性大于home的进程而言,重要性越高,内存回收等级越低
// 对于重要性小于home的进程,排在LRU列表越靠后,即越重要回收等级越高
// 这么安排的理由有两个:
// 1、此时越不重要的进程,其中运行的组件越少,能够回收的内存不多,不需要高回收等级
// 2、越不重要的进程越有可能被LMK kill掉,没必要以高等级回收内存
//反向遍历LRU链表
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
setProcessTrackerStateLocked(app, trackerMemFactor, now);
app.procStateChanged = false;
}
//process_state大于等于HOME进程,没HOME这么重要的进程
if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
if (app.trimMemoryLevel < curLevel && app.thread != null) {
try {
//加大内存回收
app.thread.scheduleTrimMemory(curLevel);
} catch (RemoteException e) {
}
}
//调整 trimMemoryLevel 到 curlevel
app.trimMemoryLevel = curLevel;
step++;
//当前factor满了,下一个factor
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;
}
}
} else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
&& !app.killedByAm) {//重量级后台进程
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
&& app.thread != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Trimming memory of heavy-weight " + app.processName
+ " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
//level提到TRIM_MEMORY_BACKGROUND
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
} else {//其他进程级别
//级别大于等于重要的后台进程
if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
|| app.systemNoUi) && app.hasPendingUiClean()) {
// 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.setPendingUiClean(false);
}
if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
try {
//关掉showingUI回收
app.thread.scheduleTrimMemory(fgTrimLevel);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = fgTrimLevel;
}
}
} else { //memFactor == NORMAL时的处理
if (mLowRamStartTime != 0) {
//统计总的LowRam持续时间
mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
//NORMAL状态取消LowRam状态和计时
mLowRamStartTime = 0;
}
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
setProcessTrackerStateLocked(app, trackerMemFactor, now);
app.procStateChanged = false;
}
//当前内存factor是NORMAL,根据当前进程state和trimmemorylevel,
// 关掉showingUI回收(只处理比PROCESS_STATE_IMPORTANT_BACKGROUND不重要的进程)
//PROCESS_STATE_IMPORTANT_BACKGROUND重要的后台进程
// systemNoUi:系统进程但是没有正在显示的UI;hasPendingUiClean:是否想从showingUI回收内存
if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
|| app.systemNoUi) && app.hasPendingUiClean()) {
//内存等级小于TRIM_MEMORY_UI_HIDDEN
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
&& app.thread != null) {
try {
//调整TrimMemoryLevel到TRIM_MEMORY_UI_HIDDEN
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
} catch (RemoteException e) {
}
}
//清理showingUI:false
app.setPendingUiClean(false);
}
app.trimMemoryLevel = 0;
}
}
return allChanged;
}