Android oom_adj 更新原理(androidU)

1. adj 概念

Android 系统的设计理念希望应用进程尽可能长时间的存活,以此来提升用户体验。在Android 中,应用首次打开会比较慢,这个过程包含进程的创建、application 初始化应用其他逻辑等,所以,在应用退出时并非直接exit 进程或被 kill,而是会存活一段时间,这样就保证在下次启动时跟快启动。

当然,物极必反。在大量应用启动后就会造成内存大量使用,手机性能会随着下降。如果放任所有进程存活,系统内存就会枯竭。因此需要合理的回收机制,Android 中通过 adjprocess state 两个重要的标准来进行衡量。系统根据进程组建的状态来决定每个进程的优先级adj 值,然后再根据一定的策略选择优先级低的进程kill,以此类推,通过回收预期的系统资源来保证系统的正常运转。

可以通过ProcessList.java中的setOomAdj方法去调整进程的优先级, OOM_ADJ (Out-Of-Memory Adjustment),进程优先级影响系统对进程的内存回收策略。OOM_ADJ 值越低,表示该进程的优先级越高,系统回收内存时越不会杀死该进程。OOM_ADJ 值越高,则表示该进程的优先级越低,系统回收内存时越容易杀死该进程。

在 Android 中,OOM_ADJ 值的范围为 -1000 到 1000,其中 -1000 表示最高优先级(最不容易被杀死),而 1000 表示最低优先级(最容易被杀死)。

具体来说,-

1000 到 -900 被认为是“native进程,系统进程”;

-800 到 0 被认为是“系统常驻进程,前台进程,可见进程,可感知进程等”;

而 1000 则被认为是“空进程”。

关于 -1000 和 1000 优先级的区别,主要体现在它们所代表的进程类型不同。具体来说:

-1000 优先级的进程是属于前台进程,这些进程通常是用户当前正在操作的应用程序。这些进程可以使用大量的系统资源,并且在系统内存不足时也不容易被杀死。因此,系统会尽量保留这些进程的内存,以保证用户体验的流畅性。
1000 优先级的进程是属于空进程,即没有任何应用程序或服务的进程。这些进程不占用任何内存,因此在系统内存不足时,它们往往会被最先杀死。因此,这些进程通常只会被用来占位,或者用来作为一些系统服务的容器。
可以在/proc/pid/oom_score_adj查看当前OomAdj
 

2. adj 等级

Android中根据进程相对用户的重要程度,将进程分五个层次:

1. 前台进程
    用户当前操作所必需的进程。如果一个进程满足以下任一条件,即视为前台进程:
    托管用户正在交互的 Activity(已调用 Activity 的 onResume() 方法)
    托管某个 Service,后者绑定到用户正在交互的 Activity
    托管正在“前台”运行的 Service(服务已调用 startForeground())
    托管正执行一个生命周期回调的 Service(onCreate()、onStart() 或 onDestroy())
    托管正执行其 onReceive() 方法的 BroadcastReceiver

2. 可见进程

没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。 如果一个进程满足以下任一条件,即视为可见进程:
    (1) 托管不在前台、但仍对用户可见的 Activity(已调用其 onPause() 方法)。例如,如果前台 Activity 启动了一个对话框,允许在其后显示上一 Activity,则有可能会发生这种情况。
    托管绑定到可见(或前台)Activity 的 Service。
    (2) 可见进程被视为是极其重要的进程,除非为了维持所有前台进程同时运行而必须终止,否则系统不会终止这些进程。 
3. 服务进程
    正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程。尽管服务进程与用户所见内容没直接关联,但是它们通常在执行一些用户关心的操作(例如,在后台播放音乐或从网络下载数据)。因此,除非内存不足以维持所有前台进程和可见进程同时运行,否则系统会让服务进程保持运行状态。 
4.  后台进程
    包含目前对用户不可见的 Activity 的进程(已调用 Activity 的 onStop() 方法)。
5.  空进程
不含任何活动应用组件的进程。保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间。 为使总体系统资源在进程缓存和底层内核缓存之间保持平衡,系统往往会终止这些进程。 
 

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

ADJ 等级 取值 说明
UNKNOWN_ADJ
1001
用于特定地方,一般指将要cache进程,不知道确切值.
CACHED_APP_MAX_ADJ 999 不可见进程的最大值,进程可以无任何干扰的被杀
CACHED_APP_LMK_FIRST_ADJ 950 oom_adj 等级第一个允许被杀的level,不能等于CACHED_APP_MAX_ADJ
CACHED_APP_MIN_ADJ 900 不可见进程的最小值
SERVICE_B_ADJ 800 B List中的Service(较老的、使用可能性更小)
PREVIOUS_APP_ADJ 700 上一个App的进程(往往通过按返回键)
HOME_APP_ADJ 600 Home进程
SERVICE_ADJ 500 app service 进程,杀掉它一般不会有太大的影响
HEAVY_WEIGHT_APP_ADJ 400 后台的重量级进程,system/rootdir/init.rc文件中startup
BACKUP_APP_ADJ 300 备份进程,杀掉它不完全致命,但不好
PERCEPTIBLE_LOW_APP_ADJ 250 被用户或系统绑定的进程,比service 要重要,但是如果被杀掉,不会立即影响客户的感官
PERCEPTIBLE_MEDIUM_APP_ADJ 225 这是一个托管服务的进程,用户无法感知,但绑定到它的客户端(系统)请求将其视为可感知的,并尽可能避免杀死它。
PERCEPTIBLE_APP_ADJ 200 可感知的进程,如后台music 播放
VISIBLE_APP_ADJ 100 可见进程
PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ 50 recently TOP and moved to FGS
FOREGROUND_APP_ADJ 0 前台进程
PERSISTENT_SERVICE_ADJ -700 这是系统或持久进程已绑定的进程,并表明它很重要。
PERSISTENT_PROC_ADJ -800

系统常驻进程,例如systemui

绝对不想杀,但不完全致命

SYSTEM_ADJ -900 杀掉手机会重启
NATIVE_ADJ -1000 native 进程,不归系统管理,所以没有oom_adj 适配

3. 进程状态

androidu/frameworks/base/core/java/android/app/ActivityManager.java

状态等级 取值 说明
PROCESS_STATE_CACHED_EMPTY 19 进程将被cached,且是空进程
PROCESS_STATE_CACHED_RECENT 18 进程将被cached,而且有个activity与一个recent task 通信
PROCESS_STATE_CACHED_ACTIVITY_CLIENT 17 进程正在被缓存以供以后使用,并且具有与现有的最近任务相对应的活动。
PROCESS_STATE_CACHED_ACTIVITY 16 进程正在被缓存以供以后使用,并且包含活动。
PROCESS_STATE_LAST_ACTIVITY 15 进程位于后台,但托管最后显示的活动
PROCESS_STATE_HOME 14 后台进程,且拥有home Activity
PROCESS_STATE_HEAVY_WEIGHT 13 后台进程,但无法执行restore,因此尽量避免kill该进程
PROCESS_STATE_TOP_SLEEPING 12 与PROCESS_STATE_TOP一样,但此时设备正处于休眠状态
PROCESS_STATE_RECEIVER 11 后台进程,且正在运行receiver
PROCESS_STATE_SERVICE 10 后台进程,且正在运行service
PROCESS_STATE_BACKUP 9 后台进程,正在运行backup/restore操作
PROCESS_STATE_TRANSIENT_BACKGROUND 8 短暂的后台进程,需要keep running
PROCESS_STATE_IMPORTANT_BACKGROUND 7 对用户重要的进程,但并不能感知到
PROCESS_STATE_IMPORTANT_FOREGROUND 6 对用户重要的进程,且可以感知到
PROCESS_STATE_BOUND_FOREGROUND_SERVICE 5 进程拥有一个前台Service,且由系统绑定
PROCESS_STATE_FOREGROUND_SERVICE 4 进程拥有一个前台service
PROCESS_STATE_BOUND_TOP 3 被绑定为TOP app 的进程
PROCESS_STATE_TOP 2 进程拥有当前top activities,对于用户是可见的
PROCESS_STATE_PERSISTENT_UI 1 进程为persisent 系统进程,且doing UI
PROCESS_STATE_PERSISTENT 0 常驻的系统进程

4. bind类型

binder类型 说明
BIND_WAIVE_PRIORITY 不影响调度或目标服务托管进程的内存管理优先级。,像通用的应用进程一样将服务放在一个LRU表中
BIND_TREAT_LIKE_ACTIVITY 将binding 视为持有一个activity,unbinding视为activity在后台,这个通常用在输入法进程,以便更快捷的切换键盘。
BIND_ALLOW_OOM_MANAGEMENT 保持服务受默认的服务管理器管理,当内存不足时候,会销毁服务.
BIND_ABOVE_CLIENT 设置服务的进程优先级高于客户端的优先级,只有当需要服务晚于客户端被销毁这种情况才这样设置
BIND_IMPORTANT 标识服务对客户端是非常重要的,会将服务提升至前台进程优先级,通常情况下,即时客户端是前台优先级,服务最多也只能被提升至可见进程优先级
BIND_NOT_FOREGROUND 不会将被绑定的服务提升到前台优先级,但是这个服务也至少会和客户端在内存中优先级是相同的
BIND_SCHEDULE_LIKE_TOP_APP 此标志仅用于系统调整IME(以及与top应用程序紧密配合的任何进程外用户可见组件)的调度策略。所以托管此类服务的UI能够拥有top app一样的调度策略。仅限于系统调用,否则会抛出安全异常
BIND_ADJUST_WITH_ACTIVITY Service的优先级将相对于其绑定的Activity,Activity到前台,则Service优先级相对提升,Activity到后台,则Servcie优先级相对降低
 
BIND_AUTO_CREATE 绑定服务时候,如果服务尚未创建,服务会自动创建

5. 4个核心函数


oom_adj 涉及三个重要函数:

frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java

updateOomAdjLocked:更新 LRU 列表中所有进程的 OomAdj;

updateAndTrimProcessLSP:检查当前进程的状态,若符合回收要求,则直接杀掉。
computeOomAdjLSP:计算adj.
applyOomAdjLSP:应用计算出的 oomadj、procstate 和 sched 组值并将它们冻结在集合中。
 

当四大组件状态改变时会通过 updateOomAdjLocked() 来同步更新相应进程的 ADJ 优先级。需要注意的是,当同一个进程有多个决定其优先级的组件状态时,取优先级最高的 ADJ 作为最终的 ADJ。另外,进程会通过设置 maxAdj 来限定ADJ 的上限。

6. updateOomAdjLocked() 简析

在上一节中我们得知 oom_adj 涉及三个重要的函数,源头都是 updateOomAdjLocked(),在详细剖析该函数之前先来了解下。

首先该接口的源头都位于 AMS 中,在AMS 中提供了三个接口:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @GuardedBy("this")
    final void updateOomAdjLocked(String oomAdjReason) {
        mOomAdjuster.updateOomAdjLocked(oomAdjReason);
    }

    /**
     * Update OomAdj for a specific process and its reachable processes.
     *
     * @param app The process to update
     * @param oomAdjReason
     * @return whether updateOomAdjLocked(app) was successful.
     */
    @GuardedBy("this")
    final boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
        return mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
    }

    /**
     * Kick off an oom adj update pass for the pending targets which are enqueued via
     * {@link #enqueueOomAdjTargetLocked}.
     */
    @GuardedBy("this")
    void updateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason) {
        mOomAdjuster.updateOomAdjPendingTargetsLocked(oomAdjReason);
    }

AMS 中提供的三个接口分别对应 OomAdjuster 中的三个接口,四大组件在更新 ADJ 时都是通过这里的接口。

7. ADJ 更新时机


7.1 activity 中更新 oom_adj
ASS.realStartActivityLocked():启动Activity    -->待验证
AS.resumeTopActivityInnerLocked():恢复栈顶Activity -->待验证
AS.finishCurrentActivityLocked():结束当前Activity-->待验证
AS.destroyActivityLocked():摧毁当前Activity-->待验证

 7.2 service 中更新 oom_adj
ActiveServices.realStartServiceLocked():启动服务
ActiveServices.bindServiceLocked():绑定服务(只更新当前app)
ActiveServices.unbindServiceLocked():解绑服务 (只更新当前app)
ActiveServices.bringDownServiceLocked():结束服务 (只更新当前app)
ActiveServices.sendServiceArgsLocked():在bringup或则cleanup服务过程调用 (只更新当前app)
 

8. 函数分析:

