从源码角度看 Android 进程保活原理与优先级调度机制

简介

私以为,阅读Android源码必然需要先看看AMS核心组件部分的代码,因为它掌管着和应用打交道最频繁的四大组件生命周期,和应用的联系最为密切。然而,AMS中的集大成者我认为却是进程的管理与调度。阅读过四大组件的源码过后再去读进程的源码,会有一种打通了任督六脉的感觉,对系统的理解不再是停留在某个模块,而是有着更深一层的大局观的感觉。

Android进程管理这块代码中,其中最重要的一块又在进程的优先级调度。阅读这块代码期间你将会看到,系统更新、计算进程的优先级完完全全会根据此时四大组件的状态来完成。

能从进程优先级这块源码汲取出来的知识点很多,其中应用开发者最关心的便是进程保活这块。从近年来国内流氓APP进程霸占系统资源的情况来看,很多大厂的程序员为了自己APP能够长期存活,肯定是殚精竭虑的阅读过各个版本的Android进程源码。

这篇文章里,我将先列举进程被杀场景、保活方法的表格,这些都只停留在表层的知晓阶段;随后我会深入到源码中分析进程优先级调度3个最重要的方法:updateOomAdjLocked, computeOomAdjLocked, applyOomAdjLocked;每段分析中会有一副大致的逻辑图;最后的总结中我会分别列出adj, schedGroup, procState三个重要进程优先级数值与场景对应表格。

进程保活

此章节中列举出了杀进程的场景以及常见的保活方法

杀进程场景

序号 场景
1 被lmk杀死
2 成为空进程,缓存进程后被杀
3 最近任务一键清理
4 最近任务上滑被死
5 使用Setting forceStop
6 第三方应用如猎豹,360杀进程
7 出现FC或者ANR
  • 1,2两种情况属于用户没有察觉的情况下,进程属于"自然死亡",在内存紧缺或者是用户不再关注的时候被系统杀死的
  • 3,4,5,6的情况属于用户主动去杀死进程;国产的安卓中,一键清理的威力更大,甚至可以杀死前台Service
  • 7的情况属于应用出现异常被系统杀死

以上是原生Android的进程被杀的场景,国外很多如CM等的定制系统差别不大;但是国内安卓系统如小米、华为、乐视这些大厂为了禁止国内流氓应用乱来,往往会定制许多其它杀进程的规则。

保活方法

序号 保活方法 API限制 效果&原理
1 正常的开启前台Servce 无限制 启动前台Service伴随着Notification,如正在播放音乐、正在导航,系统默认给进程高优先级
2 正常弹出悬浮窗 无限制 展示用户可见的窗口,如一键清理火箭,系统默认给进程高优先级
3 设置persistent=true 无限制 成为系统常驻进程
4 启动前台Service传入无意义Notification API<=17 利用系统漏洞,不展示Notification但享受前台Service优先级待遇
5 启动两个相同id前台Service,stop后者 18<=API<=24 同上,享受前台Service优先级待遇
6 native层保活 API<=23 进程互保,通过文件锁监听死亡,如果死亡则拉起
7 桌面放置一像素页面 未知 享受可见进程优先级待遇
8 静态注册系统常用广播 未知 满足权限的前提下,收到广播前进程会被拉起
9 进程Service/Provider互绑 无限制 效果并不好,forceStop下等场景无法存活,只是procState优先级很高
10 AlarmManager/JobScheduler 未知 守护服务,如果被守护进程死亡则拉起
11 账户同步 未知 Android原生机制会定期唤醒账户更新服务

可以看到,除了正常的展示Activity、Notification和浮窗,向用户表示自己的进程正在使用系统的资源之外,其它方法虽然能够在用户不能察觉的情况下使自己的进程相比普通进程存活的更久,但是多多少有着API的限制。在原生Android如果发展到8.0的现在,网络普遍的流行的灰色保活都已经不适用。而且,许多国产的定制xxUI都会对非系统应用进程进行更加严厉的把控,也就是说,即时在原生Android 8.0依然能够使用的漏洞,在国产定制的安卓中很大概率是不可行的。毕竟,进程长期占用,手机的性能、电池使用时间的体验都会下降,这些对用户不友好的灰色手段都应该被直接禁止。

