AMS computeOomAdjLocked 进程优先级调整

概述

每个进程都有自己的优先级adj,但是进程的有显示具体是如何计算的?根据什么条件决定的呢?computeOomAdjLocked方法主要就是来根据当前进程的各种条件分配合适的Adj优先级的.

ADJ优先级介绍

ADJ取值 进程类别 含义
-1000 NATIVE_ADJ native进程
-900 SYSTEM_ADJ System_server进程
-800 PERSISTENT_PROC_ADJ 系统persistent进程
-700 PERSISTENT_SERVICE_ADJ 系统或者persistent进程绑定的进程
0 FOREGROUND_APP_ADJ 前台进程 :和用户交互的进程,不到万不得已不能杀死
100 VISIBLE_APP_ADJ 可见进程:该进程的某个UI组件是可以被用户看见的,但是没有和用户进行交互,不能随便杀死,影响用户体验
200 PERCEPTIBLE_APP_ADJ 可感知进程:该进程的某个组件可以被用户感知到,如后台音乐播放
300 BACKUP_APP_ADJ 备份进程:不可轻易打断,否则容易引起不可修复的数据错误
400 HEAVY_WEIGHT_APP_ADJ 重量级进程
500 SERVICE_ADJ 服务进程
600 HOME_APP_ADJ Lanucher进程
700 PREVIOUS_APP_ADJ 上一个访问的进程
800 SERVICE_B_ADJ B list中的进程
900 CACHED_APP_MIN_ADJ 不可见进程adj最小值
906 CACHED_APP_MAX_ADJ 不可见进程adj最大值
1001 UNKNOWN_ADJ 错误的adj值

进程状态介绍

状态值 进程状态类别 含义
-1 PROCESS_STATE_UNKNOWN 错误的进程状态
0 PROCESS_STATE_PERSISTENT persistent进程
1 PROCESS_STATE_PERSISTENT_UI 该进程是persistent进程并且有UI界面显示
2 PROCESS_STATE_TOP 运行Top Activity正在和用户交互的进程
3 PROCESS_STATE_FOREGROUND_SERVICE 运行了Foreground service的进程
4 PROCESS_STATE_BOUND_FOREGROUND_SERVICE 运行有系统绑定的前台服务
5 PROCESS_STATE_IMPORTANT_FOREGROUND 用户可感知的重要进程
6 PROCESS_STATE_IMPORTANT_BACKGROUND 用户不可感知的重要进程
7 PROCESS_STATE_TRANSIENT_BACKGROUND
8 PROCESS_STATE_BACKUP 备份进程
9 PROCESS_STATE_SERVICE 后台运行Service的进程
10 PROCESS_STATE_RECEIVER 后台运行广播的进程
11 PROCESS_STATE_TOP_SLEEPING 设备处于Sleep状态时的Top进程
12 PROCESS_STATE_HEAVY_WEIGHT
13 PROCESS_STATE_HOME Launcher进程
14 PROCESS_STATE_LAST_ACTIVITY 上一个Activity所处的进程
15 PROCESS_STATE_CACHED_ACTIVITY 包含Activity且处于缓存状态的进程
16 PROCESS_STATE_CACHED_ACTIVITY_CLIENT 处于缓存状态且是另一个缓存状态进程的Client进程
17 PROCESS_STATE_CACHED_RECENT
18 PROCESS_STATE_CACHED_EMPTY 缓存空进程
19 PROCESS_STATE_NONEXISTENT 不存在的进程

如何调整优先级

AMS中将进程分为来这么多个优先级等级,但是AMS是如何给每个进程分配优先级的呢?这个过程主要是在computeOomAdjLocked方法中处理的。