8.1 computeOomAdjLSP 函数:
    @GuardedBy({"mService", "mProcLock"})
    private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
            ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
            boolean computeClients) {
        
        //1.判断adj 是否需要更新. 
        final ProcessStateRecord state = app.mState;
        if (mAdjSeq == state.getAdjSeq()) {
            if (state.getAdjSeq() == state.getCompletedAdjSeq()) {
                // This adjustment has already been computed successfully.
                //调整策略没有变化,不需要调整
                return false;
            } else {
                // The process is being computed, so there is a cycle. We cannot
                // rely on this process's state.
                //在加入循环列表中
                state.setContainsCycle(true);
                mProcessesInCycle.add(app);

                return false;
            }
        }
        //当app的thread为null时,设置为空进程
        if (app.getThread() == null) {
            state.setAdjSeq(mAdjSeq);
            state.setCurrentSchedulingGroup(SCHED_GROUP_BACKGROUND);
            state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
            state.setCurAdj(CACHED_APP_MAX_ADJ);
            state.setCurRawAdj(CACHED_APP_MAX_ADJ);
            state.setCompletedAdjSeq(state.getAdjSeq());
            state.setCurCapability(PROCESS_CAPABILITY_NONE);
            return false;
        }

        state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN);
        state.setAdjSource(null);
        state.setAdjTarget(null);
        state.setEmpty(false);
        state.setCached(false);
        if (!cycleReEval) {
            // Don't reset this flag when doing cycles re-evaluation.
            state.setNoKillOnBgRestrictedAndIdle(false);
            // If this UID is currently allowlisted, it should not be frozen.
            final UidRecord uidRec = app.getUidRecord();
             //如果此 UID 当前已列入白名单,则不应冻结它。
            app.mOptRecord.setShouldNotFreeze(uidRec != null && uidRec.isCurAllowListed());
        }

        final int appUid = app.info.uid;
        final int logUid = mService.mCurOomAdjUid;

        int prevAppAdj = state.getCurAdj();
        int prevProcState = state.getCurProcState();
        int prevCapability = state.getCurCapability();
        final ProcessServiceRecord psr = app.mServices;

        //2. 针对maxADJ小于FOREGROUND_APP_ADJ的逻辑处理
        if (state.getMaxAdj() <= 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.
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app);
            }
            state.setAdjType("fixed");
            state.setAdjSeq(mAdjSeq);
            state.setCurRawAdj(state.getMaxAdj());
            state.setHasForegroundActivities(false);
            state.setCurrentSchedulingGroup(SCHED_GROUP_DEFAULT);
            state.setCurCapability(PROCESS_CAPABILITY_ALL); // BFSL allowed
            state.setCurProcState(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.
            state.setSystemNoUi(true);
            if (app == topApp) {
                //若是TOP APP
                state.setSystemNoUi(false);
                state.setCurrentSchedulingGroup(SCHED_GROUP_TOP_APP);
                state.setAdjType("pers-top-activity");
            } else if (state.hasTopUi()) {
                // sched group/proc state adjustment is below
                state.setSystemNoUi(false);
                state.setAdjType("pers-top-ui");
            } else if (state.getCachedHasVisibleActivities()) {
                state.setSystemNoUi(false);
            }
            if (!state.isSystemNoUi()) {
                if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE
                        || state.isRunningRemoteAnimation()) {
                    // screen on or animating, promote UI
            //针对亮屏或者正在做动画,加强UI
 state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
                    state.setCurrentSchedulingGroup(SCHED_GROUP_TOP_APP);
                } else {
                    // screen off, restrict UI scheduling
                    //熄屏限制UI调度
                    state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
                    state.setCurrentSchedulingGroup(SCHED_GROUP_RESTRICTED);
                }
            }
            state.setCurRawProcState(state.getCurProcState());
            state.setCurAdj(state.getMaxAdj());
            state.setCompletedAdjSeq(state.getAdjSeq());
            // if curAdj is less than prevAppAdj, then this process was promoted
            return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
        }
        //3. 针oom进行分类
        state.setSystemNoUi(false);

        final int PROCESS_STATE_CUR_TOP = mService.mAtmInternal.getTopProcessState();

        // Determine the importance of the process, starting with most
        // important to least, and assign an appropriate OOM adjustment.
        int adj;
        int schedGroup;
        int procState;
        int capability = cycleReEval ? app.mState.getCurCapability() : 0;

        boolean foregroundActivities = false;
        boolean hasVisibleActivities = false;

        if (app == topApp && PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP) {
            // The last app on the list is the foreground app.
            //前台列表
            adj = FOREGROUND_APP_ADJ;
            if (mService.mAtmInternal.useTopSchedGroupForTopProcess()) {
                schedGroup = SCHED_GROUP_TOP_APP;
                state.setAdjType("top-activity");
            } else {
                // Demote the scheduling group to avoid CPU contention if there is another more
                // important process which also uses top-app, such as if SystemUI is animating.    
         //降级显示
                schedGroup = SCHED_GROUP_DEFAULT;
                state.setAdjType("intermediate-top-activity");
            }
            //标记为FG 和visble
            foregroundActivities = true;
            hasVisibleActivities = true;
            procState = PROCESS_STATE_TOP;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
            }
        } else if (state.isRunningRemoteAnimation()) {
            //若有动画正在运行
            adj = VISIBLE_APP_ADJ;
            schedGroup = 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.
       // 正在运行的instrumentation
            adj = FOREGROUND_APP_ADJ;
            schedGroup = SCHED_GROUP_DEFAULT;
            state.setAdjType("instrumentation");
            procState = PROCESS_STATE_FOREGROUND_SERVICE;
            capability |= PROCESS_CAPABILITY_BFSL;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
            }
        } else if (state.getCachedIsReceivingBroadcast(mTmpSchedGroup)) {
            // 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 = FOREGROUND_APP_ADJ;
            schedGroup = mTmpSchedGroup[0];
            state.setAdjType("broadcast");
            procState = ActivityManager.PROCESS_STATE_RECEIVER;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
            }
        } else if (psr.numberOfExecutingServices() > 0) {
            // An app that is currently executing a service callback also
            // counts as being in the foreground.
            //有正在运行的Service
            adj = FOREGROUND_APP_ADJ;
            schedGroup = psr.shouldExecServicesFg()
                    ? SCHED_GROUP_DEFAULT : 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) {
             //属于TOP APP
            adj = FOREGROUND_APP_ADJ;
            schedGroup = 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);
            }
        } else {
            // As far as we know the process is empty.  We may change our mind later.
       //以上条件都不能满足,可以认为是缓存进程
            schedGroup = 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);
            }
        }

        // Examine all activities if not already foreground.
     //不是前台activity并且在缓存存在activitys
        if (!foregroundActivities && state.getCachedHasActivities()) {
            state.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
                    adj, foregroundActivities, hasVisibleActivities, procState, schedGroup,
                    appUid, logUid, PROCESS_STATE_CUR_TOP);

            adj = state.getCachedAdj();
            foregroundActivities = state.getCachedForegroundActivities();
            hasVisibleActivities = state.getCachedHasVisibleActivities();
            procState = state.getCachedProcState();
            schedGroup = state.getCachedSchedGroup();
        }
        //进程状态大于PROCESS_STATE_CACHED_RECENT(说明是至少是空进程) ,并且存在recent task.
        if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) {
            procState = PROCESS_STATE_CACHED_RECENT;
            state.setAdjType("cch-rec");
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app);
            }
        }

        int capabilityFromFGS = 0; // capability from foreground service.
     //是否有前台service
        final boolean hasForegroundServices = psr.hasForegroundServices();
     // 是否存在short fg service
        final boolean hasNonShortForegroundServices = psr.hasNonShortForegroundServices();
        //
        final boolean hasShortForegroundServices = hasForegroundServices
                && !psr.areAllShortForegroundServicesProcstateTimedOut(now);

        // Adjust for FGS or "has-overlay-ui".
        //可感知的app
        if (adj > PERCEPTIBLE_APP_ADJ
                || procState > PROCESS_STATE_FOREGROUND_SERVICE) {
            String adjType = null;
            int newAdj = 0;
            int newProcState = 0;
            //有前台服务并且没有Short前台服务
            if (hasForegroundServices && hasNonShortForegroundServices) {
                // For regular (non-short) FGS.
                adjType = "fg-service";
                newAdj = PERCEPTIBLE_APP_ADJ;
                newProcState = PROCESS_STATE_FOREGROUND_SERVICE;
                capabilityFromFGS |= PROCESS_CAPABILITY_BFSL;

            } else if (hasShortForegroundServices) {
                //在short FG
                // For short FGS.
                adjType = "fg-service-short";

                // We use MEDIUM_APP_ADJ + 1 so we can tell apart EJ
                // (which uses MEDIUM_APP_ADJ + 1)
                // from short-FGS.
                // (We use +1 and +2, not +0 and +1, to be consistent with the following
                // RECENT_FOREGROUND_APP_ADJ tweak)
                newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 1;

                // We give the FGS procstate, but not PROCESS_CAPABILITY_BFSL, so
                // short-fgs can't start FGS from the background.
                newProcState = PROCESS_STATE_FOREGROUND_SERVICE;

            } else if (state.hasOverlayUi()) {
                adjType = "has-overlay-ui";
                newAdj = PERCEPTIBLE_APP_ADJ;
                newProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
            }

            if (adjType != null) {
                adj = newAdj;
                procState = newProcState;
                state.setAdjType(adjType);
                state.setCached(false);
                schedGroup = SCHED_GROUP_DEFAULT;

                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType + ": "
                            + app + " ");
                }
            }
        }

        // If the app was recently in the foreground and moved to a foreground service status,
        // allow it to get a higher rank in memory for some time, compared to other foreground
        // services so that it can finish performing any persistence/processing of in-memory state.
        //
        if (psr.hasForegroundServices() && adj > PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
                && (state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION > now
                || state.getSetProcState() <= PROCESS_STATE_TOP)) {
            if (psr.hasNonShortForegroundServices()) {
                adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
                state.setAdjType("fg-service-act");
            } else {
                // For short-service FGS, we +1 the value, so we'll be able to detect it in
                // various dashboards.
                adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 1;
                state.setAdjType("fg-service-short-act");
            }
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
            }
        }

        // If the app was recently in the foreground and has expedited jobs running,
        // allow it to get a higher rank in memory for some time, compared to other EJS and even
        // foreground services so that it can finish performing any persistence/processing of
        // in-memory state.
        if (psr.hasTopStartedAlmostPerceptibleServices()
                && (adj > PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2)
                && (state.getLastTopTime()
                        + mConstants.TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION > now
                || state.getSetProcState() <= PROCESS_STATE_TOP)) {
            // For EJ, we +2 the value, so we'll be able to detect it in
            // various dashboards.
            adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2;
            // This shall henceforth be called the "EJ" exemption, despite utilizing the
            // ALMOST_PERCEPTIBLE flag to work.
            state.setAdjType("top-ej-act");
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg for EJ: " + app);
            }
        }

        if (adj > PERCEPTIBLE_APP_ADJ
                || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
            if (state.getForcingToImportant() != null) {
                // This is currently used for toasts...  they are not interactive, and
                // we don't want them to cause the app to become fully foreground (and
                // thus out of background check), so we yes the best background level we can.
                adj = PERCEPTIBLE_APP_ADJ;
                procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
                state.setCached(false);
                state.setAdjType("force-imp");
                state.setAdjSource(state.getForcingToImportant());
                schedGroup = SCHED_GROUP_DEFAULT;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app);
                }
            }
        }

        if (state.getCachedIsHeavyWeight()) {
            if (adj > HEAVY_WEIGHT_APP_ADJ) {
                // We don't want to kill the current heavy-weight process.
                //通过adj的方式变成重量级的应用
                adj = HEAVY_WEIGHT_APP_ADJ;
                schedGroup = SCHED_GROUP_BACKGROUND;
                state.setCached(false);
                state.setAdjType("heavy");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app);
                }
            }
            if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
                //通过proc state的方式,变成重量级应用
                procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
                state.setAdjType("heavy");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app);
                }
            }
        }

        if (state.getCachedIsHomeProcess()) {
            if (adj > HOME_APP_ADJ) {
                // This process is hosting what we currently consider to be the
                // home app, so we don't want to let it go into the background.
                //判断为home app
                adj = HOME_APP_ADJ;
                schedGroup = SCHED_GROUP_BACKGROUND;
                state.setCached(false);
                state.setAdjType("home");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app);
                }
            }
            if (procState > ActivityManager.PROCESS_STATE_HOME) {
                //通过proc state 判断为home app
                procState = ActivityManager.PROCESS_STATE_HOME;
                state.setAdjType("home");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app);
                }
            }
        }
        //
        if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
            // This was the previous process that showed UI to the user.  We want to
            // try to keep it around more aggressively, to give a good experience
            // around switching between two apps. However, we don't want to keep the
            // process in this privileged state indefinitely. Eventually, allow the
            // app to be demoted to cached.

            //这是向用户显示UI的上一个流程.我们希望更积极地保留它,以便在两个应用程序之间切换时提供良好的体验。 但是,我们不想让进程无限期地保持这种特权状态。 最终,允许应用程序降级为缓存。

            if (procState >= PROCESS_STATE_LAST_ACTIVITY
                    && state.getSetProcState() == PROCESS_STATE_LAST_ACTIVITY
                    && (state.getLastStateTime() + mConstants.MAX_PREVIOUS_TIME) < now) {
                procState = PROCESS_STATE_LAST_ACTIVITY;
                schedGroup = SCHED_GROUP_BACKGROUND;
                state.setAdjType("previous-expired");
                adj = CACHED_APP_MIN_ADJ;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Expire prev adj: " + app);
                }
            } else {
                if (adj > PREVIOUS_APP_ADJ) {
                    adj = PREVIOUS_APP_ADJ;
                    schedGroup = SCHED_GROUP_BACKGROUND;
                    state.setCached(false);
                    state.setAdjType("previous");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
                    }
                }
                if (procState > PROCESS_STATE_LAST_ACTIVITY) {
                    procState = PROCESS_STATE_LAST_ACTIVITY;
                    state.setAdjType("previous");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
                    }
                }
            }
        }

        //打印app的adj 和对应的type
        if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
                + " reason=" + state.getAdjType());

        // By default, we use the computed adjustment.  It may be changed if
        // there are applications dependent on our services or providers, but
        // this gives us a baseline and makes sure we don't get into an
        // infinite recursion. If we're re-evaluating due to cycles, use the previously computed
        // values.
        //若是循环评估
        if (cycleReEval) {
            procState = Math.min(procState, state.getCurRawProcState());
            adj = Math.min(adj, state.getCurRawAdj());
            schedGroup = Math.max(schedGroup, state.getCurrentSchedulingGroup());
        }
        state.setCurRawAdj(adj);
        state.setCurRawProcState(procState);

        state.setHasStartedServices(false);
        state.setAdjSeq(mAdjSeq);

        final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId);
        if (backupTarget != null && app == backupTarget.app) {
            // If possible we want to avoid killing apps while they're being backed up
            //将adj 设置成back up
            if (adj > BACKUP_APP_ADJ) {
                if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
                adj = BACKUP_APP_ADJ;
                if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
                    //设置为短暂后台进程
                    procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
                }
                state.setAdjType("backup");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app);
                }
                state.setCached(false);
            }
            if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
                //设置为back up 进程
                procState = ActivityManager.PROCESS_STATE_BACKUP;
                state.setAdjType("backup");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app);
                }
            }
        }
        //是否受后台约束
        boolean boundByNonBgRestricted = state.isCurBoundByNonBgRestrictedApp();

        boolean scheduleLikeTopApp = false;
        //遍历startService的service
        for (int is = psr.numberOfRunningServices() - 1;
                is >= 0 && (adj > FOREGROUND_APP_ADJ
                        || schedGroup == SCHED_GROUP_BACKGROUND
                        || procState > PROCESS_STATE_TOP);
                is--) {
            ServiceRecord s = psr.getRunningServiceAt(is);
            if (s.startRequested) {
                state.setHasStartedServices(true);
                if (procState > PROCESS_STATE_SERVICE) {
                    //设置为PROCESS_STATE_SERVICE
                    procState = PROCESS_STATE_SERVICE;
                    //更新状态为"started-services"
                    state.setAdjType("started-services");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise procstate to started service: " + app);
                    }
                }

                if (!s.mKeepWarming && state.hasShownUi() && !state.getCachedIsHomeProcess()) {
                    // If this process has shown some UI, let it immediately
                    // go to the LRU list because it may be pretty heavy with
                    // UI stuff.  We'll tag it with a label just to help
                    // debug and understand what is going on.
                    if (adj > SERVICE_ADJ) {
                        state.setAdjType("cch-started-ui-services");
                    }
                } else {
                    if (s.mKeepWarming
                            || now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
                        // This service has seen some activity within
                        // recent memory, so we will keep its process ahead
                        // of the background processes.
                        // 调整Service的adj
                        if (adj > SERVICE_ADJ) {
                            adj = SERVICE_ADJ;
                            state.setAdjType("started-services");
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                        "Raise adj to started service: " + app);
                            }
                            state.setCached(false);
                        }
                    }
                    // If we have let the service slide into the background
                    // state, still have some text describing what it is doing
                    // even though the service no longer has an impact.
                    // 调节 service adj
                    if (adj > SERVICE_ADJ) {
                        state.setAdjType("cch-started-services");
                    }
                }
            }
            //若是前台进程
            if (s.isForeground) {
                //是否前台Service
                final int fgsType = s.foregroundServiceType;
                //是否允许前台服务中的使用时权限.
                if (s.mAllowWhileInUsePermissionInFgs) {
                  
                    capabilityFromFGS |=
                            (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
                                    != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;

                    final boolean enabled = state.getCachedCompatChange(
                            CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY);
                    
                    if (enabled) {
                        //判断是否包含FOREGROUND_SERVICE_TYPE_CAMERA,包含则增加在前台可以访问camera
                        capabilityFromFGS |=
                                (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
                                        != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0;
                        //判断是否包含FOREGROUND_SERVICE_TYPE_MICROPHONE,包含则增加前台可访问MICROPHONE
                        capabilityFromFGS |=
                                (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
                                        != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0;
                    } else {
                        //增加PROCESS_CAPABILITY_FOREGROUND_CAMERA 和 PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
                        capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
                                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
                    }
                }
            }

            ArrayMap> serviceConnections = s.getConnections();

            for (int conni = serviceConnections.size() - 1;
                    conni >= 0 && (adj > FOREGROUND_APP_ADJ
                            || schedGroup == SCHED_GROUP_BACKGROUND
                            || procState > PROCESS_STATE_TOP);
                    conni--) {

                ArrayList clist = serviceConnections.valueAt(conni);

                for (int i = 0;
                        i < clist.size() && (adj > FOREGROUND_APP_ADJ
                                || schedGroup == SCHED_GROUP_BACKGROUND
                                || procState > PROCESS_STATE_TOP);
                        i++) {

                    // XXX should compute this based on the max of
                    // all connected clients.
                    ConnectionRecord cr = clist.get(i);
                    if (cr.binding.client == app) {
                        // Binding to oneself is not interesting.
                        continue;
                    }

                    boolean trackedProcState = false;

                    ProcessRecord client = cr.binding.client;
                    if (app.isSdkSandbox && cr.binding.attributedClient != null) {
                        // For SDK sandboxes, use the attributed client (eg the app that
                        // requested the sandbox)
                        client = cr.binding.attributedClient;
                    }
                    final ProcessStateRecord cstate = client.mState;
                    //是否计算
                    if (computeClients) {
                        //计算OOMADJ
                        computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
                                cycleReEval, true);
                    } else {
                        //若不用计算,直接设置对应的值
                        cstate.setCurRawAdj(cstate.getCurAdj());
                        cstate.setCurRawProcState(cstate.getCurProcState());
                    }
                    //获取到当前的ADJ
                    int clientAdj = cstate.getCurRawAdj();
                    //获取当前的进程状态
                    int clientProcState = cstate.getCurRawProcState();
                    //是否属于persistent 进程
                    final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
                    //非 Bg 限制的状态
                    boundByNonBgRestricted |= cstate.isCurBoundByNonBgRestrictedApp()
                            || clientProcState <= PROCESS_STATE_BOUND_TOP
                            || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE
                                    && !cstate.isBackgroundRestricted());

                    if (client.mOptRecord.shouldNotFreeze()) {
                        // Propagate the shouldNotFreeze flag down the bindings.
                        //设置不冻结的标识
                        app.mOptRecord.setShouldNotFreeze(true);
                    }

                    // We always propagate PROCESS_CAPABILITY_BFSL over bindings here,
                    // but, right before actually setting it to the process,
                    // we check the final procstate, and remove it if the procsate is below BFGS.
                    capability |= getBfslCapabilityFromClient(client);

                    if (cr.notHasFlag(Context.BIND_WAIVE_PRIORITY)) {
                        if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
                            capability |= cstate.getCurCapability();
                        }

                        // If an app has network capability by default
                        // (by having procstate <= BFGS), then the apps it binds to will get
                        // elevated to a high enough procstate anyway to get network unless they
                        // request otherwise, so don't propagate the network capability by default
                        // in this case unless they explicitly request it.
                        if ((cstate.getCurCapability()
                                & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0) {
                            if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
                                // This is used to grant network access to Expedited Jobs.
                                if (cr.hasFlag(Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)) {
                                    capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
                                }
                            } else {
                                capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
                            }
                        }
                        if ((cstate.getCurCapability()
                                & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0) {
                            if (clientProcState <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
                                // This is used to grant network access to User Initiated Jobs.
                                if (cr.hasFlag(Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS)) {
                                    capability |= PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
                                }
                            }
                        }

                        if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                            continue;
                        }

                        if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                            // If the other app is cached for any reason, for purposes here
                            // we are going to consider it empty.  The specific cached state
                            // doesn't propagate except under certain conditions.
                            //为空进程
                            clientProcState = PROCESS_STATE_CACHED_EMPTY;
                        }
                        String adjType = null;
                        if (cr.hasFlag(Context.BIND_ALLOW_OOM_MANAGEMENT)) {
                            // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
                            if (clientAdj < CACHED_APP_MIN_ADJ) {
                                app.mOptRecord.setShouldNotFreeze(true);
                            }
                            // Not doing bind OOM management, so treat
                            // this guy more like a started service.
                            //有UI显示并且不是home 进程.
                            if (state.hasShownUi() && !state.getCachedIsHomeProcess()) {
                                // If this process has shown some UI, let it immediately
                                // go to the LRU list because it may be pretty heavy with
                                // UI stuff.  We'll tag it with a label just to help
                                // debug and understand what is going on.
                                if (adj > clientAdj) {
                                    //标记为绑定UI的Service
                                    adjType = "cch-bound-ui-services";
                                }
                                state.setCached(false);
                                clientAdj = adj;
                                clientProcState = procState;
                            } else {
                                if (now >= (s.lastActivity
                                        + mConstants.MAX_SERVICE_INACTIVITY)) {
                                    // This service has not seen activity within
                                    // recent memory, so allow it to drop to the
                                    // LRU list if there is no other reason to keep
                                    // it around.  We'll also tag it with a label just
                                    // to help debug and undertand what is going on.
                                    if (adj > clientAdj) {
                                        //绑定服务
                                        adjType = "cch-bound-services";
                                    }
                                    clientAdj = adj;
                                }
                            }
                        }
                        if (adj > clientAdj) {
                            // If this process has recently shown UI, and
                            // the process that is binding to it is less
                            // important than being visible, then we don't
                            // care about the binding as much as we care
                            // about letting this process get into the LRU
                            // list to be killed and restarted if needed for
                            // memory.
                            if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                                    && clientAdj > PERCEPTIBLE_APP_ADJ) {
                                if (adj >= CACHED_APP_MIN_ADJ) {
                                    adjType = "cch-bound-ui-services";
                                }
                            } else {
                                int newAdj;
                                int lbAdj = VISIBLE_APP_ADJ; // lower bound of adj.
                                if (cr.hasFlag(Context.BIND_ABOVE_CLIENT
                                        | Context.BIND_IMPORTANT)) {
                                    if (clientAdj >= PERSISTENT_SERVICE_ADJ) {
                                        newAdj = clientAdj;
                                    } else {
                                        // make this service persistent
                                        newAdj = PERSISTENT_SERVICE_ADJ;
                                        schedGroup = SCHED_GROUP_DEFAULT;
                                        procState = ActivityManager.PROCESS_STATE_PERSISTENT;
                                        cr.trackProcState(procState, mAdjSeq);
                                        trackedProcState = true;
                                    }
                                } else if (cr.hasFlag(Context.BIND_NOT_PERCEPTIBLE)
                                        && clientAdj <= PERCEPTIBLE_APP_ADJ
                                        && adj >= (lbAdj = PERCEPTIBLE_LOW_APP_ADJ)) {
                                    newAdj = PERCEPTIBLE_LOW_APP_ADJ;
                                } else if (cr.hasFlag(Context.BIND_ALMOST_PERCEPTIBLE)
                                        && cr.notHasFlag(Context.BIND_NOT_FOREGROUND)
                                        && clientAdj < PERCEPTIBLE_APP_ADJ
                                        && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) {
                                    // This is for user-initiated jobs.
                                    // We use APP_ADJ + 1 here, so we can tell them apart from FGS.
                                    newAdj = PERCEPTIBLE_APP_ADJ + 1;
                                } else if (cr.hasFlag(Context.BIND_ALMOST_PERCEPTIBLE)
                                        && cr.hasFlag(Context.BIND_NOT_FOREGROUND)
                                        && clientAdj < PERCEPTIBLE_APP_ADJ
                                        && adj >= (lbAdj = (PERCEPTIBLE_MEDIUM_APP_ADJ + 2))) {
                                    // This is for expedited jobs.
                                    // We use MEDIUM_APP_ADJ + 2 here, so we can tell apart
                                    // EJ and short-FGS.
                                    newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 2;
                                } else if (cr.hasFlag(Context.BIND_NOT_VISIBLE)
                                        && clientAdj < PERCEPTIBLE_APP_ADJ
                                        && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) {
                                    newAdj = PERCEPTIBLE_APP_ADJ;
                                } else if (clientAdj >= PERCEPTIBLE_APP_ADJ) {
                                    newAdj = clientAdj;
                                } else if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)
                                        && clientAdj <= VISIBLE_APP_ADJ
                                        && adj > VISIBLE_APP_ADJ) {
                                    newAdj = VISIBLE_APP_ADJ;
                                } else {
                                    if (adj > VISIBLE_APP_ADJ) {
                                        // TODO: Is this too limiting for apps bound from TOP?
                                        newAdj = Math.max(clientAdj, lbAdj);
                                    } else {
                                        newAdj = adj;
                                    }
                                }
                                if (!cstate.isCached()) {
                                    state.setCached(false);
                                }
                                if (adj >  newAdj) {
                                    adj = newAdj;
                                    state.setCurRawAdj(adj);
                                    adjType = "service";
                                }
                            }
                        }
                        if (cr.notHasFlag(Context.BIND_NOT_FOREGROUND
                                | Context.BIND_IMPORTANT_BACKGROUND)) {
                            // This will treat important bound services identically to
                            // the top app, which may behave differently than generic
                            // foreground work.
                            final int curSchedGroup = cstate.getCurrentSchedulingGroup();
                            if (curSchedGroup > schedGroup) {
                                if (cr.hasFlag(Context.BIND_IMPORTANT)) {
                                    schedGroup = curSchedGroup;
                                } else {
                                    schedGroup = SCHED_GROUP_DEFAULT;
                                }
                            }
                            if (clientProcState < PROCESS_STATE_TOP) {
                                // Special handling for above-top states (persistent
                                // processes).  These should not bring the current process
                                // into the top state, since they are not on top.  Instead
                                // give them the best bound state after that.
                                if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)) {
                                    clientProcState = PROCESS_STATE_FOREGROUND_SERVICE;
                                } else if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
                                    clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                } else if (mService.mWakefulness.get()
                                        == PowerManagerInternal.WAKEFULNESS_AWAKE
                                        && cr.hasFlag(Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE))
                                {
                                    clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                } else {
                                    clientProcState =
                                            PROCESS_STATE_IMPORTANT_FOREGROUND;
                                }
                            } else if (clientProcState == PROCESS_STATE_TOP) {
                                // Go at most to BOUND_TOP, unless requested to elevate
                                // to client's state.
                                clientProcState = PROCESS_STATE_BOUND_TOP;
                                final boolean enabled = cstate.getCachedCompatChange(
                                        CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY);
                                if (enabled) {
                                    if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
                                        // TOP process passes all capabilities to the service.
                                        capability |= cstate.getCurCapability();
                                    } else {
                                        // TOP process passes no capability to the service.
                                    }
                                } else {
                                    // TOP process passes all capabilities to the service.
                                    capability |= cstate.getCurCapability();
                                }
                            }
                        } else if (cr.notHasFlag(Context.BIND_IMPORTANT_BACKGROUND)) {
                            if (clientProcState <
                                    PROCESS_STATE_TRANSIENT_BACKGROUND) {
                                clientProcState =
                                        PROCESS_STATE_TRANSIENT_BACKGROUND;
                            }
                        } else {
                            if (clientProcState <
                                    PROCESS_STATE_IMPORTANT_BACKGROUND) {
                                clientProcState =
                                        PROCESS_STATE_IMPORTANT_BACKGROUND;
                            }
                        }

                        if (schedGroup < SCHED_GROUP_TOP_APP
                                && cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP)
                                && clientIsSystem) {
                            schedGroup = SCHED_GROUP_TOP_APP;
                            scheduleLikeTopApp = true;
                        }

                        if (!trackedProcState) {
                            cr.trackProcState(clientProcState, mAdjSeq);
                        }

                        if (procState > clientProcState) {
                            procState = clientProcState;
                            state.setCurRawProcState(procState);
                            if (adjType == null) {
                                adjType = "service";
                            }
                        }
                        if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND
                                && cr.hasFlag(Context.BIND_SHOWING_UI)) {
                            app.setPendingUiClean(true);
                        }
                        if (adjType != null) {
                            state.setAdjType(adjType);
                            state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                                    .REASON_SERVICE_IN_USE);
                            state.setAdjSource(client);
                            state.setAdjSourceProcState(clientProcState);
                            state.setAdjTarget(s.instanceName);
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                        + ": " + app + ", due to " + client
                                        + " adj=" + adj + " procState="
                                        + ProcessList.makeProcStateString(procState));
                            }
                        }
                    } else { // BIND_WAIVE_PRIORITY == true
                        // BIND_WAIVE_PRIORITY bindings are special when it comes to the
                        // freezer. Processes bound via WPRI are expected to be running,
                        // but they are not promoted in the LRU list to keep them out of
                        // cached. As a result, they can freeze based on oom_adj alone.
                        // Normally, bindToDeath would fire when a cached app would die
                        // in the background, but nothing will fire when a running process
                        // pings a frozen process. Accordingly, any cached app that is
                        // bound by an unfrozen app via a WPRI binding has to remain
                        // unfrozen.
                        if (clientAdj < CACHED_APP_MIN_ADJ) {
                            app.mOptRecord.setShouldNotFreeze(true);
                        }
                    }
                    if (cr.hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) {
                        psr.setTreatLikeActivity(true);
                    }
                    final ActivityServiceConnectionsHolder a = cr.activity;
                    if (cr.hasFlag(Context.BIND_ADJUST_WITH_ACTIVITY)) {
                        if (a != null && adj > FOREGROUND_APP_ADJ
                                && a.isActivityVisible()) {
                            adj = FOREGROUND_APP_ADJ;
                            state.setCurRawAdj(adj);
                            if (cr.notHasFlag(Context.BIND_NOT_FOREGROUND)) {
                                if (cr.hasFlag(Context.BIND_IMPORTANT)) {
                                    schedGroup = SCHED_GROUP_TOP_APP_BOUND;
                                } else {
                                    schedGroup = SCHED_GROUP_DEFAULT;
                                }
                            }
                            state.setCached(false);
                            state.setAdjType("service");
                            state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                                    .REASON_SERVICE_IN_USE);
                            state.setAdjSource(a);
                            state.setAdjSourceProcState(procState);
                            state.setAdjTarget(s.instanceName);
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                        "Raise to service w/activity: " + app);
                            }
                        }
                    }
                }
            }
        }

        final ProcessProviderRecord ppr = app.mProviders;
        for (int provi = ppr.numberOfProviders() - 1;
                provi >= 0 && (adj > FOREGROUND_APP_ADJ
                        || schedGroup == SCHED_GROUP_BACKGROUND
                        || procState > PROCESS_STATE_TOP);
                provi--) {
            ContentProviderRecord cpr = ppr.getProviderAt(provi);
            for (int i = cpr.connections.size() - 1;
                    i >= 0 && (adj > FOREGROUND_APP_ADJ
                            || schedGroup == SCHED_GROUP_BACKGROUND
                            || procState > PROCESS_STATE_TOP);
                    i--) {
                ContentProviderConnection conn = cpr.connections.get(i);
                ProcessRecord client = conn.client;
                final ProcessStateRecord cstate = client.mState;
                if (client == app) {
                    // Being our own client is not interesting.
                    continue;
                }
                if (computeClients) {
                    //contentprovider 会影响adj
                    computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true);
                } else {
                    cstate.setCurRawAdj(cstate.getCurAdj());
                    cstate.setCurRawProcState(cstate.getCurProcState());
                }

                if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                    continue;
                }

                int clientAdj = cstate.getCurRawAdj();
                int clientProcState = cstate.getCurRawProcState();

                // We always propagate PROCESS_CAPABILITY_BFSL to providers here,
                // but, right before actually setting it to the process,
                // we check the final procstate, and remove it if the procsate is below BFGS.
                capability |= getBfslCapabilityFromClient(client);

                if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                    // If the other app is cached for any reason, for purposes here
                    // we are going to consider it empty.
                    clientProcState = PROCESS_STATE_CACHED_EMPTY;
                }
                if (client.mOptRecord.shouldNotFreeze()) {
                    // Propagate the shouldNotFreeze flag down the bindings.
                    app.mOptRecord.setShouldNotFreeze(true);
                }

                boundByNonBgRestricted |= cstate.isCurBoundByNonBgRestrictedApp()
                        || clientProcState <= PROCESS_STATE_BOUND_TOP
                        || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE
                                && !cstate.isBackgroundRestricted());

                String adjType = null;
                if (adj > clientAdj) {
                    if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                            && clientAdj > PERCEPTIBLE_APP_ADJ) {
                        adjType = "cch-ui-provider";
                    } else {
                        adj = Math.max(clientAdj, FOREGROUND_APP_ADJ);
                        state.setCurRawAdj(adj);
                        adjType = "provider";
                    }
                    state.setCached(state.isCached() & cstate.isCached());
                }

                if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
                    if (adjType == null) {
                        adjType = "provider";
                    }
                    if (clientProcState == PROCESS_STATE_TOP) {
                        clientProcState = PROCESS_STATE_BOUND_TOP;
                    } else {
                        clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                    }
                }

                conn.trackProcState(clientProcState, mAdjSeq);
                if (procState > clientProcState) {
                    procState = clientProcState;
                    state.setCurRawProcState(procState);
                }
                if (cstate.getCurrentSchedulingGroup() > schedGroup) {
                    schedGroup = SCHED_GROUP_DEFAULT;
                }
                if (adjType != null) {
                    state.setAdjType(adjType);
                    state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                            .REASON_PROVIDER_IN_USE);
                    state.setAdjSource(client);
                    state.setAdjSourceProcState(clientProcState);
                    state.setAdjTarget(cpr.name);
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                + ": " + app + ", due to " + client
                                + " adj=" + adj + " procState="
                                + ProcessList.makeProcStateString(procState));
                    }
                }
            }
            // If the provider has external (non-framework) process
            // dependencies, ensure that its adjustment is at least
            // FOREGROUND_APP_ADJ.
            if (cpr.hasExternalProcessHandles()) {
                if (adj > FOREGROUND_APP_ADJ) {
                    adj = FOREGROUND_APP_ADJ;
                    state.setCurRawAdj(adj);
                    schedGroup = SCHED_GROUP_DEFAULT;
                    state.setCached(false);
                    state.setAdjType("ext-provider");
                    state.setAdjTarget(cpr.name);
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise adj to external provider: " + app);
                    }
                }
                if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) {
                    procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
                    state.setCurRawProcState(procState);
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise procstate to external provider: " + app);
                    }
                }
            }
        }

        if (ppr.getLastProviderTime() > 0
                && (ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
            if (adj > PREVIOUS_APP_ADJ) {
                adj = PREVIOUS_APP_ADJ;
                schedGroup = SCHED_GROUP_BACKGROUND;
                state.setCached(false);
                state.setAdjType("recent-provider");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                            "Raise adj to recent provider: " + app);
                }
            }
            if (procState > PROCESS_STATE_LAST_ACTIVITY) {
                procState = PROCESS_STATE_LAST_ACTIVITY;
                state.setAdjType("recent-provider");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                            "Raise procstate to recent provider: " + app);
                }
            }
        }

        if (procState >= PROCESS_STATE_CACHED_EMPTY) {
            if (psr.hasClientActivities()) {
                // This is a cached process, but with client activities.  Mark it so.
                procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
                state.setAdjType("cch-client-act");
            } else if (psr.isTreatedLikeActivity()) {
                // This is a cached process, but somebody wants us to treat it like it has
                // an activity, okay!
                procState = PROCESS_STATE_CACHED_ACTIVITY;
                state.setAdjType("cch-as-act");
            }
        }
        //adj 为 Service_adj 
        if (adj == SERVICE_ADJ) {
            if (doingAll && !cycleReEval) {
                state.setServiceB(mNewNumAServiceProcs > (mNumServiceProcs / 3));
                mNewNumServiceProcs++;
                if (!state.isServiceB()) {
                    // This service isn't far enough down on the LRU list to
                    // normally be a B service, but if we are low on RAM and it
                    // is large we want to force it down since we would prefer to
                    // keep launcher over it.
                    if (!mService.mAppProfiler.isLastMemoryLevelNormal()
                            && app.mProfile.getLastPss()
                            >= mProcessList.getCachedRestoreThresholdKb()) {
                        state.setServiceHighRam(true);
                        state.setServiceB(true);
                        //Slog.i(TAG, "ADJ " + app + " high ram!");
                    } else {
                        mNewNumAServiceProcs++;
                        //Slog.i(TAG, "ADJ " + app + " not high ram!");
                    }
                } else {
                    state.setServiceHighRam(false);
                }
            }
            if (state.isServiceB()) {
                adj = SERVICE_B_ADJ;
            }
        }

        state.setCurRawAdj(adj);
        adj = psr.modifyRawOomAdj(adj);
        if (adj > state.getMaxAdj()) {
            adj = state.getMaxAdj();
            if (adj <= PERCEPTIBLE_LOW_APP_ADJ) {
                schedGroup = SCHED_GROUP_DEFAULT;
            }
        }

        // Put bound foreground services in a special sched group for additional
        // restrictions on screen off
        if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                && mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
                && !scheduleLikeTopApp) {
            if (schedGroup > SCHED_GROUP_RESTRICTED) {
                schedGroup = SCHED_GROUP_RESTRICTED;
            }
        }

        // apply capability from FGS.
        if (psr.hasForegroundServices()) {
            capability |= capabilityFromFGS;
        }

        capability |= getDefaultCapability(app, procState);

        // Procstates below BFGS should never have this capability.
        if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
            capability &= ~PROCESS_CAPABILITY_BFSL;
        }

        // Do final modification to adj.  Everything we do between here and applying
        // the final setAdj must be done in this function, because we will also use
        // it when computing the final cached adj later.  Note that we don't need to
        // worry about this for max adj above, since max adj will always be used to
        // keep it out of the cached vaues.
        state.setCurAdj(adj);
        state.setCurCapability(capability);
        state.setCurrentSchedulingGroup(schedGroup);
        state.setCurProcState(procState);
        state.setCurRawProcState(procState);
        state.updateLastInvisibleTime(hasVisibleActivities);
        state.setHasForegroundActivities(foregroundActivities);
        state.setCompletedAdjSeq(mAdjSeq);
        state.setCurBoundByNonBgRestrictedApp(boundByNonBgRestricted);

        // if curAdj or curProcState improved, then this process was promoted
        return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
                || state.getCurCapability() != prevCapability;
    }

