androidU oomadj

一 oomadj機(jī)制引入原因

oomadj機(jī)制是一種內(nèi)存管理機(jī)制许饿,用于處理操作系統(tǒng)中的內(nèi)存不足(Out-Of-Memory)問題。當(dāng)系統(tǒng)的可用內(nèi)存空間不足時(shí)燥筷,操作系統(tǒng)會(huì)使用oomadj機(jī)制來決定哪些進(jìn)程應(yīng)該被終止软瞎,以釋放內(nèi)存闯割。

oomadj機(jī)制引入的原因是為了提高系統(tǒng)的穩(wěn)定性和性能,以及保護(hù)用戶體驗(yàn)省店。oomadj機(jī)制可以根據(jù)進(jìn)程的重要性和內(nèi)存占用情況嚣崭,動(dòng)態(tài)調(diào)整進(jìn)程的優(yōu)先級(jí)笨触,使得系統(tǒng)在內(nèi)存緊張時(shí),優(yōu)先殺死那些不重要或者占用內(nèi)存過多的進(jìn)程雹舀,從而保證那些重要或者用戶可見的進(jìn)程能夠繼續(xù)運(yùn)行芦劣。

oomadj機(jī)制是基于Linux內(nèi)核的oom_score和oom_score_adj機(jī)制的擴(kuò)展,它增加了一些Android特有的因素说榆,例如進(jìn)程的狀態(tài)(前臺(tái)虚吟、后臺(tái)、服務(wù)等)签财、進(jìn)程的類型(系統(tǒng)串慰、應(yīng)用、第三方等)荠卷、進(jìn)程的關(guān)聯(lián)性(是否有其他進(jìn)程依賴它)等模庐,來更精細(xì)地控制進(jìn)程的優(yōu)先級(jí)。

二 oomadj架構(gòu)圖

oomadj架構(gòu)圖.drawio.png

framework計(jì)算完進(jìn)程oomadj的值以后會(huì)做三件事油宜。

  1. 將adj同步到lmkd模塊掂碱,當(dāng)psi壓力大時(shí)進(jìn)程查殺
  2. 通過process.setProcessGroup來調(diào)整進(jìn)程的優(yōu)先級(jí)
  3. 通過appProfile從libmeminfo獲取lru進(jìn)程的pss值

當(dāng)內(nèi)存不足時(shí),lmkd會(huì)進(jìn)行查殺進(jìn)程慎冤。Oomadj值越大越容易被殺疼燥,相同oomadj優(yōu)先殺pss值大的。

三 oomadj的查詢方法

3.1 查看進(jìn)程的oomadj值

adb shell
cd /proc/pid/
oom_adj   oom_score  oom_score_adj
cat oom_adj
0 表示前臺(tái)進(jìn)程FOREGROUND_APP_ADJ

oom_adj蚁堤,oom_score和oom_score_adj三者的區(qū)別醉者。oom_adj,oom_score和oom_score_adj都是用來表示進(jìn)程的優(yōu)先級(jí)的指標(biāo)披诗,它們決定了當(dāng)系統(tǒng)內(nèi)存不足時(shí)撬即,哪些進(jìn)程會(huì)被殺死以釋放內(nèi)存12。

  • oom_adj是一個(gè)舊的打分因子呈队,它的取值范圍是-17到15剥槐,其中-17表示永遠(yuǎn)不會(huì)被殺死,15表示最容易被殺死3?宪摧。oom_adj已經(jīng)在Linux 2.6.36版本中被廢棄粒竖,取而代之的是oom_score_adj12。

  • oom_score是一個(gè)絕對(duì)值几于,它反映了進(jìn)程的內(nèi)存占用情況蕊苗,越高表示越占用內(nèi)存12。oom_score的取值范圍是0到1000沿彭,其中0表示永遠(yuǎn)不會(huì)被殺死朽砰,1000表示最容易被殺死12。oom_score是由內(nèi)核根據(jù)進(jìn)程的狀態(tài)和oom_score_adj動(dòng)態(tài)計(jì)算的,用戶不能直接修改12锅移。

  • oom_score_adj是一個(gè)相對(duì)值熔掺,它反映了進(jìn)程的重要性,越低表示越重要12非剃。oom_score_adj的取值范圍是-1000到1000,其中-1000表示永遠(yuǎn)不會(huì)被殺死推沸,1000表示最容易被殺死12备绽。oom_score_adj可以由進(jìn)程自己設(shè)置,或者由系統(tǒng)根據(jù)進(jìn)程的狀態(tài)動(dòng)態(tài)調(diào)整12鬓催。

