AMS computeOomAdjLocked 進(jìn)程優(yōu)先級(jí)調(diào)整

概述

每個(gè)進(jìn)程都有自己的優(yōu)先級(jí)adj傻昙,但是進(jìn)程的有顯示具體是如何計(jì)算的?根據(jù)什么條件決定的呢素标?computeOomAdjLocked方法主要就是來根據(jù)當(dāng)前進(jìn)程的各種條件分配合適的Adj優(yōu)先級(jí)的.

ADJ優(yōu)先級(jí)介紹

ADJ取值 進(jìn)程類別 含義
-1000 NATIVE_ADJ native進(jìn)程
-900 SYSTEM_ADJ System_server進(jìn)程
-800 PERSISTENT_PROC_ADJ 系統(tǒng)persistent進(jìn)程
-700 PERSISTENT_SERVICE_ADJ 系統(tǒng)或者persistent進(jìn)程綁定的進(jìn)程
0 FOREGROUND_APP_ADJ 前臺(tái)進(jìn)程 :和用戶交互的進(jìn)程,不到萬不得已不能殺死
100 VISIBLE_APP_ADJ 可見進(jìn)程:該進(jìn)程的某個(gè)UI組件是可以被用戶看見的院刁,但是沒有和用戶進(jìn)行交互糯钙,不能隨便殺死,影響用戶體驗(yàn)
200 PERCEPTIBLE_APP_ADJ 可感知進(jìn)程:該進(jìn)程的某個(gè)組件可以被用戶感知到退腥,如后臺(tái)音樂播放
300 BACKUP_APP_ADJ 備份進(jìn)程:不可輕易打斷任岸,否則容易引起不可修復(fù)的數(shù)據(jù)錯(cuò)誤
400 HEAVY_WEIGHT_APP_ADJ 重量級(jí)進(jìn)程
500 SERVICE_ADJ 服務(wù)進(jìn)程
600 HOME_APP_ADJ Lanucher進(jìn)程
700 PREVIOUS_APP_ADJ 上一個(gè)訪問的進(jìn)程
800 SERVICE_B_ADJ B list中的進(jìn)程
900 CACHED_APP_MIN_ADJ 不可見進(jìn)程adj最小值
906 CACHED_APP_MAX_ADJ 不可見進(jìn)程adj最大值
1001 UNKNOWN_ADJ 錯(cuò)誤的adj值

進(jìn)程狀態(tài)介紹

狀態(tài)值 進(jìn)程狀態(tài)類別 含義
-1 PROCESS_STATE_UNKNOWN 錯(cuò)誤的進(jìn)程狀態(tài)
0 PROCESS_STATE_PERSISTENT persistent進(jìn)程
1 PROCESS_STATE_PERSISTENT_UI 該進(jìn)程是persistent進(jìn)程并且有UI界面顯示
2 PROCESS_STATE_TOP 運(yùn)行Top Activity正在和用戶交互的進(jìn)程
3 PROCESS_STATE_FOREGROUND_SERVICE 運(yùn)行了Foreground service的進(jìn)程
4 PROCESS_STATE_BOUND_FOREGROUND_SERVICE 運(yùn)行有系統(tǒng)綁定的前臺(tái)服務(wù)
5 PROCESS_STATE_IMPORTANT_FOREGROUND 用戶可感知的重要進(jìn)程
6 PROCESS_STATE_IMPORTANT_BACKGROUND 用戶不可感知的重要進(jìn)程
7 PROCESS_STATE_TRANSIENT_BACKGROUND
8 PROCESS_STATE_BACKUP 備份進(jìn)程
9 PROCESS_STATE_SERVICE 后臺(tái)運(yùn)行Service的進(jìn)程
10 PROCESS_STATE_RECEIVER 后臺(tái)運(yùn)行廣播的進(jìn)程
11 PROCESS_STATE_TOP_SLEEPING 設(shè)備處于Sleep狀態(tài)時(shí)的Top進(jìn)程
12 PROCESS_STATE_HEAVY_WEIGHT
13 PROCESS_STATE_HOME Launcher進(jìn)程
14 PROCESS_STATE_LAST_ACTIVITY 上一個(gè)Activity所處的進(jìn)程
15 PROCESS_STATE_CACHED_ACTIVITY 包含Activity且處于緩存狀態(tài)的進(jìn)程
16 PROCESS_STATE_CACHED_ACTIVITY_CLIENT 處于緩存狀態(tài)且是另一個(gè)緩存狀態(tài)進(jìn)程的Client進(jìn)程
17 PROCESS_STATE_CACHED_RECENT
18 PROCESS_STATE_CACHED_EMPTY 緩存空進(jìn)程
19 PROCESS_STATE_NONEXISTENT 不存在的進(jìn)程

