Android adj调整 --- computeOomAdjLSP流程详解

Android adj调整 --- computeOomAdjLSP流程详解

Android adj调整 — computeOomAdjLSP流程详解

这次就先讲OomAdjuster.java中adj调整最为关键的函数computeOomAdjLSP,这个函数几乎占了adj调整代码1/3的代码量,非常重要,建议阅读之前先看一下之前的:Android S进程的adj值Android adj调整时的各类进程状态。至于OomAdjuster.java里面的其它逻辑,下次有时间再来写吧。希望对大家有帮助

下面是各个关系对应的表格(以adj为例)
在这里插入图片描述

1. computeOomAdjLSP的参数

注意此处上了2把锁mService(ActivityManagerService), ActivityManagerService的mProcLock

    @GuardedBy({"mService", "mProcLock"})
    private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
            ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
            boolean computeClients) {

//调整adj的函数(查看这个函数之前先看一下adj各个值的意思和procState各个值的含义,具体可以参考之前的文章)
//1. app是需要调整adj的进程
//2. cachedAdj是adj调整的时候的默认值(除了一些正在使用的app都是这个默认值),默认只有一般是oldAdj或则UNKNOWN_ADJ
//3. topApp(当前最顶端activity)是从AMS的getTopApp(这个函数有点性能问题)里面拿到的(这里又是从ActivityTaskManagerService获得)
//updateTopResumedActivityIfNeeded/mRootWindowContainer.getTopDisplayFocusedRootTask/topRootTask.getResumedActivity(ActivityTaskSupervisor)
//-> updateTopApp(ActivityTaskManagerService),大概是意思是:top的task(writeWmTaskMoved/writeWmTaskToFront),而且是isTopActivityFocusable和可见shouldBeVisible
//注意顶端activity和顶端Window不是一个概念,如在桌面的时候下拉状态栏,此时顶端activity(topApp)是桌面,而focus Window是systemui
//4. doingAll在这里主要是用于调整A、B service,在updateOomAdjInnerLSP时fullUpdate或者computeClients为true时才有可能设置为true
//而A、B service调整除了doingAll这个参数,还跟cycleReEval有关系,也就是说实际有用到的地方只有fullUpdate为true是才会调整A、B services
//5. now是此次调整adj的当前时间
//6. cycleReEval只有在设置了setContainsCycle true(如正在计算computeOomAdjLSP的时候还没计算完又跑进来,
//如上面的mAdjSeq == state.getAdjSeq()或者(服务/provider的客户端有这种情况的时候)),
//在updateOomAdjInnerLSP会让cycleReEval=true(具体可以看上面的updateOomAdjInnerLSP,大概意思是循环计算依赖)
//7. computeClients是否需要计算当前进程的时候计算服务、provider提供者对端的adj
//8. 它的返回值state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
// || state.getCurCapability() != prevCapability
//当满足当前调整的mSetAdj(函数结束的时候)比prevAppAdj(刚进入这里mSetAdj)小的时候,或者mCurProcState有变小;这些都代表优先级提升
//或者mCurCapability能力不一样才返回true,其它都是false.
//这个返回值目前只在updateOomAdjInnerLSP中的循环计算adj中使用,用于判断是否需要中断循环调整adj,其它场景都未使用
//只有true才代表循环调整成功,单个进程false代表忽略,只有全部循环调整的进程都是fasle才会跳过循环调整的重试逻辑

2. 是否存在循环计算

设置该进程是循环计算setContainsCycle(true)、将循环计算的进程进程放入mProcessesInCycle

        final ProcessStateRecord state = app.mState;
        //mAdjSeq在updateOomAdjInnerLSP/performUpdateOomAdjLSP有mAdjSeq++,代表是当前oom_adj调整的序列号
        //如果mAdjSeq == getAdjSeq(取得的是正在处理的mAdjSeq值),代表这个进程已经参与过本次调整
        if (mAdjSeq == state.getAdjSeq()) {
            //getCompletedAdjSeq是已经完成的adj值
            if (state.getAdjSeq() == state.getCompletedAdjSeq()) {
                // This adjustment has already been computed successfully.
                // 如果该进程调整过了,而且已经完成,则直接返回,同时由于是没有调整,则返回值是false
                // 只有true才代表循环调整成功,单个进程false代表忽略,
                // 只有全部循环调整的进程都是fasle才会跳过循环调整的重试逻辑
                // 返回值只有在重复调整的时候使用,具体请查看updateOomAdjInnerLSP的使用
                return false;
            } else {
                // The process is being computed, so there is a cycle. We cannot
                // rely on this process's state.
                //由于该进程之前已经计算过,而且adj还在计算值没有计算完,则设置需要adj循环调整的标记位mContainsCycle为true
                state.setContainsCycle(true);
                //同时将该进程放入循环计算的list里面mProcessesInCycle,后面如果需要重新计算该进程adj的时候会从此处取回
                mProcessesInCycle.add(app);

                // 返回值只有在重复调整的时候使用,具体请查看updateOomAdjInnerLSP的使用
                return false;
            }
        }

3. 没有ApplicationThread的时候的调整

进程app没有ApplicationThread(应用线程)的时候会进入

        //如果app没有ApplicationThread(应用线程),那么进入这里
        if (app.getThread() == null) {
            //设置当前进程的adj任务的序列号为mAdjSeq,代表正在调整该进程
            state.setAdjSeq(mAdjSeq);
            //设置默认cgroup为backgroud
            //backgroud分组原生配置了 "HighEnergySaving"(cpuctl或者schedtune), 
            //"ProcessCapacityLow"(cpuset), "LowIoPriority"(blkio), "TimerSlackHigh"(timerslack_ns)
            state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND);
            //设置当前进程状态为PROCESS_STATE_CACHED_EMPTY
            state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
            //设置mCurAdj为999,这是oom调整的值;
            //而mSetAdj是上一次oom设置过的值(一般用的mSetAdj做为oomadj的判断, setSetAdj设置)
            //applyOomAdjLSP中会调用state.setSetAdj(state.getCurAdj());
            //将正在调整的mCurAdj更新到mSetAdj,同时修改ProcessList.setOomAdj(更新lmkd中的状态值)
            state.setCurAdj(ProcessList.CACHED_APP_MAX_ADJ);
/*
//AndroidS\frameworks\base\services\core\java\com\android\server\am\ProcessServiceRecord.java
    int modifyRawOomAdj(int adj) {
        if (mHasAboveClient) {
            // If this process has bound to any services with BIND_ABOVE_CLIENT,
            // then we need to drop its adjustment to be lower than the service's
            // in order to honor the request.  We want to drop it by one adjustment
            // level...  but there is special meaning applied to various levels so
            // we will skip some of them.
            if (adj < ProcessList.FOREGROUND_APP_ADJ) {
                // System process will not get dropped, ever
            } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
                adj = ProcessList.VISIBLE_APP_ADJ;
            } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
            } else if (adj < ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                adj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
            } else if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
                adj = ProcessList.CACHED_APP_MIN_ADJ;
            } else if (adj < ProcessList.CACHED_APP_MAX_ADJ) {
                adj++;
            }
        }
        return adj;
    }
    state.setCurRawAdj(curEmptyAdj);//mCurRawAdj是直接设置的
    state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj));//类似这里就是约束过的adj在复制给mCurAdj,而且一般都是adj调整完成后设置
*/
            //mCurRawAdj是未被约束过的adj,mCurAdj可能由于依赖关系被调整过
            //mCurAdj当前调整的adj值,进过约束的(如mHasAboveClient进行约束,client app进程优先级会相应降低)
            //mCurRawAdj当前调整的adj值,但是未经过约束
            //mSetRawAdj上一次applyOomAdjLSP后设置的mCurRawAdj值
            //mSetAdj上一次applyOomAdjLSP后设置的mCurAdj值
            state.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ);
            //设置已经完成了mCompletedAdjSeq为mAdjSeq(代表这个adj调整任务已经完成)
            state.setCompletedAdjSeq(state.getAdjSeq());

/*
    public static final int PROCESS_CAPABILITY_NONE = 0;

    //进程在前台的时候可以访问location 
    public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 0;

    //进程在前台的时候可以调用camera 
    public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 1;

    //进程在前台的时候可以调用电话 
    public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;

    //即使是功耗优化的限制,这个进程也可以访问网络
    //AndroidS\frameworks\base\core\java\android\net\NetworkPolicyManager.java的
    //isProcStateAllowedWhileIdleOrPowerSaveMode有下面逻辑
    //procState <= FOREGROUND_THRESHOLD_STATE || (capability & ActivityManager.PROCESS_CAPABILITY_NETWORK) != 0
    public static final int PROCESS_CAPABILITY_NETWORK = 1 << 3;
*/
            //由于这个进程连应用线程都没有,设置该进程没有任何能力
            state.setCurCapability(PROCESS_CAPABILITY_NONE);
            //同时返回false,这种场景不需要考虑重复计算adj的逻辑
            return false;
        }

4. 对ProcessStateRecord进程状态记录的一些初始化

/*
        public static final int REASON_UNKNOWN = 0;

        //这个是在provider依赖关系的时候才调用,代表进程状态改变是由于provider正在使用中导致
        public static final int REASON_PROVIDER_IN_USE = 1;

        //这个是在service依赖关系的时候才调用,代表进程状态改变是由于service正在使用中导致
        public static final int REASON_SERVICE_IN_USE = 2;

*/
        //设置adj调整的大概原因,如由于service或者provider的依赖,初始化为未知
        state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN);
        //设置adj调整时由于客户端clinet或者force-imp时由于什么对象导致进程状态调整
        state.setAdjSource(null);
        //设置adj调整的对象名字,如由于service或者provider的依赖关系,那么对端的service/provider的名字会被记录在这里
        state.setAdjTarget(null);
        //目前只有cch-empty && PROCESS_STATE_CACHED_EMPTY才会设置setEmptyd的mEmpty为true,代表空进程
        state.setEmpty(false);
        //这里设置mCached初始化值为false,用isCached取得mCached来判断是否缓存进程
        state.setCached(false);

        //设置mAllowStartFgsState(getAllowStartFgsState)为PROCESS_STATE_NONEXISTENT进程不存在
        //这个目前只有在"top-activity"、常驻进程、"fg-service"、客户端是常驻进程而且设置了BIND_FOREGROUND_SERVICE、客户端是top才会设置
        state.resetAllowStartFgsState();

5. 设置默认是否允许冻结

//cycleReEval只有在设置了setContainsCycle true(如正在计算computeOomAdjLSP的时候还没计算完又跑进来,
//如上面的mAdjSeq == state.getAdjSeq()或者(服务/provider的客户端有这种情况的时候)),
//在updateOomAdjInnerLSP会让cycleReEval=true(具体可以看上面的updateOomAdjInnerLSP,大概意思是循环计算依赖)

        if (!cycleReEval) {
            //如果是非循环遍历计算,则设置ProcessCachedOptimizerRecord的mShouldNotFreeze,这个用于冻结cached进程,
            //在applyOomAdjLSP的updateAppFreezeStateLSP会进行进程冻结,主要有2个操作freezeBinder/setProcessFrozen
            // Don't reset this flag when doing cycles re-evaluation.
            app.mOptRecord.setShouldNotFreeze(false);
        }

6. 获取调整之前的一些状态

        //取得app的uid
        final int appUid = app.info.uid;
        //这个主要是存在OomAdjObserver的时候,发送消息reportOomAdjMessageLocked/onOomAdjMessage,
        //如我们需要监控某个应用的adj调整情况,可以使用ActivityManagerShellCommand.java,只是调试功能而已
        //adb shell cat /data/system/packages.list可以查看每个进程的uid
        //使用方法:adb shell am watch-uids --oom +上面找出的应用的uid
        //会输出adj调整日志Slog.d和在终端pw打印相关信息
        final int logUid = mService.mCurOomAdjUid;

        //获取调整adj前的mCurAdj(当前调整的adj,进过约束的),保存成prevAppAdj之前的adj状态
        int prevAppAdj = state.getCurAdj();
        //将之前的进程状态mCurProcState保存成prevProcState
        int prevProcState = state.getCurProcState();
        //将之前的能力mCurCapability保存成prevCapability
        int prevCapability = state.getCurCapability();
        //获取ProcessServiceRecord,这个在ActiveServices的realStartServiceLocked会调用ProcessServiceRecord的startService,
        //将ServiceRecord加入ProcessServiceRecord的mServices中去,主要保存的是进程服务相关信息
        final ProcessServiceRecord psr = app.mServices;

7. system_server或者常驻进程的调整