oom_score和oom_score_adj的關(guān)系是12:

oom\_score = oom\_score\_adj + (oom\_score\_adj \times \frac{totalvm - sharedvm}{totalvm})

其中肺素,totalvm是進(jìn)程的虛擬內(nèi)存大小,sharedvm是進(jìn)程共享的內(nèi)存大小宇驾。

ProcessStateRecord保存進(jìn)程oomadj

[ProcessStateRecord]
    /**
     * Current OOM adjustment for this process.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private int mCurAdj = ProcessList.INVALID_ADJ;

3.2 查看進(jìn)程pss值

console:/proc/1764 # cat smaps_rollup
0dd6b000-ffff1000 ---p 00000000 00:00 0          [rollup]
Rss:              149452 kB
Pss:               30997 kB
Shared_Clean:     102188 kB
Shared_Dirty:      23284 kB
Private_Clean:      3296 kB
Private_Dirty:     20684 kB
Referenced:       113148 kB
Anonymous:         43700 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:               6320 kB
SwapPss:            3771 kB
Locked:                0 kB

從圖中可以看到1764進(jìn)程pss占用300997Kb倍靡。

3.3 查看進(jìn)程是否被凍結(jié)

console:/dev/freezer/frozen # cat cgroup.procs
1764
2013
2149
2595
2714
2936
3122
3529

上面的進(jìn)程就是已經(jīng)被凍結(jié)的進(jìn)程號(hào)。
U有改變课舍。路徑不對(duì)了塌西。

四 framewok中用于輔助oomadj機(jī)制表示進(jìn)程狀態(tài)的類

4.1 ProcessList

    // OOM adjustments for processes in various states:

    // Uninitialized value for any major or minor adj fields
    public static final int INVALID_ADJ = -10000;

    // Adjustment used in certain places where we don't know it yet.
    // (Generally this is something that is going to be cached, but we
    // don't know the exact value in the cached range to assign yet.)
    public static final int UNKNOWN_ADJ = 1001;

    // This is a process only hosting activities that are not visible,
    // so it can be killed without any disruption.
    public static final int CACHED_APP_MAX_ADJ = 999;
    public static final int CACHED_APP_MIN_ADJ = 900;

    // This is the oom_adj level that we allow to die first. This cannot be equal to
    // CACHED_APP_MAX_ADJ unless processes are actively being assigned an oom_score_adj of
    // CACHED_APP_MAX_ADJ.
    public static final int CACHED_APP_LMK_FIRST_ADJ = 950;

    // Number of levels we have available for different service connection group importance
    // levels.
    static final int CACHED_APP_IMPORTANCE_LEVELS = 5;

    // The B list of SERVICE_ADJ -- these are the old and decrepit
    // services that aren't as shiny and interesting as the ones in the A list.
    public static final int SERVICE_B_ADJ = 800;

    // This is the process of the previous application that the user was in.
    // This process is kept above other things, because it is very common to
    // switch back to the previous app.  This is important both for recent
    // task switch (toggling between the two top recent apps) as well as normal
    // UI flow such as clicking on a URI in the e-mail app to view in the browser,
    // and then pressing back to return to e-mail.
    public static final int PREVIOUS_APP_ADJ = 700;

    // This is a process holding the home application -- we want to try
    // avoiding killing it, even if it would normally be in the background,
    // because the user interacts with it so much.
    public static final int HOME_APP_ADJ = 600;

    // This is a process holding an application service -- killing it will not
    // have much of an impact as far as the user is concerned.
    public static final int SERVICE_ADJ = 500;

    // This is a process with a heavy-weight application.  It is in the
    // background, but we want to try to avoid killing it.  Value set in
    // system/rootdir/init.rc on startup.
    public static final int HEAVY_WEIGHT_APP_ADJ = 400;

    // This is a process currently hosting a backup operation.  Killing it
    // is not entirely fatal but is generally a bad idea.
    public static final int BACKUP_APP_ADJ = 300;

    // This is a process bound by the system (or other app) that's more important than services but
    // not so perceptible that it affects the user immediately if killed.
    public static final int PERCEPTIBLE_LOW_APP_ADJ = 250;

    // This is a process hosting services that are not perceptible to the user but the
    // client (system) binding to it requested to treat it as if it is perceptible and avoid killing
    // it if possible.
    public static final int PERCEPTIBLE_MEDIUM_APP_ADJ = 225;

    // This is a process only hosting components that are perceptible to the
    // user, and we really want to avoid killing them, but they are not
    // immediately visible. An example is background music playback.
    public static final int PERCEPTIBLE_APP_ADJ = 200;

    // This is a process only hosting activities that are visible to the
    // user, so we'd prefer they don't disappear.
    public static final int VISIBLE_APP_ADJ = 100;
    static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;

    // This is a process that was recently TOP and moved to FGS. Continue to treat it almost
    // like a foreground app for a while.
    // @see TOP_TO_FGS_GRACE_PERIOD
    public static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;

    // This is the process running the current foreground app.  We'd really
    // rather not kill it!
    public static final int FOREGROUND_APP_ADJ = 0;

    // This is a process that the system or a persistent process has bound to,
    // and indicated it is important.
    public static final int PERSISTENT_SERVICE_ADJ = -700;

    // This is a system persistent process, such as telephony.  Definitely
    // don't want to kill it, but doing so is not completely fatal.
    public static final int PERSISTENT_PROC_ADJ = -800;

    // The system process runs at the default adjustment.
    public static final int SYSTEM_ADJ = -900;

    // Special code for native processes that are not being managed by the system (so
    // don't have an oom adj assigned by the system).
    public static final int NATIVE_ADJ = -1000;

4.2 ProcessStateEnum.aidl

/**
 * Defines the PROCESS_STATE_* values used by ActivityManager.
 * These values are shared by Java and native side.
 * {@hide}
 */