如何調(diào)整優(yōu)先級(jí)

AMS中將進(jìn)程分為來這么多個(gè)優(yōu)先級(jí)等級(jí),但是AMS是如何給每個(gè)進(jìn)程分配優(yōu)先級(jí)的呢狡刘?這個(gè)過程主要是在computeOomAdjLocked方法中處理的享潜。

ComputeOomAdjLocked 計(jì)算進(jìn)程的Adj值


    private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
            boolean doingAll, long now) {
        // mAdjSeq 是 adj調(diào)整的序號(hào),每次進(jìn)行一輪調(diào)整的時(shí)候 mAdjSeq 加1嗅蔬,進(jìn)程ProcessRecord的adjSeq
        //代表最后一次計(jì)算的mAdjSeq的序號(hào)
        // 如果當(dāng)前進(jìn)程的adjSeq == mAdjSeq說明剑按,當(dāng)前進(jìn)程ProcessRecord已經(jīng)計(jì)算adj完成疾就,無需再次計(jì)算
        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;
            }
        }

        //如果當(dāng)前進(jìn)程的ActivityThread = NULL, 說明當(dāng)前進(jìn)程沒有真正運(yùn)行的實(shí)體艺蝴,是一個(gè)緩存的進(jìn)程
        //直接將當(dāng)前進(jìn)程設(shè)置為緩存進(jìn)程之后猬腰,該進(jìn)程的adj計(jì)算就算完成了
        // 當(dāng)前進(jìn)程的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;

        //處理某一個(gè)進(jìn)程的maxAdj <= FOREGROUND_APP_ADJ ( 0 )情況???????????????????,此類進(jìn)程屬于系統(tǒng)級(jí)重要進(jìn)程
        //maxAdj是ProcessRecord在創(chuàng)建的時(shí)候設(shè)置的一個(gè)允許該進(jìn)程最大的adj值
        //搜索系統(tǒng)中maxAdj設(shè)置的地方猜敢,只有system_server進(jìn)程啟動(dòng)的時(shí)候和系統(tǒng)persistent進(jìn)程啟動(dòng)的
        //時(shí)候會(huì)進(jìn)行設(shè)置姑荷,所以只要maxAdj小于FOREGROUND_APP_ADJ  0的時(shí)候,此時(shí)是系統(tǒng)的一些重
        //要的進(jìn)程缩擂,不需要在調(diào)整adj鼠冕,只需呀設(shè)置為maxAdj即可。
        if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
            //初始化進(jìn)程相關(guān)信息
            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;
            //判斷當(dāng)前的系統(tǒng)進(jìn)程是否包含正在顯示的UI,根據(jù)是否顯示UI來設(shè)置進(jìn)程的curProcState以及進(jìn)程調(diào)度策略
            app.systemNoUi = true;
            if (app == TOP_APP) {
                //如果當(dāng)前系統(tǒng)進(jìn)程屬于TOP_APP, 那這個(gè)進(jìn)程一定含有UI
                app.systemNoUi = false;
                app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
                app.adjType = "pers-top-activity";
            } else if (app.hasTopUi) {
                // 如果當(dāng)前系統(tǒng)進(jìn)程有TopUI
                app.systemNoUi = false;
                app.adjType = "pers-top-ui";
            } else if (activitiesSize > 0) {
                // 當(dāng)前進(jìn)程有正在顯示的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) {
                  // 屏幕顯示胯盯,且當(dāng)前進(jìn)程有UI界面
                  app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
                  app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
              } else {
                  // 屏幕休眠懈费,且當(dāng)前進(jìn)程有UI界面
                  app.curProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                  app.curSchedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
              }
            }
            app.curAdj = app.maxAdj;
            app.completedAdjSeq = app.adjSeq;
            // 如果此次的計(jì)算的Adj<上次的Adj, 說明adj計(jì)算完成了
            return app.curAdj < prevAppAdj;
        }