//getMaxAdj拿到的是mMaxAdj,一般只有系统system_server、常驻进程PERSISTENT或者isolated的app才会设置该值
//而小于等于前台的adj,那么就只有系统system_server、常驻进程PERSISTENT、常驻服务PERSISTENT_SERVICE才会进来
//目前除了测试用例,系统默认的setMaxAdj都是会进来这里的

        if (state.getMaxAdj() <= ProcessList.FOREGROUND_APP_ADJ) {
            // The max adjustment doesn't allow this app to be anything
            // below foreground, so it is not worth doing work for it.
            // 可以看到oom的日志一般需要打开DEBUG_OOM_ADJ_REASON或者跟上面调试的logUid一致才会输出
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app);
            }
            //设置adj类型为fixed,类似dumpsys activity p中输出的,下面括号部分打印的就是adj类型
            //PERS #46: sys    F/ /PER  LCMN  t: 0 1239:system/1000 (fixed)
            state.setAdjType("fixed");
            //在app中设置当前调整的adj系列为setAdjSeq
            state.setAdjSeq(mAdjSeq);
            //设置指定的mCurRawAdj(未被约束过的adj)为当前最大的adj
            state.setCurRawAdj(state.getMaxAdj());
            //暂时初始化,先标定没有前台activity
            state.setHasForegroundActivities(false);
            //设置当前的cgroup调度分组为SCHED_GROUP_DEFAULT默认,
            //对应cgroup分组的SCHED_SP_DEFAULT(task_profiles.json), android默认只在这个分组设置了TimerSlackNormal
            //TimerSlackNormal会将/proc/(pid)/timerslack_ns设置成50000ns(0.05ms,内核中断定时器最大的超时时间,
            //定时器会在定时时间到超时直接范围内执行,主要为了避免频繁中断引起的性能损耗,类似于对齐);
            //于之对应的设置是TimerSlackHigh,这个android默认设置的是40000000ns=40ms,
            //这个时间就很大(对于实际执行的内容会可能wait等待时间较长,导致性能问题);
            //至于其它cgroup分组节点就是默认上一次行为,本次不移动节点(只操作了timerslack_ns)
            //cgroup对性能也很重要,但是不是本次重点,先带过
            state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
            //设置该进程拥有所有能力(只有系统system_server、常驻进程PERSISTENT才会进来,所以相对安全)
            state.setCurCapability(PROCESS_CAPABILITY_ALL);
            //设置当前进程的状态为PROCESS_STATE_PERSISTENT,字符串转换是"PER "
            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.
            //初始化设定当前系统进程没有ui界面
            state.setSystemNoUi(true);
            //如果调整的是当前应用是最顶端的activity
            if (app == topApp) {
                //设置这类应用是带有界面的
                state.setSystemNoUi(false);
                //cgroup分组标记成top app(用户后面分组切换到类似*** cgroup的分组,cpuset的分组如:/dev/cpuset/top-app)
                state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
                //adj类型标记成pers-top-activity
                state.setAdjType("pers-top-activity");
            //是否有top ui,目前只有systemui才会设置setHasTopUi(通过AMS设置),如下拉状态栏、灭屏幕时
            } else if (state.hasTopUi()) {
                // sched group/proc state adjustment is below
                //设置这类应用是带有界面的
                state.setSystemNoUi(false);
                //设置这类应用的类型是"pers-top-ui"
                state.setAdjType("pers-top-ui");
            //如果是有可见的activity的话
            } else if (state.getCachedHasVisibleActivities()) {
                //设置这类应用是带有界面的
                state.setSystemNoUi(false);
            }
            //只有带有界面的常驻进程才会进入这里面(如systemui会灭屏幕进入;phone进程灭屏由于isSystemNoUi是true所以不进入)
            if (!state.isSystemNoUi()) {
                //mWakefulness获取的是当前是否唤醒状态,如亮屏是唤醒状态则是PowerManagerInternal.WAKEFULNESS_AWAKE
                //isRunningRemoteAnimation代表是否播放远端动画,如锁屏动画这个也是true
                //(如在WAKEFULNESS_DOZING的状态的时候,systemui的isRunningRemoteAnimation也可能是true)
                if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE
                        || state.isRunningRemoteAnimation()) {
                    // screen on or animating, promote UI
                    //进程状态还是设置成PROCESS_STATE_PERSISTENT_UI ("PERU")
                    state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
                    //cgroup分组标记成top app
                    state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
                } else {
                    // screen off, restrict UI scheduling
                    //灭屏没有播放动画才进入这里,如systemui进程状态会从"PERU"切换到"BFGS"
                    state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
                    //cgroup分组标记成限制的分组,systemui也会进入这里
                    state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED);
                }
            }
            //设置mCurRawProcState为当前计算的mCurProcState的值,这个值一般都是用于计算client的mCurRawProcState状态
            //相当于依赖调整后的状态
            state.setCurRawProcState(state.getCurProcState());
            //这种进程(系统system_server、常驻进程PERSISTENT)不需要调整adj,直接设置的是传入的max adj
            state.setCurAdj(state.getMaxAdj());
            //设置当前进程完成调整的adj为mAdjSeq,代表本次adj调整完成
            state.setCompletedAdjSeq(state.getAdjSeq());
            //更新mAllowStartFgsState,代表是否允许启动前台服务,进程状态需要不比PROCESS_STATE_BOUND_FOREGROUND_SERVICE优先级低
            state.bumpAllowStartFgsState(state.getCurProcState());
            // if curAdj is less than prevAppAdj, then this process was promoted
            //如果当前的adj比上一次调整的adj小、或者当前的进程状态比上一次的优先,则返回true(有效调整),其它则返回false
            return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
        }

8. 调整之前的一些变量的定义

        //其它的进程先预设拥有界面,初始值
        state.setSystemNoUi(false);

        //如果当前唤醒状态的话,getTopProcessState返回的是PROCESS_STATE_TOP,否者是PROCESS_STATE_TOP_SLEEPING
        //PROCESS_STATE_CUR_TOP定义成final,代表初始化之后就不能改了,仅当次调整有效
        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.
        //adj是准备进行调整计算进程优先级的临时变量
        int adj;
        //schedGroup是准备进行调整计算进程cgrup的临时变量
        int schedGroup;
        //procState是准备进行调整计算进程状态的临时变量
        int procState;
        //cachedAdjSeq是准备进行调整计算cached adj的临时变量(旧的代码,这个在这里完全没有用到,是个bug,可以提交给google)
        int cachedAdjSeq;
        //capability是准备进行调整计算进程能力的临时变量
        int capability = 0;

        //foregroundActivities(是否有前台的activity)默认设定为false
        boolean foregroundActivities = false;
        //hasVisibleActivities(是否有可见的activity)默认设定为false
        boolean hasVisibleActivities = false;

9. top顶端app的调整

//如果当前是唤醒状态(如亮屏),而且本次调整的进程是topApp(顶端的activity)

        //当前是唤醒状态(如亮屏),PROCESS_STATE_CUR_TOP才会是PROCESS_STATE_TOP
        if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
            // The last app on the list is the foreground app.
            //设置adj是0(FOREGROUND_APP_ADJ),一般代表正在运行
            adj = ProcessList.FOREGROUND_APP_ADJ;
            //进程分组是top app
            schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
            //进程状态是"top-activity"
            state.setAdjType("top-activity");
            //拥有前台活动对象
            foregroundActivities = true;
            //拥有可见的activity
            hasVisibleActivities = true;
            //当前进程状态是PROCESS_STATE_TOP
            procState = PROCESS_STATE_CUR_TOP;
            //将是否允许启动forground service的状态设置成PROCESS_STATE_TOP
            //进程状态不低于PROCESS_STATE_BOUND_FOREGROUND_SERVICE即可启动前台服务
            state.bumpAllowStartFgsState(PROCESS_STATE_TOP);
            //打印日志或者在终端中监控某个app的时候会进去
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
            }

10. 正在播放远端动画的调整

        //如果正在播放远端动画
        } else if (state.isRunningRemoteAnimation()) {
            //设置adj为100(VISIBLE_APP_ADJ)
            adj = ProcessList.VISIBLE_APP_ADJ;
            //进程分组是top app
            schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
            //进程状态是"running-remote-anim"
            state.setAdjType("running-remote-anim");
            //当前进程状态是PROCESS_STATE_TOP(设备唤醒时)/PROCESS_STATE_TOP_SLEEPING(休眠时)
            procState = PROCESS_STATE_CUR_TOP;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app);
            }

11. instrumentation的调整

        //如果拥有活跃的instrumentation的时候(如自动化测试,或者qq downloader也会使用类似形式活跃在后台)
        } else if (app.getActiveInstrumentation() != null) {
            // Don't want to kill running instrumentation.
            //设置adj是0(FOREGROUND_APP_ADJ),这种类型也认为是当前运行的进程
            adj = ProcessList.FOREGROUND_APP_ADJ;
            //进程分组是default默认
            schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            //adj类型是"instrumentation");
            state.setAdjType("instrumentation");
            //进程状态是forground service
            procState = PROCESS_STATE_FOREGROUND_SERVICE;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
            }

12. 正在接受广播进程的调整

//如果正在接受广播(getCurReceiverAt)或者广播挂起(mPendingBroadcast)马上会接收时
//可以看到广播adj设置优先于服务adj设置

        } else if (state.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
            // An app that is currently receiving a broadcast also
            // counts as being in the foreground for OOM killer purposes.
            // It's placed in a sched group based on the nature of the
            // broadcast as reflected by which queue it's active in.
            // adj = 0,代表正在前台运行中的进程
            adj = ProcessList.FOREGROUND_APP_ADJ;
            //如果接收的是前台广播队列mFgBroadcastQueue,则分组设置成SCHED_GROUP_DEFAULT,
            //否者cgroup分组设置成后台SCHED_GROUP_BACKGROUND
            schedGroup = (mTmpBroadcastQueue.contains(mService.mFgBroadcastQueue))
                    ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
            //设置adj类型为广播"broadcast"
            state.setAdjType("broadcast");
            //设置当前进程状态是PROCESS_STATE_RECEIVER
            procState = ActivityManager.PROCESS_STATE_RECEIVER;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
            }

13. 正在运行服务进程的调整

//如果正在运行服务bumpServiceExecutingLocked(startExecutingService加入运行服务,stopExecutingService移除)

        } else if (psr.numberOfExecutingServices() > 0) {
            // An app that is currently executing a service callback also
            // counts as being in the foreground.
            // adj = 0,代表正在前台运行中的进程
            adj = ProcessList.FOREGROUND_APP_ADJ;
            //如果运行的是前台服务,则分组设置成SCHED_GROUP_DEFAULT,
            //否者cgroup分组设置成后台SCHED_GROUP_BACKGROUND
            schedGroup = psr.shouldExecServicesFg()
                    ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
            //设置adj类型为正在运行的服务"exec-service"
            state.setAdjType("exec-service");
            //设置当前进程状态是PROCESS_STATE_SERVICE
            procState = PROCESS_STATE_SERVICE;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
            }

14. 系统在休眠时topApp的调整

//如果调整的是topApp,但是在休眠的时候

        } else if (app == topApp) {
            //adj也是调整成0
            adj = ProcessList.FOREGROUND_APP_ADJ;
            //只是cgroup分组设置成后台SCHED_GROUP_BACKGROUND
            schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
            //设置adj类型为顶端,而且休眠状态"top-sleeping"
            state.setAdjType("top-sleeping");
            //拥有前台活动对象foregroundActivities设置成yrue, 注意此时拥有可见的activity(hasVisibleActivities)并未设置成ture
            foregroundActivities = true;
            //进程状态设置成PROCESS_STATE_TOP_SLEEPING
            procState = PROCESS_STATE_CUR_TOP;
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app);
            }

15. 其它app的默认状态初始化

        } else {
            // As far as we know the process is empty.  We may change our mind later.
            //cgroup分组设置成后台SCHED_GROUP_BACKGROUND
            schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
            // At this point we don't actually know the adjustment.  Use the cached adj
            // value that the caller wants us to.
            // 其它情况,先设置成cachedAdj(oldAdj或则UNKNOWN_ADJ),
            // 初始化为是空进程adj或者上一次调整的adj值,一会在进行adj调整
            adj = cachedAdj;
            //进程状态设置成空的缓存进程PROCESS_STATE_CACHED_EMPTY
            procState = PROCESS_STATE_CACHED_EMPTY;
            //如果不是循环计算,才进入里面
            if (!state.containsCycle()) {
                //设置成cached缓存进程
                state.setCached(true);
                //设置成empty空进程
                state.setEmpty(true);
                //adj类型是空的缓存进程"cch-empty"
                state.setAdjType("cch-empty");
            }
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app);
            }
        }