@Backing(type="int")
enum ProcessStateEnum {
    /** @hide Not a real process state. */
    UNKNOWN = -1,

    /** @hide Process is a persistent system process. */
    PERSISTENT = 0,

    /** @hide Process is a persistent system process and is doing UI. */
    PERSISTENT_UI = 1,

    /** @hide Process is hosting the current top activities.  Note that this covers
     * all activities that are visible to the user. */
    TOP = 2,

    /** @hide Process is bound to a TOP app. */
    BOUND_TOP = 3,

    /** @hide Process is hosting a foreground service. */
    FOREGROUND_SERVICE = 4,

    /** @hide Process is hosting a foreground service due to a system binding. */
    BOUND_FOREGROUND_SERVICE = 5,

    /** @hide Process is important to the user, and something they are aware of. */
    IMPORTANT_FOREGROUND = 6,

    /** @hide Process is important to the user, but not something they are aware of. */
    IMPORTANT_BACKGROUND = 7,

    /** @hide Process is in the background transient so we will try to keep running. */
    TRANSIENT_BACKGROUND = 8,

    /** @hide Process is in the background running a backup/restore operation. */
    BACKUP = 9,

    /** @hide Process is in the background running a service.  Unlike oom_adj, this level
     * is used for both the normal running in background state and the executing
     * operations state. */
    SERVICE = 10,