第一部分:

  1. 判斷進(jìn)程在此次調(diào)整中是否調(diào)整完畢,調(diào)整完畢則直接返回
  2. 如果本進(jìn)程的ActivityThread已經(jīng)掛掉了博脑, 則直接設(shè)置進(jìn)程的優(yōu)先級(jí)為CACHED_APP_MAX_ADJ = 906
  3. 計(jì)算maxAdj < FOREGROUND_APP_ADJ的情況憎乙, 系統(tǒng)自己創(chuàng)建的系統(tǒng)級(jí)進(jìn)程,設(shè)置adj為maxAdj即可趋厉,無需對(duì)Adj做其他調(diào)整

ADJ < 0的進(jìn)程包括哪些進(jìn)程寨闹?

NATIVE_ADJ(-1000):是由init進(jìn)程fork出來的Native進(jìn)程,并不受system管控君账;
SYSTEM_ADJ(-900):是指system_server進(jìn)程繁堡;
PERSISTENT_PROC_ADJ(-800): 是指在AndroidManifest.xml中申明android:persistent=”true”的系統(tǒng)(即帶有FLAG_SYSTEM標(biāo)記)進(jìn)程,persistent進(jìn)程一般情況并不會(huì)被殺乡数,即便被殺或者發(fā)生Crash系統(tǒng)會(huì)立即重新拉起該進(jìn)程椭蹄。
PERSISTENT_SERVICE_ADJ(-700):是由startIsolatedProcess()方式啟動(dòng)的進(jìn)程,或者是由system_server或者persistent進(jìn)程所綁定(并且?guī)в蠦IND_ABOVE_CLIENT或者BIND_IMPORTANT)的服務(wù)進(jìn)程

        // mTopProcessState 代表運(yùn)行TopActivity的進(jìn)程狀態(tài)净赴,只有兩種狀態(tài)
        // 1 : ActivityManager.PROCESS_STATE_TOP 顯示狀態(tài)
        // 2 : ActivityManager.PROCESS_STATE_TOP_SLEEPING 休眠狀態(tài)
        final int PROCESS_STATE_CUR_TOP = mTopProcessState;

        // 開始遍歷并計(jì)算普通進(jìn)程 即adj值 > 0的情況绳矩,重要性從高到低進(jìn)行計(jì)算,然后為進(jìn)程設(shè)置一個(gè)合適的Adj優(yōu)先級(jí)
        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) {
            // 如果當(dāng)前進(jìn)程為TOP_APP進(jìn)程玖翅,即處于和用戶交互的進(jìn)程翼馆,并且當(dāng)前進(jìn)程不是休眠狀態(tài)
            // 那么先當(dāng)前進(jìn)程優(yōu)先級(jí)設(shè)置為FOREGROUND_APP_ADJ (0)
            // 進(jìn)程狀態(tài) procState 為 PROCESS_STATE_CUR_TOP
            // foregroundActivities 為 true, 表明當(dāng)前進(jìn)程包含顯示的Activity界面
            // 設(shè)置調(diào)度策略為 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) {
            // 如果是正在運(yùn)行動(dòng)畫的進(jìn)程,則設(shè)置Adj = VISIBLE_APP_ADJ = 100
            // 進(jìn)程狀態(tài)procState 為 PROCESS_STATE_CUR_TOP
            // 設(shè)置調(diào)度策略為 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) {
            //如果是正在進(jìn)行測(cè)試的進(jìn)程金度,設(shè)置進(jìn)程adj = FOREGROUND_APP_ADJ = 0
            //設(shè)置procState 進(jìn)程狀態(tài)為 PROCESS_STATE_FOREGROUND_SERVICE
            //設(shè)置調(diào)度策略為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)) {
            // 如果是一個(gè)正在接受廣播的進(jìn)程应媚,此時(shí)我們也要把這個(gè)進(jìn)程看作是前臺(tái)進(jìn)程
            // adj 設(shè)置為 FOREGROUND_APP_ADJ = 0
            // 進(jìn)程狀態(tài) procState 設(shè)置 PROCESS_STATE_RECEIVER
            // 設(shè)置調(diào)度策略為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) {
            // 如果是正在執(zhí)行service生命周期回調(diào)的進(jìn)程
            // 設(shè)置進(jìn)程adj = FOREGROUND_APP_ADJ = 0
            // 設(shè)置進(jìn)程狀態(tài) procState = PROCESS_STATE_SERVICE
            // 設(shè)置調(diào)度策略為 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) {
            // 如果當(dāng)前進(jìn)程是top進(jìn)程,且系統(tǒng)處于休眠狀態(tài)
            // 設(shè)置進(jìn)程adj = FOREGROUND_APP_ADJ
            // 設(shè)置進(jìn)程狀態(tài)procState = PROCESS_STATE_CUR_TOP
            // 設(shè)置調(diào)度策略為 SCHED_GROUP_BACKGROUND
            // foregroundActivities = true 表示當(dāng)前進(jìn)程有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 {
            // 其他進(jìn)程則默認(rèn)初始化adj = 1000, 進(jìn)程state默認(rèn)初始化為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);
            }
        }

