Android進程調度之adj算法

一、概述

提到進程調度,可能大家首先想到的是cpu調度算法,進程優先級這些概念,本文并不打算介紹這些內容,而是介紹Android framework層中承載activity/service/contentprovider/broadcastrecevier的進程是如何根據組件運行狀態而動態調節進程自身的狀態。進程有兩個比較重要的狀態值,即adj(定義在 ProcessList.java )和procState(定義在 ActivityManager.java )。

1.1 核心方法

調整進程的adj的3大護法:

  • updateOomAdjLocked :更新adj,當目標進程為空,或者被殺則返回false;否則返回true;
  • computeOomAdjLocked :計算adj,返回計算后RawAdj值;
  • applyOomAdjLocked :應用adj,當需要殺掉目標進程則返回false;否則返回true。

前面提到調整adj的3大護法,最為常見的方法便是computeOomAdjLocked,這也是其他各個方法在需要更新adj時會調用的方法,該方法有3個不同參數的同名方法,定義如下:

無參方法:updateOomAdjLocked()
一參方法:updateOomAdjLocked(ProcessRecord app)
三參方法:updateOomAdjLocked(ProcessRecord app, int cachedAdj,
    ProcessRecord TOP_APP, boolean doingAll, long now)

updateOomAdjLocked的實現過程中依次會 computeOomAdjLocked 和 applyOomAdjLocked 。

1.2 使用場景

到底哪些地方會需要updateOomAdjLocked呢,其實很多地方,下面列舉常見場景:

  • Activity的start/resume/finish;
  • Service的start/bind/unbind;
  • broadcast的分發/處理;
  • contentprovider的發布/移除/獲取;
  • 進程的kill/attach等。

二、ADJ算法

ADJ算法,其核心也就是updateOomAdjLocked方法。

2.1 一參updateOomAdjLocked

[-> ActivityManagerService.java]

final boolean updateOomAdjLocked(ProcessRecord app) {
    //獲取棧頂的Activity
    final ActivityRecord TOP_ACT = resumedAppLocked();
    final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
    final boolean wasCached = app.cached;

mAdjSeq++;

//確保cachedAdj>=9
final int cachedAdj = app.curRawAdj >= ProcessList.CACHED_APP_MIN_ADJ
        ? app.curRawAdj : ProcessList.UNKNOWN_ADJ;

//執行三參updateOomAdjLocked【見小節2.2】
boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
        SystemClock.uptimeMillis());

//當app cached狀態改變,或者curRawAdj=16,則執行無參數updateOomAdjLocked【見小節2.3】
if (wasCached != app.cached || app.curRawAdj == ProcessList.UNKNOWN_ADJ) {
    updateOomAdjLocked();
}
return success;

}</code></pre>