ComputeOomAdjLocked 计算进程的Adj值


    private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
            boolean doingAll, long now) {
        // mAdjSeq 是 adj调整的序号,每次进行一轮调整的时候 mAdjSeq 加1,进程ProcessRecord的adjSeq
        //代表最后一次计算的mAdjSeq的序号
        // 如果当前进程的adjSeq == mAdjSeq说明,当前进程ProcessRecord已经计算adj完成,无需再次计算
        if (mAdjSeq == app.adjSeq) {
            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;
            }
        }

        //如果当前进程的ActivityThread = NULL, 说明当前进程没有真正运行的实体,是一个缓存的进程
        //直接将当前进程设置为缓存进程之后,该进程的adj计算就算完成了
        // 当前进程的cured = curRawAdj = 906
        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();
        final int appUid = app.info.uid;
        final int logUid = mCurOomAdjUid;

        int prevAppAdj = app.curAdj;
        int prevProcState = app.curProcState;

        //处理某一个进程的maxAdj <= FOREGROUND_APP_ADJ ( 0 )情况�������������������,此类进程属于系统级重要进程
        //maxAdj是ProcessRecord在创建的时候设置的一个允许该进程最大的adj值
        //搜索系统中maxAdj设置的地方,只有system_server进程启动的时候和系统persistent进程启动的
        //时候会进行设置,所以只要maxAdj小于FOREGROUND_APP_ADJ  0的时候,此时是系统的一些重
        //要的进程,不需要在调整adj,只需呀设置为maxAdj即可。
        if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
            //初始化进程相关信息
            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;
            //判断当前的系统进程是否包含正在显示的UI,根据是否显示UI来设置进程的curProcState以及进程调度策略
            app.systemNoUi = true;
            if (app == TOP_APP) {
                //如果当前系统进程属于TOP_APP, 那这个进程一定含有UI
                app.systemNoUi = false;
                app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
                app.adjType = "pers-top-activity";
            } else if (app.hasTopUi) {
                // 如果当前系统进程有TopUI
                app.systemNoUi = false;
                app.adjType = "pers-top-ui";
            } else if (activitiesSize > 0) {
                // 当前进程有正在显示的Activity
                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) {
                  // 屏幕显示,且当前进程有UI界面
                  app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
                  app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
              } else {
                  // 屏幕休眠,且当前进程有UI界面
                  app.curProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                  app.curSchedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
              }
            }
            app.curAdj = app.maxAdj;
            app.completedAdjSeq = app.adjSeq;
            // 如果此次的计算的Adj<上次的Adj, 说明adj计算完成了
            return app.curAdj < prevAppAdj;
        }

第一部分:

  1. 判断进程在此次调整中是否调整完毕,调整完毕则直接返回
  2. 如果本进程的ActivityThread已经挂掉了, 则直接设置进程的优先级为CACHED_APP_MAX_ADJ = 906
  3. 计算maxAdj < FOREGROUND_APP_ADJ的情况, 系统自己创建的系统级进程,设置adj为maxAdj即可,无需对Adj做其他调整

ADJ < 0的进程包括哪些进程?