第二部分:先處理進(jìn)程adj應(yīng)該設(shè)置為前臺(tái)進(jìn)程FOREGROUND_APP_ADJ的幾種情況

滿足以下任一條件的進(jìn)程都屬于FOREGROUND_APP_ADJ(0)優(yōu)先級(jí):

  1. 正處于resumed狀態(tài)的Activity
  2. 正執(zhí)行一個(gè)生命周期回調(diào)的Service(比如執(zhí)行onCreate,onStartCommand,onDestroy等)
  3. 正執(zhí)行onReceive()的BroadcastReceiver
  4. 通過startInstrumentation()啟動(dòng)的進(jìn)程

把這幾種情況的進(jìn)程adj設(shè)置為FOREGROUND_APP_ADJ = 0猜极, 雖然以上幾種進(jìn)程的adj值一樣中姜,即對(duì)于LowMemorykiller來講,他們的重要性是相同的跟伏,但是這些進(jìn)程的proceState不同丢胚,從AMS角度而言翩瓜,他們的重要性不一樣。此外對(duì)不同的進(jìn)程根據(jù)重要情況設(shè)置了不同的調(diào)度策略schedGroup, 通過linux的接口來使進(jìn)程有不同的調(diào)度策略携龟。

最后其他進(jìn)程adj都默認(rèn)設(shè)置為1000兔跌,進(jìn)程state 都設(shè)置初始化為CACHE_EMPTY。然后在后續(xù)的流程里再進(jìn)行處理峡蟋。