    /** @hide Process is in the background running a receiver.   Note that from the
     * perspective of oom_adj, receivers run at a higher foreground level, but for our
     * prioritization here that is not necessary and putting them below services means
     * many fewer changes in some process states as they receive broadcasts. */
    RECEIVER = 11,

    /** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
    TOP_SLEEPING = 12,

    /** @hide Process is in the background, but it can't restore its state so we want
     * to try to avoid killing it. */
    HEAVY_WEIGHT = 13,

    /** @hide Process is in the background but hosts the home activity. */
    HOME = 14,

    /** @hide Process is in the background but hosts the last shown activity. */
    LAST_ACTIVITY = 15,

    /** @hide Process is being cached for later use and contains activities. */
    CACHED_ACTIVITY = 16,

    /** @hide Process is being cached for later use and is a client of another cached
     * process that contains activities. */
    CACHED_ACTIVITY_CLIENT = 17,

    /** @hide Process is being cached for later use and has an activity that corresponds
     * to an existing recent task. */
    CACHED_RECENT = 18,

    /** @hide Process is being cached for later use and is empty. */
    CACHED_EMPTY = 19,

    /** @hide Process does not exist. */
    NONEXISTENT = 20,

}

此aild為系統(tǒng)側(cè)定義,app開發(fā)者需要使用ActivityManager來定義筝尾。

4.2.1 ActivityManager.java

    /** @hide Process is hosting a foreground service due to a system binding. */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE =
            ProcessStateEnum.BOUND_FOREGROUND_SERVICE;
---分割線
    /** @hide */
    public static String procStateToString(int procState) {
        final String procStateStr;
        switch (procState) {
            case ActivityManager.PROCESS_STATE_PERSISTENT:
                procStateStr = "PER ";
                break;
            case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
                procStateStr = "PERU";
                break;
            case ActivityManager.PROCESS_STATE_TOP:
                procStateStr = "TOP ";
                break;
            case ActivityManager.PROCESS_STATE_BOUND_TOP:
                procStateStr = "BTOP";
                break;
            case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
                procStateStr = "FGS ";
                break;
            case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
                procStateStr = "BFGS";
                break;
            case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
                procStateStr = "IMPF";
                break;
            case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
                procStateStr = "IMPB";
                break;
            case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:
                procStateStr = "TRNB";
                break;
            case ActivityManager.PROCESS_STATE_BACKUP:
                procStateStr = "BKUP";
                break;
            case ActivityManager.PROCESS_STATE_SERVICE:
                procStateStr = "SVC ";
                break;
            case ActivityManager.PROCESS_STATE_RECEIVER:
                procStateStr = "RCVR";
                break;
            case ActivityManager.PROCESS_STATE_TOP_SLEEPING:
                procStateStr = "TPSL";
                break;
            case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
                procStateStr = "HVY ";
                break;
            case ActivityManager.PROCESS_STATE_HOME:
                procStateStr = "HOME";
                break;
            case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
                procStateStr = "LAST";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                procStateStr = "CAC ";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                procStateStr = "CACC";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_RECENT:
                procStateStr = "CRE ";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                procStateStr = "CEM ";
                break;
            case ActivityManager.PROCESS_STATE_NONEXISTENT:
                procStateStr = "NONE";
                break;
            default:
                procStateStr = "??";
                break;
        }
        return procStateStr;
    }

4.2 和4.2.1 oomadj和procState的區(qū)別和聯(lián)系

系統(tǒng)側(cè)用ProcessStateRecord.mAdjType來保存進(jìn)程狀態(tài)類型捡需。
進(jìn)程查殺主要依據(jù)還是oomadj的值,但是進(jìn)程當(dāng)前的狀態(tài)沒法從oomadj的值上直觀體現(xiàn)筹淫,所有引入了進(jìn)程狀態(tài)和adjType站辉,進(jìn)程狀態(tài)procState和進(jìn)程adjType永遠(yuǎn)保持一致。