小结:

(1)判断adj 是否需要更新和一些基本参数的初始化。

     针对uidRec.isCurAllowListed()函数,其实是来自于updateTempWhitelistAppIdsLocke

    app.mOptRecord.setShouldNotFreeze(uidRec != null && uidRec.isCurAllowListed());

   对应的堆栈:

 [1] android/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java

@GuardedBy({"mService", "mProcLock"})

void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {

boolean changed = false;

for (int i = mActiveUids.size() - 1; i >= 0; i--) {

final UidRecord uidRec = mActiveUids.valueAt;

if (uidRec.getUid() == uid && uidRec.isCurAllowListed() != onAllowlist) { uidRec.setCurAllowListed(onAllowlist);

changed = true; } }

if (changed)

{ updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST); }
 

[2]android/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

 final void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
 mOomAdjuster.setAppIdTempAllowlistStateLSP(uid, onAllowlist);
 }

[3] frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

 @Override
 public void updateDeviceIdleTempAllowlist(int[] appids, int changingUid, boolean adding,
 long durationMs, @TempAllowListType int type, @ReasonCode int reasonCode,
 @Nullable String reason, int callingUid) {

setAppIdTempAllowlistStateLSP(changingUid, adding);

}

[4] frameworks/base/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java

 private void updateTempWhitelistAppIdsLocked(int uid, boolean adding, long durationMs,
 @TempAllowListType int type, @ReasonCode int reasonCode, @Nullable String reason,
 int callingUid) {

 mLocalActivityManager.updateDeviceIdleTempAllowlist(mTempWhitelistAppIdArray, uid,
 adding, durationMs, type, reasonCode, reason, callingUid);

(2)针对maxADJ小于FOREGROUND_APP_ADJ的逻辑处理.

(3)设置前台进程oom相关信息,根据状态匹配对应的adj类型

打印对应的adj和对应的type.

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

(4) 对adj 进行分类:

1)对adj初步分类: 

    [1] 若是app 是topApp 并且top 进程属于处于PROCESS_STATE_TOP状态,

    则:

      //进程状态(procState)属于PROCESS_STATE_TOP, adj FOREGROUND_APP_ADJ

      adj = FOREGROUND_APP_ADJ;

      foregroundActivities = true;
      hasVisibleActivities = true;

     //进程状态为PROCESS_STATE_TOP
      procState = PROCESS_STATE_TOP;

        若mService.mAtmInternal.useTopSchedGroupForTopProcess()(如果返回为true,则可能有比TOP应用程序更重要的UI/动画)

        则:

         

            schedGroup = SCHED_GROUP_TOP_APP;

            // adj type 为"top-activity"
            state.setAdjType("top-activity");

       否则:

            // important process which also uses top-app, such as if SystemUI is animating.
            schedGroup = SCHED_GROUP_DEFAULT;

            / /adj type 为"intermediate-top-activity"

             state.setAdjType("intermediate-top-activity");

     [2] 若正在播放RemoteAnimation,

            则:

            schedGroup = SCHED_GROUP_TOP_APP;

           adj = VISIBLE_APP_ADJ;

           //进程状态是PROCESS_STATE_CUR_TOP

           procState = PROCESS_STATE_CUR_TOP;

          // adj type 为"running-remote-anim"

          state.setAdjType("running-remote-anim");

     [3] 当前进程正在执行instrumentation时,

        则:

            adj = FOREGROUND_APP_ADJ;

            schedGroup = SCHED_GROUP_DEFAULT;

            //进程状态为前台服务

            procState = PROCESS_STATE_FOREGROUND_SERVICE.;

            //adj type 为"instrumentation"。

           state.setAdjType("instrumentation");

    [4] 当前有接受广播时,

       则:

           adj = ProcessList.FOREGROUND_APP_ADJ;

           procState = ActivityManager.PROCESS_STATE_RECEIVER; 

           //adj type 为 "broadcast"

            state.setAdjType("broadcast");

    [5] 当前有service 在执行时,    adj = ProcessList.FOREGROUND_APP_ADJ;