进程优先级的更新:updateOomAdjLocked

更新场景对应表格

序号 代码 场景
1 BroadcastQueue.processNextBroadcast 开始派发广播
2 BroadcastQueue.processNextBroadcast 派发串行广播结束
3 ActivityStackSupervisor.realStartActivityLocked 启动Activity
4 ActivityStack.destroyActivityLocked 进程已无Activity
5 ActivityStack.finishSubActivityLocked finish掉上一个Activity
6 ActivityStack.finishVoiceTask
7 ActivityStack.resumeTopActivityInnerLocked Activity.onResume
8 ActivityManagerService.addAppLocked
9 ActivityManagerService.appDiedLocked 进程死亡后
10 ActivityManagerService.attachApplicationLocked 进程绑定Application
11 ActivityManagerService.foregroundTokenDied
12 ActivityManagerService.killAllBackgroundProcesses
13 ActivityManagerService.killPackageProcessesLocked
14 ActivityManagerService.removeContentProvider ContentProvider被销毁
15 ActivityManagerService.removeContentProviderExternalUnchecked
16 ActivityManagerService.setProcessForeground
17 ActivityManagerService.setSystemProcess 设置系统进程
18 ActivityManagerService.trimApplications trim
19 ActivityManagerService.updateProcessForegroundLocked
20 ActivityManagerService.updateSleepIfNeededLocked
21 ActiveServices.realStartServiceLocked 启动Service

updateOomAdjLocked (1) - 空进程、缓存进程

final void updateOomAdjLocked() {
    final ActivityRecord TOP_ACT = resumedAppLocked();
    // 获取TOP_APP,即前台Activity,这个会在后面的updateOomAdjLocked方法中也会用到
    final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
...
    final int N = mLruProcesses.size();
...

    // 重置所有UidRecord
    for (int i = mActiveUids.size() - 1; i >= 0; i--) {
        final UidRecord uidRec = mActiveUids.valueAt(i);
        if (false && DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                "Starting update of " + uidRec);
        uidRec.reset();
    }

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

    // 获取空进程、缓存进程个数上限
    final int emptyProcessLimit;
    final int cachedProcessLimit;
    if (mProcessLimit <= 0) {
        emptyProcessLimit = cachedProcessLimit = 0;
    } else if (mProcessLimit == 1) {
        emptyProcessLimit = 1;
        cachedProcessLimit = 0;
    } else {
        emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
        cachedProcessLimit = mProcessLimit - emptyProcessLimit;
    }

    // Let's determine how many processes we have running vs.
    // how many slots we have for background processes; we may want
    // to put multiple processes in a slot of there are enough of
    // them.
    int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
            - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
    int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
    if (numEmptyProcs > cachedProcessLimit) {
...
        numEmptyProcs = cachedProcessLimit;
    }
...

    // 计算出当前所有正在运行进程的adj
    int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
    int nextCachedAdj = curCachedAdj + 1;
    int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
    int nextEmptyAdj = curEmptyAdj + 2;
    for (int i = N - 1; i >= 0; i--) {
        ProcessRecord app = mLruProcesses.get(i);
        if (!app.killedByAm && app.thread != null) {
            app.procStateChanged = false;
            // 计算单个进程的adj, procState, schedGroup
            computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);

            // 如果adj尚未计算出
            if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
                switch (app.curProcState) {
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        // 计算出当前adj
                        app.curRawAdj = curCachedAdj;
                        app.curAdj = app.modifyRawOomAdj(curCachedAdj);
                        if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
                                + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
                                + ")");
                        // cachedAdj进行叠加
                        if (curCachedAdj != nextCachedAdj) {
                            stepCached++;
                            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);
                        if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
                                + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
                                + ")");
                        if (curEmptyAdj != nextEmptyAdj) {
                            stepEmpty++;
                            if (stepEmpty >= emptyFactor) {
                                stepEmpty = 0;
                                curEmptyAdj = nextEmptyAdj;
                                nextEmptyAdj += 2;
                                if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                    nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                }
                            }
                        }
                        break;
                }
            }

              // 应用进程优先级
            applyOomAdjLocked(app, true, now, nowElapsed);

            // 空进程、缓存进程个数计数
            switch (app.curProcState) {
                case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        // 空进程个数计数
                    mNumCachedHiddenProcs++;
                    numCached++;
                    // 如果到了上限,开始杀掉空进程
                    if (numCached > cachedProcessLimit) {
                        app.kill("cached #" + numCached, true);
                    }
                    break;
                case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                    if (numEmpty > ProcessList.TRIM_EMPTY_APPS
                            && app.lastActivityTime < oldTime) {
                        app.kill("empty for "
                                + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
                                / 1000) + "s", true);
                    } else {
                        // 缓存进程个数计数
                        numEmpty++;
                        // 如果到了上限,开始杀死缓存进程
                        if (numEmpty > emptyProcessLimit) {
                            app.kill("empty #" + numEmpty, true);
                        }
                    }
                    break;
                default:
                    mNumNonCachedProcs++;
                    break;
            }

              // 进程是isolated并且没有在运行Service
            if (app.isolated && app.services.size() <= 0) {
                app.kill("isolated not needed", true);
            } else {
                // Keeping this process, update its uid.
                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++;
            }
        }
    }