foregroundActivitys 變量用于表示當(dāng)前進(jìn)程是否有處于前臺(tái)和用戶交互的Activity

  // 開始處理包含Activity, 但是卻不在前臺(tái)的進(jìn)程
        if (!foregroundActivities && activitiesSize > 0) {
            // PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1 = 200 - 100 - 1 = 99
            //之前分析updateOomAdjLocked的第一部分時(shí)浮定,簡單提到過rankTaskLayersIfNeeded函數(shù)
            //該函數(shù)會(huì)更新包含Activity的Task的rankLayer
            //按照顯示層次從上到下,rankLayer逐漸增加层亿,對(duì)應(yīng)的最大值就是VISIBLE_APP_LAYER_MAX
            int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
            for (int j = 0; j < activitiesSize; j++) {
                            ......
                if (r.visible) {
                    // 如果進(jìn)程包含可見activity, 設(shè)置該進(jìn)程adj = VISIBLE_APP_ADJ.
                    if (adj > ProcessList.VISIBLE_APP_ADJ) {
                    //adj大于VISIBLE_APP_ADJ時(shí),才更新對(duì)應(yīng)的adj
                        //之前提到的正在處理廣播立美、服務(wù)或測(cè)試的進(jìn)程匿又,adj為FOREGROUND,是小于VISIBLE_APP_ADJ
                        //因此不會(huì)在此更新
                        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; //設(shè)置可見進(jìn)程的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進(jìn)程
                    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)) {
                                //如果進(jìn)程包含處于PAUSING或PAUSED狀態(tài)的Activity時(shí)
                            //將其oom_adj調(diào)整為“用戶可察覺”的的等級(jí)建蹄,這個(gè)等級(jí)還是很高的
                    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狀態(tài)Activity的進(jìn)程碌更,其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的進(jìn)程洞慎, state設(shè)置為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的進(jìn)程痛单,設(shè)置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);
                        }
                    }
                }
            }
                //不同可見進(jìn)程的oom_adj有一定的差異,處在下層的oom_adj越大
            //即越老的Activity所在進(jìn)程劲腿,重要性越低
            if (adj == ProcessList.VISIBLE_APP_ADJ) {
                adj += minLayer;
            }
        }

  if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
            if (app.foregroundServices) {
                // oregroundServices非空:前臺(tái)服務(wù)進(jìn)程旭绒,執(zhí)行startForegroundService()方法, 此時(shí)該進(jìn)程為可感知進(jìn)程
                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) {
                // 進(jìn)程有OverlayUI 該進(jìn)程為可感知進(jìn)程.
                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非空:執(zhí)行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);
                }
            }
        }

第三部分:

根據(jù)進(jìn)程的Activity狀態(tài)和Service狀態(tài)決定Adj

  • VISIBLE_APP_ADJ 可見進(jìn)程:
    進(jìn)程中存在可見Activity
  • PERCEPTIBLE_APP_ADJ 可感知進(jìn)程:
    1.進(jìn)程中存在處于PAUSING焦人、PAUSED或STOPPING狀態(tài)的Activity時(shí)
    2.foregroundServices非空:前臺(tái)服務(wù)進(jìn)程挥吵,執(zhí)行startForegroundService()方法
    3.app.forcingToImportant非空:執(zhí)行setProcessImportant()方法,比如Toast彈出過程花椭。
    4.hasOverlayUi非空:非activity的UI位于屏幕最頂層忽匈,比如顯示類型TYPE_APPLICATION_OVERLAY的窗口進(jìn)程.

其余的進(jìn)程仍是UNKNOW_ADJ。

        //開始處理一些特殊的進(jìn)程

      //如果進(jìn)程是heavyWeightProcess進(jìn)程矿辽, 則設(shè)置進(jìn)程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進(jìn)程丹允, 則設(shè)置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);
                }
            }
        }

        //如果進(jìn)程為前一個(gè)進(jìn)程, 則設(shè)置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;
        //如果是備份進(jìn)程袋倔, 則設(shè)置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);
                }
            }
        }

第四部分:
處理了一些特殊的進(jìn)程雕蔽,并設(shè)置其adj值和processState值

包含前臺(tái)服務(wù)的進(jìn)程
重量級(jí)進(jìn)程
Home進(jìn)程
previous進(jìn)程
Backup進(jìn)程

        //根據(jù)Service來調(diào)整進(jìn)程優(yōu)先級(jí)
        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);
            //當(dāng)前進(jìn)程的Service是startService方式啟動(dòng)的
            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之內(nèi)活躍過的Service服務(wù),將該進(jìn)程的優(yōu)先級(jí)設(shè)置為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";
                    }
                }
            }

           //根據(jù)綁定該Service的客戶端進(jìn)程來調(diào)整當(dāng)前進(jìn)程的優(yōu)先級(jí)
            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) {
                        // 是自己進(jìn)程綁定的當(dāng)前Service服務(wù)奕污,無需處理
                        continue;
                    }
                    //BIND_WAIVE_PRIORITY
                    //是指客戶端進(jìn)程的優(yōu)先級(jí)不會(huì)影響目標(biāo)服務(wù)進(jìn)程的優(yōu)先級(jí)萎羔。比如當(dāng)調(diào)用bindService
                    //又不希望提升目標(biāo)服務(wù)進(jìn)程的優(yōu)先級(jí)的情況下,可以使用該flags
                    // 根據(jù)Srevise Client進(jìn)程來調(diào)整當(dāng)前進(jìn)程的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;
                    }
                    //是指當(dāng)從Activity綁定到該進(jìn)程時(shí)碳默,允許目標(biāo)服務(wù)進(jìn)程根據(jù)該activity的可見性來提升優(yōu)先級(jí)
                    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);
                            }
                        }
                    }
                }
            }
        }