procState/oomadj

4.3 Process.java

THREAD_GROUP_* 用于為pid設(shè)置group-> setProcessGroup

    // Keep in sync with SP_* constants of enum type SchedPolicy
    // declared in system/core/include/cutils/sched_policy.h,
    // except THREAD_GROUP_DEFAULT does not correspond to any SP_* value.

    /**
     * Default thread group -
     * has meaning with setProcessGroup() only, cannot be used with setThreadGroup().
     * When used with setProcessGroup(), the group of each thread in the process
     * is conditionally changed based on that thread's current priority, as follows:
     * threads with priority numerically less than THREAD_PRIORITY_BACKGROUND
     * are moved to foreground thread group.  All other threads are left unchanged.
     * @hide
     */
    public static final int THREAD_GROUP_DEFAULT = -1;

    /**
     * Background thread group - All threads in
     * this group are scheduled with a reduced share of the CPU.
     * Value is same as constant SP_BACKGROUND of enum SchedPolicy.
     * @hide
     */
    public static final int THREAD_GROUP_BACKGROUND = 0;

    /**
     * Foreground thread group - All threads in
     * this group are scheduled with a normal share of the CPU.
     * Value is same as constant SP_FOREGROUND of enum SchedPolicy.
     * Not used at this level.
     * @hide
     **/
    private static final int THREAD_GROUP_FOREGROUND = 1;

    /**
     * System thread group.
     * @hide
     **/
    public static final int THREAD_GROUP_SYSTEM = 2;

    /**
     * Application audio thread group.
     * @hide
     **/
    public static final int THREAD_GROUP_AUDIO_APP = 3;

    /**
     * System audio thread group.
     * @hide
     **/
    public static final int THREAD_GROUP_AUDIO_SYS = 4;

    /**
     * Thread group for top foreground app.
     * @hide
     **/
    public static final int THREAD_GROUP_TOP_APP = 5;

    /**
     * Thread group for RT app.
     * @hide
     **/
    public static final int THREAD_GROUP_RT_APP = 6;

    /**
     * Thread group for bound foreground services that should
     * have additional CPU restrictions during screen off
     * @hide
     **/
    public static final int THREAD_GROUP_RESTRICTED = 7;

4.4 觸發(fā)oomadj的原因

    @IntDef(prefix = {"OOM_ADJ_REASON_"}, value = {
        OOM_ADJ_REASON_NONE,
        OOM_ADJ_REASON_ACTIVITY,
        OOM_ADJ_REASON_FINISH_RECEIVER,
        OOM_ADJ_REASON_START_RECEIVER,
        OOM_ADJ_REASON_BIND_SERVICE,
        OOM_ADJ_REASON_UNBIND_SERVICE,
        OOM_ADJ_REASON_START_SERVICE,
        OOM_ADJ_REASON_GET_PROVIDER,
        OOM_ADJ_REASON_REMOVE_PROVIDER,
        OOM_ADJ_REASON_UI_VISIBILITY,
        OOM_ADJ_REASON_ALLOWLIST,
        OOM_ADJ_REASON_PROCESS_BEGIN,
        OOM_ADJ_REASON_PROCESS_END,
        OOM_ADJ_REASON_SHORT_FGS_TIMEOUT,
        OOM_ADJ_REASON_SYSTEM_INIT,
        OOM_ADJ_REASON_BACKUP,
        OOM_ADJ_REASON_SHELL,
        OOM_ADJ_REASON_REMOVE_TASK,
        OOM_ADJ_REASON_UID_IDLE,
        OOM_ADJ_REASON_STOP_SERVICE,
        OOM_ADJ_REASON_EXECUTING_SERVICE,
        OOM_ADJ_REASON_RESTRICTION_CHANGE,
        OOM_ADJ_REASON_COMPONENT_DISABLED,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface OomAdjReason {}

5 oomadj源碼流程解析

    @GuardedBy({"mService", "mProcLock"})
    private boolean updateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
        if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
            updateOomAdjLSP(oomAdjReason);
            return true;
        }
// 1. 判斷oomadj是否正在進(jìn)行
        if (checkAndEnqueueOomAdjTargetLocked(app)) {
            // Simply return true as there is an oomAdjUpdate ongoing
            return true;
        }

        try {
//2. 設(shè)置oomadj正在進(jìn)行中
            mOomAdjUpdateOngoing = true;
//3. 執(zhí)行oomadj計(jì)算
            return performUpdateOomAdjLSP(app, oomAdjReason);
        } finally {
            // Kick off the handling of any pending targets enqueued during the above update
            mOomAdjUpdateOngoing = false;
            updateOomAdjPendingTargetsLocked(oomAdjReason);
        }
    }