NATIVE_ADJ(-1000):是由init进程fork出来的Native进程,并不受system管控;
SYSTEM_ADJ(-900):是指system_server进程;
PERSISTENT_PROC_ADJ(-800): 是指在AndroidManifest.xml中申明android:persistent=”true”的系统(即带有FLAG_SYSTEM标记)进程,persistent进程一般情况并不会被杀,即便被杀或者发生Crash系统会立即重新拉起该进程。
PERSISTENT_SERVICE_ADJ(-700):是由startIsolatedProcess()方式启动的进程,或者是由system_server或者persistent进程所绑定(并且带有BIND_ABOVE_CLIENT或者BIND_IMPORTANT)的服务进程

        // mTopProcessState 代表运行TopActivity的进程状态,只有两种状态
        // 1 : ActivityManager.PROCESS_STATE_TOP 显示状态
        // 2 : ActivityManager.PROCESS_STATE_TOP_SLEEPING 休眠状态
        final int PROCESS_STATE_CUR_TOP = mTopProcessState;

        // 开始遍历并计算普通进程 即adj值 > 0的情况,重要性从高到低进行计算,然后为进程设置一个合适的Adj优先级
        int adj;
        int schedGroup;
        int procState;
        int cachedAdjSeq;

        boolean foregroundActivities = false;
        mTmpBroadcastQueue.clear();
        if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) {
            // 如果当前进程为TOP_APP进程,即处于和用户交互的进程,并且当前进程不是休眠状态
            // 那么先当前进程优先级设置为FOREGROUND_APP_ADJ (0)
            // 进程状态 procState 为 PROCESS_STATE_CUR_TOP
            // foregroundActivities 为 true, 表明当前进程包含显示的Activity界面
            // 设置调度策略为 SCHED_GROUP_TOP_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 = VISIBLE_APP_ADJ = 100
            // 进程状态procState 为 PROCESS_STATE_CUR_TOP
            // 设置调度策略为 SCHED_GROUP_TOP_APP
            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) {
            //如果是正在进行测试的进程,设置进程adj = FOREGROUND_APP_ADJ = 0
            //设置procState 进程状态为 PROCESS_STATE_FOREGROUND_SERVICE
            //设置调度策略为SCHED_GROUP_DEFAULT
            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)) {
            // 如果是一个正在接受广播的进程,此时我们也要把这个进程看作是前台进程
            // adj 设置为 FOREGROUND_APP_ADJ = 0
            // 进程状态 procState 设置 PROCESS_STATE_RECEIVER
            // 设置调度策略为SCHED_GROUP_DEFAULT或者SCHED_GROUP_BACKGROUND
            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) {
            // 如果是正在执行service生命周期回调的进程
            // 设置进程adj = FOREGROUND_APP_ADJ = 0
            // 设置进程状态 procState = PROCESS_STATE_SERVICE
            // 设置调度策略为 SCHED_GROUP_BACKGROUND 或者 SCHED_GROUP_DEFAULT
            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) {
            // 如果当前进程是top进程,且系统处于休眠状态
            // 设置进程adj = FOREGROUND_APP_ADJ
            // 设置进程状态procState = PROCESS_STATE_CUR_TOP
            // 设置调度策略为 SCHED_GROUP_BACKGROUND
            // foregroundActivities = true 表示当前进程有UI和用户交互
            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 {
            // 其他进程则默认初始化adj = 1000, 进程state默认初始化为PROCESS_STATE_CACHED_EMPTY
            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);
            }
        }

第二部分:先处理进程adj应该设置为前台进程FOREGROUND_APP_ADJ的几种情况

满足以下任一条件的进程都属于FOREGROUND_APP_ADJ(0)优先级:

  1. 正处于resumed状态的Activity
  2. 正执行一个生命周期回调的Service(比如执行onCreate,onStartCommand,onDestroy等)
  3. 正执行onReceive()的BroadcastReceiver
  4. 通过startInstrumentation()启动的进程

把这几种情况的进程adj设置为FOREGROUND_APP_ADJ = 0, 虽然以上几种进程的adj值一样,即对于LowMemorykiller来讲,他们的重要性是相同的,但是这些进程的proceState不同,从AMS角度而言,他们的重要性不一样。此外对不同的进程根据重要情况设置了不同的调度策略schedGroup, 通过linux的接口来使进程有不同的调度策略。

最后其他进程adj都默认设置为1000,进程state 都设置初始化为CACHE_EMPTY。然后在后续的流程里再进行处理。