...
  • 获取前台Activity
  • 计算出空进程、缓存进程上限个数
  • 更新所有正在运行的APP的adj并应用
  • 杀死达到上限个数的空进程与缓存进程

updateOomAdjLocked (2) - 对进程内存trim

...
    mNumServiceProcs = mNewNumServiceProcs;

    // 开始针对后台进程,对内存进行trim
    // 初始化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;
            if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
        }
    }
    mLastMemoryLevel = memFactor;
    mLastNumProcesses = mLruProcesses.size();
    boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
    final int trackerMemFactor = mProcessStats.getMemFactorLocked();
    // 计算memFactor
    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;
        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;
            }
            if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                    && !app.killedByAm) {
                // 如果当前进程memLevel小于当前的level,则需要对进程内存做trim
                if (app.trimMemoryLevel < curLevel && app.thread != null) {
                    try {
                        if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
                                "Trimming memory of " + app.processName + " to " + curLevel);
                        app.thread.scheduleTrimMemory(curLevel);
                    } catch (RemoteException e) {
                    }
...
                }
                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) {
                    try {
                        if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
                                "Trimming memory of heavy-weight " + app.processName
                                        + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                        app.thread.scheduleTrimMemory(
                                ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                    } catch (RemoteException e) {
                    }
                }
                app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
            } else {
                if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                        || app.systemNoUi) && app.pendingUiClean) {
                    // If this application is now in the background and it
                    // had done UI, then give it the special trim level to
                    // have it free UI resources.
                    final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
                    if (app.trimMemoryLevel < level && app.thread != null) {
                        try {
                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
                                    "Trimming memory of bg-ui " + app.processName
                                            + " to " + level);
                            app.thread.scheduleTrimMemory(level);
                        } catch (RemoteException e) {
                        }
                    }
                    app.pendingUiClean = false;
                }
                if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
                    try {
                        if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
                                "Trimming memory of fg " + app.processName
                                        + " to " + fgTrimLevel);
                        app.thread.scheduleTrimMemory(fgTrimLevel);
                    } catch (RemoteException e) {
                    }
                }
                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) {
                    try {
                        if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
                                "Trimming memory of ui hidden " + app.processName
                                        + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
                        app.thread.scheduleTrimMemory(
                                ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
                    } catch (RemoteException e) {
                    }
                }
                app.pendingUiClean = false;
            }
            app.trimMemoryLevel = 0;
        }
    }

...

    // 更新UidRecord变化
    for (int i = mActiveUids.size() - 1; i >= 0; i--) {
        final UidRecord uidRec = mActiveUids.valueAt(i);
        if (uidRec.setProcState != uidRec.curProcState) {
            if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                    "Changes in " + uidRec + ": proc state from " + uidRec.setProcState
                            + " to " + uidRec.curProcState);
            uidRec.setProcState = uidRec.curProcState;
            enqueueUidChangeLocked(uidRec, false);
        }
    }

     // 异步记录状态
    if (mProcessStats.shouldWriteNowLocked(now)) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                synchronized (ActivityManagerService.this) {
                    mProcessStats.writeStateAsyncLocked();
                }
            }
        });
    }
