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

Android adj调整 --- computeOomAdjLSP流程详解-CSDN博客

Android adj调整 --- computeOomAdjLSP流程详解
Android adj调整 --- computeOomAdjLSP流程详解
1. computeOomAdjLSP的参数
2. 是否存在循环计算
3. 没有ApplicationThread的时候的调整
4. 对ProcessStateRecord进程状态记录的一些初始化
5. 设置默认是否允许冻结
6. 获取调整之前的一些状态
7. system_server或者常驻进程的调整
8. 调整之前的一些变量的定义
9. top顶端app的调整
10. 正在播放远端动画的调整
11. instrumentation的调整
12. 正在接受广播进程的调整
13. 正在运行服务进程的调整
14. 系统在休眠时topApp的调整
15. 其它app的默认状态初始化
16. 更新foregroundActivities和mHasVisibleActivities
17. 更新最近使用的activity的状态
18. 调整前台服务或者hasOverlayUi的进程
19. 调整最近活跃的前台服务进程
20. 调整强制提升到用户可感知的进程
21. 调整heavy的进程
21. 调整桌面应用
22. 调整previous上一个使用的应用
23. 循环计算时更新procState、adj、schedGroup
24. 先更新一下当前计算的值到ProcessStateRecord
25. 设置当前adj调整的系列号
26. 调整backup备份的应用
27. service服务自身和服务依赖关系调整
27.1 遍历该进程的服务numberOfRunningServices
27.2 根据Services自身的状态进行调整
27.3 获取前台服务的能力capabilityFromFGS
27.4 遍历每个服务里面的所有链接对象
27.5 取出每个服务链接对象
27.6 只调整自身是服务,由于客户端的链接的情况
27.7 computeClients循环计算时,会先计算客户端的adj
27.8 调整前获取客户端的clientAdj和clientProcState
27.9 进行没有豁免优先级情况的调整
27.9.1 循环计算的时候是否需要先跳过本次计算
27.9.2 能力capability初始化
27.9.3 低于cached activity的进程状态clientProcState约束
27.9.4 如果进程设置了在低内存时托管给系统
27.9.5 如果clientAdj大于当前服务的adj,则开始adj依赖关系调整
27.9.6 clientProcState依赖关系调整
27.9.7 service依赖关系原因的输出
27.10 BIND_WAIVE_PRIORITY == true豁免优先级调整
27.11 绑定客户端对象是activity的调整
28. provider依赖关系调整
28.1 只有当前是provider内容提供者进程才调整
28.2 循环计算computeClients和判断是否需要跳过本次计算shouldSkipDueToCycle
28.3 调整前客户端的clientAdj、clientProcState的记录
28.4 clientAdj大于provider的adj才进行adj依赖关系调整
28.5 clientProcState进程状态依赖调整
28.6 客户端分组依赖关系调整
28.7 输出provider调整的原因
28.8 hasExternalProcessHandles的调整
29. recent-provider最近使用的provider调整
30. 服务相关缓存进程CACHED的调整
31. A、B service分布调整
32. 更新最新的adj到mCurRawAdj中
33. 如果还有未处理完的getMaxAdj进程的调整
34. 非唤醒状态时受限制分组SCHED_GROUP_RESTRICTED调整
35. 更新进程的能力capability
36. 更新最新的状态到ProcessStateRecord,完成本次adj调整
37. 本次adj调整的返回值
38. 其它相关代码
38.1 获取默认的进程能力
38.1 shouldSkipDueToCycle是否需要在计算依赖关系时跳过计算
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) {
1
2
3
4
//调整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;
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
        }
1
2
3
4
5
6
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;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
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);
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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();
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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);
            }
        }
1
2
3
4
5
6
7
8
9
10
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);
                }
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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);
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
                }
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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);
                }
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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);
                }
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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());
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
24. 先更新一下当前计算的值到ProcessStateRecord
先更新一下当前计算的值到ProcessStateRecord(进程状态信息记录)

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

        //先默认该进程没有启动的服务,给初始化值
        state.setHasStartedServices(false);
1
2
3
4
5
6
7
25. 设置当前adj调整的系列号
        //到这里我们开始调整adj的值,设置当前进程adj调整的序列是mAdjSeq
        state.setAdjSeq(mAdjSeq);
1
2
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);
                }
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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");
                    }
                }
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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;
                    }
                }
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
1
2
3
4
5
6
7
8
9
10
11
27.6 只调整自身是服务,由于客户端的链接的情况
只有服务端的adj,才会由于客户端的adj提升而得到相应的提升

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


                    //如果服务链接的客户端是当前app,则跳过,客户端的adj不会由于服务端的adj提升而升高
                    //只有服务端的adj,才会由于客户端的adj提升而得到相应的提升(不然会出现客户端在使用的时候服务端由于优先级低给回收掉了)
                    if (cr.binding.client == app) {
                        // Binding to oneself is not interesting.
                        continue;
                    }
1
2
3
4
5
6
7
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());
                    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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);
                    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
27.9 进行没有豁免优先级情况的调整
                    //如果当前没有设置豁免绑定的优先级调整,一般没有设置
                    //则会进入根据客户端的adj去调整服务端的adj
                    if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
1
2
3
27.9.1 循环计算的时候是否需要先跳过本次计算
                        //判断是是否客户端adj没有计算完成,是否需要跳过本次依赖关系的计算,具体请看shouldSkipDueToCycle的解释
                        if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                            continue;
                        }
1
2
3
4
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;
                            }
                        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
                        }
1
2
3
4
5
6
7
8
9
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;
                                }
                            }
                        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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";
                                }
                            }
                        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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);
                        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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);
                            }
                        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
                        }
                    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
                            }
                        }
                    }
                }
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
到这里就结束了服务依赖调整:当前是服务进程,由于客户端进程的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;
                }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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;
                }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);
                }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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());
                }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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);
                }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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;
                }
1
2
3
4
5
6
7
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 );
                    }
                }
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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);
                    }
                }
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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);
                }
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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");
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
32. 更新最新的adj到mCurRawAdj中
        //更新最新的adj到mCurRawAdj中
        state.setCurRawAdj(adj);
1
2
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;
            }
        }
1
2
3
4
5
6
7
8
9
10
11
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;
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
35. 更新进程的能力capability
        // apply capability from FGS.
        //如果有前台服务(ContextImpl启动前台服务或者service启动时设置服务是前台的)
        if (psr.hasForegroundServices()) {
            //则将当前进程的能力capability设置成前台服务的能力capabilityFromFGS(具体请查看之前的介绍)
            capability |= capabilityFromFGS;
        }

        //通过进程的服务记录psr和进程状态procState得到默认的能力
        capability |= getDefaultCapability(psr, procState);
1
2
3
4
5
6
7
8
9
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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
    }
1
2
3
4
5
6
7
8
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;
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
文章知识点与官方知识档案匹配,可进一步学习相关知识
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/yun_hen/article/details/123778440

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值