procState = PROCESS_STATE_SERVICE; adj type 为 "exec-service"

    [6]以上条件都不满足若是topapp 时,则 adj = cachedAdj;            procState = PROCESS_STATE_CACHED_EMPTY; 属于缓存并且是空进程。adj type 为"top-sleeping"

2) 若检查所有活动(topapp则不做检查),判断是否存在前台活动,是否存在可见的活动。从传递过来的信息,获取进程状态(procState),预计组(schedGroup)。

3)  若进程状态(procState)大于PROCESS_STATE_CACHED_RECENT (说明进程状态优先级很低,应该属于PROCESS_STATE_CACHED_EMPTY 状态) ,并且,存在activity与一个recent task 通信,

 进程状态(procState) 是 PROCESS_STATE_CACHED_RECENT;

设置adj type 为"cch-rec"。

4) 若adj 大于PERCEPTIBLE_APP_ADJ(也就说,adj的优先级小于PERCEPTIBLE_APP_ADJ),或者进程状态(procState)大于PROCESS_STATE_FOREGROUND_SERVICE,(也就说进程状态优先级小于拥有前台服务),则再判断.;

[1] 若有前台服务并且没有short前台进程(FGS 是在androidu上新加的),

则 

adj = ProcessList.PERCEPTIBLE_APP_ADJ(可感知进程);