foregroundActivitys 变量用于表示当前进程是否有处于前台和用户交互的Activity

  // 开始处理包含Activity, 但是却不在前台的进程
        if (!foregroundActivities && activitiesSize > 0) {
            // PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1 = 200 - 100 - 1 = 99
            //之前分析updateOomAdjLocked的第一部分时,简单提到过rankTaskLayersIfNeeded函数
            //该函数会更新包含Activity的Task的rankLayer
            //按照显示层次从上到下,rankLayer逐渐增加,对应的最大值就是VISIBLE_APP_LAYER_MAX
            int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
            for (int j = 0; j < activitiesSize; j++) {
                            ......
                if (r.visible) {
                    // 如果进程包含可见activity, 设置该进程adj = VISIBLE_APP_ADJ.
                    if (adj > ProcessList.VISIBLE_APP_ADJ) {
                    //adj大于VISIBLE_APP_ADJ时,才更新对应的adj
                        //之前提到的正在处理广播、服务或测试的进程,adj为FOREGROUND,是小于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; //设置可见进程的state = STATE_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; //属于foregroundActivities进程
                    final TaskRecord task = r.getTask();
                    if (task != null && minLayer > 0) {
                        final int layer = task.mLayerRank;
                        if (layer >= 0 && minLayer > layer) {
                            //更新rankLayer
                            minLayer = layer;
                        }
                    }
                    break;
                } else if (r.isState(ActivityState.PAUSING, ActivityState.PAUSED)) {
                                //如果进程包含处于PAUSING或PAUSED状态的Activity时
                            //将其oom_adj调整为“用户可察觉”的的等级,这个等级还是很高的
                    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)) {
                  //包含处于Stopping状态Activity的进程,其oom_adj也被置为PERCEPTIBLE_APP_ADJ
                    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);
                        }
                    }
                    //处于stoping,但是还没有finish的进程, state设置为PROCESS_STATE_LAST_ACTIVITY
                    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 {
                    //stop且finish的进程,设置adj为PROCESS_STATE_CACHED_ACTIVITY
                    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);
                        }
                    }
                }
            }
                //不同可见进程的oom_adj有一定的差异,处在下层的oom_adj越大
            //即越老的Activity所在进程,重要性越低
            if (adj == ProcessList.VISIBLE_APP_ADJ) {
                adj += minLayer;
            }
        }

  if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
            if (app.foregroundServices) {
                // oregroundServices非空:前台服务进程,执行startForegroundService()方法, 此时该进程为可感知进程
                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) {
                // 进程有OverlayUI 该进程为可感知进程.
                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 the app was recently in the foreground and moved to a foreground service status,
        // allow it to get a higher rank in memory for some time, compared to other foreground
        // services so that it can finish performing any persistence/processing of in-memory state.
        if (app.foregroundServices && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
                && (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now
                    || app.setProcState <= ActivityManager.PROCESS_STATE_TOP)) {
            adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
            app.adjType = "fg-service-act";
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
            }
        }

        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
            if (app.forcingToImportant != null) {
                // app.forcingToImportant非空:执行setProcessImportant()方法,比如Toast弹出过程
                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);
                }
            }
        }

第三部分:

根据进程的Activity状态和Service状态决定Adj

  • VISIBLE_APP_ADJ 可见进程:
    进程中存在可见Activity
  • PERCEPTIBLE_APP_ADJ 可感知进程:
    1.进程中存在处于PAUSING、PAUSED或STOPPING状态的Activity时
    2.foregroundServices非空:前台服务进程,执行startForegroundService()方法
    3.app.forcingToImportant非空:执行setProcessImportant()方法,比如Toast弹出过程。
    4.hasOverlayUi非空:非activity的UI位于屏幕最顶层,比如显示类型TYPE_APPLICATION_OVERLAY的窗口进程.

其余的进程仍是UNKNOW_ADJ。

        //开始处理一些特殊的进程

      //如果进程是heavyWeightProcess进程, 则设置进程adj = HEAVY_WEIGHT_APP_ADJ
       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);
                }
            }
        }

        //如果是Home进程, 则设置adj = HOME_APP_ADJ
        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);
                }
            }
        }

        //如果进程为前一个进程, 则设置adj = PREVIOUS_APP_ADJ
        if (app == mPreviousProcess && app.activities.size() > 0) {
            if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                // This was the previous process that showed UI to the user.
                // We want to try to keep it around more aggressively, to give
                // a good experience around switching between two apps.
                adj = ProcessList.PREVIOUS_APP_ADJ;
                schedGroup = 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);
                }
            }
        }

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

        // By default, we use the computed adjustment.  It may be changed if
        // there are applications dependent on our services or providers, but
        // this gives us a baseline and makes sure we don't get into an
        // infinite recursion.
        app.curRawAdj = adj;
        app.hasStartedServices = false;
        app.adjSeq = mAdjSeq;
        //如果是备份进程, 则设置adj = BACKUP_APP_ADJ
        if (mBackupTarget != null && app == mBackupTarget.app) {
            // If possible we want to avoid killing apps while they're being backed up
            if (adj > ProcessList.BACKUP_APP_ADJ) {
                if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
                adj = ProcessList.BACKUP_APP_ADJ;
                if (procState > ActivityManager.PROCESS_STATE_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);
                }
            }
        }