...
}

这一块代码主要是根据当前的memory level,遍历所有正在运行中的进程,并选择对它们其中的进程内存做trim

查看大图

进程优先级的计算:computeOomAdjLocked

computeOomAdjLocked (1) - 进行特殊检查

private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
                                      boolean doingAll, long now) {
    // 检查当前adj是否已经被计算
    if (mAdjSeq == app.adjSeq) {
        return app.curRawAdj;
    }

     // 检查当前进程是否已经死亡
    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.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
    app.adjSource = null;
    app.adjTarget = null;
    app.empty = false;
    app.cached = false;

    final int activitiesSize = app.activities.size();

     // 检查当前进程是否被设置了adj下限
    if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
        // The max adjustment doesn't allow this app to be anything
        // below foreground, so it is not worth doing work for it.
        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;
        // System processes can do UI, and when they do we want to have
        // them trim their memory after the user leaves the UI.  To
        // facilitate this, here we need to determine whether or not it
        // is currently showing UI.
        app.systemNoUi = true;
        if (app == TOP_APP) {
            app.systemNoUi = false;
        } 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);
    }

    app.systemNoUi = false;

    final int PROCESS_STATE_TOP = mTopProcessState;

这一步主要是对进程优先级更新时做一次检查;可以看到adj是进程优先级的主要衡量值

computeOomAdjLocked (2) - 根据四大组件计算

```java
// 开始计算adj, curProc, schedGroup这些重要指标
// 从最重要的开始计算
// adj, curProc的最终值取值标准是取最小值
int adj;
int schedGroup;
int procState;
boolean foregroundActivities = false;
BroadcastQueue queue;
// 是否有前台Activity
if (app == TOP_APP) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_TOP;
// 是否在运行intrumentation
} else if (app.instrumentationClass != null) {
// Don't want to kill running instrumentation.
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) {
// An app that is currently receiving a broadcast also
// counts as being in the foreground for OOM killer purposes.
// It's placed in a sched group based on the nature of the
// broadcast as reflected by which queue it's active in.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = (queue == mFgBroadcastQueue)
? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
// 是否正在执行Service
} else if (app.executingServices.size() > 0) {
// An app that is currently executing a service callback also
// counts as being in the foreground.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = app.execServicesFg ?
Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.adjType = "exec-service";
procState = ActivityManager.PROCESS_STATE_SERVICE;
//Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
// 都不符合则暂时为空
} else {
// As far as we know the process is empty. We may change our mind later.
schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
// At this point we don't actually know the adjustment. Use the cached adj
// value that the caller wants us to.
adj = cachedAdj;
procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
app.cached = true;
app.empty = true;
app.adjType = "cch-empty";
}

// 检查进程所有在"后台"的Activity
if (!foregroundActivities && activitiesSize > 0) {
    for (int j = 0; j < activitiesSize; j++) {
        final ActivityRecord r = app.activities.get(j);
        if (r.app != app) {
            Slog.w(TAG, "Wtf, activity " + r + " in proc activity list not using proc "
                    + app + "?!? Using " + r.app + " instead.");
            continue;
        }
        // 如果Activity可见
        if (r.visible) {
            // App has a visible activity; only upgrade adjustment.
            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;
        // 如果在pause状态
        } 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;
        // 如果在stop状态
        } else if (r.state == ActivityState.STOPPING) {
            if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                app.adjType = "stopping";
            }
            // For the process state, we will at this point consider the
            // process to be cached.  It will be cached either as an activity
            // or empty depending on whether the activity is finishing.  We do
            // this so that we can treat the process as cached for purposes of
            // memory trimming (determing current memory level, trim command to
            // send to process) since there can be an arbitrary number of stopping
            // processes and they should soon all go into the cached state.
            if (!r.finishing) {
                if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                    procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
                }
            }
            app.cached = false;
            app.empty = false;
            foregroundActivities = true;
        // 如果都不符合则暂时为空
top Created with Sketch.