进程状态(ProcState)是PROCESS_STATE_FOREGROUND_SERVICE

设置adj type为"fg-service",

 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;

设置为缓存(catched)。

[3] 若有FGS,则:

adjType = "fg-service-short";

Adj = PERCEPTIBLE_MEDIUM_APP_ADJ + 1;(表现是比托管进程低一点)

进程状态(ProcState) = PROCESS_STATE_FOREGROUND_SERVICE(前台进程)

[2]若显示non-activity的界面(譬如悬浮框)时,

则:

adj = ProcessList.PERCEPTIBLE_APP_ADJ(可感知,后台进程)

procState = PROCESS_STATE_IMPORTANT_FOREGROUND;

adjType="has-overlay-ui",

schedGroup = ProcessList.SCHED_GROUP_DEFAULT;(默认的group)

5)

只要满足条件1或者条件2,任意一条都可以。

条件1:

若有前台服务,并且adj 大于PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ(低于由top进程转移到前台进程)并且,最后一次是top的时间+最长的间隔(TOP_TO_FGS_GRACE_DURATION,默认为15秒)大于现在的时间,也就说从top 级别的时间变成前台进程的时间在15秒以内;

条件2:

进程状态ProcState小于等于PROCESS_STATE_TOP,意思是比top的优先级还高。

则:

[1] 若满足: 没有FGS

                 adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
                 state.setAdjType("fg-service-act");

[2] 其他条件:

                //优先级比PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ 低一点

                 adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 1;
                 state.setAdjType("fg-service-short-act");

6) 只要满足条件1或者条件2,任意一条都可以.

   条件1:

    拥有几乎可感知的顶级服务并且 adj 要比PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ 低于2格 并且最后一次是top的时间+最长的间隔(TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION ,默认为15秒)大于现在的时间.

  条件2:

    进程状态ProcState小于等于PROCESS_STATE_TOP,意思是比top的优先级还高。

  则:

     //对于EJ,我们将值加2,因此我们将能够在各种仪表板中检测到它。

     //优先级比PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ 低两点

     adj = PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2;

     //尽管使用了ALMOST_PERCEPTIBLE标志,但此后这应被称为“EJ”豁免。

     state.setAdjType("top-ej-act");

7) 只要满足条件1或者条件2,任意一条都可以.

   条件1:

若adj大于 PERCEPTIBLE_APP_ADJ(也就说,adj的优先级小于PERCEPTIBLE_APP_ADJ[可感知的进程])

  条件2: 

procState > PROCESS_STATE_TRANSIENT_BACKGROUND  也就是说进程状态(procState) 优先级小于PROCESS_STATE_TRANSIENT_BACKGROUND

则:

   若有调用           frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

::setProcessImportant函数,迫使进程变得重要的令牌。

   则:

                  //adj是PERCEPTIBLE_APP_ADJ

                  adj = PERCEPTIBLE_APP_ADJ;

                 //进程状态(procState)是PROCESS_STATE_TRANSIENT_BACKGROUND
                  procState = PROCESS_STATE_TRANSIENT_BACKGROUND;

                 //设置为非缓存
                  state.setCached(false);

                  //设置adj的type 为"force-imp"
                  state.setAdjType("force-imp");

                  //设置group 是SCHED_GROUP_DEFAULT
                  schedGroup = SCHED_GROUP_DEFAULT;

8) 是否存在重量级的进程,

    若存在:(注意下面流程是串行)

      [1] 若 adj > HEAVY_WEIGHT_APP_ADJ:

            则:

                  // We don't want to kill the current heavy-weight process.
                  adj = HEAVY_WEIGHT_APP_ADJ;
                  schedGroup = SCHED_GROUP_BACKGROUND;
                  //状态为非缓存   

                  state.setCached(false);

                  //设置adj的type 为"heavy"
                  state.setAdjType("heavy");

       [2] 若procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT

             则:

                   procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;

                   //设置adj的type 为"heavy"
                   state.setAdjType("heavy");

    9)若是home进程

     (home进程:This is the process holding what we currently consider to be the "home" activity.) ,

      则:

     [1] 若adj > HOME_APP_ADJ,

           则:

                  // This process is hosting what we currently consider to be the
                  // home app, so we don't want to let it go into the background.

                 //此进程正在托管我们当前认为是家庭应用程序的内容,因此我们不想让它进入后台
                  adj = HOME_APP_ADJ;
                  schedGroup = SCHED_GROUP_BACKGROUND;

                  //状态为非缓存   
                  state.setCached(false);

                   //设置adj的type 为"home"
                  state.setAdjType("home");

     [2]  procState > ActivityManager.PROCESS_STATE_HOME,

          则:

                   procState = ActivityManager.PROCESS_STATE_HOME;

                   //设置adj的type 为"home"
                    state.setAdjType("home");

10)若在缓存中存在上一个UI进程 并且 这个进程是活跃的

(这是向用户显示 UI 的上一个流程。 我们希望更积极地保留它,以便在两个应用程序之间切换时提供良好的体验。 但是,我们不想让进程无限期地保持这种特权状态。 最终,允许应用程序降级为缓存。)

        则:

         [1]若进程状态优先级小于PROCESS_STATE_LAST_ACTIVITY 并且 获取进程状态是PROCESS_STATE_LAST_ACTIVITY  和上次进程状态的记录时间已经超过MAX_PREVIOUS_TIME 时间:

                  则:

                     //表示优先级进行降级

                     //进场状态为PROCESS_STATE_LAST_ACTIVITY

                     procState = PROCESS_STATE_LAST_ACTIVITY;

                     //schedGroup 为SCHED_GROUP_BACKGROUND
                     schedGroup = SCHED_GROUP_BACKGROUND;

                     //设置adj type 是"previous-expired"
                     state.setAdjType("previous-expired");

                     //adj 由PREVIOUS_APP_ADJ降低到CACHED_APP_MIN_ADJ
                      adj = CACHED_APP_MIN_ADJ;

         [2] 否则:

                 1] 若 adj > PREVIOUS_APP_ADJ ,

                      则:

                      //提升adj 优先级

                      //设置adj 为PREVIOUS_APP_ADJ

                      adj = PREVIOUS_APP_ADJ;

                     //schedGroup 为SCHED_GROUP_BACKGROUND
                      schedGroup = SCHED_GROUP_BACKGROUND;

                      //设置缓存
                      state.setCached(false);

                      //设置adj type 是"previous"

                      state.setAdjType("previous");

                  2] 若 procState > PROCESS_STATE_LAST_ACTIVITY,

                       则:

                           //提升procState 优先级

                           procState = PROCESS_STATE_LAST_ACTIVITY;

                           //adj type 是"previous"
                            state.setAdjType("previous");

   

     11) 若存在备份记录(BackupRecord ) 并且 备份的应用是当前统计的进程,