第四部分:
处理了一些特殊的进程,并设置其adj值和processState值

包含前台服务的进程
重量级进程
Home进程
previous进程
Backup进程

        //根据Service来调整进程优先级
        boolean mayBeTop = false;
        String mayBeTopType = null;
        Object mayBeTopSource = null;
        Object mayBeTopTarget = null;

        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是startService方式启动的
            if (s.startRequested) {
                app.hasStartedServices = true;
                if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
                    procState = ActivityManager.PROCESS_STATE_SERVICE;
                    app.adjType = "started-services";
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise procstate to started service: " + app);
                    }
                }
                if (app.hasShownUi && app != mHomeProcess) {
                    // If this process has shown some UI, let it immediately
                    // go to the LRU list because it may be pretty heavy with
                    // UI stuff.  We'll tag it with a label just to help
                    // debug and understand what is going on.
                    if (adj > ProcessList.SERVICE_ADJ) {
                        app.adjType = "cch-started-ui-services";
                    }
                } else {
                    if (now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
                        // 30min之内活跃过的Service服务,将该进程的优先级设置为SERVICE_ADJ 500
                        if (adj > ProcessList.SERVICE_ADJ) {
                            adj = ProcessList.SERVICE_ADJ;
                            app.adjType = "started-services";
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                        "Raise adj to started service: " + app);
                            }
                            app.cached = false;
                        }
                    }
                    // If we have let the service slide into the background
                    // state, still have some text describing what it is doing
                    // even though the service no longer has an impact.
                    if (adj > ProcessList.SERVICE_ADJ) {
                        app.adjType = "cch-started-services";
                    }
                }
            }

           //根据绑定该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);
                for (int i = 0;
                        i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
                                || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                                || procState > ActivityManager.PROCESS_STATE_TOP);
                        i++) {
                    // XXX should compute this based on the max of
                    // all connected clients.
                    ConnectionRecord cr = clist.get(i);
                    if (cr.binding.client == app) {
                        // 是自己进程绑定的当前Service服务,无需处理
                        continue;
                    }
                    //BIND_WAIVE_PRIORITY
                    //是指客户端进程的优先级不会影响目标服务进程的优先级。比如当调用bindService
                    //又不希望提升目标服务进程的优先级的情况下,可以使用该flags
                    // 根据Srevise Client进程来调整当前进程的Adj
                    if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
                        ProcessRecord client = cr.binding.client;
                        computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
                        if (client.containsCycle) {
                            // We've detected a cycle. We should retry computeOomAdjLocked later in
                            // case a later-checked connection from a client  would raise its
                            // priority legitimately.
                            app.containsCycle = true;
                            // If the client has not been completely evaluated, skip using its
                            // priority. Else use the conservative value for now and look for a
                            // better state in the next iteration.
                            if (client.completedAdjSeq < mAdjSeq) {
                                continue;
                            }
                        }
                        int clientAdj = client.curRawAdj;
                        int clientProcState = client.curProcState;
                        if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                            // If the other app is cached for any reason, for purposes here
                            // we are going to consider it empty.  The specific cached state
                            // doesn't propagate except under certain conditions.
                            clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                        }
                        String adjType = null;
                        if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                            // Not doing bind OOM management, so treat
                            // this guy more like a started service.
                            if (app.hasShownUi && app != mHomeProcess) {
                                // If this process has shown some UI, let it immediately
                                // go to the LRU list because it may be pretty heavy with
                                // UI stuff.  We'll tag it with a label just to help
                                // debug and understand what is going on.
                                if (adj > clientAdj) {
                                    adjType = "cch-bound-ui-services";
                                }
                                app.cached = false;
                                clientAdj = adj;
                                clientProcState = procState;
                            } else {
                                if (now >= (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
                                    // This service has not seen activity within
                                    // recent memory, so allow it to drop to the
                                    // LRU list if there is no other reason to keep
                                    // it around.  We'll also tag it with a label just
                                    // to help debug and undertand what is going on.
                                    if (adj > clientAdj) {
                                        adjType = "cch-bound-services";
                                    }
                                    clientAdj = adj;
                                }
                            }
                        }
                        if (adj > clientAdj) {
                            // If this process has recently shown UI, and
                            // the process that is binding to it is less
                            // important than being visible, then we don't
                            // care about the binding as much as we care
                            // about letting this process get into the LRU
                            // list to be killed and restarted if needed for
                            // memory.
                            if (app.hasShownUi && app != mHomeProcess
                                    && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
                                    adjType = "cch-bound-ui-services";
                                }
                            } else {
                                int newAdj;
                                if ((cr.flags&(Context.BIND_ABOVE_CLIENT
                                        |Context.BIND_IMPORTANT)) != 0) {
                                    if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
                                        newAdj = clientAdj;
                                    } else {
                                        // make this service persistent
                                        newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
                                        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                        procState = ActivityManager.PROCESS_STATE_PERSISTENT;
                                    }
                                } else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0
                                        && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                        && adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) {
                                    newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1;
                                } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                        && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                        && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                    newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
                                    newAdj = clientAdj;
                                } else {
                                    if (adj > ProcessList.VISIBLE_APP_ADJ) {
                                        newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
                                    } else {
                                        newAdj = adj;
                                    }
                                }
                                if (!client.cached) {
                                    app.cached = false;
                                }
                                if (adj >  newAdj) {
                                    adj = newAdj;
                                    adjType = "service";
                                }
                            }
                        }
                        if ((cr.flags & (Context.BIND_NOT_FOREGROUND
                                | Context.BIND_IMPORTANT_BACKGROUND)) == 0) {
                            // This will treat important bound services identically to
                            // the top app, which may behave differently than generic
                            // foreground work.
                            if (client.curSchedGroup > schedGroup) {
                                if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                                    schedGroup = client.curSchedGroup;
                                } else {
                                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                }
                            }
                            if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
                                if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
                                    // Special handling of clients who are in the top state.
                                    // We *may* want to consider this process to be in the
                                    // top state as well, but only if there is not another
                                    // reason for it to be running.  Being on the top is a
                                    // special state, meaning you are specifically running
                                    // for the current top app.  If the process is already
                                    // running in the background for some other reason, it
                                    // is more important to continue considering it to be
                                    // in the background state.
                                    mayBeTop = true;
                                    mayBeTopType = "service";
                                    mayBeTopSource = cr.binding.client;
                                    mayBeTopTarget = s.name;
                                    clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                                } else {
                                    // Special handling for above-top states (persistent
                                    // processes).  These should not bring the current process
                                    // into the top state, since they are not on top.  Instead
                                    // give them the best state after that.
                                    if ((cr.flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
                                        clientProcState =
                                                ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                    } else if (mWakefulness
                                                    == PowerManagerInternal.WAKEFULNESS_AWAKE &&
                                            (cr.flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
                                                    != 0) {
                                        clientProcState =
                                                ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                    } else {
                                        clientProcState =
                                                ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
                                    }
                                }
                            }
                        } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
                            if (clientProcState <
                                    ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
                                clientProcState =
                                        ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
                            }
                        } else {
                            if (clientProcState <
                                    ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
                                clientProcState =
                                        ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
                            }
                        }
                        if (procState > clientProcState) {
                            procState = clientProcState;
                            if (adjType == null) {
                                adjType = "service";
                            }
                        }
                        if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                                && (cr.flags&Context.BIND_SHOWING_UI) != 0) {
                            app.pendingUiClean = true;
                        }
                        if (adjType != null) {
                            app.adjType = adjType;
                            app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                    .REASON_SERVICE_IN_USE;
                            app.adjSource = cr.binding.client;
                            app.adjSourceProcState = clientProcState;
                            app.adjTarget = s.name;
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                        + ": " + app + ", due to " + cr.binding.client
                                        + " adj=" + adj + " procState="
                                        + ProcessList.makeProcStateString(procState));
                            }
                        }
                    }
                    if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                        app.treatLikeActivity = true;
                    }
                    //是指当从Activity绑定到该进程时,允许目标服务进程根据该activity的可见性来提升优先级
                    final ActivityRecord a = cr.activity;
                    if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
                        if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && (a.visible
                                || a.isState(ActivityState.RESUMED, ActivityState.PAUSING))) {
                            adj = ProcessList.FOREGROUND_APP_ADJ;
                            if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                                if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                                    schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
                                } 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;
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                        "Raise to service w/activity: " + app);
                            }
                        }
                    }
                }
            }
        }