第五部分:
分為兩個(gè)部分:

  1. 根據(jù)當(dāng)前進(jìn)程的Service來調(diào)整當(dāng)前進(jìn)程的優(yōu)先級(jí)
  2. 根據(jù)綁定在當(dāng)前進(jìn)程Service上的客戶端進(jìn)程來調(diào)整優(yōu)先級(jí)

ServiceRecord的成員變量startRequested=true贾陷,是指被顯式調(diào)用了startService()方法缘眶。當(dāng)service被stop或kill會(huì)將其置為false。

一般情況下髓废,即便客戶端進(jìn)程處于前臺(tái)進(jìn)程(ADJ=0)級(jí)別巷懈,服務(wù)進(jìn)程只會(huì)提升到可見(ADJ=1)級(jí)別。以下flags是由調(diào)用bindService()過程所傳遞的flags來決定的慌洪。

flag 含義
BIND_WAIVE_PRIORITY 是指客戶端進(jìn)程的優(yōu)先級(jí)不會(huì)影響目標(biāo)服務(wù)進(jìn)程的優(yōu)先級(jí)顶燕。比如當(dāng)調(diào)用bindService又不希望提升目標(biāo)服務(wù)進(jìn)程的優(yōu)先級(jí)的情況下,可以使用該flags
BIND_ADJUST_WITH_ACTIVITY 是指當(dāng)從Activity綁定到該進(jìn)程時(shí)冈爹,允許目標(biāo)服務(wù)進(jìn)程根據(jù)該activity的可見性來提升優(yōu)先級(jí)
BIND_ABOVE_CLIENT 當(dāng)客戶端進(jìn)程綁定到一個(gè)服務(wù)進(jìn)程時(shí)涌攻,則服務(wù)進(jìn)程比客戶端進(jìn)程更重要
BIND_IMPORTANT 標(biāo)記該服務(wù)對(duì)于客戶端進(jìn)程很重要,當(dāng)客戶端進(jìn)程處于前臺(tái)進(jìn)程(ADJ=0)級(jí)別時(shí)频伤,會(huì)把服務(wù)進(jìn)程也提升到前臺(tái)進(jìn)程級(jí)別
BIND_NOT_VISIBLE 當(dāng)客戶端進(jìn)程處于可見(ADJ=1)級(jí)別恳谎,也不允許被綁定的服務(wù)進(jìn)程提升到可見級(jí)別,該類服務(wù)進(jìn)程的優(yōu)先級(jí)上限為可感知(ADJ=2)級(jí)別
BIND_NOT_FOREGROUND 不允許被綁定的服務(wù)進(jìn)程提升到前臺(tái)調(diào)度優(yōu)先級(jí)憋肖,但是內(nèi)存優(yōu)先級(jí)可以提升到前臺(tái)級(jí)別因痛。比如不希望服務(wù)進(jìn)程占用

具體服務(wù)端進(jìn)程受客戶端進(jìn)程影響的ADJ上限如下:

BIND_ABOVE_CLIENT或BIND_IMPORTANT的情況下,ADJ上限為PERSISTENT_SERVICE_ADJ岸更;
BIND_NOT_VISIBLE的情況下鸵膏, ADJ上限為PERCEPTIBLE_APP_ADJ;
否則怎炊,一般情況下谭企,ADJ上限為VISIBLE_APP_ADJ;
由此评肆,可見當(dāng)bindService過程帶有BIND_ABOVE_CLIENT或者BIND_IMPORTANT flags的同時(shí)赞咙,客戶端進(jìn)程ADJ小于或等于PERSISTENT_SERVICE_ADJ的情況下,該進(jìn)程則為PERSISTENT_SERVICE_ADJ糟港。另外攀操,即便是啟動(dòng)過Activity的進(jìn)程,當(dāng)客戶端進(jìn)程ADJ<=200時(shí)秸抚,還是可以提升該服務(wù)進(jìn)程的優(yōu)先級(jí)速和。

        // 根據(jù) ContentProvider調(diào)整進(jìn)程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);
            //根據(jù)client來調(diào)整provider進(jìn)程的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.
           //根據(jù)provider外部依賴情況來調(diào)整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);
                }
            }
        }

第六部分
對(duì)于provider進(jìn)程,還有以下兩個(gè)條件能成為前臺(tái)進(jìn)程:

  1. 當(dāng)Provider的客戶端進(jìn)程ADJ<=FOREGROUND_APP_ADJ時(shí)剥汤,則Provider進(jìn)程ADJ等于FOREGROUND_APP_ADJ
  2. 當(dāng)Provider有外部(非框架)進(jìn)程依賴颠放,也就是調(diào)用了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;
            }
        }

第七部分
進(jìn)程由SERVICE_ADJ(500)降低到SERVICE_B_ADJ(800)吭敢,有以下兩種情況:

A類Service占比過高:當(dāng)A類Service個(gè)數(shù) > Service總數(shù)的1/3時(shí)碰凶,則加入到B類Service。換句話說,B Service的個(gè)數(shù)至少是A Service的2倍欲低。
內(nèi)存緊張&&A類Service占用內(nèi)存較高:當(dāng)系統(tǒng)內(nèi)存緊張級(jí)別(mLastMemoryLevel)高于ADJ_MEM_FACTOR_NORMAL辕宏,且該應(yīng)用所占內(nèi)存lastPss大于或等于CACHED_APP_MAX_ADJ級(jí)別所對(duì)應(yīng)的內(nèi)存閾值的1/3(默認(rèn)值閾值約等于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個(gè)部分調(diào)整后的adj值砾莱。調(diào)整完成后的adj值保存到了ProcessRecord的curRawAdj中
  2. 調(diào)整后的adj不能大于預(yù)設(shè)置的maxAdj
  3. 將調(diào)整的調(diào)度策略設(shè)置到 ProcessRecord的curSchedGroup
  4. 將調(diào)成后的進(jìn)程狀態(tài)設(shè)置到ProcessRecord的procState中
  5. 調(diào)整完成瑞筐,記錄此次調(diào)整到序號(hào)到completedAdjSeq中
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市腊瑟,隨后出現(xiàn)的幾起案子聚假,更是在濱河造成了極大的恐慌,老刑警劉巖闰非,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膘格,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡财松,警方通過查閱死者的電腦和手機(jī)闯袒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來游岳,“玉大人,你說我怎么就攤上這事其徙∨咂龋” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵唾那,是天一觀的道長访锻。 經(jīng)常有香客問我,道長闹获,這世上最難降的妖魔是什么期犬? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮避诽,結(jié)果婚禮上龟虎,老公的妹妹穿的比我還像新娘。我一直安慰自己沙庐,他們只是感情好鲤妥,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拱雏,像睡著了一般棉安。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铸抑,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天贡耽,我揣著相機(jī)與錄音,去河邊找鬼。 笑死蒲赂,一個(gè)胖子當(dāng)著我的面吹牛阱冶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凳宙,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼熙揍,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了氏涩?” 一聲冷哼從身側(cè)響起届囚,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎是尖,沒想到半個(gè)月后意系,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饺汹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年蛔添,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兜辞。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡迎瞧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出逸吵,到底是詐尸還是另有隱情凶硅,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布扫皱,位于F島的核電站足绅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏韩脑。R本人自食惡果不足惜氢妈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望段多。 院中可真熱鬧首量,春花似錦、人聲如沸进苍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琅捏。三九已至生百,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間柄延,已是汗流浹背蚀浆。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國打工缀程, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人市俊。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓杨凑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親摆昧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子撩满,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容