16. 更新foregroundActivities和mHasVisibleActivities

        // Examine all activities if not already foreground.
        //foregroundActivities目前只有top app才是true,除了了top它的值都是false
        //只要进程有activity(getCachedHasActivities其实是hasActivities),则getCachedHasActivities返回true
        //如realStartActivityLocked(ActivityTaskSupervisor)通过setProcess(ActivityRecord)/addActivityIfNeeded(WindowProcessController)
        //将ActivityRecord add进入mActivities,而移除也就是从mActivities移除, 
        //其中的一种移除情况如:ActivityRecord在destroyImmediately(events出现wm_destroy_activity的时候)
        if (!foregroundActivities && state.getCachedHasActivities()) {
            //通过activity不同的状态计算其adj,
            //PROCESS_STATE_CUR_TOP的值是PROCESS_STATE_TOP(设备唤醒时)/PROCESS_STATE_TOP_SLEEPING(休眠时)
            //一般情况procState进程状态越小越优先,adj越小越优先,cgroup分组schedGroup一般越大越优先
            //1.如visable可见的activity则会通过onVisibleActivity设置adj最低是VISIBLE_APP_ADJ(其adj通过minLayer/mLayerRank会约束到100-199)
            //foregroundActivities和mHasVisibleActivities都是true,procState进程状态设置成小于等于PROCESS_STATE_CUR_TOP
            //cgroup分组schedGroup设置成大于等于SCHED_GROUP_DEFAULT()
            //2.pausing正在暂停的activity则会通过onPausedActivity设置adj最低是PERCEPTIBLE_APP_ADJ
            //foregroundActivities = true和mHasVisibleActivities是false,procState进程状态设置成小于等于PROCESS_STATE_CUR_TOP
            //cgroup分组schedGroup设置成大于等于SCHED_GROUP_DEFAULT
            //3.stopping正在停止的activity则会通过onStoppingActivity设置adj最低是PERCEPTIBLE_APP_ADJ
            //foregroundActivities = true和mHasVisibleActivities是false,
            //如果所有activity正在STOPPING都是finishing状态(如wm_finish_activity/wm_destroy_activity),
            //procState进程状态设置成小于等于PROCESS_STATE_LAST_ACTIVITY,schedGroup不变更
            //4.其它状态的activity则会通过onOtherActivity,adj不更改
            //foregroundActivities不变(默认foregroundActivities是false才会进来)和mHasVisibleActivities是false
            //procState进程状态设置成小于等于PROCESS_STATE_CACHED_ACTIVITY,代表缓存的activity
            state.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
                    adj, foregroundActivities, hasVisibleActivities, procState, schedGroup,
                    appUid, logUid, PROCESS_STATE_CUR_TOP);

            //将上面获取的mCachedAdj设置成当前adj
            adj = state.getCachedAdj();
            //将上面改变ProcessStateRecord的foregroundActivities复制给当前的foregroundActivities变量
            foregroundActivities = state.getCachedForegroundActivities();
            //将上面改变ProcessStateRecord的mHasVisibleActivities复制给当前的hasVisibleActivities变量
            hasVisibleActivities = state.getCachedHasVisibleActivities();
            //将上面的procState进程状态保存在当前的procState变量
            procState = state.getCachedProcState();
            //将上面的cgroup分组schedGroup状态保存在当前的schedGroup变量
            schedGroup = state.getCachedSchedGroup();
        }

17. 更新最近使用的activity的状态

        //有activity在最近任务mRecentTasks,代表最近启动的activity,进程状态设置成小于等于PROCESS_STATE_CACHED_RECENT
        if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) {
            //进程状态最大就是PROCESS_STATE_CACHED_RECENT
            procState = PROCESS_STATE_CACHED_RECENT;
            //adj类型是cch-rec,缓存的最近任务
            state.setAdjType("cch-rec");
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app);
            }
        }

18. 调整前台服务或者hasOverlayUi的进程

//如果当前adj大于200(PERCEPTIBLE_APP_ADJ用户可感知的进程)
//或者当前进程状态大于PROCESS_STATE_FOREGROUND_SERVICE(前台运行的服务)

        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > PROCESS_STATE_FOREGROUND_SERVICE) {
            //如果其拥有前台服务(通过AMS的updateProcessForegroundLocked设置,
            //目前只有updateServiceForegroundLocked(ActiveServices)才可能设置true)
            // 一般前台服务带有通知
            if (psr.hasForegroundServices()) {
                // 将设置成200(PERCEPTIBLE_APP_ADJ)用户可感知的级别
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                // 将进程状态设置成前台服务
                procState = PROCESS_STATE_FOREGROUND_SERVICE;
                // 设置是否允许启动前台服务,这里是允许的(只要小于等于PROCESS_STATE_BOUND_FOREGROUND_SERVICE都是允许)
                state.bumpAllowStartFgsState(PROCESS_STATE_FOREGROUND_SERVICE);
                // adj类型是"fg-service"前台服务
                state.setAdjType("fg-service");
                // 设置成非cached的进程
                state.setCached(false);
                //此时设置cgroup的分组为默认
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + state.getAdjType() + ": "
                            + app + " ");
                }
            // hasOverlayUi是true的时候(需要设置TYPE_APPLICATION_OVERLAY,有覆盖之上的界面,类似悬浮窗)
            } else if (state.hasOverlayUi()) {
                // adj设置成用户可感知的优先级200
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                // 将进程状态设置成重要的前台进程
                procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
                // 设置成非cached的进程
                state.setCached(false);
                // adj类型是"has-overlay-ui"拥有覆盖界面的进程
                state.setAdjType("has-overlay-ui");
                //此时设置cgroup的分组为默认
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to overlay ui: " + app);
                }
            }
        }

19. 调整最近活跃的前台服务进程

        // 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.
        //如果有前台服务,而且adj比50(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ最近使用的前台进程)大;
        //而且是最近15s内在top级别(最前台),或者当前进程状态起码是top
        if (psr.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
                && (state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION > now
                || state.getSetProcState() <= PROCESS_STATE_TOP)) {
            //将adj设定成50(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ),
            //代表最近使用过的前台应用(hasForegroundServices最低是200,最近使用过的前台服务最低是50)
            adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
            //设置adj类型为前台服务最近活跃
            state.setAdjType("fg-service-act");
            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
            }
        }

20. 调整强制提升到用户可感知的进程

调整通过setProcessImportant来提升优先级的应用

        // adj大于200(PERCEPTIBLE_APP_ADJ用户可感知的进程),或者进程状态大于8(PROCESS_STATE_TRANSIENT_BACKGROUND后台临时状态)
        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
            //如果设置了getForcingToImportant不为null(调用AMS的setProcessImportant设置),
            //而且adj是用户可感知的PERCEPTIBLE_APP_ADJ,例如toasts是这种情况(NotificationManagerService中调用setProcessImportant)
            //如果不想要通知又想提升优先级,setProcessImportant是个不错的选择
            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设置成200
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                // 进程状态设置成后台临时状态(PROCESS_STATE_TRANSIENT_BACKGROUND)
                procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
                // 设置成非cached的进程
                state.setCached(false);
                // adj类型是"force-imp"强制设置的重要应用
                state.setAdjType("force-imp");
                // adj改变的原因是ImportanceToken(pid, token, reason)对象,包括提升优先级进程的pid、传递的IBinder对象token,还有原因reason
                state.setAdjSource(state.getForcingToImportant());
                //此时设置cgroup的分组为默认
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app);
                }
            }
        }

21. 调整heavy的进程

        //当app无法保存状态,如AndroidManifest.xml设置了"android:cantSaveState="true"",
        //同时系统配置了<feature name="android.software.cant_save_state" />这个feature
        //由于其无法保存状态,故尽量不要杀死, 一般只有一个,adj类型是"heavy"
        if (state.getCachedIsHeavyWeight()) {
            //如果adj大于400(HEAVY_WEIGHT_APP_ADJ重要app的优先级)
            if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
                // We don't want to kill the current heavy-weight process.
                //将adj设置成400
                adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
                //不过将cgroup分组设置成后台的
                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                // 设置成非cached的进程
                state.setCached(false);
                // adj类型是"heavy"(由于adj改变设置)
                state.setAdjType("heavy");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app);
                }
            }
            //如果进程状态大于PROCESS_STATE_HEAVY_WEIGHT(重要应用)
            if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
                //将进程状态设置成PROCESS_STATE_HEAVY_WEIGHT(起码是这个进程状态级别,mHeavyWeightProcess的级别不会比这个低)
                procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
                // adj类型是"heavy"(由于进程状态改变设置)
                state.setAdjType("heavy");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app);
                }
            }
        }

21. 调整桌面应用

        //如果是桌面应用mHomeProcess
        //在ActivityRecord的completeResumeLocked中会将ACTIVITY_TYPE_HOME类型的应用设置成mHomeProcess桌面应用
        //(具体ACTIVITY_TYPE_HOME的设置在ActivityRecord的setActivityType)
        if (state.getCachedIsHomeProcess()) {
            //桌面应用的adj不能小于600(HOME_APP_ADJ)
            if (adj > ProcessList.HOME_APP_ADJ) {
                // This process is hosting what we currently consider to be the
                // home app, so we don't want to let it go into the background.
                //adj设置成600,桌面应用有点特殊,经常会返回使用,放在A、B service中间,比上一个应用稍微优先一点
                adj = ProcessList.HOME_APP_ADJ;
                //将cgroup分组设置成后台的
                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                // 设置成非cached的进程
                state.setCached(false);
                // adj类型是"home"
                state.setAdjType("home");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app);
                }
            }
            //桌面应用的进程状态不能低于PROCESS_STATE_HOME(14)
            if (procState > ActivityManager.PROCESS_STATE_HOME) {
                //桌面应用的进程状态设置成PROCESS_STATE_HOME(14)
                procState = ActivityManager.PROCESS_STATE_HOME;
                // adj类型是"home"
                state.setAdjType("home");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app);
                }
            }
        }

22. 调整previous上一个使用的应用

        //1. getCachedIsPreviousProcess: 在上一个前台进程activity stop的时候,则会将进程ActivityRecord的app(WindowProcessController)加入到mPreviousProcess,做为上一个进程
        //2. getCachedHasActivities:在realStartActivityLocked()的时候将activity add进来,在detachFromProcess或者destroyImmediately()的时候移除activity,
        //也就是说是否有启动过但是未destory的activity
        if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
            //如果是上一个应用,而且activity没有销毁,那么adj最少设置成700(PREVIOUS_APP_ADJ)
            if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                // This was the previous process that showed UI to the user.
                // We want to try to keep it around more aggressively, to give
                // a good experience around switching between two apps.
                // adj设置成700
                adj = ProcessList.PREVIOUS_APP_ADJ;
                //设置cgroup的分组为默认
                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                // 设置成非cached的进程
                state.setCached(false);
                // 设置adj类型为"previous"上一个应用
                state.setAdjType("previous");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
                }
            }
            //进程状态最少设置成PROCESS_STATE_LAST_ACTIVITY(15)
            if (procState > PROCESS_STATE_LAST_ACTIVITY) {
                //进程状态设置成PROCESS_STATE_LAST_ACTIVITY(15)
                procState = PROCESS_STATE_LAST_ACTIVITY;
                // 设置adj类型为"previous"上一个应用
                state.setAdjType("previous");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
                }
            }
        }

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

23. 循环计算时更新procState、adj、schedGroup

循环计算时更新进程状态procState、进程优先级adj、进程分组cgroup信息schedGroup

        // 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.
        //cycleReEval只有在设置了setContainsCycle true(如正在计算computeOomAdjLSP的时候还没计算完又跑进来,
        //如上面的mAdjSeq == state.getAdjSeq()或者(服务/provider的客户端有这种情况的时候)),
        //在updateOomAdjInnerLSP会让cycleReEval=true(具体可以看上面的updateOomAdjInnerLSP,大概意思是循环计算依赖)
        //如果是循环计算的话
        if (cycleReEval) {
            //取之前的进程状态getCurRawProcState和上面计算出来的进程状态procState的最小值,也就是去优先级大的
            procState = Math.min(procState, state.getCurRawProcState());
            //取之前的进程adj(getCurRawAdj)和上面计算出来的adj的最小值,也就是去优先级大的
            adj = Math.min(adj, state.getCurRawAdj());
            //cgroup分组也是取小的值
            schedGroup = Math.max(schedGroup, state.getCurrentSchedulingGroup());
        }

24. 先更新一下当前计算的值到ProcessStateRecord

先更新一下当前计算的值到ProcessStateRecord(进程状态信息记录)

        //将当前adj更新到mCurRawAdj
        state.setCurRawAdj(adj);
        //将当前进程状态procState更新到mCurRawProcState
        state.setCurRawProcState(procState);

        //先默认该进程没有启动的服务,给初始化值
        state.setHasStartedServices(false);

25. 设置当前adj调整的系列号

        //到这里我们开始调整adj的值,设置当前进程adj调整的序列是mAdjSeq
        state.setAdjSeq(mAdjSeq);