5.1 checkAndEnqueueOomAdjTargetLocked

    /**
     * Check if there is an ongoing oomAdjUpdate, enqueue the given process record
     * to {@link #mPendingProcessSet} if there is one.
     *
     * @param app The target app to get an oomAdjUpdate, or a full oomAdjUpdate if it's null.
     * @return {@code true} if there is an ongoing oomAdjUpdate.
     */
    @GuardedBy("mService")
    private boolean checkAndEnqueueOomAdjTargetLocked(@Nullable ProcessRecord app) {
        if (!mOomAdjUpdateOngoing) {
            return false;
        }
        if (app != null) {
            mPendingProcessSet.add(app);
        } else {
            mPendingFullOomAdjUpdate = true;
        }
        return true;
    }

5.2 performUpdateOomAdjLSP

    private boolean performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
// 1.獲取頂層app的processRecord
        final ProcessRecord topApp = mService.getTopApp();
// 2. trace記錄损姜,并記錄本次開始時(shí)間
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
        mService.mOomAdjProfiler.oomAdjStarted();
//3. 更新當(dāng)前進(jìn)程的oomadj值
        boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp,
                SystemClock.uptimeMillis());

//4. 找到可達(dá)進(jìn)程
        // Next to find out all its reachable processes
        ArrayList<ProcessRecord> processes = mTmpProcessList;
        boolean containsCycle = collectReachableProcessesLocked(mPendingProcessSet,
                processes, uids);
        int size = processes.size();
        if (size > 0) {
            mAdjSeq--;
// 5. 更新可達(dá)進(jìn)程的oomadj饰剥,什么叫可達(dá)進(jìn)程: pending中的進(jìn)程、bindservice摧阅、contentprovider的進(jìn)程
// eg1.: final ProcessServiceRecord psr = pr.mServices;
// eg2.: final ProcessProviderRecord ppr = pr.mProviders;
// 計(jì)算可達(dá)進(jìn)程的oomadj
            // Update these reachable processes
            updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false);
        mTmpProcessList.clear();
// 6 結(jié)束計(jì)時(shí)汰蓉,函數(shù)返回
        mService.mOomAdjProfiler.oomAdjEnded();
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        return true;