第五部分:
分为两个部分:

  1. 根据当前进程的Service来调整当前进程的优先级
  2. 根据绑定在当前进程Service上的客户端进程来调整优先级

ServiceRecord的成员变量startRequested=true,是指被显式调用了startService()方法。当service被stop或kill会将其置为false。

一般情况下,即便客户端进程处于前台进程(ADJ=0)级别,服务进程只会提升到可见(ADJ=1)级别。以下flags是由调用bindService()过程所传递的flags来决定的。

flag 含义
BIND_WAIVE_PRIORITY 是指客户端进程的优先级不会影响目标服务进程的优先级。比如当调用bindService又不希望提升目标服务进程的优先级的情况下,可以使用该flags
BIND_ADJUST_WITH_ACTIVITY 是指当从Activity绑定到该进程时,允许目标服务进程根据该activity的可见性来提升优先级
BIND_ABOVE_CLIENT 当客户端进程绑定到一个服务进程时,则服务进程比客户端进程更重要
BIND_IMPORTANT 标记该服务对于客户端进程很重要,当客户端进程处于前台进程(ADJ=0)级别时,会把服务进程也提升到前台进程级别
BIND_NOT_VISIBLE 当客户端进程处于可见(ADJ=1)级别,也不允许被绑定的服务进程提升到可见级别,该类服务进程的优先级上限为可感知(ADJ=2)级别
BIND_NOT_FOREGROUND 不允许被绑定的服务进程提升到前台调度优先级,但是内存优先级可以提升到前台级别。比如不希望服务进程占用