26. 调整backup备份的应用

        //获取backup的目标
        final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId);
        //如果backup app就是当前调整的app
        if (backupTarget != null && app == backupTarget.app) {
            // If possible we want to avoid killing apps while they're being backed up
            //那么adj最小不低于300(BACKUP_APP_ADJ)
            if (adj > ProcessList.BACKUP_APP_ADJ) {
                if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
                //那么adj设置成300(BACKUP_APP_ADJ)
                adj = ProcessList.BACKUP_APP_ADJ;
                //调整adj值之后,进程状态最低不低于8(TRANSIENT_BACKGROUND)
                if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
                    procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
                }
                //adj的类型是"backup"
                state.setAdjType("backup");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app);
                }
                // 设置成非cached的进程
                state.setCached(false);
            }
            //进程状态最低不低于9(BACKUP)
            if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
                //设置进程状态为9(BACKUP)
                procState = ActivityManager.PROCESS_STATE_BACKUP;
                //adj的类型是"backup"
                state.setAdjType("backup");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app);
                }
            }
        }

27. service服务自身和服务依赖关系调整

27.1 遍历该进程的服务numberOfRunningServices

        //用于计算前台服务都拥有哪些能力
        int capabilityFromFGS = 0; // capability from foreground service.
        //用来用来判断分组是否需要将分组设置成top
        boolean scheduleLikeTopApp = false;
        //numberOfRunningServices是查看还有多少正在运行的服务(只要startService了就会放入ProcessServiceRecord的mServices中,
        //stopService或者kill会从mServices移除)
        //而且满足其中之一才会进来:adj需要大于0的才调整,如果是0前台或者常驻进程adj是负数,或者分组是后台,或者进程状态状态大于top
        for (int is = psr.numberOfRunningServices() - 1;
                is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                        || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                        || procState > PROCESS_STATE_TOP);
                is--) {
            //取得保存服务的对象ServiceRecord
            ServiceRecord s = psr.getRunningServiceAt(is);

27.2 根据Services自身的状态进行调整


/*
realStartServiceLocked:, ActiveServices (com.android.server.am) //psr.startService将ServiceRecord放入mServices
bringUpServiceLocked:, ActiveServices (com.android.server.am)
startServiceInnerLocked:, ActiveServices (com.android.server.am)//设置startRequested = true
startServiceLocked:, ActiveServices (com.android.server.am)
startService:, ActivityManagerService (com.android.server.am)
*/
            //startRequested是在startServiceInnerLocked中设置,在realStartServiceLocked(会将service放入mServices)之前
            if (s.startRequested) {
                //设置有启动的服务
                state.setHasStartedServices(true);
                //没有stop的服务的进程,最低进程状态就是10(SERVICE)
                if (procState > PROCESS_STATE_SERVICE) {
                    procState = PROCESS_STATE_SERVICE;
                    //adj类型是"started-services"
                    state.setAdjType("started-services");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise procstate to started service: " + app);
                    }
                }
                //如果不是config_keep_warming_services(目前这个是空的,也就是mKeepWarming是false)的服务,
                //而且hasShownUi是true,且不是桌面
                //hasShownUi只要该进程有onStartActivity的操作,就会设置成true,不管activity是否destroy,只要进程还在都是true
                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.
                    //如果adj比500(SERVICE_ADJ)大(adj越大优先级越低),SERVICE_ADJ是A services
                    if (adj > ProcessList.SERVICE_ADJ) {
                        //则将adj类型设置成"cch-started-ui-services缓存的启动了ui的服务
                        state.setAdjType("cch-started-ui-services");
                    }
                } else {
                    //mKeepWarming都是false,而且lastActivity服务启动或者bind时间是30分钟以内
                    //ServiceRecord的lastActivity代表的是上一次该服务
                    //startServiceInnerLocked/bindServiceLocked/realStartServiceLocked的时间
                    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.
                        //如果adj比500(SERVICE_ADJ)大
                        if (adj > ProcessList.SERVICE_ADJ) {
                            //则将adj设置成500
                            adj = ProcessList.SERVICE_ADJ;
                            //adj类型也是设置成"started-services"
                            state.setAdjType("started-services");
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                        "Raise adj to started service: " + app);
                            }
                            // 设置成非cached的进程
                            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,将adj类型设置成"cch-started-services"
                    if (adj > ProcessList.SERVICE_ADJ) {
                        state.setAdjType("cch-started-services");
                    }
                }
            }

27.3 获取前台服务的能力capabilityFromFGS


            //启动的是前台服务的时候isForeground这个值才是true
            if (s.isForeground) {
                //foregroundServiceType一般是AndroidManifest中设置,也可以在startForeground的时候传入
                //frameworks/base/core/res/res/values/attrs_manifest.xml的foregroundServiceType有各个类型定义
                //例如下面前台服务的时候拥有dataSync、mediaPlayback、phoneCall、location、connectedDevice的(mediaProjection/camera/microphone)
                //<service android:name="SchedulerService"
                //     android:foregroundServiceType="dataSync|mediaPlayback|phoneCall|location|connectedDevice">
                final int fgsType = s.foregroundServiceType;
                //mAllowWhileInUsePermissionInFgs用于是否允许前台服务使用一些权限
                if (s.mAllowWhileInUsePermissionInFgs) {
                    //此时location的权限是否允许取决于foregroundServiceType是否有location权限(GPS、地图、导航)
                    capabilityFromFGS |=
                            (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
                                    != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;

                    boolean enabled = false;
                    try {
/*
    boolean isEnabled(ApplicationInfo app, AndroidBuildClassifier buildClassifier) {
        if (app == null) {
            return defaultValue();
        }
        if (mEvaluatedOverrides.containsKey(app.packageName)) {
            return mEvaluatedOverrides.get(app.packageName);
        }
        if (getDisabled()) {
            return false;
        }
        if (getEnableSinceTargetSdk() != -1) {
            // If the change is gated by a platform version newer than the one currently installed
            // on the device, disregard the app's target sdk version.
            //Google这里的代码也有有点奇怪,app.targetSdkVersion是app的targetSdkVersion,而platformTargetSdk是
            //看注释是取最小的做为compareSdk 
            int compareSdk = Math.min(app.targetSdkVersion, buildClassifier.platformTargetSdk());
            //但是这里不等于targetSdkVersion有赋值成targetSdkVersion,那其实是一个意思
            if (compareSdk != app.targetSdkVersion) {
                compareSdk = app.targetSdkVersion;
            }
            return compareSdk >= getEnableSinceTargetSdk();
        }
        return true;
    }
*/
                        //ChangeId(136219221; name=CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID; enableSinceTargetSdk=30)
                        //获取camera,具体配置是读取/system/etc/compatconfig/services-platform-compat-config.xml进行初始话,这个是在30(android R)之后支持
                        //isChangeEnabled其实最终调用的是CompatChange的isEnabled,目前只是用apk的targetSdkVersion进行判断,主要大于30就返回true
                        enabled = getPlatformCompatCache().isChangeEnabled(
                                CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID, s.appInfo);
                    } catch (RemoteException e) {
                    }

                    //Android S中,如果apk是针对S做的,一般enabled都是true
                    if (enabled) {
                        //判断foregroundServiceType是否有"camera"标签,有的话赋予访问camera的权限
                        capabilityFromFGS |=
                                (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
                                        != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0;
                        //判断foregroundServiceType是否有"microphone"标签,有的话赋予访问听筒的权限
                        capabilityFromFGS |=
                                (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
                                        != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0;
                    } else {
                        //如果是版本过低,这默认将camera、听筒的权限赋值给前台服务
                        capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
                                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
                    }
                }
            }

27.4 遍历每个服务里面的所有链接对象


            //bindService就会往connections add相关的链接对象,key是IServiceConnection对象
            //unbindService移除链接
            ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
            //遍历所有的服务,ArrayMap是按照key的hashCode/identityHashCode进行排序的,不是按照add进去的时间进行排序
            //这里是从serviceConnections尾部向头部遍历(反过来其实也是一样的,可能是考虑add/remove修改数组大小的时候的健壮性才从尾部开始遍历)
            //如果当前进程的adj > 0或者进程分组schedGroup是后台或者进程状态 > top,才进行调整(高优先级的不进行依赖调整,减少调整次数)
            for (int conni = serviceConnections.size() - 1;
                    conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                            || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                            || procState > PROCESS_STATE_TOP);
                    conni--) {
                //取出服务连接对象
                ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);

27.5 取出每个服务链接对象


                //取出每次链接的对象,只要(当前进程的adj > 0或者进程分组schedGroup是后台或者进程状态 > top)是非前台的都进行调整
                for (int i = 0;
                        i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
                                || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                                || procState > PROCESS_STATE_TOP);
                        i++) {
                    // XXX should compute this based on the max of
                    // all connected clients.
                    //取出每一个ConnectionRecord对象
                    ConnectionRecord cr = clist.get(i);

27.6 只调整自身是服务,由于客户端的链接的情况

只有服务端的adj,才会由于客户端的adj提升而得到相应的提升

这里就是服务依赖关系调整的开始


                    //如果服务链接的客户端是当前app,则跳过,客户端的adj不会由于服务端的adj提升而升高
                    //只有服务端的adj,才会由于客户端的adj提升而得到相应的提升(不然会出现客户端在使用的时候服务端由于优先级低给回收掉了)
                    if (cr.binding.client == app) {
                        // Binding to oneself is not interesting.
                        continue;
                    }

27.7 computeClients循环计算时,会先计算客户端的adj


                    //通过mProcessStats.mTrackingAssociations.add(this);将其放入记录ProcessState列表中
                    //在updateOomAdjInnerLSP的updateTrackingAssociationsLocked会去更新这些add进去的进程状态
                    //data/system/procstats里面有保存相关数据
                    boolean trackedProcState = false;

                    //服务链接中获取绑定的客户端进程
                    ProcessRecord client = cr.binding.client;
                    //客户端的进程状态
                    final ProcessStateRecord cstate = client.mState;
                    //computeClients是否需要计算当前进程的时候计算服务、provider提供者对端client的adj
                    if (computeClients) {
                        //调整之前先计算client的adj,将client按照当前传递计算app的重新计算一次,此处就有可能循环计算,mAdjSeq目前都是一个
                        computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
                                cycleReEval, true);
                    } else {
                        //如果不需要计算客户端的优先级,那么setCurRawAdj先将客户端当前调整的mCurAdj更新到mCurRawAdj中
                        //mCurAdj当前调整的adj值,进过约束的(如mHasAboveClient进行约束,client app进程优先级会相应降低)
                        //mCurRawAdj当前调整的adj值,但是未经过约束
                        //mSetRawAdj上一次applyOomAdjLSP后设置的mCurRawAdj值
                        //mSetAdj上一次applyOomAdjLSP后设置的mCurAdj值
                        cstate.setCurRawAdj(cstate.getCurAdj());
                        //mCurProcState是跑完一次computeOomAdjLSP的出的进程状态结果
                        //而mCurRawProcState是当前的进程状态,是在计算中的临时结果
                        //setCurRawProcState将上一次计算的进程状态mCurProcState赋值给mCurRawProcState(临时计算值)
                        cstate.setCurRawProcState(cstate.getCurProcState());
                    }

27.8 调整前获取客户端的clientAdj和clientProcState

获取客户端的clientAdj(客户端的adj)clientProcState(客户端的进程状态procState)


                    //取得客户端的mCurRawAdj当前调整的adj值(未经过约束)
                    int clientAdj = cstate.getCurRawAdj();
                    //取得客户端的临时计算的最新进程状态值mCurRawProcState
                    int clientProcState = cstate.getCurRawProcState();

                    //如果进程状态比top还小,代表是起码是常驻进程,clientIsSystem标记为true
                    final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;

                    //如果客户端mShouldNotFreeze是true,则服务端也被设置不允许冻结。
                    //(原生冻结有2个条件,一个是adj大于等于900,而且mShouldNotFreeze=false)
                    if (client.mOptRecord.shouldNotFreeze()) {
                        // Propagate the shouldNotFreeze flag down the bindings.
                        app.mOptRecord.setShouldNotFreeze(true);
                    }

27.9 进行没有豁免优先级情况的调整

                    //如果当前没有设置豁免绑定的优先级调整,一般没有设置
                    //则会进入根据客户端的adj去调整服务端的adj
                    if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
27.9.1 循环计算的时候是否需要先跳过本次计算
                        //判断是是否客户端adj没有计算完成,是否需要跳过本次依赖关系的计算,具体请看shouldSkipDueToCycle的解释
                        if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                            continue;
                        }