( If possible we want to avoid killing apps while they're being backed up[如果可能的话,我们希望避免在备份时杀死应用程序])

            则:

           [1]若 adj > BACKUP_APP_ADJ ,

                则:

                  //adj 为BACKUP_APP_ADJ

                   adj = BACKUP_APP_ADJ;

                 //若进程优先级小于PROCESS_STATE_TRANSIENT_BACKGROUND,提高进程优先级为PROCESS_STATE_TRANSIENT_BACKGROUND

                 if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
                      procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
                  }

                  //adj为"backup"

                  state.setAdjType("backup");

                  //设置为非缓存
                  state.setCached(false);

           [2] 若进程优先级(procState) 小于 ActivityManager.PROCESS_STATE_BACKUP,

                 则:

                  //进程状态为PROCESS_STATE_BACKUP

                  procState = ActivityManager.PROCESS_STATE_BACKUP;

                  //adj type为"backup" 属于升级adj级别
                  state.setAdjType("backup");

 12)  遍历所有正在运行的服务:

         需要满足任意条件:

         [1] adj 优先级小于 FOREGROUND_APP_ADJ

         [2] schedGroup == SCHED_GROUP_BACKGROUND

         [3]  进程状态(procState) 小于 PROCESS_STATE_TOP

      1) 若Service 正在调用:

             [1] 进程优先级小于PROCESS_STATE_SERVICE

                  if (procState > PROCESS_STATE_SERVICE) {

                       //设置进程状态为PROCESS_STATE_SERVICE
                      procState = PROCESS_STATE_SERVICE;

                      //设置adj type 为"started-services"
                      state.setAdjType("started-services");
                  }

              [2]若 关键服务 并且 进程显示UI 并且 非home 缓存进程

If this process has shown some UI, let it immediately go to the LRU list because it may be pretty heavy with UI stuff.  We'll tag it with a label just to help debug and understand what is going on.

                   则:

                     //若adj 优先级小于SERVICE_ADJ

                      if (adj > SERVICE_ADJ) {

                          //显示adj type为"cch-started-ui-services"
                          state.setAdjType("cch-started-ui-services");
                      }

                  否则:

                     若有关键服务 或者 此服务启动后没有做任何事情并且运行时间不到MAX_SERVICE_INACTIVITY(30分钟):

                         则:

                           // This service has seen some activity within recent memory, so we will keep its process ahead

                         //adj 优先级小于SERVICE_ADJ

                          if (adj > SERVICE_ADJ) {

                             //adj 的值是SERVICE_ADJ
                              adj = SERVICE_ADJ;

                             //设置adj type 为"started-services"
                              state.setAdjType("started-services");

                              //设置缓存
                              state.setCached(false);
                          }
                      }

                      // If we have let the service slide into the background
                      // state, still have some text describing what it is doing
                      // even though the service no longer has an impact.

                      //adj的优先级低于SERVICE_ADJ,则修改adj type 为"cch-started-services"

                      if (adj > SERVICE_ADJ) {

                          //adj type 为"cch-started-services"
                          state.setAdjType("cch-started-services");
                      }

13)  关于provider:

        [1] 循环第一层关于provider 进程:

        若adj 优先级小于FOREGROUND_APP_ADJ,或者schedGroup == SCHED_GROUP_BACKGROUND 或者进程状态(procState) 优先级小于 PROCESS_STATE_TOP

        [2]循环第二层,provider 记录adj > FOREGROUND_APP_ADJ
                             或者 schedGroup == SCHED_GROUP_BACKGROUND
                              或者 procState > PROCESS_STATE_TOP

        [3]

                 //若adj 比clientAdj 优先级低

                  if (adj > clientAdj) {

                     //若状态有UI 并且 没有Home Process 并且 clientAdj 优先级小于 PERCEPTIBLE_APP_ADJ ,则讲adj type 修改为"cch-ui-provider"
                      if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                              && clientAdj > PERCEPTIBLE_APP_ADJ) {

                          //修改adj type 为"cch-ui-provider"
                          adjType = "cch-ui-provider";
                      } else {
                          adj = Math.max(clientAdj, FOREGROUND_APP_ADJ);

                          //选择FOREGROUND_APP_ADJ 和clientAdj 优先级最低
                          state.setCurRawAdj(adj);

                          //设置adj type 为"provider"
                          adjType = "provider";
                      }

                      //只有state 和 cstate 都是缓存状态,才将state的状态设置为缓存状态
                      state.setCached(state.isCached() & cstate.isCached());
                  }

      [4]

              // If the provider has external (non-framework) process
              // dependencies, ensure that its adjustment is at least
              // FOREGROUND_APP_ADJ.

             //若provider正在执行
              if (cpr.hasExternalProcessHandles()) {

                  //若adj 优先级小于 FOREGROUND_APP_ADJ
                  if (adj > FOREGROUND_APP_ADJ) {

                      //将adj 设置成FOREGROUND_APP_ADJ
                      adj = FOREGROUND_APP_ADJ;
                      state.setCurRawAdj(adj);
                      schedGroup = SCHED_GROUP_DEFAULT;
                      state.setCached(false);

                      //adj 设置成"ext-provider"
                      state.setAdjType("ext-provider");
                      state.setAdjTarget(cpr.name);
                  }

                 //若进程状态(procState)优先级小于PROCESS_STATE_IMPORTANT_FOREGROUND
                  if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) {

                      //则设置成PROCESS_STATE_IMPORTANT_FOREGROUND
                      procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
                      state.setCurRawProcState(procState);
                  }
              }
          }

   14)  若有provider 调用 并且 最后一次时间间隔不到DEFAULT_CONTENT_PROVIDER_RETAIN_TIME(默认是20s)

          则:

            [1] 若adj 级别小于PREVIOUS_APP_ADJ,

                 则:

                        //adj 设置为PREVIOUS_APP_ADJ

                        adj = PREVIOUS_APP_ADJ;
                        schedGroup = SCHED_GROUP_BACKGROUND;

                        //缓存
                        state.setCached(false);

                        // adj type 是"recent-provider"
                        state.setAdjType("recent-provider");

                 [2] 若进程状态(procState) 优先级小于PROCESS_STATE_LAST_ACTIVITY

                      则:

                         //进程状态(procState)设置为PROCESS_STATE_LAST_ACTIVITY

                         procState = PROCESS_STATE_LAST_ACTIVITY;

                        //设置adj type为"recent-provider"
                         state.setAdjType("recent-provider");

   15)  若进程状态(procState) 低于等于PROCESS_STATE_CACHED_EMPTY,

           则:

          [1] 若缓存进程,但具有客户端活动,

                则:

                 //进程状态为PROCESS_STATE_CACHED_ACTIVITY_CLIENT

                 procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;

                 //adj type 是"cch-client-act"

                 state.setAdjType("cch-client-act");

          [2]若进程含有BIND_TREAT_LIKE_ACTIVITY,

           (这是一个缓存的进程,但有人希望我们将其视为有活动)

           则:

                      //进程状态(procState) 为PROCESS_STATE_CACHED_ACTIVITY

                      procState = PROCESS_STATE_CACHED_ACTIVITY;

                     //adj type是"cch-as-act"
                     state.setAdjType("cch-as-act")

(5) 小结:

一个函数快 1000 行代码,确实分析起来非常累,里面有很多逻辑,大致逻辑如下:

[1] 通过 mAdjSeq 确认此次计算是否有必要,是否已经计算过;
[2] 判断是否为空进程;
[3] 当maxAdj<=FOREGROUND_APP_ADJ(都是重要的系统进程)根据是否显示系统UI、是否为TOPAPP等条件设置adj、procState等,然后return;
[4] 前台进程相关处理,根据不同场景(远程动画、接受广播、运行service等)设置前台进程adj、adjType、procState、schedGroup;
[5] 如果不是前台进程,但存有cache activities,通过 computeOomAdjFromActivitiesIfNecessary()确定进程cachedadj等;
[6] 分别根据adj是否大于PERCEPTIBLE_APP_ADJ、HEAVY_WEIGHT_APP_ADJ、HOME_APP_ADJ、PREVIOUS_APP_ADJ等判断大致adj值,在根据activity具体运行状态进一步确认adj等值;
[7] 确认是否为backup进程;
[8] 遍历在进程上运行所有services,根据service的运行状态修正当前进程adj等值。还可能遍历引用service的所有client,进一步计算这些client 的adj值;
[9] 同service,遍历进程上关联的providers,根据providers以及客户端进一步修正adj值;
收尾,进一步确认:
[10] 当一个进程20s前带有contentProvider,不会把他降到LRU list,避免provider进程陷入低内存状态;
[11] procState >= PROCESS_STATE_CACHED_EMPTY时进一步调整procState和adjType;
[12] 当adj==SERVICE_ADJ,确认是否在serviceb中,如果是adj改成SERVICE_B_ADJ;
[13] 其他的限制确认;
 