該方法:

  1. 執行 三參updateOomAdjLocked ;
  2. 當app經過更新adj操作后,其cached狀態改變(包括由cached變成非cached,或者非cached變成cached),或者curRawAdj=16,則執行``無參updateOomAdjLocked`;

2.2 三參updateOomAdjLocked

private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
        ProcessRecord TOP_APP, boolean doingAll, long now) {
    if (app.thread == null) {
        return false;
    }
    //【見小節2.4】
    computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);

//【見小節2.5】
return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());

}</code></pre>

該方法是private方法,只提供給一參和無參的同名方法調用,系統中并沒有其他地方調用。

2.3 無參updateOomAdjLocked

2.3.1 涉及的部分參數

[-> ProcessList.java]

  • 空進程存活時長: MAX_EMPTY_TIME = 30min
  • (緩存+空)進程個數上限: MAX_CACHED_APPS = SystemProperties.getInt(“sys.fw.bg_apps_limit”,32) = 32(默認);
  • 空進程個數上限: MAX_EMPTY_APPS = computeEmptyProcessLimit(MAX_CACHED_APPS) = MAX_CACHED_APPS/2 = 16;
  • trim空進程個數上限: TRIM_EMPTY_APPS = computeTrimEmptyApps() = MAX_EMPTY_APPS/2 = 8;
  • trim緩存進程個數上限: TRIM_CACHED_APPS = computeTrimCachedApps() = MAX_CACHED_APPS-MAX_EMPTY_APPS)/3 = 5;
  • TRIM_CRITICAL_THRESHOLD = 3;

[-> AMS.java]

  • mBServiceAppThreshold = SystemProperties.getInt(“ro.sys.fw.bservice_limit”, 5);
  • mMinBServiceAgingTime =SystemProperties.getInt(“ro.sys.fw.bservice_age”, 5000);
  • mProcessLimit = ProcessList.MAX_CACHED_APPS
  • mProcessLimit = emptyProcessLimit(空進程上限) + cachedProcessLimit(緩存進程上限)
  • oldTime = now - ProcessList.MAX_EMPTY_TIME;
  • LRU進程隊列長度 = numEmptyProcs(空進程數) + mNumCachedHiddenProcs(cached進程) + mNumNonCachedProcs(非cached進程)
  • emptyFactor = numEmptyProcs/3, 且大于等于1
  • cachedFactor = mNumCachedHiddenProcs/3, 且大于等于1

2.3.2 代碼

final void updateOomAdjLocked() {
    //獲取棧頂的Activity
    final ActivityRecord TOP_ACT = resumedAppLocked();
    final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
    final long now = SystemClock.uptimeMillis();
    final long nowElapsed = SystemClock.elapsedRealtime();
    final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
    final int N = mLruProcesses.size();

//重置所有uid記錄,把curProcState設置成16(空進程)
for (int i=mActiveUids.size()-1; i>=0; i--) {
    final UidRecord uidRec = mActiveUids.valueAt(i);
    uidRec.reset();
}

mAdjSeq++;
mNewNumServiceProcs = 0;
mNewNumAServiceProcs = 0;

final int emptyProcessLimit;
final int cachedProcessLimit;
// mProcessLimit默認值等于32,通過開發者選擇可設置,或者廠商會自行調整
if (mProcessLimit <= 0) {
    emptyProcessLimit = cachedProcessLimit = 0;
} else if (mProcessLimit == 1) {
    emptyProcessLimit = 1;
    cachedProcessLimit = 0;
} else {
    //則emptyProcessLimit = 16, cachedProcessLimit = 16
    emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
    cachedProcessLimit = mProcessLimit - emptyProcessLimit;
}

//經過計算得 numSlots =3
int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
        - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;

//確保空進程個數不大于cached進程數
if (numEmptyProcs > cachedProcessLimit) {
    numEmptyProcs = cachedProcessLimit;
}
int emptyFactor = numEmptyProcs/numSlots;
if (emptyFactor < 1) emptyFactor = 1;
int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
if (cachedFactor < 1) cachedFactor = 1;
int stepCached = 0;
int stepEmpty = 0;
int numCached = 0;
int numEmpty = 0;
int numTrimming = 0;

mNumNonCachedProcs = 0;
mNumCachedHiddenProcs = 0;

//更新所有進程狀態(基于當前狀態)
int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextCachedAdj = curCachedAdj+1;
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextEmptyAdj = curEmptyAdj+2;
ProcessRecord selectedAppRecord = null;
long serviceLastActivity = 0;
int numBServices = 0;
for (int i=N-1; i>=0; i--) {
    ProcessRecord app = mLruProcesses.get(i);
    if (mEnableBServicePropagation && app.serviceb
            && (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
        numBServices++;
        for (int s = app.services.size() - 1; s >= 0; s--) {
            ServiceRecord sr = app.services.valueAt(s);
            //上次活躍時間距離現在小于5s,則不會遷移到BService
            if (SystemClock.uptimeMillis() - sr.lastActivity
                    < mMinBServiceAgingTime) {
                continue;
            }
            if (serviceLastActivity == 0) {
                serviceLastActivity = sr.lastActivity;
                selectedAppRecord = app;
            //記錄service上次活動時間最長的那個app
            } else if (sr.lastActivity < serviceLastActivity) {
                serviceLastActivity = sr.lastActivity;
                selectedAppRecord = app;
            }
        }
    }

    if (!app.killedByAm && app.thread != null) {
        app.procStateChanged = false;
        //計算app的adj值【見小節2.4】
        computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);

        //當進程未分配adj的情況下,更新adj(cached和empty算法是相同的)
        if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
            switch (app.curProcState) {
                case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                    //當進程procState=14或15,則設置adj=9;
                    app.curRawAdj = curCachedAdj;
                    app.curAdj = app.modifyRawOomAdj(curCachedAdj);
                    //當前cacheadj不等于下一次cachedadj時
                    if (curCachedAdj != nextCachedAdj) {
                        stepCached++;
                        //當stepCached大于cachedFactor,則將nextCachedAdj賦值給curCachedAdj,并且nextCachedAdj加2,nextCachedAdj最大等于15;
                        if (stepCached >= cachedFactor) {
                            stepCached = 0;
                            curCachedAdj = nextCachedAdj;
                            nextCachedAdj += 2;
                            if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                            }
                        }
                    }
                    break;
                default:
                    app.curRawAdj = curEmptyAdj;
                    app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                    //更新curCachedAdj值
                    if (curEmptyAdj != nextEmptyAdj) {
                        stepEmpty++;
                        //當stepEmpty大于emptyFactor,則將nextEmptyAdj賦值給curEmptyAdj,并且nextEmptyAdj加2,nextEmptyAdj最大等于15;
                        if (stepEmpty >= emptyFactor) {
                            stepEmpty = 0;
                            curEmptyAdj = nextEmptyAdj;
                            nextEmptyAdj += 2;
                            if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                            }
                        }
                    }
                    break;
            }
        }

        //【見小節2.5】
        applyOomAdjLocked(app, true, now, nowElapsed);

        //根據當前進程procState狀態來決策
        switch (app.curProcState) {
            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                mNumCachedHiddenProcs++;
                numCached++;
                // 當cached進程超過上限(cachedProcessLimit),則殺掉該進程
                if (numCached > cachedProcessLimit) {
                    app.kill("cached #" + numCached, true);
                }
                break;
            case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                // 當空進程超過上限(TRIM_EMPTY_APPS),且空閑時間超過30分鐘,則殺掉該進程
                if (numEmpty > ProcessList.TRIM_EMPTY_APPS
                        && app.lastActivityTime < oldTime) {
                    app.kill("empty for "
                            + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
                            / 1000) + "s", true);
                } else {
                    // 當空進程超過上限(emptyProcessLimit),則殺掉該進程
                    numEmpty++;
                    if (numEmpty > emptyProcessLimit) {
                        if (!CT_PROTECTED_PROCESS.equals(app.processName))
                            app.kill("empty #" + numEmpty, true);
                    }
                }
                break;
            default:
                mNumNonCachedProcs++;
                break;
        }

        if (app.isolated && app.services.size() <= 0) {
            //沒有services運行的孤立進程,則直接殺掉
            app.kill("isolated not needed", true);
        } else {
            final UidRecord uidRec = app.uidRecord;
            if (uidRec != null && uidRec.curProcState > app.curProcState) {
                uidRec.curProcState = app.curProcState;
            }
        }

        if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                && !app.killedByAm) {
            numTrimming++;
        }
    }
}

//當BServices個數超過上限(mBServiceAppThreshold),則
if ((numBServices > mBServiceAppThreshold) && (true == mAllowLowerMemLevel)
        && (selectedAppRecord != null)) {
    ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
            ProcessList.CACHED_APP_MAX_ADJ);
    selectedAppRecord.setAdj = selectedAppRecord.curAdj;
}
mNumServiceProcs = mNewNumServiceProcs;

//根據CachedAndEmpty個數來調整內存因子memFactor
final int numCachedAndEmpty = numCached + numEmpty;
int memFactor;
if (numCached <= ProcessList.TRIM_CACHED_APPS
        && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
    if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
        memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
    } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
        memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
    } else {
        memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
    }
} else {
    memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
}

if (memFactor > mLastMemoryLevel) {
    if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
        memFactor = mLastMemoryLevel;
    }
}
mLastMemoryLevel = memFactor;
mLastNumProcesses = mLruProcesses.size();
boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
final int trackerMemFactor = mProcessStats.getMemFactorLocked();
//當內存因子不是普通0級別的情況下
if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
    if (mLowRamStartTime == 0) {
        mLowRamStartTime = now;
    }
    int step = 0;
    int fgTrimLevel;
    switch (memFactor) {
        case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
            fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
            break;
        case ProcessStats.ADJ_MEM_FACTOR_LOW:
            fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
            break;
        default:
            fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
            break;
    }
    int factor = numTrimming/3;
    int minFactor = 2;
    if (mHomeProcess != null) minFactor++;
    if (mPreviousProcess != null) minFactor++;
    if (factor < minFactor) factor = minFactor;

    //TRIM_MEMORY_COMPLETE:該進程處于LRU隊列的尾部,當進程不足則會殺掉該進程
    int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
    for (int i=N-1; i>=0; i--) {
        ProcessRecord app = mLruProcesses.get(i);
        if (allChanged || app.procStateChanged) {
            setProcessTrackerStateLocked(app, trackerMemFactor, now);
            app.procStateChanged = false;
        }
        //當curProcState > 12且沒有被am殺掉的情況;
        if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                && !app.killedByAm) {
            if (app.trimMemoryLevel < curLevel && app.thread != null) {
                //調度app執行trim memory的操作
                app.thread.scheduleTrimMemory(curLevel);
            }
            app.trimMemoryLevel = curLevel;
            step++;
            if (step >= factor) {
                step = 0;
                switch (curLevel) {
                    case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                        curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
                        break;
                    case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                        curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
                        break;
                }
            }
        } else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
            if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
                    && app.thread != null) {
                app.thread.scheduleTrimMemory(
                        ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
            }
            app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
        } else {
            if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                    || app.systemNoUi) && app.pendingUiClean) {
                final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
                if (app.trimMemoryLevel < level && app.thread != null) {
                    app.thread.scheduleTrimMemory(level);
                }
                app.pendingUiClean = false;
            }
            if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
                app.thread.scheduleTrimMemory(fgTrimLevel);
            }
            app.trimMemoryLevel = fgTrimLevel;
        }
    }
} else {
    if (mLowRamStartTime != 0) {
        mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
        mLowRamStartTime = 0;
    }
    for (int i=N-1; i>=0; i--) {
        ProcessRecord app = mLruProcesses.get(i);
        if (allChanged || app.procStateChanged) {
            setProcessTrackerStateLocked(app, trackerMemFactor, now);
            app.procStateChanged = false;
        }
        if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                || app.systemNoUi) && app.pendingUiClean) {
            if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
                    && app.thread != null) {
                app.thread.scheduleTrimMemory(
                        ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
            }
            app.pendingUiClean = false;
        }
        app.trimMemoryLevel = 0;
    }
}

//是否finish activity
if (mAlwaysFinishActivities) {
    mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
}

if (allChanged) {
    requestPssAllProcsLocked(now, false, mProcessStats.isMemFactorLowered());
}
...

}</code></pre>

2.3.3 updateOomAdjLocked小節

updateOomAdjLocked過程比較復雜,主要分為更新adj(滿足條件則殺進程)和根據memFactor來調度執行TrimMemory操作;

第一部分:更新adj(滿足條件則殺進程)

  • 遍歷mLruProcesses進程
    • 當進程未分配adj的情況
      • 當進程procState=14或15,則設置 adj=curCachedAdj(初始化=9) ;
        • 當curCachedAdj != nextCachedAdj,且stepCached大于cachedFactor時 則 curCachedAdj = nextCachedAdj ,(nextCachedAdj加2,nextCachedAdj上限為15);
        </li>
      • 否則,則設置 adj=curEmptyAdj(初始化=9) ;
        • 當curEmptyAdj != nextEmptyAdj,且stepEmpty大于EmptyFactor時 則 curEmptyAdj = nextEmptyAdj ,(nextEmptyAdj加2,nextEmptyAdj上限為15);
        • </ul> </li> </ul> </li>
        • 根據當前進程procState狀態來決策:
          • 當curProcState=14或15,且cached進程超過上限(cachedProcessLimit=32),則殺掉該進程
          • 當curProcState=16的前提下:
            • 當空進程超過上限(TRIM_EMPTY_APPS=8),且空閑時間超過30分鐘,則殺掉該進程
            • 否則,當空進程超過上限(emptyProcessLimit=16),則殺掉該進程
            • </ul> </li> </ul> </li>
            • 沒有services運行的孤立進程,則殺掉該進程;
            • </ul> </li> </ul>

              第二部分:根據memFactor來調度執行TrimMemory操作;

              • 根據CachedAndEmpty個數來調整內存因子memFactor(值越大,級別越高):
                • 當CachedAndEmpty < 3,則memFactor=3;
                • 當CachedAndEmpty < 5,則memFactor=2;
                • 當CachedAndEmpty >=5,且numCached<=5,numEmpty<=8,則memFactor=1;
                • 當numCached>5 或numEmpty>8,則memFactor=0;
                </li>
              • 當內存因子不是普通0級別的情況下,根據memFactor來調整前臺trim級別(fgTrimLevel):
                • 當memFactor=3,則fgTrimLevel=TRIM_MEMORY_RUNNING_CRITICAL;
                • 當memFactor=2,則fgTrimLevel=TRIM_MEMORY_RUNNING_LOW;
                • 否則(其實就是memFactor=1),則fgTrimLevel=TRIM_MEMORY_RUNNING_MODERATE

                • 再遍歷mLruProcesses隊列進程:
                  • 當curProcState > 12且沒有被am殺掉,則執行TrimMemory操作;
                  • 否則,當curProcState = 9 且trimMemoryLevel<TRIM_MEMORY_BACKGROUND,則執行TrimMemory操作;
                  • 否則,當curProcState > 7, 且pendingUiClean =true時
                    • 當trimMemoryLevel<TRIM_MEMORY_UI_HIDDEN,則執行TrimMemory操作;
                    • 當trimMemoryLevel<fgTrimLevel,則執行TrimMemory操作;
                    • </ul> </li> </ul> </li> </ul> </li>
                    • 當內存因子等于0的情況下,遍歷mLruProcesses隊列進程:
                      • 當curProcState >=7, 且pendingUiClean =true時,
                        • 當trimMemoryLevel< TRIM_MEMORY_UI_HIDDEN,則執行TrimMemory操作;
                        • </ul> </li> </ul> </li> </ul>

                          2.4 computeOomAdjLocked

                          private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
                                   boolean doingAll, long now);

                          該方法比較長,下面分幾個部分來展開說明: (adj和procState的取值原則是以優先級高為主)

                          2.4.1 進程為空的情況

                          if (mAdjSeq == app.adjSeq) {
                                //已經調整完成
                               return app.curRawAdj;
                           }

                          // 當進程對象為空時,則設置curProcState=16, curAdj=curRawAdj=15 if (app.thread == null) { app.adjSeq = mAdjSeq; app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ); } //app中包含的activity個數 final int activitiesSize = app.activities.size();</code></pre>

                          2.4.2 當maxAdj<=0情況

                          當maxAdj <=0的情況,也就意味這不允許app將其adj調整到低于前臺app的優先級別。

                          if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
                               app.adjType = "fixed";
                               app.adjSeq = mAdjSeq;
                               app.curRawAdj = app.maxAdj;
                               app.foregroundActivities = false;
                               app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
                               app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;

                           app.systemNoUi = true;
                           //頂部的activity就是當前app,則代表正處于展現UI
                           if (app == TOP_APP) {
                               app.systemNoUi = false;
                           } else if (activitiesSize > 0) {
                               for (int j = 0; j < activitiesSize; j++) {
                                   final ActivityRecord r = app.activities.get(j);
                                   if (r.visible) {
                                       app.systemNoUi = false;
                                   }
                               }
                           }
                           if (!app.systemNoUi) {
                               app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
                           }
                           return (app.curAdj=app.maxAdj);
                          

                          }</code></pre>

                          該過程執行后將直接返回

                          • curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
                          • curAdj = app.maxAdj

                          2.4.3 計算adj和procState

                          if (app == TOP_APP) {
                               adj = ProcessList.FOREGROUND_APP_ADJ;
                               schedGroup = Process.THREAD_GROUP_DEFAULT;
                               app.adjType = "top-activity";
                               foregroundActivities = true;
                               procState = PROCESS_STATE_TOP;
                               if(app == mHomeProcess) {
                                   mHomeKilled = false;
                                   mHomeProcessName = mHomeProcess.processName;
                               }
                           } else if (app.instrumentationClass != null) {
                               adj = ProcessList.FOREGROUND_APP_ADJ;
                               schedGroup = Process.THREAD_GROUP_DEFAULT;
                               app.adjType = "instrumentation";
                               procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
                           } else if ((queue = isReceivingBroadcast(app)) != null) {
                               adj = ProcessList.FOREGROUND_APP_ADJ;
                               schedGroup = (queue == mFgBroadcastQueue)
                                       ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
                               app.adjType = "broadcast";
                               procState = ActivityManager.PROCESS_STATE_RECEIVER;
                           } else if (app.executingServices.size() > 0) {
                               adj = ProcessList.FOREGROUND_APP_ADJ;
                               schedGroup = app.execServicesFg ?
                                       Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
                               app.adjType = "exec-service";
                               procState = ActivityManager.PROCESS_STATE_SERVICE;
                           } else {
                               //top app; isReceivingBroadcast;executingServices;除此之外則為PROCESS_STATE_CACHED_EMPTY【】
                               schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
                               adj = cachedAdj;
                               procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                               app.cached = true;
                               app.empty = true;
                               app.adjType = "cch-empty";

                           if (mHomeKilled && app.processName.equals(mHomeProcessName)) {
                               adj = ProcessList.PERSISTENT_PROC_ADJ;
                               schedGroup = Process.THREAD_GROUP_DEFAULT;
                               app.cached = false;
                               app.empty = false;
                               app.adjType = "top-activity";
                           }
                          

                          }</code></pre>

                          Case adj procState
                          當app是當前展示的app adj=0 procState=2
                          當instrumentation不為空時 adj=0 procState=4
                          當進程存在正在接收的broadcastrecevier adj=0 procState=11
                          當進程存在正在執行的service adj=0 procState=10
                          以上條件都不符合 adj=cachedAdj procState=16

                          其中cachedAdj大于等于9,該值來源于computeOomAdjLocked輸入參數

                          2.4.4 非前臺activity的情況

                          if (!foregroundActivities && activitiesSize > 0) {
                               for (int j = 0; j < activitiesSize; j++) {
                                   final ActivityRecord r = app.activities.get(j);
                                   if (r.app != app) {
                                       continue;
                                   }
                                   當activity可見, 則adj=1,procState=2
                                   if (r.visible) {
                                       if (adj > ProcessList.VISIBLE_APP_ADJ) {
                                           adj = ProcessList.VISIBLE_APP_ADJ;
                                           app.adjType = "visible";
                                       }
                                       if (procState > PROCESS_STATE_TOP) {
                                           procState = PROCESS_STATE_TOP;
                                       }
                                       schedGroup = Process.THREAD_GROUP_DEFAULT;
                                       app.cached = false;
                                       app.empty = false;
                                       foregroundActivities = true;
                                       break;
                                   當activity正在暫停或者已經暫停, 則adj=2,procState=2
                                   } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
                                       if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                           adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                           app.adjType = "pausing";
                                       }
                                       if (procState > PROCESS_STATE_TOP) {
                                           procState = PROCESS_STATE_TOP;
                                       }
                                       schedGroup = Process.THREAD_GROUP_DEFAULT;
                                       app.cached = false;
                                       app.empty = false;
                                       foregroundActivities = true;
                                   當activity正在停止, 則adj=2,procState=13(activity尚未finish)
                                   } else if (r.state == ActivityState.STOPPING) {
                                       if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                           adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                           app.adjType = "stopping";
                                       }

                                   if (!r.finishing) {
                                       if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                                           procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
                                       }
                                   }
                                   app.cached = false;
                                   app.empty = false;
                                   foregroundActivities = true;
                               否則procState=14
                               } else {
                                   if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                                       procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
                                       app.adjType = "cch-act";
                                   }
                               }
                           }
                          

                          }</code></pre>

                          對于進程中的activity處于非前臺情況

                          • 當activity可見, 則adj=1,procState=2;
                          • 當activity正在暫停或者已經暫停, 則adj=2,procState=2;
                          • 當activity正在停止, 則adj=2,procState=13(且activity尚未finish);
                          • 以上都不滿足,否則procState=14

                          2.4.5 adj > 2的情況

                          if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                               當存在前臺service時,則adj=2, procState=4;
                               if (app.foregroundServices) {
                                   adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                   procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
                                   app.cached = false;
                                   app.adjType = "fg-service";
                                   schedGroup = Process.THREAD_GROUP_DEFAULT;
                               當強制前臺時,則adj=2, procState=6;
                               } else if (app.forcingToForeground != null) {
                                   adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                   procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
                                   app.cached = false;
                                   app.adjType = "force-fg";
                                   app.adjSource = app.forcingToForeground;
                                   schedGroup = Process.THREAD_GROUP_DEFAULT;
                               }
                           }

                          當adj > 2的情況的前提下:

                          • 當存在前臺service時,則adj=2, procState=4;
                          • 當強制前臺時,則adj=2, procState=6;

                          2.4.6 HeavyWeightProces情況

                          if (app == mHeavyWeightProcess) {
                               if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
                                   adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
                                   schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
                                   app.cached = false;
                                   app.adjType = "heavy";
                               }
                               if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
                                   procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
                               }
                           }

                          當進程為HeavyWeightProcess,則adj=4, procState=9;

                          2.4.7 HomeProcess情況

                          if (app == mHomeProcess) {
                               if (adj > ProcessList.HOME_APP_ADJ) {
                                   adj = ProcessList.HOME_APP_ADJ;
                                   schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
                                   app.cached = false;
                                   app.adjType = "home";
                               }
                               if (procState > ActivityManager.PROCESS_STATE_HOME) {
                                   procState = ActivityManager.PROCESS_STATE_HOME;
                               }
                           }

                          當進程為HomeProcess情況,則adj=6, procState=12;

                          2.4.8 PreviousProcess情況

                          if (app == mPreviousProcess && app.activities.size() > 0) {
                               if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                                   adj = ProcessList.PREVIOUS_APP_ADJ;
                                   schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
                                   app.cached = false;
                                   app.adjType = "previous";
                               }
                               if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                                   procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
                               }
                           }

                          當進程為PreviousProcess情況,則adj=7, procState=13;

                          2.4.9 備份進程情況

                          if (mBackupTarget != null && app == mBackupTarget.app) {
                               if (adj > ProcessList.BACKUP_APP_ADJ) {
                                   adj = ProcessList.BACKUP_APP_ADJ;
                                   if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
                                       procState = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
                                   }
                                   app.adjType = "backup";
                                   app.cached = false;
                               }
                               if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
                                   procState = ActivityManager.PROCESS_STATE_BACKUP;
                               }
                           }

                          對于備份進程的情況,則adj=3, procState=7或8

                          2.4.10 Service情況

                          //是否顯示在最頂部
                           boolean mayBeTop = false;
                           for (int is = app.services.size()-1;
                                   is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                                           || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                                           || procState > ActivityManager.PROCESS_STATE_TOP);
                                   is--) {
                               //當adj>0 或 schedGroup為后臺線程組 或procState>2時執行
                               ServiceRecord s = app.services.valueAt(is);
                               if (s.startRequested) {
                                   app.hasStartedServices = true;
                                   //當service已啟動,則procState<=10;
                                   if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
                                       procState = ActivityManager.PROCESS_STATE_SERVICE;
                                   }
                                   if (app.hasShownUi && app != mHomeProcess) {
                                       if (adj > ProcessList.SERVICE_ADJ) {
                                           app.adjType = "cch-started-ui-services";
                                       }
                                   } else {
                                       if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) {
                                           //當service在30分鐘內活動過,則adj=5;
                                           if (adj > ProcessList.SERVICE_ADJ) {
                                               adj = ProcessList.SERVICE_ADJ;
                                               app.adjType = "started-services";
                                               app.cached = false;
                                           }
                                       }
                                       if (adj > ProcessList.SERVICE_ADJ) {
                                           app.adjType = "cch-started-services";
                                       }
                                   }
                               }

                           for (int conni = s.connections.size()-1;
                                   conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                                           || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                                           || procState > ActivityManager.PROCESS_STATE_TOP);
                                   conni--) {
                               // 獲取service所綁定的connections
                               ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
                               for (int i = 0;
                                       i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
                                               || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                                               || procState > ActivityManager.PROCESS_STATE_TOP);
                                       i++) {
                                   ConnectionRecord cr = clist.get(i);
                                   //當client與當前app同一個進程,則continue;
                                   if (cr.binding.client == app) {
                                       continue;
                                   }
                                   if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
                                       ProcessRecord client = cr.binding.client;
                                       //計算connections所對應的client進程的adj
                                       int clientAdj = computeOomAdjLocked(client, cachedAdj,
                                               TOP_APP, doingAll, now);
                                       int clientProcState = client.curProcState;
                          
                                       //當client進程的ProcState >=cache,則設置為空進程
                                       if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                                           clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                                       }
                                       String adjType = null;
                                       if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                                           //當進程存在顯示的ui,則將當前進程的adj和ProcState值賦予給client進程
                                           if (app.hasShownUi && app != mHomeProcess) {
                                               if (adj > clientAdj) {
                                                   adjType = "cch-bound-ui-services";
                                               }
                                               app.cached = false;
                                               clientAdj = adj;
                                               clientProcState = procState;
                                           } else {
                                               //當不存在顯示的ui,且service上次活動時間距離現在超過30分鐘,則只將當前進程的adj值賦予給client進程
                                               if (now >= (s.lastActivity
                                                       + ActiveServices.MAX_SERVICE_INACTIVITY)) {
                                                   if (adj > clientAdj) {
                                                       adjType = "cch-bound-services";
                                                   }
                                                   clientAdj = adj;
                                               }
                                           }
                                       }
                                       //當前進程adj > client進程adj的情況
                                       if (adj > clientAdj) {
                                           if (app.hasShownUi && app != mHomeProcess
                                                   && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                               adjType = "cch-bound-ui-services";
                                           } else {
                                               //當service進程比較重要時,設置adj >= -11
                                               if ((cr.flags&(Context.BIND_ABOVE_CLIENT
                                                       |Context.BIND_IMPORTANT)) != 0) {
                                                   adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
                                                           ? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ;
                                               //當client進程adj<2,且當前進程adj>2時,設置adj=2;
                                               } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                                       && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                                       && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                                   adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                               //當client進程adj>1時,則設置adj = clientAdj
                                               } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
                                                   adj = clientAdj;
                                               } else {
                                                   //否則,設置adj <= 1
                                                   if (adj > ProcessList.VISIBLE_APP_ADJ) {
                                                       adj = ProcessList.VISIBLE_APP_ADJ;
                                                   }
                                               }
                                               //當client進程不是cache進程,則當前進程也設置為非cache進程
                                               if (!client.cached) {
                                                   app.cached = false;
                                               }
                                               adjType = "service";
                                           }
                                       }
                          
                                       //當綁定的是前臺進程的情況
                                       if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                                           if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
                                               schedGroup = Process.THREAD_GROUP_DEFAULT;
                                           }
                                           if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
                                               //當client進程狀態為前臺時,則設置mayBeTop=true,并設置client進程procState=16
                                               if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
                                                   mayBeTop = true;
                                                   clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                                               //當client進程狀態 < 2的前提下:若綁定前臺service,則clientProcState=3;否則clientProcState=6
                                               } else {
                                                   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;
                                                   }
                                               }
                                           }
                                       //當connections并沒有綁定前臺service時,則clientProcState >= 7
                                       } else {
                                           if (clientProcState <
                                                   ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
                                               clientProcState =
                                                       ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
                                           }
                                       }
                                       //保證當前進程procState不會必client進程的procState大
                                       if (procState > clientProcState) {
                                           procState = clientProcState;
                                       }
                                       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 ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                                       app.treatLikeActivity = true;
                                   }
                                   final ActivityRecord a = cr.activity;
                                   if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
                                       //當進程adj >0,且activity可見 或者resumed 或 正在暫停,則設置adj = 0
                                       if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
                                               (a.visible || a.state == ActivityState.RESUMED
                                                || a.state == ActivityState.PAUSING)) {
                                           adj = ProcessList.FOREGROUND_APP_ADJ;
                                           if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                                               schedGroup = Process.THREAD_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;
                                       }
                                   }
                               }
                           }
                          

                          }</code></pre>

                          當adj>0 或 schedGroup為后臺線程組 或procState>2時,雙重循環遍歷:

                          • 當service已啟動,則procState<=10;
                            • 當service在30分鐘內活動過,則adj=5,cached=false;
                            </li>
                          • 獲取service所綁定的connections
                            • 當client與當前app同一個進程,則continue;
                            • 當client進程的ProcState >=cache,則設置為空進程
                            • 當進程存在顯示的ui,則將當前進程的adj和ProcState值賦予給client進程
                            • 當不存在顯示的ui,且service上次活動時間距離現在超過30分鐘,則只將當前進程的adj值賦予給client進程
                            • 當前進程adj > client進程adj的情況
                              • 當service進程比較重要時,則設置adj >= -11
                              • 當client進程adj<2,且當前進程adj>2時,則設置adj=2;
                              • 當client進程adj>1時,則設置adj = clientAdj
                              • 否則,設置adj <= 1;
                              • 若client進程不是cache進程,則當前進程也設置為非cache進程
                              • </ul> </li>
                              • 當綁定的是前臺進程的情況
                                • 當client進程狀態為前臺時,則設置mayBeTop=true,并設置client進程procState=16
                                • 當client進程狀態 < 2的前提下:若綁定前臺service,則clientProcState=3;否則clientProcState=6
                                • </ul> </li>
                                • 當connections并沒有綁定前臺service時,則clientProcState >= 7
                                • 保證當前進程procState不會必client進程的procState大
                                • </ul> </li>
                                • 當進程adj >0,且activity可見 或者resumed 或 正在暫停,則設置adj = 0
                                • </ul>

                                  2.4.11 ContentProvider情況

                                  //當adj>0 或 schedGroup為后臺線程組 或procState>2時
                                   for (int provi = app.pubProviders.size()-1;
                                           provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                                                   || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                                                   || procState > ActivityManager.PROCESS_STATE_TOP);
                                           provi--) {
                                       ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
                                       for (int i = cpr.connections.size()-1;
                                               i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                                                       || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                                                       || procState > ActivityManager.PROCESS_STATE_TOP);
                                               i--) {
                                           ContentProviderConnection conn = cpr.connections.get(i);
                                           ProcessRecord client = conn.client;
                                           // 當client與當前app同一個進程,則continue;
                                           if (client == app) {
                                               continue;
                                           }
                                           // 計算client進程的adj
                                           int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
                                           int clientProcState = client.curProcState;
                                           //當client進程procState >=14,則設置成procState =16
                                           if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                                               clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; 【】
                                           }
                                           if (adj > clientAdj) {
                                               if (app.hasShownUi && app != mHomeProcess
                                                       && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                                   app.adjType = "cch-ui-provider";
                                               } else {
                                                   //沒有ui展示,則保證adj >=0
                                                   adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
                                                           ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
                                                   app.adjType = "provider";
                                               }
                                               app.cached &= client.cached;
                                               app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                                       .REASON_PROVIDER_IN_USE;
                                               app.adjSource = client;
                                               app.adjSourceProcState = clientProcState;
                                               app.adjTarget = cpr.name;
                                           }
                                           if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
                                               if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
                                                   mayBeTop = true;
                                                   //當client進程狀態為前臺時,則設置mayBeTop=true,并設置client進程procState=16設置為空進程
                                                   clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                                               } else {
                                                   //當client進程狀態 < 2時,則clientProcState=3;
                                                   clientProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                               }
                                           }
                                           //procState 比client進程值更大時,則取client端的狀態值。
                                           if (procState > clientProcState) {
                                               procState = clientProcState;
                                           }
                                           if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
                                               schedGroup = Process.THREAD_GROUP_DEFAULT;
                                           }
                                       }
                                       //當contentprovider存在外部進程依賴(非framework)時
                                       if (cpr.hasExternalProcessHandles()) {
                                           //設置adj =0, procState=6
                                           if (adj > ProcessList.FOREGROUND_APP_ADJ) {
                                               adj = ProcessList.FOREGROUND_APP_ADJ;
                                               schedGroup = Process.THREAD_GROUP_DEFAULT;
                                               app.cached = false;
                                               app.adjType = "provider";
                                               app.adjTarget = cpr.name;
                                           }
                                           if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
                                               procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
                                           }
                                       }
                                   }

                                  當adj>0 或 schedGroup為后臺線程組 或procState>2時,雙重循環遍歷:

                                  • 當client與當前app同一個進程,則continue;
                                  • 當client進程procState >=14,則設置成procState =16
                                  • 沒有ui展示,則保證adj >=0
                                  • 當client進程狀態為前臺時,則設置mayBeTop=true,并設置client進程procState=16設置為空進程
                                  • 當client進程狀態 < 2時,則clientProcState=3;
                                  • procState 比client進程值更大時,則取client端的狀態值。
                                  • 當contentprovider存在外部進程依賴(非framework)時,則設置adj =0, procState=6

                                  2.4.12 調整adj

                                  // 當client進程處于top,且procState>2時
                                   if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) {
                                       switch (procState) {
                                           case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
                                           case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
                                           case ActivityManager.PROCESS_STATE_SERVICE:
                                               //對于procState=6,7,10時,則設置成3
                                               procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                               break;
                                           default:
                                               //其他情況,直接設置成2
                                               procState = ActivityManager.PROCESS_STATE_TOP;
                                               break;
                                       }
                                   }

                                  //當procState>= 16時, if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) { if (app.hasClientActivities) { //當進程存在client activity,則設置procState=15; procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; app.adjType = "cch-client-act"; } else if (app.treatLikeActivity) { //當進程可以像activity一樣對待時,則設置procState=14; procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; app.adjType = "cch-as-act"; } }

                                  //當adj = 5時 if (adj == ProcessList.SERVICE_ADJ) { if (doingAll) { //當A類Service個數 > service/3時,則加入到B類Service app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3); mNewNumServiceProcs++; if (!app.serviceb) { //當對于低RAM設備,則把該service直接放入B類Service if (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL && app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) { app.serviceHighRam = true; app.serviceb = true; } else { mNewNumAServiceProcs++; } } else { app.serviceHighRam = false; } } //調整adj=8 if (app.serviceb) { adj = ProcessList.SERVICE_B_ADJ; } } //將計算得到的adj賦給curRawAdj app.curRawAdj = adj;

                                  //當adj大小上限為maxAdj if (adj > app.maxAdj) { adj = app.maxAdj; if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { schedGroup = Process.THREAD_GROUP_DEFAULT; } } //對于hasAboveClient=true,則降低該進程adj app.curAdj = app.modifyRawOomAdj(adj); app.curSchedGroup = schedGroup; app.curProcState = procState; app.foregroundActivities = foregroundActivities; //返回進程的curRawAdj return app.curRawAdj; }</code></pre>

                                  2.5 AMS.applyOomAdjLocked

                                  private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
                                          long nowElapsed) {
                                      boolean success = true;

                                  //將curRawAdj賦給setRawAdj
                                  if (app.curRawAdj != app.setRawAdj) {
                                      app.setRawAdj = app.curRawAdj;
                                  }
                                  
                                  if (app.curAdj != app.setAdj) {
                                      //將adj值 發送給lmkd守護進程
                                      ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
                                      app.setAdj = app.curAdj;
                                  }
                                  
                                  //情況為: waitingToKill
                                  if (app.setSchedGroup != app.curSchedGroup) {
                                      app.setSchedGroup = app.curSchedGroup;
                                      if (app.waitingToKill != null && app.curReceiver == null
                                              && app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
                                          //殺進程,并設置applyOomAdjLocked過程失敗
                                          app.kill(app.waitingToKill, true);
                                          success = false;
                                      } else {
                                          long oldId = Binder.clearCallingIdentity();
                                          try {
                                              //設置進程組信息
                                              Process.setProcessGroup(app.pid, app.curSchedGroup);
                                          } catch (Exception e) {
                                          } finally {
                                              Binder.restoreCallingIdentity(oldId);
                                          }
                                          //調整進程的swappiness值
                                          Process.setSwappiness(app.pid,
                                                  app.curSchedGroup <= Process.THREAD_GROUP_BG_NONINTERACTIVE);
                                      }
                                  }
                                  if (app.repForegroundActivities != app.foregroundActivities) {
                                      app.repForegroundActivities = app.foregroundActivities;
                                      changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
                                  }
                                  if (app.repProcState != app.curProcState) {
                                      app.repProcState = app.curProcState;
                                      changes |= ProcessChangeItem.CHANGE_PROCESS_STATE;
                                      if (app.thread != null) {
                                          //設置進程狀態
                                          app.thread.setProcessState(app.repProcState);
                                      }
                                  }
                                  
                                  if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT
                                          || ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) {
                                      app.lastStateTime = now;
                                      //當setProcState = -1或者curProcState與setProcState值不同時,則計算pss下次時間(參數true)
                                      app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
                                              mTestPssMode, isSleeping(), now);
                                  } else {
                                      當前時間超過pss下次時間,則請求統計pss,并計算pss下次時間(參數false)
                                      if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL)
                                              && now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
                                              mTestPssMode)))) {
                                          requestPssLocked(app, app.setProcState);
                                          app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
                                                  mTestPssMode, isSleeping(), now);
                                      }
                                  }
                                  
                                  if (app.setProcState != app.curProcState) {
                                      boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE;
                                      boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE;
                                      if (setImportant && !curImportant) {
                                          BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
                                          synchronized (stats) {
                                              app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
                                                      app.pid, nowElapsed);
                                          }
                                          app.lastCpuTime = app.curCpuTime;
                                  
                                      }
                                      maybeUpdateUsageStatsLocked(app, nowElapsed);
                                  
                                      app.setProcState = app.curProcState;
                                      if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
                                          app.notCachedSinceIdle = false;
                                      }
                                      if (!doingAll) {
                                          setProcessTrackerStateLocked(app, mProcessStats.getMemFactorLocked(), now);
                                      } else {
                                          app.procStateChanged = true;
                                      }
                                  } else if (app.reportedInteraction && (nowElapsed-app.interactionEventTime)
                                          > USAGE_STATS_INTERACTION_INTERVAL) {
                                      maybeUpdateUsageStatsLocked(app, nowElapsed);
                                  }
                                  
                                  if (changes != 0) {
                                      int i = mPendingProcessChanges.size()-1;
                                      ProcessChangeItem item = null;
                                      while (i >= 0) {
                                          item = mPendingProcessChanges.get(i);
                                          if (item.pid == app.pid) {
                                              break;
                                          }
                                          i--;
                                      }
                                      if (i < 0) {
                                          final int NA = mAvailProcessChanges.size();
                                          if (NA > 0) {
                                              item = mAvailProcessChanges.remove(NA-1);
                                          } else {
                                              item = new ProcessChangeItem();
                                          }
                                          item.changes = 0;
                                          item.pid = app.pid;
                                          item.uid = app.info.uid;
                                          if (mPendingProcessChanges.size() == 0) {
                                              mUiHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED).sendToTarget();
                                          }
                                          mPendingProcessChanges.add(item);
                                      }
                                      item.changes |= changes;
                                      item.processState = app.repProcState;
                                      item.foregroundActivities = app.repForegroundActivities;
                                  }
                                  
                                  return success;
                                  

                                  }</code></pre>

                                  該方法主要功能:

                                  1. 把curRawAdj值賦給setRawAdj
                                  2. 把adj值 發送給lmkd守護進程
                                  3. 當app標記waitingToKill,且沒有廣播接收器運行在該進程,并且調度組為后臺非交互組,則殺掉該進程,設置applyOomAdjLocked過程失敗;
                                  4. 設置進程組信息
                                  5. 設置進程狀態
                                  6. 執行pss統計操作,以及計算下一次pss時間
                                  7. 設置進程狀態改變;

                                  三、總結

                                  調整進程的adj的3大護法:

                                  • updateOomAdjLocked :更新adj,當目標進程為空,或者被殺則返回false;否則返回true;
                                  • computeOomAdjLocked :計算adj,返回計算后RawAdj值;
                                  • applyOomAdjLocked :應用adj,當需要殺掉目標進程則返回false;否則返回true。

                                  3.1 updateOomAdjLocked

                                  主要工作:

                                  • 遍歷mLruProcesses進程,更新進程adj,并殺掉滿足以下條件的進程:
                                    • 當curProcState=14或15,且cached進程超過上限(cachedProcessLimit=32)
                                    • 當curProcState=16,且空進程超過上限(TRIM_EMPTY_APPS=8),且空閑時間超過30分鐘
                                    • 當curProcState=16,且空進程超過上限(emptyProcessLimit=16)
                                    </li>
                                  • 根據memFactor來調度執行TrimMemory操作;
                                  • </ul>

                                    3.2 computeOomAdjLocked

                                    主要工作:計算進程的adj和procState

                                    • 進程為空的情況
                                    • maxAdj<=0
                                    • 計算各種狀態下(當前顯示activity, 癥結接收的廣播/service等)的adj和procState
                                    • 非前臺activity的情況
                                    • adj > 2的情況
                                    • HeavyWeightProces情況
                                    • HomeProcess情況
                                    • PreviousProcess情況
                                    • 備份進程情況
                                    • Service情況
                                    • ContentProvider情況
                                    • 調整adj

                                    3.3 applyOomAdjLocked

                                    主要工作:

                                    • 把adj值相關信息發送給lmkd守護進程
                                    • 當app標記waitingToKill,且沒有廣播接收器運行在該進程,并且調度組為后臺非交互組,則殺掉該進程;
                                    • 設置進程組信息/進程狀態
                                    • 執行pss統計操作,以及計算下一次pss時間

                                    apply過程中只有當waitingToKill情況下殺掉該進程,則會返回false;否則都是返回true。

                                     

                                    來自:http://gityuan.com/2016/08/07/android-adj/

                                     

 本文由用戶 AmeWaterhou 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!