27.9.2 能力capability初始化
                        //如果包含BIND_INCLUDE_CAPABILITIES,则会将客户端的能力全部赋值给服务端
                        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_NETWORK) != 0) {
                            //客户端的状态小于等于PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                            if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
                                //只有设置了BIND_BYPASS_POWER_NETWORK_RESTRICTIONS(power相关限制都不会阻止服务获取网络权限)
                                //才会给当前进程(是服务)赋予网络相关的能力
                                if ((cr.flags & Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)
                                        != 0) {
                                    capability |= PROCESS_CAPABILITY_NETWORK;
                                }
                            } else {
                                //如果客户端优先级大于等于PROCESS_STATE_FOREGROUND_SERVICE
                                //则直接赋予当前进程(是服务)网络相关能力
                                capability |= PROCESS_CAPABILITY_NETWORK;
                            }
                        }
27.9.3 低于cached activity的进程状态clientProcState约束

                        //客户端的进程状态优先级低于cached activity
                        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.
                            //客户端的进程状态优先级低于全部归类为cached empty的进程
                            clientProcState = PROCESS_STATE_CACHED_EMPTY;
                        }
27.9.4 如果进程设置了在低内存时托管给系统

如果进程设置了在低内存时托管给系统,就可以减少很多进程依赖关系的调整,
不过目前大部分应用没有使用,而且这里规则也不是很细致


                        // adjType先初始化为null
                        String adjType = null;
                        // 如果服务连接记录设置了BIND_ALLOW_OOM_MANAGEMENT
                        //这个标记位的意思是允许系统在低内存的时候会删除这个进程,或者服务长时间运行会被杀死和重启
                        if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                            // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
                            //如果绑定服务的客户端的adj(clientAdj),小于900,则服务也不会进行冻结
                            if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
                                app.mOptRecord.setShouldNotFreeze(true);
                            }
                            // Not doing bind OOM management, so treat
                            // this guy more like a started service.
                            //如果当前调整的进程拥有界面(hasShownUi只要该进程有onStartActivity的操作,就会设置成true,不管activity是否destroy,只要进程还在都是true)
                            //而且不是桌面的情况下
                            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.
                                //如果服务端的adj大于客户端clientAdj,则将adj类型设置成"cch-bound-ui-services"(缓存的拥有ui、被绑定的服务)
                                if (adj > clientAdj) {
                                    adjType = "cch-bound-ui-services";
                                }
                                //设置cached为fasle,代表这个不是cached进程
                                state.setCached(false);
                                //将服务的adj赋值给clientAdj,注意一下这里的clientAdj只是用来调整服务端的adj,
                                //这里的意思是此时将不根据客户端的优先级调整服务端的优先级
                                //这样可以有效的避免互相依赖关系,这个功能还不错,只是目前大多数服务绑定时没有设置这个TAG
                                //而且目前该逻辑也相对简单,不太适合统一打开,需要更精细控制
                                clientAdj = adj;
                                //将服务的进程状态procState赋值给clientProcState ,跟上面是一个意思,调整adj时忽略客户端的进程状态
                                clientProcState = procState;
                            } else {
                                //针对没有界面服务,或者是桌面
                                //则看一下s.lastActivity(服务启动或者绑定的时候会设置该时间)
                                //是否上一次服务启动或者绑定的时间已经超过MAX_SERVICE_INACTIVITY(默认30分钟)
                                //30分钟以内的话不进入这里,还是会根据客户端的优先级来调整服务端的优先级,
                                //30分钟以内,相当于没有设置BIND_ALLOW_OOM_MANAGEMENT一样的逻辑
                                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.
                                    //如果是的话,当前服务端的adj小于clientAdj,也就是服务adj优先级没有客户端高
                                    if (adj > clientAdj) {
                                        //那么将adj类型设置成"cch-bound-services"(缓存的绑定服务),代表不通过客户端来调整服务端的adj
                                        adjType = "cch-bound-services";
                                    }
                                    //忽略客户端adj,不管客户端adj的大小,将服务的adj赋值给clientAdj后,都将忽略clientAdj
                                    clientAdj = adj;
                                }
                            }
                        }
27.9.5 如果clientAdj大于当前服务的adj,则开始adj依赖关系调整

                        //如果客户端的clientAdj小于当前服务的adj,
                        //那么将会根据客户端的clientAdj进行服务的优先级调整,我们认为这是依赖关系调整即可
                        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.
                            //如果当前调整的进程拥有界面(hasShownUi只要该进程有onStartActivity的操作,就会设置成true,不管activity是否destroy,只要进程还在都是true)
                            //而且不是桌面的情况下,这里逻辑跟上面一样,不过多了一个clientAdj如果是大于用户可感知的200才会进来
                            //如果clientAdj小于等于200(优先级大于等于用户可感知级别的话),那就不会进来
                            if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                                    && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                //注意就算是进来,也只进行了一个操作,就是当前进程的adj如果大于等于900
                                if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
                                    //则将当前进程的adj类型设置成"cch-bound-ui-services"
                                    adjType = "cch-bound-ui-services";
                                }
                                //这里少了对比上面少了state.setCached(false);clientAdj = adj;clientProcState = procState;
                                //isCached没有直接设置成false,isCached用的地方比较少,主要用在performUpdateOomAdjLSP
                                //state.setCached(false);
                                //这个确实没有作用了,目前已经跑完了if (adj > clientAdj)的逻辑,没有用到clientAdj的地方了,
                                //起码adj暂时不会由于clientAdj去调整
                                //clientAdj = adj;
                                //这个不设置是由于后面还需要用到,还会由于客户端的进程状态调整当前进程的进程状态
                                //clientProcState = procState;
                            } else {
                                //其它情况会根据客户端的clientAdj,看情况调整当前进程的adj
                                int newAdj;

                                //如果服务链接里面包含BIND_ABOVE_CLIENT或者BIND_IMPORTANT的时候
                                //BIND_ABOVE_CLIENT: 代表服务的优先级需要比客户端client的高
                                //BIND_IMPORTANT: 正常情况是就客户端是前台,服务端最多也只是visable,不过设置了这个,
                                //adj可以到0(fg)或者-700(PERSISTENT_SERVICE)
                                //StorageUserConnection里面bindServiceAsUser就有设置BIND_IMPORTANT
                                if ((cr.flags&(Context.BIND_ABOVE_CLIENT
                                        |Context.BIND_IMPORTANT)) != 0) {
                                    //如果客户端的adj大于等于-700,直接将客户端的clientAdj赋值给当前进程的newAdj
                                    if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
                                        newAdj = clientAdj;
                                    } else {
                                        //如果客户端的adj是常驻进程(-800)或者系统(-900)
                                        // make this service persistent
                                        // 直接赋值newAdj为PERSISTENT_SERVICE_ADJ(常驻服务)级别,
                                        //这类进程和常驻进程有区别,不需要开机之前启动,可以动态设置和关闭
                                        newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
                                        //cgroup分组设置成default,具体之前有解释
                                        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                        //进程状态设置成PROCESS_STATE_PERSISTENT
                                        procState = ActivityManager.PROCESS_STATE_PERSISTENT;
                                        //将关联关系记录的信息保存在AssociationState.SourceState中,主要是进程状态,当前调整的序列号和调整时间
                                        cr.trackProcState(procState, mAdjSeq, now);
                                        //标记已经记录过进程状态信息trackedProcState了,后面就不需要再做一次了
                                        trackedProcState = true;
                                    }
                                //如果服务链接里面包含BIND_NOT_PERCEPTIBLE(服务进程的优先级提升不会高于250)
                                //clientAdj优先级比200高(或等于PERCEPTIBLE_APP_ADJ),而且当前进程优先级小于250(PERCEPTIBLE_LOW_APP_ADJ)
                                } else if ((cr.flags & Context.BIND_NOT_PERCEPTIBLE) != 0
                                        && clientAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
                                        && adj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                                    //则会设置成250(PERCEPTIBLE_LOW_APP_ADJ)
                                    newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
                                //如果设置了BIND_ALMOST_PERCEPTIBLE(接近是perceptible)
                                //而且客户端clientAdj小于200(优先级大于PERCEPTIBLE_APP_ADJ)
                                //而且当前进程adj大于等于225(优先级小于等于PERCEPTIBLE_MEDIUM_APP_ADJ 250)
                                //看逻辑貌似adj == 225的不需要将newAdj赋值成225(没用到),这里等于还有一个含义,就是进入此处的else,不进行别的else判断
                                } else if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0
                                        && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                        && adj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) {
                                    //newAdj设置成225(PERCEPTIBLE_MEDIUM_APP_ADJ)
                                    newAdj = ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
                                //如果设置了BIND_NOT_VISIBLE(不要绑定成为visible 100进程)
                                //而且客户端clientAdj小于200(优先级大于PERCEPTIBLE_APP_ADJ)
                                //而且当前进程adj大于等于200(优先级小于等于PERCEPTIBLE_APP_ADJ)
                                } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                        && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                        && adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
                                    //newAdj设置成200(PERCEPTIBLE_APP_ADJ)
                                    newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                //而且客户端clientAdj大于等于200(优先级小于等于PERCEPTIBLE_APP_ADJ)
                                } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
                                    //newAdj设置成客户端的优先级clientAdj
                                    newAdj = clientAdj;
                                } else {
                                    //假设你什么都没有设置,而且客户端clientAdj优先级大于200
                                    //(那么客户端就是visible/fg/persistent/system的应用)
                                    //如果应用进程adj优先级小于100(VISIBLE_APP_ADJ)
                                    if (adj > ProcessList.VISIBLE_APP_ADJ) {
                                        // TODO: Is this too limiting for apps bound from TOP?
                                        //则新的adj由于依赖关系,最多设置成visiable级别(100),此处是[100, 200)
                                        newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
                                    } else {
                                        //如果应用进程adj优先级本来就很高,如adj小于等于100,则将当前进程adj赋值给newAdj,不做adj改变
                                        newAdj = adj;
                                    }
                                }
                                //只要是客户端不是cached process缓存进程
                                if (!cstate.isCached()) {
                                    //那么服务端也会设置成非缓存进程
                                    state.setCached(false);
                                }

                                //只要当前adj大于新的newAdj(新的adj优先级大于当前adj的优先级)
                                if (adj >  newAdj) {
                                    //将新的优先级newAdj,赋值给当前进程的adj
                                    adj = newAdj;
                                    //将adj保存在未经过约束的mCurRawAdj中,这里保存的是比较新的值
                                    state.setCurRawAdj(adj);
                                    if (DEBUG_OOM_ADJ_REASON) {
                                        //打开DEBUG_OOM_ADJ_REASON会输出adj调整的日志,此处的nowActivityTime表示是否上一次start/bind到现在超过30分钟
                                        boolean nowActivityTime = (now > (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY));
                                        Slog.d(TAG, "newAdjservice: " + app + ", adj = " + adj + ", client = " + client + ", client.uid = " + client.uid
                                            +", nowActivityTime = " + nowActivityTime + ", state.hasShownUi = " + state.hasShownUi()
                                            + ", clientProcState =" + clientProcState + ", cr = " + cr);
                                    }
                                    //将adj类型设置成服务
                                    adjType = "service";
                                }
                            }
                        }