具体服务端进程受客户端进程影响的ADJ上限如下:

BIND_ABOVE_CLIENT或BIND_IMPORTANT的情况下,ADJ上限为PERSISTENT_SERVICE_ADJ;
BIND_NOT_VISIBLE的情况下, ADJ上限为PERCEPTIBLE_APP_ADJ;
否则,一般情况下,ADJ上限为VISIBLE_APP_ADJ;
由此,可见当bindService过程带有BIND_ABOVE_CLIENT或者BIND_IMPORTANT flags的同时,客户端进程ADJ小于或等于PERSISTENT_SERVICE_ADJ的情况下,该进程则为PERSISTENT_SERVICE_ADJ。另外,即便是启动过Activity的进程,当客户端进程ADJ<=200时,还是可以提升该服务进程的优先级。

        // 根据 ContentProvider调整进程ADJ 
        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);
            //根据client来调整provider进程的adj和procState
            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;
                }
                computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
                if (client.containsCycle) {
                    // We've detected a cycle. We should retry computeOomAdjLocked later in
                    // case a later-checked connection from a client  would raise its
                    // priority legitimately.
                    app.containsCycle = true;
                    // If the client has not been completely evaluated, skip using its
                    // priority. Else use the conservative value for now and look for a
                    // better state in the next iteration.
                    if (client.completedAdjSeq < mAdjSeq) {
                        continue;
                    }
                }
                int clientAdj = client.curRawAdj;
                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;
                }
                String adjType = null;
                if (adj > clientAdj) {
                    if (app.hasShownUi && app != mHomeProcess
                            && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                        adjType = "cch-ui-provider";
                    } else {
                        adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
                                ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
                        adjType = "provider";
                    }
                    app.cached &= client.cached;
                }
                if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
                    if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
                        // Special handling of clients who are in the top state.
                        // We *may* want to consider this process to be in the
                        // top state as well, but only if there is not another
                        // reason for it to be running.  Being on the top is a
                        // special state, meaning you are specifically running
                        // for the current top app.  If the process is already
                        // running in the background for some other reason, it
                        // is more important to continue considering it to be
                        // in the background state.
                        mayBeTop = true;
                        clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                        mayBeTopType = adjType = "provider-top";
                        mayBeTopSource = client;
                        mayBeTopTarget = cpr.name;
                    } else {
                        // Special handling for above-top states (persistent
                        // processes).  These should not bring the current process
                        // into the top state, since they are not on top.  Instead
                        // give them the best state after that.
                        clientProcState =
                                ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                        if (adjType == null) {
                            adjType = "provider";
                        }
                    }
                }
                if (procState > clientProcState) {
                    procState = clientProcState;
                }
                if (client.curSchedGroup > schedGroup) {
                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                }
                if (adjType != null) {
                    app.adjType = adjType;
                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                            .REASON_PROVIDER_IN_USE;
                    app.adjSource = client;
                    app.adjSourceProcState = clientProcState;
                    app.adjTarget = cpr.name;
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                + ": " + app + ", due to " + client
                                + " adj=" + adj + " procState="
                                + ProcessList.makeProcStateString(procState));
                    }
                }
            }
            // If the provider has external (non-framework) process
            // dependencies, ensure that its adjustment is at least
            // FOREGROUND_APP_ADJ.
           //根据provider外部依赖情况来调整adj和schedGroup
            if (cpr.hasExternalProcessHandles()) {
                if (adj > ProcessList.FOREGROUND_APP_ADJ) {
                    adj = ProcessList.FOREGROUND_APP_ADJ;
                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                    app.cached = false;
                    app.adjType = "ext-provider";
                    app.adjTarget = cpr.name;
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise adj to external provider: " + app);
                    }
                }
                if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
                    procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                            "Raise procstate to external provider: " + app);
                }
            }
        }

        if (app.lastProviderTime > 0 &&
                (app.lastProviderTime+mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
            if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                adj = ProcessList.PREVIOUS_APP_ADJ;
                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                app.cached = false;
                app.adjType = "recent-provider";
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                            "Raise adj to recent provider: " + app);
                }
            }
            if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
                app.adjType = "recent-provider";
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                            "Raise procstate to recent provider: " + app);
                }
            }
        }