5.3 performUpdateOomAdjLSP

    private boolean performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj,
            ProcessRecord topApp, long now) {
// 獲取當(dāng)前進(jìn)程的UidRecord
        UidRecord uidRec = app.getUidRecord();
        if (uidRec != null) {
            if (DEBUG_UID_OBSERVERS) {
                Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
            }
//2. 將Uid中狀態(tài)恢復(fù)默認(rèn),mForegroundServices=false逸尖,procstate = PROCESS_STATE_CACHED_EMPTY
            uidRec.reset();
        }
//3.
        computeOomAdjLSP(app, cachedAdj, topApp, false, now, false, true);
//4
        return applyOomAdjLSP(app, false, now, SystemClock.elapsedRealtime());

5.3.1 computeOomAdjLSP

    @GuardedBy({"mService", "mProcLock"})
    private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
            ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
            boolean computeClients) {
//1. 保存當(dāng)前狀態(tài)
        int prevAppAdj = state.getCurAdj();
        int prevProcState = state.getCurProcState();
        int prevCapability = state.getCurCapability();
        final ProcessServiceRecord psr = app.mServices;
// 2. 如果當(dāng)前進(jìn)程是大于前臺(tái)進(jìn)程古沥,例如系統(tǒng)進(jìn)程則無需計(jì)算。
if (state.getMaxAdj() <= ProcessList.FOREGROUND_APP_ADJ) {
// 3. 如果當(dāng)前app是ams保存的topapp則直接賦值即可娇跟。
        if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
            // The last app on the list is the foreground app.
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
            state.setAdjType("top-activity");
            foregroundActivities = true;
            hasVisibleActivities = true;
            procState = PROCESS_STATE_CUR_TOP;
            state.bumpAllowStartFgsState(PROCESS_STATE_TOP);
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
            }
//4. 如果正在執(zhí)行動(dòng)畫岩齿、或者測(cè)試中,則賦值高優(yōu)先級(jí)
        } else if (state.isRunningRemoteAnimation()) {
            adj = ProcessList.VISIBLE_APP_ADJ;
            schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
            state.setAdjType("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.getActiveInstrumentation() != null) {
            // Don't want to kill running instrumentation.
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            state.setAdjType("instrumentation");
            procState = PROCESS_STATE_FOREGROUND_SERVICE;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
            }
//5. 如果正在接收廣播則賦值接廣播狀態(tài)
        } else if (state.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
            // An app that is currently receiving a broadcast also
            // counts as being in the foreground for OOM killer purposes.
            // It's placed in a sched group based on the nature of the
            // broadcast as reflected by which queue it's active in.
// 5.1 正在接收廣播狀態(tài)的進(jìn)程被認(rèn)為是前臺(tái)進(jìn)程苞俘。
            adj = ProcessList.FOREGROUND_APP_ADJ;
//5.2 狀態(tài)設(shè)置為廣播
            state.setAdjType("broadcast");
            procState = ActivityManager.PROCESS_STATE_RECEIVER;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
            }
// 6. 如果正在執(zhí)行service盹沈,也設(shè)置為前臺(tái),設(shè)置類型為"exec-service"
        } else if (psr.numberOfExecutingServices() > 0) {
            // An app that is currently executing a service callback also
            // counts as being in the foreground.
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = psr.shouldExecServicesFg()
                    ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
            state.setAdjType("exec-service");
            procState = PROCESS_STATE_SERVICE;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
            }
        } else if (app == topApp) {
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
            state.setAdjType("top-sleeping");
            foregroundActivities = true;
            procState = PROCESS_STATE_CUR_TOP;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app);
            }
// 7. 進(jìn)程不為以上類型,認(rèn)為是后臺(tái)進(jìn)程乞封。
        }   else {
            // As far as we know the process is empty.  We may change our mind later.
            schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
            // At this point we don't actually know the adjustment.  Use the cached adj
            // value that the caller wants us to.
            adj = cachedAdj;
            procState = PROCESS_STATE_CACHED_EMPTY;
            if (!state.containsCycle()) {
                state.setCached(true);
                state.setEmpty(true);
                state.setAdjType("cch-empty");
            }
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app);
            }
        }
// 還有其他provider做裙、uioverlay等判斷,不再一一列舉肃晚,總之根據(jù)狀態(tài)設(shè)置1.schedGroup 2.adj 3.procState 4.setAdjType
// 8. 如果計(jì)算后的oomadj狀態(tài)比之前提升了锚贱,那么需要對(duì)進(jìn)程進(jìn)行提權(quán)處理。
        // if curAdj or curProcState improved, then this process was promoted
        return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
                || state.getCurCapability() != prevCapability;