27.9.6 clientProcState依赖关系调整

                        //如果没有设置BIND_NOT_FOREGROUND(非前台绑定)和BIND_IMPORTANT_BACKGROUND(绑定重要后台)的时候
                        if ((cr.flags & (Context.BIND_NOT_FOREGROUND
                                | Context.BIND_IMPORTANT_BACKGROUND)) == 0) {
                            // This will treat important bound services identically to
                            // the top app, which may behave differently than generic
                            // foreground work.
                            //获取客户端cgroup设置的分组信息赋值给curSchedGroup
                            final int curSchedGroup = cstate.getCurrentSchedulingGroup();
                            //如果当前curSchedGroup(客户端分组优先级)大于schedGroup(当前进程分组优先级)
                            if (curSchedGroup > schedGroup) {
                                //如果设置了BIND_IMPORTANT(重要的绑定)
                                if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                                    //则将客户端的cgroup分组优先级设置给当前进程的分组信息
                                    schedGroup = curSchedGroup;
                                } else {
                                    //如果没有设置,则默认的分组先设置成defalut
                                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                }
                            }
                            //如果客户端进程状态小于top(2),也就是说客户端是常驻进程
                            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.
                                //如有拥有BIND_FOREGROUND_SERVICE(绑定前台服务,一般来自系统的绑定)
                                if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
                                    //客户端的进程状态clientProcState设置成PROCESS_STATE_BOUND_FOREGROUND_SERVICE(5)(绑定了前台进程的服务)
                                    //此处修改clientProcState不会直接修改客户端的进程状态,只是为了后面去修改服务端的进程状态使用
                                    clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                    //更新mAllowStartFgsState,最小设置成PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                                    //只要mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE则有前台服务启动的权限
                                    state.bumpAllowStartFgsState(
                                            PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
                                //其它情况,mWakefulness是唤醒状态
                                //而且包含BIND_FOREGROUND_SERVICE_WHILE_AWAKE(在唤醒时绑定前台服务)
                                } else if (mService.mWakefulness.get()
                                        == PowerManagerInternal.WAKEFULNESS_AWAKE
                                        && (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
                                                != 0) {
                                    //将clientProcState设置成PROCESS_STATE_BOUND_FOREGROUND_SERVICE(5)(绑定了前台进程的服务)
                                    clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                } else {
                                    //将clientProcState设置成PROCESS_STATE_IMPORTANT_FOREGROUND(6)(重要的前台,这个进程状态级别不能启动前台服务)
                                    clientProcState =
                                            PROCESS_STATE_IMPORTANT_FOREGROUND;
                                }
                            //如果clientProcState是PROCESS_STATE_TOP(2),当前顶端的Activity(非睡眠状态才会是这个级别)
                            } 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(3)(绑定了前台进程)
                                clientProcState = PROCESS_STATE_BOUND_TOP;
                                //更新是否运行启动前台服务的进程状态信息mAllowStartFgsState,允许启动前台服务
                                state.bumpAllowStartFgsState(PROCESS_STATE_BOUND_TOP);
                                boolean enabled = false;
                                try {
                                    //" enableAfterTargetSdk="29" id="136274596" name="PROCESS_CAPABILITY_CHANGE_ID",代表mEnableSinceTargetSdk=20
                                    //具体配置是读取/system/etc/compatconfig/services-platform-compat-config.xml进行初始话,这个是在30(android R)之后支持
                                    //isChangeEnabled其实最终调用的是CompatChange的isEnabled,目前只是用apk的targetSdkVersion进行判断,主要大于30就返回true
                                    enabled = getPlatformCompatCache().isChangeEnabled(
                                            PROCESS_CAPABILITY_CHANGE_ID, client.info);
                                } catch (RemoteException e) {
                                }

                                //如果sdk版本支持PROCESS_CAPABILITY_CHANGE_ID(30(android R)之后支持)
                                if (enabled) {
                                    //如果包含BIND_INCLUDE_CAPABILITIES,则会将客户端的能力全部赋值给服务端
                                    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.
                                    //如果是旧版本sdk的apk,则将客户端的能力直接赋给服务端(也就是旧版本不约束)
                                    capability |= cstate.getCurCapability();
                                }
                            }
                        //如果设置了BIND_NOT_FOREGROUND(非前台绑定),而且没有设置BIND_IMPORTANT_BACKGROUND(绑定重要后台)的时候
                        } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
                            //客户端进程状态clientProcState如果优先级大于PROCESS_STATE_TRANSIENT_BACKGROUND(8)
                            if (clientProcState <
                                    PROCESS_STATE_TRANSIENT_BACKGROUND) {
                                //将clientProcState设置成PROCESS_STATE_TRANSIENT_BACKGROUND(8)
                                clientProcState =
                                        PROCESS_STATE_TRANSIENT_BACKGROUND;
                            }
                        } else {
                            //如果设置了BIND_IMPORTANT_BACKGROUND(绑定重要后台)的时候
                            //客户端进程状态小于PROCESS_STATE_IMPORTANT_BACKGROUND(7),也就是起码是IMPORTANT_FOREGROUND(6)
                            if (clientProcState <
                                    PROCESS_STATE_IMPORTANT_BACKGROUND) {
                                //将clientProcState设置成PROCESS_STATE_IMPORTANT_BACKGROUND(7)
                                clientProcState =
                                        PROCESS_STATE_IMPORTANT_BACKGROUND;
                            }
                        }

                        //如果cgroup分组小于top(default/resticted/background)
                        //而且flag包含了BIND_SCHEDULE_LIKE_TOP_APP(分组就像是top一样),如IMEs输入法在有界面的情况下
                        //而且客户端是系统或者常驻进程clientIsSystem=true
                        if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP
                                && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0
                                && clientIsSystem) {
                            //将分组信息设置成top app
                            schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
                            //标记这种app为scheduleLikeTopApp=true
                            scheduleLikeTopApp = true;
                        }

                        //如果之前没有设置过trackedProcState=true(目前只有persistent service才有设置)
                        if (!trackedProcState) {
                            //则将关联关系记录的信息保存在AssociationState.SourceState中,主要是进程状态,当前调整的序列号和调整时间
                            cr.trackProcState(clientProcState, mAdjSeq, now);
                        }

                        //如果当前进程状态procState大于clientProcState(就是没有(准备根据客户端调整的进程状态)clientProcState优先级高)
                        if (procState > clientProcState) {
                            //更新当前进程的进程状态procState 
                            procState = clientProcState;
                            //将procState赋值给mCurRawProcState(临时计算值)
                            state.setCurRawProcState(procState);
                            //如果adj类型为空,则赋值adj类型为服务
                            if (adjType == null) {
                                adjType = "service";
                            }
                        }

                        //如果进程状态procState小于PROCESS_STATE_IMPORTANT_BACKGROUND(7),
                        //而且带有BIND_SHOWING_UI的标签
                        if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND
                                && (cr.flags & Context.BIND_SHOWING_UI) != 0) {
                            //而且带有BIND_SHOWING_UI的标签,则设置ProcessProfileRecord的mPendingUiClean为true
                            //mPendingUiClean会在更新内存等级的时候会使用,用户触发thread.scheduleTrimMemory进行应用不同级别的内存回收
                            app.setPendingUiClean(true);
                        }
27.9.7 service依赖关系原因的输出

                        //如果adjType不等与null,则把设置客户端setAdjSource和当前进程setAdjTarget
                        //如果看到只有"service"没有连接对象,其中一种情况:可能是刚进入computeOomAdjLSP调整清空了之前的对象
                        if (adjType != null) {
                            //设置adj类型
                            state.setAdjType(adjType);
                            //设置adj类型的代码mAdjTypeCode,和importanceReasonCode类似,就是优先级的原因,此处是service正在使用中
                            //客户端的进程在importanceReasonPid(getAdjSource),服务端的进程在importanceReasonComponent(getAdjTarget)
                            state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                                    .REASON_SERVICE_IN_USE);
                            //cr.binding.client(AppBindRecord)这里是ProcessRecord,setAdjSource设置此次调整的来源:客户端ProcessRecord
                            state.setAdjSource(cr.binding.client);
                            //setAdjSourceProcState设置此次调整的进程状态来源:客户端约束后的clientProcState(不高于改值)
                            state.setAdjSourceProcState(clientProcState);
                            //setAdjTarget设置调整的原因的服务组件是instanceName(服务组件的实例)
                            state.setAdjTarget(s.instanceName);
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                        + ": " + app + ", due to " + cr.binding.client
                                        + " adj=" + adj + " procState="
                                        + ProcessList.makeProcStateString(procState)+ ", client=" + client
                                        + ", cr=" + cr);
                            }
                        }

27.10 BIND_WAIVE_PRIORITY == true豁免优先级调整


                    } else {
                        // 如果设置了BIND_WAIVE_PRIORITY == true,一般没有跑,此处会豁免adj优先级的调整
                        // 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.
                        //如果客户端是非cached进程,则当前的服务进程不能被冻结
                        if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
                            app.mOptRecord.setShouldNotFreeze(true);
                        }
                    }

27.11 绑定客户端对象是activity的调整

                    //链接记录对象cr是ConnectionRecord cr = clist.get(i);如果该链接设置了BIND_TREAT_LIKE_ACTIVITY
                    if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                        //服务端psr则设置setTreatLikeActivity的标记位,需要像对待activity一样对待该服务进程
                        psr.setTreatLikeActivity(true);
                    }

                    //获取绑定客户端对象的activity(只有客户端是activity的时候才有这个对象)
                    final ActivityServiceConnectionsHolder a = cr.activity;
                    //如果ConnectionRecord设置了BIND_ADJUST_WITH_ACTIVITY:可以根据客户端activity是否可见来调整优先级
                    if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
                        //如果客户端activity不为null,而且当前服务adj大于0(FOREGROUND_APP_ADJ),
                        //而且客户端activity是可见的
                        if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ
                                && a.isActivityVisible()) {
                            //则直接设置服务端adj为0(FOREGROUND_APP_ADJ)
                            adj = ProcessList.FOREGROUND_APP_ADJ;
                            //将adj保存在未经过约束的mCurRawAdj中
                            state.setCurRawAdj(adj);
                            //如果标签不包含BIND_NOT_FOREGROUND(非前台绑定,不允许上升到前台分组)
                            if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                                //包含重要绑定BIND_IMPORTANT(对客户端来说非常重要,需要提升到前台)
                                if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                                    //则分组cgroup直接设置成top app
                                    schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
                                } else {
                                    //否则分组cgroup设置成默认
                                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                }
                            }
                            //设置成非cached进程
                            state.setCached(false);
                            //adj类型为服务"service"
                            state.setAdjType("service");
                            //设置adj类型的代码mAdjTypeCode(和importanceReasonCode类似,就是优先级的原因)为service正在使用中
                            state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                                    .REASON_SERVICE_IN_USE);
                            //setAdjSource设置此次调整的来源:客户端ActivityServiceConnectionsHolder
                            state.setAdjSource(a);
                            //setAdjSourceProcState设置此次调整的进程状态来源:procState(这里已经是调整后的进程状态值)
                            state.setAdjSourceProcState(procState);
                            //setAdjTarget设置调整的原因的服务组件是instanceName(服务组件的实例)
                            state.setAdjTarget(s.instanceName);
                            //如果打开DEBUG_OOM_ADJ_REASON、或者设置了logUid,则会打印日志
                            //logUid可以通过直接介绍的adb shell am watch-uids --oom + ***来设置
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                //adj调整的原因是activity
                                reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                        "Raise to service w/activity: " + app);
                            }
                        }
                    }
                }
            }
        }

到这里就结束了服务依赖调整:当前是服务进程,由于客户端进程的adj和进程状态,进行服务进程的adj和进程状态调整

28. provider依赖关系调整

provider依赖关系调整:当前是provider内容提供者进程,由于客户端进程的adj和进程状态,进行provider进程的adj和进程状态调整

28.1 只有当前是provider内容提供者进程才调整

        //接下去就是当前进程的mProviders(provider对象保存信息)的调整,这里逻辑相对少一点
        final ProcessProviderRecord ppr = app.mProviders;
        //一样是倒叙遍历每一个ContentProviderRecord(单个provider连接信息)
        //如果adj大于0(非前台进程)或者分组cgroup是后台(0)或者进程状态小于PROCESS_STATE_TOP(2)满足一个才会进来
        for (int provi = ppr.numberOfProviders() - 1;
                provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                        || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                        || procState > PROCESS_STATE_TOP);
                provi--) {

            //取出每个保存provider连接信息的ContentProviderRecord对象
            //每个包含ActivityManagerService _service(AMS对象)
            //ProviderInfo _info(通过PMS的resolveContentProvider获得,provider的info信息)
            //ApplicationInfo ai(provider(内容提供者)的Application的信息)
            //ComponentName _name(ProviderInfo构建的组件名字)
            //boolean _singleton(provider是否singleton单例模式)
            ContentProviderRecord cpr = ppr.getProviderAt(provi);
            //每一次provider访问调用incProviderCountLocked的时候,
            //都会将ContentProviderConnection add到connections里去(cpr.connections.add(conn))
            //这里还是和上面一样adj大于0(非前台进程)或者分组cgroup是后台(0)或者进程状态小于PROCESS_STATE_TOP(2)有一个满足才会进来
            for (int i = cpr.connections.size() - 1;
                    i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                            || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                            || procState > PROCESS_STATE_TOP);
                    i--) {
                //获取ContentProviderConnection,其在ContentProviderHelper创建的时候的变量有
                //provider当前provider的ContentProviderRecord
                //client客户端调用者的ProcessRecord
                //clientPackage调用者的包名(getContentProvider传入的callingPackage)
                //mExpectedUserId(默认是调用者的UserId;如果uir的auth有制定uid则用auth的(getUserIdFromAuthority))
                //createTime创建new ContentProviderConnection的时间
                ContentProviderConnection conn = cpr.connections.get(i);

                //client客户端调用者的ProcessRecord
                ProcessRecord client = conn.client;
                //cstate是客户端进程状态记录信息ProcessStateRecord
                final ProcessStateRecord cstate = client.mState;

                //如果客户端(查询者)就是当前app,则直接返回。我们只关注提供内容的provider端(内容提供者)
                if (client == app) {
                    // Being our own client is not interesting.
                    continue;
                }

28.2 循环计算computeClients和判断是否需要跳过本次计算shouldSkipDueToCycle

                //computeClients是否需要计算当前进程的时候计算服务、provider提供者对端client的adj。和上面服务端计算依赖关系是一样的
                if (computeClients) {
                    //调整之前先计算client的adj,将client按照当前传递计算app的重新计算一次,此处就有可能循环计算,mAdjSeq目前都是一个
                    computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true);
                } else {
                    //如果不需要计算客户端的优先级,那么setCurRawAdj先将客户端当前调整的mCurAdj更新到mCurRawAdj中
                    //mCurAdj当前调整的adj值,进过约束的(如mHasAboveClient进行约束,client app进程优先级会相应降低)
                    //mCurRawAdj当前调整的adj值,但是未经过约束
                    //mSetRawAdj上一次applyOomAdjLSP后设置的mCurRawAdj值
                    //mSetAdj上一次applyOomAdjLSP后设置的mCurAdj值
                    cstate.setCurRawAdj(cstate.getCurAdj());

                    //mCurProcState是跑完一次computeOomAdjLSP的出的进程状态结果
                    //而mCurRawProcState是当前的进程状态,是在计算中的临时结果
                    //setCurRawProcState将上一次计算的进程状态mCurProcState赋值给mCurRawProcState(临时计算值)
                    cstate.setCurRawProcState(cstate.getCurProcState());
                }

                //判断是是否客户端adj没有计算完成,是否需要跳过本次依赖关系的计算,具体请看shouldSkipDueToCycle的解释
                if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                    continue;
                }