第六部分
对于provider进程,还有以下两个条件能成为前台进程:

  1. 当Provider的客户端进程ADJ<=FOREGROUND_APP_ADJ时,则Provider进程ADJ等于FOREGROUND_APP_ADJ
  2. 当Provider有外部(非框架)进程依赖,也就是调用了getContentProviderExternal()方法,则ADJ至少等于FOREGROUND_APP_ADJ

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

第七部分
进程由SERVICE_ADJ(500)降低到SERVICE_B_ADJ(800),有以下两种情况:

A类Service占比过高:当A类Service个数 > Service总数的1/3时,则加入到B类Service。换句话说,B Service的个数至少是A Service的2倍。
内存紧张&&A类Service占用内存较高:当系统内存紧张级别(mLastMemoryLevel)高于ADJ_MEM_FACTOR_NORMAL,且该应用所占内存lastPss大于或等于CACHED_APP_MAX_ADJ级别所对应的内存阈值的1/3(默认值阈值约等于110MB)。

        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 or curProcState improved, then this process was promoted
        return app.curAdj < prevAppAdj || app.curProcState < prevProcState;
    }

第八部分:

  1. adj 变量就是前面7个部分调整后的adj值。调整完成后的adj值保存到了ProcessRecord的curRawAdj中
  2. 调整后的adj不能大于预设置的maxAdj
  3. 将调整的调度策略设置到 ProcessRecord的curSchedGroup
  4. 将调成后的进程状态设置到ProcessRecord的procState中
  5. 调整完成,记录此次调整到序号到completedAdjSeq中
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容