6 applyOomAdjLSP 處理oomadj的計(jì)算結(jié)果

    /** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
    @GuardedBy({"mService", "mProcLock"})
    private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now,
            long nowElapsed) {
        boolean success = true;
// 1. 當(dāng)前的adj和上次統(tǒng)計(jì)的adj不一樣关串。
        if (state.getCurAdj() != state.getSetAdj()) {
// 1.1 更新processList中進(jìn)程的oomadj拧廊,里面會(huì)調(diào)用writeLmkd(buf, null);將pid的adj寫入lmkd模塊。
            ProcessList.setOomAdj(app.getPid(), app.uid, state.getCurAdj());
            if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
                String msg = "Set " + app.getPid() + " " + app.processName + " adj "
                        + state.getCurAdj() + ": " + state.getAdjType();
                reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
            }
            state.setSetAdj(state.getCurAdj());
            state.setVerifiedAdj(ProcessList.INVALID_ADJ);
        }
// 2. 更新進(jìn)程組信息晋修。
        final int curSchedGroup = state.getCurrentSchedulingGroup();
                switch (curSchedGroup) {
                    case ProcessList.SCHED_GROUP_BACKGROUND:
                        processGroup = THREAD_GROUP_BACKGROUND;
                        break;
                    case ProcessList.SCHED_GROUP_TOP_APP:
                    case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
                        processGroup = THREAD_GROUP_TOP_APP;
                        break;
                    case ProcessList.SCHED_GROUP_RESTRICTED:
                        processGroup = THREAD_GROUP_RESTRICTED;
                        break;
                    default:
                        processGroup = THREAD_GROUP_DEFAULT;
                        break;
                }
// 2.1 調(diào)用Process的native方法setProcessGroup設(shè)置進(jìn)程組
                setProcessGroup(pid, group);
// 2.2 根據(jù)進(jìn)程組的情況設(shè)置線程優(yōu)先級(jí)狀態(tài)吧碾,具體有哪些值可Process.THREAD_PRIORITY_***
                setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
                setThreadPriority(app.getPid(), 0);
                setThreadPriority(app.getPid(), 0);
                setThreadPriority(renderThreadTid, THREAD_PRIORITY_DISPLAY);
// 3. 省略部分信息。
        return success;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末墓卦,一起剝皮案震驚了整個(gè)濱河市倦春,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌落剪,老刑警劉巖睁本,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異著榴,居然都是意外死亡添履,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門脑又,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暮胧,“玉大人,你說我怎么就攤上這事问麸⊥裕” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵严卖,是天一觀的道長(zhǎng)席舍。 經(jīng)常有香客問我,道長(zhǎng)哮笆,這世上最難降的妖魔是什么来颤? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮稠肘,結(jié)果婚禮上福铅,老公的妹妹穿的比我還像新娘。我一直安慰自己项阴,他們只是感情好滑黔,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般略荡。 火紅的嫁衣襯著肌膚如雪庵佣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天汛兜,我揣著相機(jī)與錄音巴粪,去河邊找鬼。 笑死序无,一個(gè)胖子當(dāng)著我的面吹牛验毡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播帝嗡,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼璃氢!你這毒婦竟也來了哟玷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤一也,失蹤者是張志新(化名)和其女友劉穎巢寡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體椰苟,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抑月,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舆蝴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谦絮。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖洁仗,靈堂內(nèi)的尸體忽然破棺而出层皱,到底是詐尸還是另有隱情,我是刑警寧澤赠潦,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布叫胖,位于F島的核電站,受9級(jí)特大地震影響她奥,放射性物質(zhì)發(fā)生泄漏瓮增。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一哩俭、第九天 我趴在偏房一處隱蔽的房頂上張望绷跑。 院中可真熱鬧,春花似錦携茂、人聲如沸你踩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)带膜。三九已至吩谦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間膝藕,已是汗流浹背式廷。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芭挽,地道東北人滑废。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像袜爪,于是被迫代替她去往敵國(guó)和親蠕趁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

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