ActivityManagerService解读之进程管理computeOomAdjLocked方法
上一篇文章我们介绍了updateOomAdjLocked,我们将其分为了五个部分更新前的初始化,计算进程oom,设置进程oom,主动回收一些内存,计算进程pss进行扫尾结束工作。本篇将详细介绍部分之二计算进程oom
代码分析
分析computeOomAdjLocked之前,我们先重温一下进程oom和Android进程分类相关的基础知识以及补充一些相关的后续分析将要用的一些信息。Android中根据进程相对用户的重要程度,将进程分五个层次:
- 前台进程
用户当前操作所必需的进程。如果一个进程满足以下任一条件,即视为前台进程:
托管用户正在交互的 Activity(已调用 Activity 的 onResume() 方法)
托管某个 Service,后者绑定到用户正在交互的 Activity
托管正在“前台”运行的 Service(服务已调用 startForeground())
托管正执行一个生命周期回调的 Service(onCreate()、onStart() 或 onDestroy())
托管正执行其 onReceive() 方法的 BroadcastReceiver - 可见进程
没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。 如果一个进程满足以下任一条件,即视为可见进程:
托管不在前台、但仍对用户可见的 Activity(已调用其 onPause() 方法)。例如,如果前台 Activity 启动了一个对话框,允许在其后显示上一 Activity,则有可能会发生这种情况。
托管绑定到可见(或前台)Activity 的 Service。
可见进程被视为是极其重要的进程,除非为了维持所有前台进程同时运行而必须终止,否则系统不会终止这些进程。 - 服务进程
正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程。尽管服务进程与用户所见内容没直接关联,但是它们通常在执行一些用户关心的操作(例如,在后台播放音乐或从网络下载数据)。因此,除非内存不足以维持所有前台进程和可见进程同时运行,否则系统会让服务进程保持运行状态。 - 后台进程
包含目前对用户不可见的 Activity 的进程(已调用 Activity 的 onStop() 方法)。 - 空进程
不含任何活动应用组件的进程。保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间。 为使总体系统资源在进程缓存和底层内核缓存之间保持平衡,系统往往会终止这些进程。
针对这五个层次,在AMSoom计算中又为其细分了如下adj值
SYSTEM_ADJ | -900 | 系统进程 |
PERSISTENT_PROC_ADJ | -800 | 系统persistent进程 |
PERSISTENT_SERVICE_ADJ | -700 | 关联着系统或persistent进程 |
FOREGROUND_APP_ADJ | 0 | 前台进程 |
VISIBLE_APP_ADJ | 100 | 可见进程 |
PERCEPTIBLE_APP_ADJ | 200 | 可感知的进程 |
BACKUP_APP_ADJ | 300 | 备份进程 |
HEAVY_WEIGHT_APP_ADJ | 400 | 重量级进程 |
SERVICE_ADJ | 500 | 服务进程 |
HOME_APP_ADJ | 600 | Home进程 |
PREVIOUS_APP_ADJ | 700 | 前一个App进程 |
SERVICE_B_ADJ | 800 | B集合中的进程 |
CACHED_APP_MIN_ADJ | 900 | 缓存进程的最小值 |
CACHED_APP_MAX_ADJ | 906 | 缓存进程的最大值 |
对于各类进程的状态也有如下描述:
PROCESS_STATE_UNKNOWN | -1 | |
PROCESS_STATE_PERSISTENT | 0 | 系统persistent进程 |
PROCESS_STATE_PERSISTENT_UI | 1 | 系统persistent进程,正在进行UI相关的操作 |
PROCESS_STATE_TOP | 2 | 涵盖了用户可见活动的进程 |
PROCESS_STATE_FOREGROUND_SERVICE | 3 | 托管前台服务的进程 |
PROCESS_STATE_BOUND_FOREGROUND_SERVICE | 4 | 通过bind的形式托管前台服务的进程 |
PROCESS_STATE_IMPORTANT_FOREGROUND | 5 | 对于用户比较重要的前台进程 |
PROCESS_STATE_IMPORTANT_BACKGROUND | 6 | 对于用户比较重要的后台进程 |
PROCESS_STATE_TRANSIENT_BACKGROUND | 7 | 短暂的后台进程 |
PROCESS_STATE_BACKUP | 8 | 备份进程 |
PROCESS_STATE_SERVICE | 9 | 服务进程 |
PROCESS_STATE_RECEIVER | 10 | 广播进程 |
PROCESS_STATE_TOP_SLEEPING | 11 | 和PROCESS_STATE_TOP一样,但是区别是手机处于sleeping状态 |
PROCESS_STATE_HEAVY_WEIGHT | 12 | 重量级进程 |
PROCESS_STATE_HOME | 13 | Home进程 |
PROCESS_STATE_LAST_ACTIVITY | 14 | 后台进程,但是托管了用户最后运行的Activity |
PROCESS_STATE_CACHED_ACTIVITY | 15 | 后台托管有Activity的进程 |
PROCESS_STATE_CACHED_ACTIVITY_CLIENT | 16 | 托管存在客户端的Activity的进程 |
PROCESS_STATE_CACHED_RECENT | 17 | 与recent中关联的缓存进程 |
PROCESS_STATE_CACHED_EMPTY | 18 | 空进程 |
PROCESS_STATE_NONEXISTENT | 19 | 不存在的进程 |
cpu资源分配策略
SCHED_GROUP_BACKGROUND | 0 | 缩写B |
SCHED_GROUP_RESTRICTED | 1 | 缩写R |
SCHED_GROUP_DEFAULT | 2 | 缩写F |
SCHED_GROUP_TOP_APP | 3 | 缩写T |
SCHED_GROUP_TOP_APP_BOUND | 4 |
如下所示:
Proc # 1: home B/ /HOME trm: 0 3509:com.miui.home/u0a32 (home)Proc # 0: fore T/A/TPSL trm: 0 5215:com.tencent.mm/u0a159 (top-activity)Proc #26: vis F/ /BFGS trm: 0 3503:com.miui.analytics/u0a82 (service)
Activity的状态
INITIALIZING | 初始化 |
RESUMED | 正在运行 |
PAUSING | 暂停中 |
PAUSED | 已暂停 |
STOPPING | 停止中 |
STOPPED | 已停止 |
FINISHING | 正在执行finish |
DESTROYING | 销毁中 |
DESTROYED | 已销毁 |
同样computeOomAdjLocked方法,也将其分为几个部分,逐一分析,其中计算过程中,我们需要着重关注一些信息:adj,procState,adjType
1.计算一眼可见的空进程(app中IApplicationThread==null)oom和一些基本参数的初始化,
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, boolean doingAll, long now) { if (mAdjSeq == app.adjSeq) {//mAdjSeq记录updateOomAdjLocked方法的调用次数 if (app.adjSeq == app.completedAdjSeq) { // This adjustment has already been computed successfully. return false; } else { // The process is being computed, so there is a cycle. We cannot // rely on this process's state. app.containsCycle = true; return false; } } //设置empty进程adj if (app.thread == null) { app.adjSeq = mAdjSeq; app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND; app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ; app.completedAdjSeq = app.adjSeq; return false; } app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN; app.adjSource = null; app.adjTarget = null; app.empty = false; app.cached = false; final int activitiesSize = app.activities.size();//当前进程中的activity的数量 final int appUid = app.info.uid; final int logUid = mCurOomAdjUid; int prevAppAdj = app.curAdj;
2.计算不允许将其adj调整低于前台的优先级进程的adj,换句话说计算adj<=0进程的oom相关的值
//计算不允许将其adj调整低于前台的优先级进程的adj 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. if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app); } app.adjType = "fixed"; app.adjSeq = mAdjSeq; app.curRawAdj = app.maxAdj; app.foregroundActivities = false; app.curSchedGroup = ProcessList.SCHED_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; app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.adjType = "pers-top-activity"; } else if (app.hasTopUi) { // sched group/proc state adjustment is below app.systemNoUi = false; app.adjType = "pers-top-ui"; } else if (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) { if (mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) { // screen on, promote UI app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI; app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP; } else { // screen off, restrict UI scheduling app.curProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; app.curSchedGroup = ProcessList.SCHED_GROUP_RESTRICTED; } } app.curAdj = app.maxAdj; app.completedAdjSeq = app.adjSeq; // if curAdj is less than prevAppAdj, then this process was promoted return app.curAdj < prevAppAdj; }
1和2中的逻辑较为简单,对于确认就是空进程的情况,直接设置对应的oom相关的信息结束计算,对于adj<=0的进程,往往我们认为该类进程都是较为重要的,设置对应的信息后也结束计算。
3.设置前台进程oom相关信息,并却分adj类型
app.systemNoUi = false; final int PROCESS_STATE_CUR_TOP = mTopProcessState;//记录当请顶层用户交互进程的状态 // Determine the importance of the process, starting with most // important to least, and assign an appropriate OOM adjustment. int adj; int schedGroup;//cpu资源分配策略 int procState;//进程状态 int cachedAdjSeq; boolean foregroundActivities = false; mTmpBroadcastQueue.clear(); //满足以下情况中的多数属于前台进程,设置前台进程的adj //我们知道前台进程对应的adj=0,但是有很多中情况都是属于前台进程,因此我们需要根据app的不同场景设置adjType //同时并保存初步设置的adj schedGroup procState if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) { // The last app on the list is the foreground app. adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.adjType = "top-activity"; foregroundActivities = true; procState = PROCESS_STATE_CUR_TOP; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app); } } else if (app.runningRemoteAnimation) { adj = ProcessList.VISIBLE_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.adjType = "running-remote-anim"; procState = PROCESS_STATE_CUR_TOP; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app); } } else if (app.instr != 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; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app); } } else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) { // 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 = (mTmpBroadcastQueue.contains(mFgBroadcastQueue)) ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND; app.adjType = "broadcast"; procState = ActivityManager.PROCESS_STATE_RECEIVER; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app); } } else if (app.executingServices.size() > 0) { // 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; app.adjType = "exec-service"; procState = ActivityManager.PROCESS_STATE_SERVICE; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app); } //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app); } else if (app == TOP_APP) { adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; app.adjType = "top-sleeping"; foregroundActivities = true; procState = PROCESS_STATE_CUR_TOP; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app); } } else { // 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; procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; app.cached = true; app.empty = true; app.adjType = "cch-empty"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app); } }//由此不得不佩服android google工程师对ams的设计,简直是完美啊
4.根据app进程中activity状态,进行oom相关信息设置,从这段逻辑中我们可以看出不同的Activity的状态都将影响着oom的计算
//到了这里我们可以确认是: // adj = FOREGROUND_APP_ADJ/UNKNOWN_ADJ //对于前台正或即将要与用户交互的情况不做处理,对于其他情况下被认为是前台进程 // 或者非前台进程的情况(我们只是粗略的认为他是缓存进程),我们u需要根据他托管的activity //状态进一步设置他的oom adj,执行结束有可能会将adj重要程度提高到VISIBLE_APP_ADJ或PERCEPTIBLE_APP_ADJ,对应的 //procState,scheGroup都会做相应的修改 // Examine all activities if not already foreground. if (!foregroundActivities && activitiesSize > 0) { int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;//99 for (int j = 0; j < activitiesSize; j++) { final ActivityRecord r = app.activities.get(j); if (r.app != app) { Log.e(TAG, "Found activity " + r + " in proc activity list using " + r.app + " instead of expected " + app); if (r.app == null || (r.app.uid == app.uid)) { // Only fix things up when they look sane r.setProcess(app); } else { continue; } } if (r.visible) { // App has a visible activity; only upgrade adjustment. if (adj > ProcessList.VISIBLE_APP_ADJ) { adj = ProcessList.VISIBLE_APP_ADJ; app.adjType = "vis-activity"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to vis-activity: " + app); } } if (procState > PROCESS_STATE_CUR_TOP) { procState = PROCESS_STATE_CUR_TOP; app.adjType = "vis-activity"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to vis-activity (top): " + app); } } if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } app.cached = false; app.empty = false; foregroundActivities = true; final TaskRecord task = r.getTask(); if (task != null && minLayer > 0) { final int layer = task.mLayerRank; if (layer >= 0 && minLayer > layer) { minLayer = layer; } } break; } else if (r.isState(ActivityState.PAUSING, ActivityState.PAUSED)) { if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; app.adjType = "pause-activity"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to pause-activity: " + app); } } if (procState > PROCESS_STATE_CUR_TOP) { procState = PROCESS_STATE_CUR_TOP; app.adjType = "pause-activity"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to pause-activity (top): " + app); } } if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } app.cached = false; app.empty = false; foregroundActivities = true; } else if (r.isState(ActivityState.STOPPING)) { if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; app.adjType = "stop-activity"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to stop-activity: " + app); } } // 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.adjType = "stop-activity"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to stop-activity: " + app); } } } app.cached = false; app.empty = false; foregroundActivities = true; } else { if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) { procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; app.adjType = "cch-act"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached activity: " + app); } } } } if (adj == ProcessList.VISIBLE_APP_ADJ) { adj += minLayer; } } //存在recentTasks的情况下,我们将进程的状态降低到PROCESS_STATE_CACHED_RECENT if (procState > ActivityManager.PROCESS_STATE_CACHED_RECENT && app.recentTasks.size() > 0) { procState = ActivityManager.PROCESS_STATE_CACHED_RECENT; app.adjType = "cch-rec"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app); } }
5.再次根据进程的状态做进一步的细分,此次操作能更多的过滤出可感知的进程
//再次设置可感知的app的adj(200) if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { 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; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to fg service: " + app); } } else if (app.hasOverlayUi) { // The process is display an overlay UI. adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; app.cached = false; app.adjType = "has-overlay-ui"; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to overlay ui: " + app); } } } if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) { if (app.forcingToImportant != null) { // This is currently used for toasts... they are not interactive, and // we don't want them to cause the app to become fully foreground (and // thus out of background check), so we yes the best background level we can. adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; app.cached = false; app.adjType = "force-imp"; app.adjSource = app.forcingToImportant; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app); } } }
6.设置重量级进程
//设置heavy-weight进程的adj(400) 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 (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app); } } if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; app.adjType = "heavy"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app); } } }
7.设置Home进程
//设置home进程的adj(600) 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 (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app); } } if (procState > ActivityManager.PROCESS_STATE_HOME) { procState = ActivityManager.PROCESS_STATE_HOME; app.adjType = "home"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app); } } }
8.设置前一个app进程
//设置用户上一个使用的包含UI的进程的adj(700) 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 (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app); } } if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; app.adjType = "previous"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app); } } } // 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.curRawAdj = adj; app.hasStartedServices = false; app.adjSeq = mAdjSeq;
9.设置备份进程,截至目前,我们已经基本过滤出adj<=0,adj=100,200,300,400,600,700的情况,我们暂且先保存当前的adj到app.curRawAdj
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_TRANSIENT_BACKGROUND) { procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; } app.adjType = "backup"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app); } app.cached = false; } if (procState > ActivityManager.PROCESS_STATE_BACKUP) { procState = ActivityManager.PROCESS_STATE_BACKUP; app.adjType = "backup"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app); } } }
10.处理进程中存在service情况设置进程oom,特别的是对于bindservice的情况会结合client进程设置进程的oom,该部分代码都是细节上的处理,暂不列取代码。
11.处理进程中provider的情况,上同10
12.经过一系列复杂的处理,最终确认进程的oom相关信息
if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) { // A client of one of our services or providers is in the top state. We // *may* want to be in the top state, but not if we are already running in // the background for some other reason. For the decision here, we are going // to pick out a few specific states that we want to remain in when a client // is top (states that tend to be longer-term) and otherwise allow it to go // to the top state. switch (procState) { case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE: case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE: // Something else is keeping it at this level, just leave it. break; case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND: case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND: case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND: case ActivityManager.PROCESS_STATE_SERVICE: // These all are longer-term states, so pull them up to the top // of the background states, but not all the way to the top state. procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; app.adjType = mayBeTopType; app.adjSource = mayBeTopSource; app.adjTarget = mayBeTopTarget; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "May be top raise to " + mayBeTopType + ": " + app + ", due to " + mayBeTopSource + " adj=" + adj + " procState=" + ProcessList.makeProcStateString(procState)); } break; default: // Otherwise, top is a better choice, so take it. procState = ActivityManager.PROCESS_STATE_TOP; app.adjType = mayBeTopType; app.adjSource = mayBeTopSource; app.adjTarget = mayBeTopTarget; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "May be top raise to " + mayBeTopType + ": " + app + ", due to " + mayBeTopSource + " adj=" + adj + " procState=" + ProcessList.makeProcStateString(procState)); } break; } } if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) { if (app.hasClientActivities) { // This is a cached process, but with client activities. Mark it so. procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; app.adjType = "cch-client-act"; } else if (app.treatLikeActivity) { // This is a cached process, but somebody wants us to treat it like it has // an activity, okay! procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; app.adjType = "cch-as-act"; } } if (adj == ProcessList.SERVICE_ADJ) { if (doingAll) { app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3); mNewNumServiceProcs++; //Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb); if (!app.serviceb) { // This service isn't far enough down on the LRU list to // normally be a B service, but if we are low on RAM and it // is large we want to force it down since we would prefer to // keep launcher over it. if (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL && app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) { app.serviceHighRam = true; app.serviceb = true; //Slog.i(TAG, "ADJ " + app + " high ram!"); } else { mNewNumAServiceProcs++; //Slog.i(TAG, "ADJ " + app + " not high ram!"); } } else { app.serviceHighRam = false; } } if (app.serviceb) { adj = ProcessList.SERVICE_B_ADJ; } } app.curRawAdj = adj; //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid + // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj); if (adj > app.maxAdj) { adj = app.maxAdj; if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } } // Put bound foreground services in a special sched group for additional // restrictions on screen off if (procState >= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE && mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE) { if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) { schedGroup = ProcessList.SCHED_GROUP_RESTRICTED; } } // Do final modification to adj. Everything we do between here and applying // the final setAdj must be done in this function, because we will also use // it when computing the final cached adj later. Note that we don't need to // worry about this for max adj above, since max adj will always be used to // keep it out of the cached vaues. app.curAdj = app.modifyRawOomAdj(adj); app.curSchedGroup = schedGroup; app.curProcState = procState; app.foregroundActivities = foregroundActivities; app.completedAdjSeq = mAdjSeq; // if curAdj is less than prevAppAdj, then this process was promoted return app.curAdj < prevAppAdj; }
终于撸完了,整个计算过程还是十分清晰,但是其中的一些细节复杂程度简直恐怖到令人发指,后续的工作学习中还会继续深入理解,”路慢慢其修远兮“啊。本文分析皆本人愚见,忘各位看官不吝赐教,当万分感谢。
更多相关文章
- 一款霸榜 GitHub 的开源 Linux 资源监视器!
- Android设置选项开发及自定义Preference样式
- Android开发经验分享
- 【安卓开发】Android为什么选择binder
- Android之RxAndroid2、RxJava2的zip应用场景及示例
- android 内存使用详情查询的几种方法
- Android(安卓)App启动过程
- Android(安卓)多进程通信(2) - Binder、Messenger
- android开发新浪微博客户端 完整攻略