8.2  applyOomAdjLSP 函数:

    

  /** 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, @OomAdjReason int oomAdjReson) {
        boolean success = true;
        final ProcessStateRecord state = app.mState;
        final UidRecord uidRec = app.getUidRecord();
        //将最新的raw adj值赋值给当前raw adj值。
        if (state.getCurRawAdj() != state.getSetRawAdj()) {
            state.setSetRawAdj(state.getCurRawAdj());
        }

        int changes = 0;
        //若当前adj值赋和最后赋值的adj值不一样,则调整OOM
        if (state.getCurAdj() != state.getSetAdj()) {
            mCachedAppOptimizer.onOomAdjustChanged(state.getSetAdj(), state.getCurAdj(), app);
        }
        //若当前adj值和最新的获取的adj值不一样
        if (state.getCurAdj() != state.getSetAdj()) {
            //设置oomAdj 通知lmkd
            ProcessList.setOomAdj(app.getPid(), app.uid, state.getCurAdj());
           //更新Adj值
            state.setSetAdj(state.getCurAdj());
            if (uidRec != null) {
                uidRec.noteProcAdjChanged();
            }
            state.setVerifiedAdj(INVALID_ADJ);
        }

        final int curSchedGroup = state.getCurrentSchedulingGroup();
         //当前SchedGroup 和之前保存的chedGroup值不一样
        if (state.getSetSchedGroup() != curSchedGroup) {
            //
            int oldSchedGroup = state.getSetSchedGroup();
            //更新state的SchedGroup
            state.setSetSchedGroup(curSchedGroup);
            //若应用等待被杀并且没有接受Receiver并且该进程状态是否属于后台进程
            if (app.getWaitingToKill() != null && app.mReceivers.numberOfCurReceivers() == 0
                    && ActivityManager.isProcStateBackground(state.getSetProcState())) {

                //则此应用被杀掉。
                app.killLocked(app.getWaitingToKill(), ApplicationExitInfo.REASON_USER_REQUESTED,
                        ApplicationExitInfo.SUBREASON_REMOVE_TASK, true);
                success = false;

            } else {
                int processGroup;
                switch (curSchedGroup) {
                    case SCHED_GROUP_BACKGROUND:
                        processGroup = THREAD_GROUP_BACKGROUND;
                        break;
                    case SCHED_GROUP_TOP_APP:
                    case SCHED_GROUP_TOP_APP_BOUND:
                        processGroup = THREAD_GROUP_TOP_APP;
                        break;
                    case SCHED_GROUP_RESTRICTED:
                        processGroup = THREAD_GROUP_RESTRICTED;
                        break;
                    default:
                        processGroup = THREAD_GROUP_DEFAULT;
                        break;
                }
                mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage(
                        0 /* unused */, app.getPid(), processGroup, app.processName));
                try {
                    final int renderThreadTid = app.getRenderThreadTid();
                    if (curSchedGroup == SCHED_GROUP_TOP_APP) {
                        // do nothing if we already switched to RT
                        if (oldSchedGroup != SCHED_GROUP_TOP_APP) {
                            app.getWindowProcessController().onTopProcChanged();
                            if (mService.mUseFifoUiScheduling) {
                                // Switch UI pipeline for app to SCHED_FIFO
                                state.setSavedPriority(Process.getThreadPriority(app.getPid()));
                                mService.scheduleAsFifoPriority(app.getPid(), true);
                                if (renderThreadTid != 0) {
                                    mService.scheduleAsFifoPriority(renderThreadTid,
                                            /* suppressLogs */true);
                                    if (DEBUG_OOM_ADJ) {
                                        Slog.d("UI_FIFO", "Set RenderThread (TID " +
                                                renderThreadTid + ") to FIFO");
                                    }
                                } else {
                                    if (DEBUG_OOM_ADJ) {
                                        Slog.d("UI_FIFO", "Not setting RenderThread TID");
                                    }
                                }
                            } else {
                                // Boost priority for top app UI and render threads
                                setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
                                if (renderThreadTid != 0) {
                                    try {
                                        setThreadPriority(renderThreadTid,
                                                THREAD_PRIORITY_TOP_APP_BOOST);
                                    } catch (IllegalArgumentException e) {
                                        // thread died, ignore
                                    }
                                }
                            }
                        }
                    } else if (oldSchedGroup == SCHED_GROUP_TOP_APP
                            && curSchedGroup != SCHED_GROUP_TOP_APP) {
                        app.getWindowProcessController().onTopProcChanged();
                        if (mService.mUseFifoUiScheduling) {
                            try {
                                // Reset UI pipeline to SCHED_OTHER
                                setThreadScheduler(app.getPid(), SCHED_OTHER, 0);
                                setThreadPriority(app.getPid(), state.getSavedPriority());
                                if (renderThreadTid != 0) {
                                    setThreadScheduler(renderThreadTid,
                                            SCHED_OTHER, 0);
                                }
                            } catch (IllegalArgumentException e) {
                                Slog.w(TAG,
                                        "Failed to set scheduling policy, thread does not exist:\n"
                                                + e);
                            } catch (SecurityException e) {
                                Slog.w(TAG, "Failed to set scheduling policy, not allowed:\n" + e);
                            }
                        } else {
                            // Reset priority for top app UI and render threads
                            setThreadPriority(app.getPid(), 0);
                        }

                        if (renderThreadTid != 0) {
                            setThreadPriority(renderThreadTid, THREAD_PRIORITY_DISPLAY);
                        }
                    }
                } catch (Exception e) {
                    if (DEBUG_ALL) {
                        Slog.w(TAG, "Failed setting thread priority of " + app.getPid(), e);
                    }
                }
            }
        }
        //最后一次记录FGActivity 和 正在运行的FGActivity 不一致,则更新成正在运行的FGActivity
        if (state.hasRepForegroundActivities() != state.hasForegroundActivities()) {
            //更新最后一次记录FGActivity
            state.setRepForegroundActivities(state.hasForegroundActivities());
            changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES;
        }

        //更新app冻结状态
        updateAppFreezeStateLSP(app, oomAdjReson);
        //说明state的进程状态发生了变化,则更新当前的进程状态
        if (state.getReportedProcState() != state.getCurProcState()) {
            //更新进程状态
            state.setReportedProcState(state.getCurProcState());
            if (app.getThread() != null) {
                try {
                    if (false) {
                        //RuntimeException h = new RuntimeException("here");
                        Slog.i(TAG, "Sending new process state " + state.getReportedProcState()
                                + " to " + app /*, h*/);
                    }
                    app.getThread().setProcessState(state.getReportedProcState());
                } catch (RemoteException e) {
                }
            }
        }
        boolean forceUpdatePssTime = false;
        //执行pss统计操作,以及计算下一次pss的时间
        //若上次进程状态为不存在 或者 当前进程和最后一次统计进程状态不一致
        if (state.getSetProcState() == PROCESS_STATE_NONEXISTENT
                || ProcessList.procStatesDifferForMem(
                        state.getCurProcState(), state.getSetProcState())) {
            //更新调用时间
            state.setLastStateTime(now);
            forceUpdatePssTime = true;
            if (DEBUG_PSS) {
                Slog.d(TAG_PSS, "Process state change from "
                        + ProcessList.makeProcStateString(state.getSetProcState()) + " to "
                        + ProcessList.makeProcStateString(state.getCurProcState()) + " next pss in "
                        + (app.mProfile.getNextPssTime() - now) + ": " + app);
            }
        }
        synchronized (mService.mAppProfiler.mProfilerLock) {
                
            app.mProfile.updateProcState(app.mState);

            mService.mAppProfiler.updateNextPssTimeLPf(
                    state.getCurProcState(), app.mProfile, now, forceUpdatePssTime);
        }
        if (state.getSetProcState() != state.getCurProcState()) {
            if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) {
                String msg = "Proc state change of " + app.processName
                        + " to " + ProcessList.makeProcStateString(state.getCurProcState())
                        + " (" + state.getCurProcState() + ")" + ": " + state.getAdjType();
                reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
            }
            //若优先级高于PROCESS_STATE_SERVICE,则设置Important的状态
            boolean setImportant = state.getSetProcState() < PROCESS_STATE_SERVICE;
            boolean curImportant = state.getCurProcState() < PROCESS_STATE_SERVICE;
            
            //若上次设置为Important状态而当前不是Important 状态
            if (setImportant && !curImportant) {
                // This app is no longer something we consider important enough to allow to use
                // arbitrary amounts of battery power. Note its current CPU time to later know to
                // kill it if it is not behaving well.
                //将此状态标记为不重要状态.
                state.setWhenUnimportant(now);
                //清空最后一次CPU的记录时间
                app.mProfile.mLastCpuTime.set(0);
            }
            // Inform UsageStats of important process state change
            // Must be called before updating setProcState
            //若满足条件,则更新状态统计报告信息
            maybeUpdateUsageStatsLSP(app, nowElapsed);
            //若满足条件,则记录top时间
            maybeUpdateLastTopTime(state, now);
            //更新进程状态
            state.setSetProcState(state.getCurProcState());
            //若进程状态优先级低于PROCESS_STATE_HOME
            if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_HOME) {
                //由于进程优先级低,则设置为cache
                state.setNotCachedSinceIdle(false);
            }
            if (!doingAll) {
                synchronized (mService.mProcessStats.mLock) {
                    //记录进程Tracker状态
                    mService.setProcessTrackerStateLOSP(app,
                            mService.mProcessStats.getMemFactorLocked());
                }
            } else {
                //设置成进程状态有改变
                state.setProcStateChanged(true);
            }
        } else if (state.hasReportedInteraction()) {
            //有交互的报告
            //fgs交互是否有变化
            final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange(
                    CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME);
            //通过fgsInteractionChangeEnabled 来判断是用androids 之前还是之后的阈值
            //DEFAULT_SERVICE_USAGE_INTERACTION_TIME_POST_S 默认是60 * 1000;
            //DEFAULT_USAGE_STATS_INTERACTION_INTERVAL_PRE_S  默认是 2 * 60 * 60 * 1000;
            final long interactionThreshold = fgsInteractionChangeEnabled
                    ? mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S
                    : mConstants.USAGE_STATS_INTERACTION_INTERVAL_PRE_S;
            // For apps that sit around for a long time in the interactive state, we need
            // to report this at least once a day so they don't go idle.
            if ((nowElapsed - state.getInteractionEventTime()) > interactionThreshold) {
                //定期更新
                maybeUpdateUsageStatsLSP(app, nowElapsed);
            }
        } else {

            final boolean fgsInteractionChangeEnabled = state.getCachedCompatChange(
                    CACHED_COMPAT_CHANGE_USE_SHORT_FGS_USAGE_INTERACTION_TIME);

            final long interactionThreshold = fgsInteractionChangeEnabled
                    ? mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S
                    : mConstants.SERVICE_USAGE_INTERACTION_TIME_PRE_S;

            // For foreground services that sit around for a long time but are not interacted with.
            if ((nowElapsed - state.getFgInteractionTime()) > interactionThreshold) {
                //定期更新UsageStats
                maybeUpdateUsageStatsLSP(app, nowElapsed);
            }
        }

        if (state.getCurCapability() != state.getSetCapability()) {
            state.setSetCapability(state.getCurCapability());
        }

        final boolean curBoundByNonBgRestrictedApp = state.isCurBoundByNonBgRestrictedApp();
        //NonBgRestricted 发生了变化
        if (curBoundByNonBgRestrictedApp != state.isSetBoundByNonBgRestrictedApp()) {
            state.setSetBoundByNonBgRestrictedApp(curBoundByNonBgRestrictedApp);
            //是bound后台限制进程 并且 是后台限制状态
            if (!curBoundByNonBgRestrictedApp && state.isBackgroundRestricted()) {
                //则停止一切前台服务
                mService.mHandler.post(() -> {
                    synchronized (mService) {
                        mService.mServices.stopAllForegroundServicesLocked(
                                app.uid, app.info.packageName);
                    }
                });
            }
        }
        //若有变化
        if (changes != 0) {
            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
                    "Changes in " + app + ": " + changes);
            //则更细ProcessChangeItem 信息
            ActivityManagerService.ProcessChangeItem item =
                    mProcessList.enqueueProcessChangeItemLocked(app.getPid(), app.info.uid);

            item.changes |= changes;

            item.foregroundActivities = state.hasRepForegroundActivities();
            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
                    "Item " + Integer.toHexString(System.identityHashCode(item))
                            + " " + app.toShortString() + ": changes=" + item.changes
                            + " foreground=" + item.foregroundActivities
                            + " type=" + state.getAdjType() + " source=" + state.getAdjSource()
                            + " target=" + state.getAdjTarget());
        }

        //若此状态有缓存 并且 此shouldNotKillOnBgRestrictedAndIdle 状态false
        if (state.isCached() && !state.shouldNotKillOnBgRestrictedAndIdle()) {

            // It's eligible to get killed when in UID idle and bg restricted mode,
            // check if these states are just flipped.
            if (!state.isSetCached() || state.isSetNoKillOnBgRestrictedAndIdle()) {
                // Take the timestamp, we'd hold the killing for the background settle time
                // (for states debouncing to avoid from thrashing).
                //更新被杀的时间戳
                state.setLastCanKillOnBgRestrictedAndIdleTime(nowElapsed);
                // Kick off the delayed checkup message if needed.
                 //若UID是空闲 或者 mService.mHandler 是空闲
                if (mService.mDeterministicUidIdle
                        || !mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
                    //将不活动的进程,若超过阈值设置为空闲进程
                    mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
                            mConstants.mKillBgRestrictedAndCachedIdleSettleTimeMs);
                }
            }
        }
        state.setSetCached(state.isCached());
//更新最新的值
state.setSetNoKillOnBgRestrictedAndIdle(state.shouldNotKillOnBgRestrictedAndIdle());

        return success;
    }