28.3 调整前客户端的clientAdj、clientProcState的记录

                //取得客户端的mCurRawAdj当前调整的adj值(未经过约束)
                int clientAdj = cstate.getCurRawAdj();
                //取得客户端的临时计算的最新进程状态值mCurRawProcState
                int clientProcState = cstate.getCurRawProcState();

                //客户端的进程状态优先级低于cached activity
                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.
                    //客户端的进程状态优先级低于全部归类为cached empty的进程
                    clientProcState = PROCESS_STATE_CACHED_EMPTY;
                }

                //如果客户端mShouldNotFreeze是true,则服务端也被设置不允许冻结。
                //(原生冻结有2个条件,一个是adj大于等于900,而且mShouldNotFreeze=false)
                if (client.mOptRecord.shouldNotFreeze()) {
                    // Propagate the shouldNotFreeze flag down the bindings.
                    app.mOptRecord.setShouldNotFreeze(true);
                }

28.4 clientAdj大于provider的adj才进行adj依赖关系调整


                //新建adjType(adj类型),初始值是null
                String adjType = null;

                //如果客户端的clientAdj小于provider的adj
                //开始针对provider端的进程优先级adj进行依赖调整(主要依据是客户端clientAdj的情况)
                if (adj > clientAdj) {
                    //如果该进程有界面的,而且不是桌面,而且客户端clientAdj大于200,这类不调整adj大小,只设置adj类型
                    if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                            && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                        //则将adj类型设置成"cch-ui-provider"(缓存的带有ui的provider)
                        adjType = "cch-ui-provider";
                    } else {
                        //其它情况,如当前进程没有带界面的、桌面、或者客户端clientAdj小于等于200(PERCEPTIBLE_APP_ADJ用户可感知级别)
                        //clientAdj如果是大于0(FOREGROUND_APP_ADJ前台adj),则直接将clientAdj赋值给provider端
                        //clientAdj如果是小于等于0,则provider端的adj都会设置成0(FOREGROUND_APP_ADJ)
                        //provider由于依赖关系最高优先级调整到0
                        adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
                                ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
                        //将adj更新到mCurRawAdj中(mCurRawAdj一般是调整过程中最新的adj值)
                        state.setCurRawAdj(adj);
                        //则将adj类型设置成"provider"
                        adjType = "provider";
                    }
                    //只有客户端和provider都是cached的时候才设置当前进程为mCached = true,其它情况都是mCached = false
                    state.setCached(state.isCached() & cstate.isCached());
                }

28.5 clientProcState进程状态依赖调整


                //开始针对provider端的进程状态procState进行依赖调整(主要依据是客户端clientProcState的情况)
                //只有进程状态clientProcState小于等于PROCESS_STATE_FOREGROUND_SERVICE(4)的时候才进来
                if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
                    //只有adj类型是空的时候才进行设置
                    if (adjType == null) {
                        //只有adj类型设置成"provider"
                        adjType = "provider";
                    }
                    //客户端的进程状态clientProcState如果是top app(2)
                    if (clientProcState == PROCESS_STATE_TOP) {
                        //重新约束clientProcState到PROCESS_STATE_BOUND_TOP(3)
                        clientProcState = PROCESS_STATE_BOUND_TOP;
                    } else {
                        //重新约束clientProcState到PROCESS_STATE_BOUND_FOREGROUND_SERVICE(5),这个状态刚好是可以启动前台服务的状态
                        clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                    }
                }

                //调整之前,先保存关联关系记录的信息在AssociationState.SourceState中
                //主要是进程状态,当前调整的序列号和调整时间
                conn.trackProcState(clientProcState, mAdjSeq, now);

                //只有当前进程的进程状态procState大于约束后的客户端clientProcState的进程状态时
                if (procState > clientProcState) {
                    //才将约束后的客户端clientProcState赋值给当前进程的进程状态procState
                    procState = clientProcState;
                    //setCurRawProcState将procState赋值给mCurRawProcState(最新的计算值,可能不是最终的值)
                    state.setCurRawProcState(procState);
                }

28.6 客户端分组依赖关系调整


                //如果客户端的分组大于当前进程的schedGroup(computeOomAdjLSP默认初始化之后最低是SCHED_GROUP_BACKGROUND(1))
                //也就是客户端分组起码是SCHED_GROUP_DEFAULT(2)
                if (cstate.getCurrentSchedulingGroup() > schedGroup) {
                    //设置当前分组schedGroup为SCHED_GROUP_DEFAULT
                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                }

28.7 输出provider调整的原因

                //如果adj类型不为空,那么代表根据客户端,当前进程调整过adj或者进程状态procState
                if (adjType != null) {
                    //设置adj类型
                    state.setAdjType(adjType);
                    //设置adj类型的代码mAdjTypeCode(和importanceReasonCode类似,就是优先级的原因)为provider正在使用中
                    state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                            .REASON_PROVIDER_IN_USE);
                    //setAdjSource设置此次调整的来源:客户端ProcessRecord
                    state.setAdjSource(client);
                    //setAdjSourceProcState设置此次调整的进程状态来源:客户端约束后的clientProcState(不高于改值)
                    state.setAdjSourceProcState(clientProcState);
                    //setAdjTarget设置调整的原因的provider组件是ComponentName name(ProviderInfo构建的组件名字)
                    state.setAdjTarget(cpr.name);
                    //打印日志由于什么原因去调整该进程的adj或者进程状态
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                + ": " + app + ", due to " + client
                                + " adj=" + adj + " procState="
                                + ProcessList.makeProcStateString(procState)
                                + ", target=" + cpr.name );
                    }
                }
            }

28.8 hasExternalProcessHandles的调整

            // If the provider has external (non-framework) process
            // dependencies, ensure that its adjustment is at least
            // FOREGROUND_APP_ADJ.
            //cpr.hasExternalProcessHandles为true时,adj类型是"ext-provider"
            //通过调用getContentProviderExternalUnchecked/getContentProviderExternal来设置hasExternalProcessHandles
            //具体流程getContentProviderExternal->getContentProviderExternalUnchecked->getContentProviderImpl(caller == null)
            //->incProviderCountLocked(r == null)->addExternalProcessHandleLocked->externalProcessTokenToHandle
            if (cpr.hasExternalProcessHandles()) {
                //如果当前adj大于0前台,则设置成0
                if (adj > ProcessList.FOREGROUND_APP_ADJ) {
                    //adj设置成0(FOREGROUND_APP_ADJ),这种优先级比较高
                    //一般用在cmd、uiautomator
                    adj = ProcessList.FOREGROUND_APP_ADJ;
                    //更新adj到mCurRawAdj中
                    state.setCurRawAdj(adj);
                    //分组设置成默认
                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                    //非cached进程
                    state.setCached(false);
                    //adj类型是"ext-provider"
                    state.setAdjType("ext-provider");
                    //setAdjTarget设置调整的原因的provider组件是ComponentName name(ProviderInfo构建的组件名字)
                    state.setAdjTarget(cpr.name);
                    //打印日志,调整adj的原因是由于external provider
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise adj to external provider: " + app);
                    }
                }
                //如果当前进程状态procState大于PROCESS_STATE_IMPORTANT_FOREGROUND(6)
                if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) {
                    //则将进程状态procState设置成PROCESS_STATE_IMPORTANT_FOREGROUND(这个级别不能启动前台服务)
                    procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
                    //更新进程状态procState到mCurRawProcState
                    state.setCurRawProcState(procState);
                    //打印日志,调整进程状态procState的原因是由于external provider
                    //(这里adj和进程状态的调整都有输出日志,看起来比上面的adjType会更清晰一点,
                    //如果需要修改类似日志,建议参考这里adj和procState单独输出)
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise procstate to external provider: " + app);
                    }
                }
            }
        }

29. recent-provider最近使用的provider调整

        //getLastProviderTime(mLastProviderTime)在removeContentProvider/decProviderCountLocked/handleProviderRemoval
        //当客户端释放provider而且客户端进程状态比PROCESS_STATE_LAST_ACTIVITY(15)小,则会设置mLastProviderTime
        //大概意思是provider上一次使用的时间,设置了这个时间的话provider会延迟一小会释放,
        //一般只在比last activity重要的进程状态(客户端的)时设置
        //CONTENT_PROVIDER_RETAIN_TIME是20s,上一次使用在20s以内会进来这里,避免低内存状态下频繁启动回收provider进程
        if (ppr.getLastProviderTime() > 0
                && (ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
            //如果adj大于700(PREVIOUS_APP_ADJ上一个应用)
            if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                //则将adj设置成700(就是dumpsys meminfo里面的Previous应用)
                adj = ProcessList.PREVIOUS_APP_ADJ;
                //设置分组为后台,这里是后台,不是前台和default
                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                //非cached进程
                state.setCached(false);
                //adj类型是"recent-provider"最近使用的provider
                state.setAdjType("recent-provider");
                //输出调整adj的原因
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                            "Raise adj to recent provider: " + app);
                }
            }
            //进程状态procState如果大于PROCESS_STATE_LAST_ACTIVITY(15)
            if (procState > PROCESS_STATE_LAST_ACTIVITY) {
                //则将procState设置成PROCESS_STATE_LAST_ACTIVITY(15)
                procState = PROCESS_STATE_LAST_ACTIVITY;
                //将adj类型设置成"recent-provider",注意只要有adj或者procState的提升都会重新设置adj类型为"recent-provider"
                state.setAdjType("recent-provider");
                //输出调整procstate的原因
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                            "Raise procstate to recent provider: " + app);
                }
            }
        }

30. 服务相关缓存进程CACHED的调整

        //如果进程状态procState大于等于PROCESS_STATE_CACHED_EMPTY(19,这个优先级比较低)
        if (procState >= PROCESS_STATE_CACHED_EMPTY) {
            //看一下客户端是否有activity
            if (psr.hasClientActivities()) {
                // This is a cached process, but with client activities.  Mark it so.
                //看一下客户端是否有activity,如果有,则稍微提升一下进程状态的级别到PROCESS_STATE_CACHED_ACTIVITY_CLIENT(17)
                procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
                //设置adj类型是"cch-client-act"
                state.setAdjType("cch-client-act");
            //服务端psr是ProcessServiceRecord进程的服务信息记录对象app.mServices
            //如果设置了mTreatLikeActivity为true(setTreatLikeActivity设置),则就像对待activity一样对待这个进程
            //adj类型设置成"cch-as-act"(as "cch-act")
            } else if (psr.isTreatedLikeActivity()) {
                // This is a cached process, but somebody wants us to treat it like it has
                // an activity, okay!
                //也是稍微提升一下进程状态的级别到PROCESS_STATE_CACHED_ACTIVITY(16)
                //注意这里的优先级(值越低优先级越高)比上面17还高,但是是放在else里面,貌似不太合理,一般都是优先级高的在前面,
                //不然如果同时满足hasClientActivities和isTreatedLikeActivity,那么就只能设置成17,而不是16
                procState = PROCESS_STATE_CACHED_ACTIVITY;
                //adj类型设置成"cch-as-act"(
                state.setAdjType("cch-as-act");
            }
        }