8.3 updateOomAdjLocked 函数:
    /**
     * Update OomAdj for all processes in LRU list
     */
    @GuardedBy("mService")
    void updateOomAdjLocked(@OomAdjReason int oomAdjReason) {
        synchronized (mProcLock) {
            updateOomAdjLSP(oomAdjReason);
        }
    }
    private void updateOomAdjLSP(@OomAdjReason int oomAdjReason) {
        if (checkAndEnqueueOomAdjTargetLocked(null)) {
            // Simply return as there is an oomAdjUpdate ongoing
            return;
        }
        try {
            mOomAdjUpdateOngoing = true;
            performUpdateOomAdjLSP(oomAdjReason);
        } finally {
            // Kick off the handling of any pending targets enqueued during the above update
            mOomAdjUpdateOngoing = false;
            updateOomAdjPendingTargetsLocked(oomAdjReason);
        }
    }
    private void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason) {
        final ProcessRecord topApp = mService.getTopApp();
        // Clear any pending ones because we are doing a full update now.
        mPendingProcessSet.clear();
        mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false;
        updateOomAdjInnerLSP(oomAdjReason, topApp , null, null, true, true);
    }

   主要调用函数是updateOomAdjInnerLSP,所以分析updateOomAdjInnerLSP函数.

  更新给定列表中所有进程的 OomAdj(可以是部分),或者如果给定列表为 null,则更新整个 LRU 列表; 当它是部分更新时,每个进程的客户端进程不会在这里递归评估。

    /**
     * Update OomAdj for all processes within the given list (could be partial), or the whole LRU
     * list if the given list is null; when it's partial update, each process's client proc won't
     * get evaluated recursively here.
     */
    @GuardedBy({"mService", "mProcLock"})
    private void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
            ArrayList processes, ActiveUids uids, boolean potentialCycles,
            boolean startProfiling) {
        //若需要开始分析
        if (startProfiling) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
            //设置mOomAdjStarted为true,则表示可以记录打印dump信息
            mService.mOomAdjProfiler.oomAdjStarted();
        }

        final long now = SystemClock.uptimeMillis();
        final long nowElapsed = SystemClock.elapsedRealtime();
        //记录老的时间,往前推mMaxEmptyTimeMillis(默认值为:1000L * 60L * 60L * 1000L)
        final long oldTime = now - mConstants.mMaxEmptyTimeMillis;
        //若进程进程是null,则全部更新
        final boolean fullUpdate = processes == null;
        ActiveUids activeUids = uids;
        //若全部更新则获取全部进程,则不为空,则更新传值过来的进程
        ArrayList activeProcesses = fullUpdate ? mProcessList.getLruProcessesLOSP()
                : processes;
      
        final int numProc = activeProcesses.size();
        //若activity uid为null,则使用临时UID
        if (activeUids == null) {
            final int numUids = mActiveUids.size();
            activeUids = mTmpUidRecords;
            activeUids.clear();
            for (int i = 0; i < numUids; i++) {
                UidRecord uidRec = mActiveUids.valueAt(i);
                activeUids.put(uidRec.getUid(), uidRec);
            }
        }

        // Reset state in all uid records.
        // 重置所有的activity uid数值
        for (int  i = activeUids.size() - 1; i >= 0; i--) {
            final UidRecord uidRec = activeUids.valueAt(i);
            if (DEBUG_UID_OBSERVERS) {
                Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
            }
            uidRec.reset();
        }

        mAdjSeq++;
        //若是全部更新,则重置mNewNumServiceProcs 和 mNewNumAServiceProcs
        if (fullUpdate) {
            mNewNumServiceProcs = 0;
            mNewNumAServiceProcs = 0;
        }

        boolean retryCycles = false;
        //计算Clients
        boolean computeClients = fullUpdate || potentialCycles;

        // need to reset cycle state before calling computeOomAdjLSP because of service conns
        //
        for (int i = numProc - 1; i >= 0; i--) {
            ProcessRecord app = activeProcesses.get(i);
            final ProcessStateRecord state = app.mState;
            state.setReachable(false);
            // No need to compute again it has been evaluated in previous iteration
            // 若获取的AdjSeq 和当前的mAdjSeq 不一样,则需要重置。若一样,则不用再评估。
            if (state.getAdjSeq() != mAdjSeq) {
                //重置信息
                state.setContainsCycle(false);
                state.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
                state.setCurRawAdj(UNKNOWN_ADJ);
                state.setSetCapability(PROCESS_CAPABILITY_NONE);
                state.resetCachedInfo();
                state.setCurBoundByNonBgRestrictedApp(false);
            }
        }
        mProcessesInCycle.clear();
        //
        for (int i = numProc - 1; i >= 0; i--) {

            ProcessRecord app = activeProcesses.get(i);
            final ProcessStateRecord state = app.mState;
            //若app被am没有杀 并且 app 不存在线程
            if (!app.isKilledByAm() && app.getThread() != null) {
                //则: 默认为进程状态没有发生变化
                state.setProcStateChanged(false);
                //更新最后一次adj changed的原因
                app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason);
                //计算adj
                computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, fullUpdate, now, false,
                        computeClients); 
                // It won't enter cycle if not computing clients.
                // if any app encountered a cycle, we need to perform an additional loop later
                retryCycles |= state.containsCycle();
                // Keep the completedAdjSeq to up to date.
                state.setCompletedAdjSeq(mAdjSeq);
            }
        }
        //判断是否重新对oom排序
        if (mCacheOomRanker.useOomReranking()) {
           //进行oom排序 mCacheOomRanker.reRankLruCachedAppsLSP(mProcessList.getLruProcessesLSP(),
                    mProcessList.getLruProcessServiceStartLOSP());
        }

        if (computeClients) { // There won't be cycles if we didn't compute clients above.
            // Cycle strategy:
            // - Retry computing any process that has encountered a cycle.
            // - Continue retrying until no process was promoted.
            // - Iterate from least important to most important.
            int cycleCount = 0;
            while (retryCycles && cycleCount < 10) {
                cycleCount++;
                retryCycles = false;

                for (int i = 0; i < numProc; i++) {
                    ProcessRecord app = activeProcesses.get(i);
                    final ProcessStateRecord state = app.mState;
                    if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
                        state.decAdjSeq();
                        state.decCompletedAdjSeq();
                    }
                }

                for (int i = 0; i < numProc; i++) {
                    ProcessRecord app = activeProcesses.get(i);
                    final ProcessStateRecord state = app.mState;
                    if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
                        if (computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, true, now,
                                true, true)) {
                            retryCycles = true;
                        }
                    }
                }
            }
        }
        mProcessesInCycle.clear();
        //调整adj值
        assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());

        mNumNonCachedProcs = 0;
        mNumCachedHiddenProcs = 0;

        boolean allChanged = updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids,
                oomAdjReason);
        mNumServiceProcs = mNewNumServiceProcs;

        if (mService.mAlwaysFinishActivities) {
            // Need to do this on its own message because the stack may not
            // be in a consistent state at this point.
            mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
        }

        if (allChanged) {
            //统计pss数据
            mService.mAppProfiler.requestPssAllProcsLPr(now, false,
                    mService.mProcessStats.isMemFactorLowered());
        }
        //更新uid的状态
        updateUidsLSP(activeUids, nowElapsed);

        synchronized (mService.mProcessStats.mLock) {
            final long nowUptime = SystemClock.uptimeMillis();
            //距上次写文件若时间差大于30分钟
            if (mService.mProcessStats.shouldWriteNowLocked(nowUptime)) {
                //则:重新写入数据
                mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
                        mService.mProcessStats));
            }

            // Run this after making sure all procstates are updated.
            mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, nowUptime);
        }

        if (DEBUG_OOM_ADJ) {
            final long duration = SystemClock.uptimeMillis() - now;
            if (false) {
                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
                        new RuntimeException("here").fillInStackTrace());
            } else {
                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
            }
        }
        if (startProfiling) {
            mService.mOomAdjProfiler.oomAdjEnded();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }
8.4 updateAndTrimProcessLSP 函数

    @GuardedBy({"mService", "mProcLock"})
    private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed,
            final long oldTime, final ActiveUids activeUids, @OomAdjReason int oomAdjReason) {
        //返回对LRU列表的引用,调用该函数进行读/写访问
        //正在运行的应用程序列表,按最近使用情况排序。
        //列表中的第一个条目是最近最少使用的。
        ArrayList lruList = mProcessList.getLruProcessesLOSP();

        final int numLru = lruList.size();

        //判断被杀时间间隔是否超过时间10分内(默认时间)
        final boolean doKillExcessiveProcesses = shouldKillExcessiveProcesses(now);
         //若没有超过,则调节被杀的时间间隔
        if (!doKillExcessiveProcesses) {
            //
            if (mNextNoKillDebugMessageTime < now) {
                Slog.d(TAG, "Not killing cached processes"); // STOPSHIP Remove it b/222365734
               //调节时间
                mNextNoKillDebugMessageTime = now + 5000; // Every 5 seconds
            }
        }
        //空进程的数量限制
        final int emptyProcessLimit = doKillExcessiveProcesses
                ? mConstants.CUR_MAX_EMPTY_PROCESSES : Integer.MAX_VALUE;
        //缓存进程数量限制
        final int cachedProcessLimit = doKillExcessiveProcesses
                ? (mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit) : Integer.MAX_VALUE;

        int lastCachedGroup = 0;
        int lastCachedGroupUid = 0;
        int numCached = 0;
        int numCachedExtraGroup = 0;
        int numEmpty = 0;
        int numTrimming = 0;

        boolean proactiveKillsEnabled = mConstants.PROACTIVE_KILLS_ENABLED;
        double lowSwapThresholdPercent = mConstants.LOW_SWAP_THRESHOLD_PERCENT;
        double freeSwapPercent =  proactiveKillsEnabled ? getFreeSwapPercent() : 1.00;
        ProcessRecord lruCachedApp = null;

        for (int i = numLru - 1; i >= 0; i--) {

            ProcessRecord app = lruList.get(i);
            final ProcessStateRecord state = app.mState;
            //app 不是被am杀掉 并且 app 正在启动或者是persistent 并且 不是在等待Attach
            if (!app.isKilledByAm() && app.getThread() != null && !app.isPendingFinishAttach()) {

                // We don't need to apply the update for the process which didn't get computed
                //我们不需要对未计算的流程应用更新
                if (state.getCompletedAdjSeq() == mAdjSeq) {
                    applyOomAdjLSP(app, true, now, nowElapsed, oomAdjReason);
                }

                final ProcessServiceRecord psr = app.mServices;
                // Count the number of process types.
                switch (state.getCurProcState()) {
                    case PROCESS_STATE_CACHED_ACTIVITY:
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        mNumCachedHiddenProcs++;
                        numCached++;
                        final int connectionGroup = psr.getConnectionGroup();
                        if (connectionGroup != 0) {
                            if (lastCachedGroupUid == app.info.uid
                                    && lastCachedGroup == connectionGroup) {
                                // If this process is the next in the same group, we don't
                                // want it to count against our limit of the number of cached
                                // processes, so bump up the group count to account for it.
                                numCachedExtraGroup++;
                            } else {
                                lastCachedGroupUid = app.info.uid;
                                lastCachedGroup = connectionGroup;
                            }
                        } else {
                            lastCachedGroupUid = lastCachedGroup = 0;
                        }
                        //
                        if ((numCached - numCachedExtraGroup) > cachedProcessLimit) {
                            //杀掉此缓存进程
                            app.killLocked("cached #" + numCached,
                                    "too many cached",
                                    ApplicationExitInfo.REASON_OTHER,
                                    ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
                                    true);
                        } else if (proactiveKillsEnabled) {
                            lruCachedApp = app;
                        }
                        break;
                    case PROCESS_STATE_CACHED_EMPTY:
                        //针对空进程
                        //空进程数量大于CUR_TRIM_EMPTY_PROCESSES(默认为16)并且 oldtime要超过最后一次的记录时间
                        if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
                                && app.getLastActivityTime() < oldTime) {
                            //杀掉此空进程
                            app.killLocked("empty for " + ((now
                                    - app.getLastActivityTime()) / 1000) + "s",
                                    "empty for too long",
                                    ApplicationExitInfo.REASON_OTHER,
                                    ApplicationExitInfo.SUBREASON_TRIM_EMPTY,
                                    true);
                        } else {
                            numEmpty++;
                            //若统计空进程数量超过空进程的限制
                            if (numEmpty > emptyProcessLimit) {
                                //则杀掉该空进程
                                app.killLocked("empty #" + numEmpty,
                                        "too many empty",
                                        ApplicationExitInfo.REASON_OTHER,
                                        ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
                                        true);
                            } else if (proactiveKillsEnabled) {
                                //proactiveKillsEnabled 默认值是false
                                lruCachedApp = app;
                            }
                        }
                        break;
                    default:
                        mNumNonCachedProcs++;
                        break;
                }
                //进程是独立 并且 运行service的数量为0 并且 不是特殊的独立进程
                if (app.isolated && psr.numberOfRunningServices() <= 0
                        && app.getIsolatedEntryPoint() == null) {
                    // If this is an isolated process, there are no services
                    // running in it, and it's not a special process with a
                    // custom entry point, then the process is no longer
                    // needed.  We agressively kill these because we can by
                    // definition not re-use the same process again, and it is
                    // good to avoid having whatever code was running in them
                    // left sitting around after no longer needed.
                    //则杀死此进程
                    app.killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER,
                            ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
                } else if (app.isSdkSandbox && psr.numberOfRunningServices() <= 0
                        && app.getActiveInstrumentation() == null) {
                    // If this is an SDK sandbox process and there are no services running it, we
                    // aggressively kill the sandbox as we usually don't want to re-use the same
                    // sandbox again.
                    //沙箱进程没有运行,则杀掉。
                    app.killLocked("sandbox not needed", ApplicationExitInfo.REASON_OTHER,
                            ApplicationExitInfo.SUBREASON_SDK_SANDBOX_NOT_NEEDED, true);
                } else {
                    // Keeping this process, update its uid.
                    //其他条件都不满足的话,则更新UID
                    updateAppUidRecLSP(app);
                }

                if (state.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
                        && !app.isKilledByAm()) {
                    numTrimming++;
                }
            }
        }

        //若proactiveKillsEnabled为true 并且 距上次杀进程超过了阈值 并且 Swap 低于阈值
        //并且 没有缓存进程
        if (proactiveKillsEnabled                               // Proactive kills enabled?
                && doKillExcessiveProcesses                     // Should kill excessive processes?
                && freeSwapPercent < lowSwapThresholdPercent    // Swap below threshold?
                && lruCachedApp != null                         // If no cached app, let LMKD decide
                // If swap is non-decreasing, give reclaim a chance to catch up
                && freeSwapPercent < mLastFreeSwapPercent) {
            //则杀死该缓存进程
            lruCachedApp.killLocked("swap low and too many cached",
                    ApplicationExitInfo.REASON_OTHER,
                    ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
                    true);
        }

        mLastFreeSwapPercent = freeSwapPercent;
        //更新低内存的状态
        return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming, now);
    }

9.小知识:

[1] 判断应用是否有前台服务,可以执行adb shell dumpsys > dump.txt ,使用关键字"fgServices" 查看,

譬如: uid 是10179

    UID u0a179: UidRecord{df6a906 u0a179 FGS  fgServices change:procadj procs:0 seq(42947,31617)}
      curProcState=4 curCapability=---N
      proc=ProcessRecord{b997c1e 6682:com.google.android.setupwizard/u0a179}

你可能感兴趣的:(性能问题,android)