31. A、B service分布调整

        //如果adj是SERVICE_ADJ(500),具体可以看上面adj = ProcessList.SERVICE_ADJ;的逻辑
        //只有上一次lastActivity服务启动或者bind时间是30分钟以内的才会设置成SERVICE_ADJ级别
        //这段逻辑一直都没有变化,那么为啥Android O以前的版本那么多A、B services扎堆?现在S不见了
        //其实不是这段逻辑有变化,而是google限制了后台进程启动服务的权限,没有启动服务的权限,那么服务就少了
        //google针对后台乱象随着OS的升级逐渐砍,不够道高一尺魔高一丈,还是有很多办法绕过去的不是吗?
        if (adj == ProcessList.SERVICE_ADJ) {
            //在doingAll为true,而且cycleReEval循环计算为false,代表需要更新A/B services
            //目前满足这个条件的只有updateOomAdjInnerLSP中fullUpdate为true的时候进来时
            if (doingAll && !cycleReEval) {
                //如果mNewNumAServiceProcs(A services的个数,一会下面会设置)个数大于mNumServiceProcs(上一次fullUpdate后总的服务个数)/3
                //则将mServiceB设置为true,代表这个是b services
                //也就是1/3的服务会被设置成B services
                //从这里也可以看到其实服务的优先级还跟mLruProcesses中进程的位置index有关系,这个后面另外的文章来写吧
                state.setServiceB(mNewNumAServiceProcs > (mNumServiceProcs / 3);
                //mNewNumServiceProcs(fullUpdate更新所有进程中service的个数,调整完成后,会更新到mNumServiceProcs中)
                mNewNumServiceProcs++;
                //如果排在1/3之前的服务,也就是可能会调整成A services的进程
                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.
                    //isLastMemoryLevelNormal获取是内存压力级别,目前用的是psi,psi不太准确,下次有时间讲到AppProfiler时再来讲
                    //mLastMemoryLevel只要不是(ADJ_MEM_FACTOR_NOTHING刚初始化,还没内存压力时;或者ADJ_MEM_FACTOR_NORMAL内存压力正常)
                    //则isLastMemoryLevelNormal返回false,代表此时有内存压力
                    //getLastPss获取的是AppProfiler中recordPssSampleLPf->setLastPss设置进去的mLastPss,
                    //android本身有一个pss收集的进程在,
                    //getCachedRestoreThresholdKb,如果是32bit是184320/3 = 60M, 64bit是322560/3=105M,具体逻辑在ProcessList.java中
                    //也就是进程的mLastPss大于60M(32bit)/105M(64bit),
                    //而且是有内存压力的时候会将这类服务标记成高内存用量,而且回落到B services
/*
//ProcessList.java
    private final int[] mOomMinFreeLow = new int[] {
            12288, 18432, 24576,
            36864, 43008, 49152
    };

    private final int[] mOomMinFreeHigh = new int[] {
            73728, 92160, 110592,
            129024, 147456, 184320
    };
        for (int i = 0; i < mOomAdj.length; i++) {
            int low = mOomMinFreeLow[i];//12288, 18432, 24576, 36864, 43008, 49152
            int high = mOomMinFreeHigh[i];//73728, 92160, 110592,129024, 147456, 184320
            if (is64bit) {
                // Increase the high min-free levels for cached processes for 64-bit
                if (i == 4) high = (high * 3) / 2;//221184
                else if (i == 5) high = (high * 7) / 4;//322560
            }
            mOomMinFree[i] = (int)(low + ((high - low) * scale));//high,目前S上由于RAM大于1G,scale都是1
        }

*/
                    //mLastPss值的更新,一般在亮灭屏: 如果是内存状态有变小,是5分钟更新,没有变小是20分钟更新
                    //其它场景如开机、更新全部的procStats(3个小时以上)时也会触发mLastPss的更新
                    if (!mService.mAppProfiler.isLastMemoryLevelNormal()
                            && app.mProfile.getLastPss()
                            >= mProcessList.getCachedRestoreThresholdKb()) {
                        //设置该服务为高内存用量的服务,mServiceHighRam=true,isServiceHighRam提供给外部用,
                        //不够目前S都没有用到,Android这里也有另一个缺陷(高内存用量的进程没有单独划分出来),
                        //这个功能其实挺好的,不过竟然没有大批量用起来!
                        state.setServiceHighRam(true);
                        //回落到B service级别
                        state.setServiceB(true);
                        //这个注释其实没有必要注掉,可以用DEBUG_PSS、DEBUG_OOM_ADJ_REASON都是可以的
                        //Slog.i(TAG, "ADJ " + app + " high ram!");
                    } else {
                        //回落到B service级别
                        mNewNumAServiceProcs++;
                        //Slog.i(TAG, "ADJ " + app + " not high ram!");
                    }
                } else {
                    //其它情况下(b services)都认为不是高内存的服务(这个逻辑不敢恭维,牛头不对马尾)
                    state.setServiceHighRam(false);
                }
            }
            //如果是b services的话
            if (state.isServiceB()) {
                //则将adj设置成SERVICE_B_ADJ(800)
                adj = ProcessList.SERVICE_B_ADJ;
            }
        }

32. 更新最新的adj到mCurRawAdj中

        //更新最新的adj到mCurRawAdj中
        state.setCurRawAdj(adj);

33. 如果还有未处理完的getMaxAdj进程的调整

        //如果当前adj大于setMaxAdj中设置的值(除了测试用例才会进来,Android S这段代码专门为测试用例留的?)
        //注意了这里是没有调用setCurRawAdj更新mCurRawAdj,故进入这里的话mCurRawAdj可能不是最新调整的状态,看起来属于一个漏洞?
        if (adj > state.getMaxAdj()) {
            //adj则更新成setMaxAdj中设置的值
            adj = state.getMaxAdj();
            //如果adj小于等于250(PERCEPTIBLE_LOW_APP_ADJ用户可感知的最低级别)
            if (adj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                //则分组cgroup更新成默认分组
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            }
        }

34. 非唤醒状态时受限制分组SCHED_GROUP_RESTRICTED调整

        // Put bound foreground services in a special sched group for additional
        // restrictions on screen off
        //如果进程状态procState大于等于PROCESS_STATE_BOUND_FOREGROUND_SERVICE(5)
        //而且在灭屏状态,而且scheduleLikeTopApp(设定像对待前台一样对待该app,类似IMEs有界面时)是false
        if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                && mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
                && !scheduleLikeTopApp) {
            //分组cgroup状态大于SCHED_GROUP_RESTRICTED(1),那就是default、top的时候
            if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) {
                //设置他们的分组状态都是SCHED_GROUP_RESTRICTED受限制分组
                schedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
            }
        }

35. 更新进程的能力capability

        // apply capability from FGS.
        //如果有前台服务(ContextImpl启动前台服务或者service启动时设置服务是前台的)
        if (psr.hasForegroundServices()) {
            //则将当前进程的能力capability设置成前台服务的能力capabilityFromFGS(具体请查看之前的介绍)
            capability |= capabilityFromFGS;
        }

        //通过进程的服务记录psr和进程状态procState得到默认的能力
        capability |= getDefaultCapability(psr, procState);

36. 更新最新的状态到ProcessStateRecord,完成本次adj调整

        // 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.
        //本次adj调整即将完成,将计算的adj复制给mCurAdj
        state.setCurAdj(psr.modifyRawOomAdj(adj));
        //本次adj调整即将完成,将计算的能力capability复制给mCurCapability
        state.setCurCapability(capability);
        //本次adj调整即将完成,将计算的分组信息schedGroup复制给mCurSchedGroup
        state.setCurrentSchedulingGroup(schedGroup);
        //本次adj调整即将完成,将计算的进程状态procState复制给mCurProcState
        state.setCurProcState(procState);
        //本次adj调整即将完成,将计算的进程状态procState复制给mCurRawProcState
        state.setCurRawProcState(procState);
        //通过hasVisibleActivities更新mLastInvisibleTime,如果mHasVisibleActivities从true变成false,
        //则记录这个时候的时间,相当于当进程从可见到不可见的时间
        //主要用在是否允许启动前台服务里面,这个时间目前是mFgToBgFgsGraceDuration(5秒钟以内还是允许的)
        state.updateLastInvisibleTime(hasVisibleActivities);
        //更新mHasForegroundActivities是否拥有前台activity
        state.setHasForegroundActivities(foregroundActivities);
        //设置mCompletedAdjSeq(当前进程完成adj调整的系列号) = mAdjSeq(当前调整的adj系列号)
        state.setCompletedAdjSeq(mAdjSeq);

37. 本次adj调整的返回值

        // 如果当前的adj(mCurAdj)有相对于之前优先级有提升
        // 或者当前的进程状态mCurProcState有相对于之前优先级有提升
        // 或者当前进程的能力mCurCapability有相对于之前有改变
        // 则返回true,否则返回false
        // if curAdj or curProcState improved, then this process was promoted
        return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
                || state.getCurCapability() != prevCapability;
    }

38. 其它相关代码

38.1 获取默认的进程能力

    //通过进程的服务记录psr和进程状态procState得到默认的能力
    private int getDefaultCapability(ProcessServiceRecord psr, int procState) {
        switch (procState) {
            case PROCESS_STATE_PERSISTENT:
            case PROCESS_STATE_PERSISTENT_UI:
            case PROCESS_STATE_TOP:
                //如果是top app或者是常驻进程的进程会有所有的能力
                //包括定位、camera、电话、听筒的能力
/*
    public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
            | PROCESS_CAPABILITY_FOREGROUND_CAMERA
            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
            | PROCESS_CAPABILITY_NETWORK;
*/
                return PROCESS_CAPABILITY_ALL;
            case PROCESS_STATE_BOUND_TOP:
                //如果当前进程是service、provider,被前台(client)绑定的话,则当前进程拥有网络能力
                return PROCESS_CAPABILITY_NETWORK;
            case PROCESS_STATE_FOREGROUND_SERVICE:
                //当前进程的进程状态是PROCESS_STATE_FOREGROUND_SERVICE(4)前台服务级别(instrumentation/hasForegroundServices)
                //如果带有是前台服务(hasForegroundServices == true)
                if (psr.hasForegroundServices()) {
                    // Capability from FGS are conditional depending on foreground service type in
                    // manifest file and the mAllowWhileInUsePermissionInFgs flag.
                    // 则拥有网络能力
                    return PROCESS_CAPABILITY_NETWORK;
                } else {
                    //其它情况,如instrumentation
                    //还有service、provider依赖关系貌似不会直接设置PROCESS_STATE_FOREGROUND_SERVICE
                    //拥有camera、听筒、网络能力
/*
    public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = PROCESS_CAPABILITY_FOREGROUND_CAMERA
            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
*/
                    // process has no FGS, the PROCESS_STATE_FOREGROUND_SERVICE is from client.
                    // the implicit capability could be removed in the future, client should use
                    // BIND_INCLUDE_CAPABILITY flag.
                    return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK;
                }
            case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
                //当前进程的进程状态是PROCESS_STATE_BOUND_FOREGROUND_SERVICE(5)绑定前台服务
                //则拥有网络能力
                return PROCESS_CAPABILITY_NETWORK;
            default:
                //其它情况不赋予相关能力
                return PROCESS_CAPABILITY_NONE;
        }
    }

38.1 shouldSkipDueToCycle是否需要在计算依赖关系时跳过计算

    //app: 当前需要调整的进程
    //client: 客户端的进程状态记录
    //procState: 当前进程的进程状态
    //adj: 当前进程的adj值
    //cycleReEval: 是否处于循环计算模式,只有在updateOomAdjInnerLSP会让cycleReEval=true
    //(条件是设置了setContainsCycle true,如正在计算computeOomAdjLSP的时候还没计算完又跑进来)
    private boolean shouldSkipDueToCycle(ProcessRecord app, ProcessStateRecord client,
            int procState, int adj, boolean cycleReEval) {
        //如果客户端设置了setContainsCycle = true,也即是客户端未调整完毕又进入了computeOomAdjLSP
        if (client.containsCycle()) {
            // We've detected a cycle. We should retry computeOomAdjLSP later in
            // case a later-checked connection from a client  would raise its
            // priority legitimately.
            //这里计算依赖关系的时候,将当前的进程app,设置成包括循环,需要在后面重新计算
            app.mState.setContainsCycle(true);
            //同时将该进程放入循环计算的list里面mProcessesInCycle,后面如果需要重新计算该进程adj的时候会从此处取回
            mProcessesInCycle.add(app);
            // If the client has not been completely evaluated, check if it's worth
            // using the partial values.
            //客户端已经完成的adj调整序列号mCompletedAdjSeq,小于mAdjSeq,代表是之前的调整,本次还未更新
            if (client.getCompletedAdjSeq() < mAdjSeq) {
                //如果是循环计算进来此处
                if (cycleReEval) {
                    // If the partial values are no better, skip until the next
                    // attempt
                    //如果客户端的进程状态大于当前app进程的进程状态
                    //而且客户端的mCurRawAdj(当前调整的未约束过的adj),大于当前进程的adj
                    //代表客户端的优先级比较低,需要等客户端计算完成再来,所以本次依赖关系计算先跳过
                    if (client.getCurRawProcState() >= procState
                            && client.getCurRawAdj() >= adj) {
                        return true;
                    }
                    // Else use the client's partial procstate and adj to adjust the
                    // effect of the binding
                } else {
                    //如果是非循环计算进来此处,由于客户端还没有计算完成,那就等客户端计算完成,先跳过
                    return true;
                }
            }
        }
        return false;
    }
  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值